⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 轧板标号检测演示dlg.cpp

📁 This file (the project file) contains information at the project level and is used to build a sing
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		{
			double a=-2.0/3.1415926/dr/dr/dr/dr;
			a=a*(1-(x*x+y*y)/2.0/dr/dr);
			double b=-(x*x+y*y)/2.0/dr/dr;
			b=exp(b);
			a=a*b;
			a=12.0*a;
			Marr[x+BASE][y+BASE]=-1*a;//为什么不把它设置为double呢?周家玮修改于8月8日,2006年
		}
	}
	
	for(y=BASE;y<nHeight-BASE;y++)
	{
		for(x=BASE;x<nWidth-BASE;x++)
		{	
			temp=0.0;
			for(j=-BASE;j<=BASE;j++)
				for(i=-BASE;i<=BASE;i++)
				{
					temp+=Point[(y+j)*nWidth+i+x]*Marr[j+BASE][i+BASE];
				}
				m_LpTempPoint[y*nWidth+x]=temp;
		}
	}	
	TotalEdgePoint=0;
	TotalEdgePointGray=0;
	TotalNoEdgePoint=0;
	TotalNoEdgePointGray=0;
	float t1,t2,t3;
	int No;
	for(y=0;y<nHeight;y++)//转化成24位色彩
	{
		for(x=0;x<nWidth;x++)
		{
			No=y*nByteWidth+x*3;
			t1=m_LpTempPoint[x+y*nWidth];
			if (t1>0)  
			{   
				t1=255;
				TotalNoEdgePoint++;
				TotalNoEdgePointGray+=Point[x+y*nWidth];
			}
			else 
			{  
				t1=0;//过零点和负数
				TotalEdgePoint++;
				TotalEdgePointGray+=Point[x+y*nWidth];
			}
			m_lpBit[No]=(BYTE)t1;
			m_lpBit[No+1]=(BYTE)t1;
			m_lpBit[No+2]=(BYTE)t1;
		}
	}	
	

	//利用自动阈值法加以调整:分别计算图象中前景区域平均灰度t1和背景区域平均灰度t2;
	//如果背景区域中某点的灰度不大于t1,那么就将该点并入前景区域;
	//如果前景区域中某点的灰度大于(t1+t2)/2,那么就将该点从前景区域剔除。
	t1=(float)TotalEdgePointGray/(TotalEdgePoint);//取得所有边缘点的平均数值
	t2=(float)TotalNoEdgePointGray/(TotalNoEdgePoint);//	t3=(t1+t2)/2;//效果没有直接用t2好,容易引入干扰
	t2=(t1+t2)/2;
	t3=t1;
	//
	for(y=0;y<nHeight;y++)//转化成24位色彩
	{
		for(x=0;x<nWidth;x++)
		{	
			if (Point[x+y*nWidth]<=t3 )
			{
				t1=0;
				No=y*nByteWidth+x*3;
				m_lpBit[No]=(BYTE)t1;
				m_lpBit[No+1]=(BYTE)t1;
				m_lpBit[No+2]=(BYTE)t1;
			}
			if (Point[x+y*nWidth]>t2 )
			{
				t1=255;
				No=y*nByteWidth+x*3;
				m_lpBit[No]=(BYTE)t1;
				m_lpBit[No+1]=(BYTE)t1;
				m_lpBit[No+2]=(BYTE)t1;
			}
		}
	}


	//去除小面积
	long count;
	DelLittleArea8(20,&count,0);
				
	BYTE *tempByte= new BYTE[nByteWidth*nHeight];
	memcpy(tempByte,m_lpBit,nByteWidth*nHeight);
	No=nByteWidth*nHeight*2;
				
	m_lpBit=new BYTE[No];
	for(y=0;y<nHeight;y++)//转化成24位色彩
	{
		for(x=0;x<nByteWidth;x++)
		{	
			No=y*nByteWidth+x;
			m_lpBit[No]=tempByte[No];
		}
	}
	for(y=nHeight;y<2*nHeight;y++)//转化成24位色彩
	{
		for(x=0;x<nByteWidth;x++)
		{
			No=y*nByteWidth+x;
			m_lpBit[No]=m_lpBitOld[(y-nHeight)*nByteWidth+x];
		}
	}
	delete tempByte;
	nHeight=nHeight*2;
	
	long T2 = ::GetTickCount();//以毫秒为单位
	CString WinCap,strtemp;
	WinCap.Format("图像分割:利用Marr算子边缘完成二值化; 滤除小面积\r\n  时间花费:%ims\r\n",T2-T1); 
	m_edit1.GetWindowText(strtemp);
	WinCap=WinCap+strtemp; 
	m_edit1.SetWindowText(WinCap); 
	delete m_LpTempPoint;
	
	menuSub->EnableMenuItem(IDD_ONESTEP,MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
	menuSub->EnableMenuItem(IDD_BINARY,MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
	menuSub->EnableMenuItem(IDD_PROJECTION, MF_ENABLED);
	
	Invalidate(true);	
}

void CMyDlg::OnProjection() 
{
	//做出垂直投影,并且显示
	//利用投影法,对二值图像中的字符进行分割
	//由于水平投影的作用重要不是确定上下边界,而是滤波
	//所以现在仅仅做垂直投影
	int x,y;
	double* temp=new double[nWidth];
	long PointAddress;
    #define DISTANCE 4 //如果黑线得距离很短,就不是字符内容,该剔除
	nHeight=nHeight/2;
	BYTE *lpTempBit= new BYTE[nHeight*nByteWidth];
	BYTE *lpTempByte= new BYTE[2*nHeight*nByteWidth];
	long T1 = ::GetTickCount();
	memcpy(lpTempByte,m_lpBit,2*nByteWidth*nHeight);

	for(x=0;x<nWidth;x++)
	{
		temp[x]=0;
		for(y=0;y<nHeight;y++)
		{
			PointAddress=y*nByteWidth+3*x;
			if(m_lpBit[PointAddress]<150)
			temp[x]++;
		}
		
	}

	for(x=0;x<nWidth;x++)
	{
		for(y=0;y<nHeight;y++)
		{
			PointAddress=y*nByteWidth+3*x;
			lpTempBit[PointAddress]=255;
			if(y<temp[x])
				lpTempBit[PointAddress]=0;
			lpTempBit[PointAddress+1]=lpTempBit[PointAddress+2]=lpTempBit[PointAddress];
		}
	}
	
	m_lpBit=new BYTE[3*nHeight*nByteWidth];

	for(y=0;y<3*nHeight;y++)
	{
		for(x=0;x<nByteWidth;x++)
		{
			PointAddress=y*nByteWidth+x;
			if(y>=nHeight)
			{
				m_lpBit[PointAddress]=lpTempByte[(y-nHeight)*nByteWidth+x];
			}
			else
			{
				m_lpBit[PointAddress]=lpTempBit[PointAddress];
			}
			
		}
	}
	nHeight=3*nHeight;
	long T2 = ::GetTickCount();
	delete lpTempBit;
	delete temp;
	delete lpTempByte;
	CString WinCap,strtemp;
	WinCap.Format("二值图计算垂直投影\r\n  时间花费:%ims\r\n",T2-T1); 
	m_edit1.GetWindowText(strtemp);
	WinCap=WinCap+strtemp; 
	m_edit1.SetWindowText(WinCap); 
	menuSub->EnableMenuItem(IDD_PROJECTION, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
	menuSub->EnableMenuItem(IDD_PROJECTIONDIVIDE, MF_ENABLED);
		
	Invalidate(true);	
}

void CMyDlg::OnProjectiondivide() 
{
//在投影线上画分区线
//对于某一行进行扫描,确定0-1和1-0的变化位置 记录开始和结尾
	int x,y;
	lineBlackNum=0,lineWhiteNum=0;
	nHeight=nHeight/3;
	BYTE *lpTempBit= new BYTE[nHeight*nByteWidth];
	BYTE *lpTempByte=new BYTE[nHeight*nByteWidth*3];
    #define LINE 3 //对第三行扫描

	long T1 = ::GetTickCount();
	memcpy(lpTempBit,m_lpBit,nByteWidth*nHeight);
	memcpy(lpTempByte,m_lpBit,3*nByteWidth*nHeight);
	for(x=0;x<nWidth-1;x++)
	{
		if((lpTempBit[LINE*nByteWidth+3*x]==255)&&(lpTempBit[LINE*nByteWidth+3*x+3]==0))//白-黑
		{
			lineBlackNum++;
			lineBlackS[lineBlackNum]=x+1;//黑的开始
			lineWhiteE[lineWhiteNum]=x;//白的结束
		}
		if((lpTempBit[LINE*nByteWidth+3*x]==0)&&(lpTempBit[LINE*nByteWidth+3*x+3]==255))//黑-白
		{
			lineWhiteNum++;
			lineWhiteS[lineWhiteNum]=x+1;//白的开始
			if((x-lineBlackS[lineBlackNum])>2)
				lineBlackE[lineBlackNum]=x;//黑的结束
			else
			{
				lineBlackNum--;
			}
		}
	}

	m_lpBit=new BYTE[4*nHeight*nByteWidth];
	for(y=0;y<4*nHeight;y++)
		for(x=0;x<nByteWidth;x++)
		{
			long PointAddress=y*nByteWidth+x;
			if(y>=nHeight)
			{
				m_lpBit[PointAddress]=lpTempByte[(y-nHeight)*nByteWidth+x];
			}
			else
				m_lpBit[PointAddress]=lpTempBit[PointAddress];
		}

	for(x=1;x<=lineBlackNum;x++)//画出黑色区域  x=0 的数组没有使用
		for(y=0;y<nHeight;y++)
		{
			m_lpBit[y*nByteWidth+3*lineBlackS[x]]=255;
			m_lpBit[y*nByteWidth+3*lineBlackS[x]+1]=0;
			m_lpBit[y*nByteWidth+3*lineBlackS[x]+2]=0;
			m_lpBit[y*nByteWidth+3*lineBlackE[x]]=155;
			m_lpBit[y*nByteWidth+3*lineBlackE[x]+1]=155;
			m_lpBit[y*nByteWidth+3*lineBlackE[x]+2]=155;
		}
	long T2 = ::GetTickCount();

	nHeight=4*nHeight;
	delete lpTempBit;	
	delete lpTempByte;
    CString WinCap,strtemp;
	WinCap.Format("垂直投影图分区\r\n  时间花费:%ims\r\n",T2-T1); 
	m_edit1.GetWindowText(strtemp);
	WinCap=WinCap+strtemp; 
	m_edit1.SetWindowText(WinCap); 

	menuSub->EnableMenuItem(IDD_PROJECTIONDIVIDE,MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
	menuSub->EnableMenuItem(IDD_RECONGNISE, MF_ENABLED);

	Invalidate(true);	

}

void CMyDlg::OnRecongnise() 
{
//识别字符,得到结果
	int x,y,i;
	long PointAddress;
	nHeight=nHeight/4;
	BYTE *lpTempBit= new BYTE[nHeight*nByteWidth];
	BYTE *lpTempByte=new BYTE[nHeight*nByteWidth*4];
	long T1 = ::GetTickCount();
	memcpy(lpTempBit,m_lpBit,nByteWidth*nHeight);
	memcpy(lpTempByte,m_lpBit,4*nByteWidth*nHeight);
	m_lpBit=new BYTE[nHeight*nByteWidth];

	//显示图中的第3排为此步骤的分析数据
	for(y=2*nHeight;y<3*nHeight;y++)
		for(x=0;x<nByteWidth;x++)
		{
			PointAddress=y*nByteWidth+x;
			m_lpBit[(y-2*nHeight)*nByteWidth+x]=lpTempByte[PointAddress];
		}
	for(i=1;i<=lineBlackNum;i++)//画出黑色区域  x=0 的数组没有使用
	{
		CharTop[i]=0;CharBottom[i]=nHeight;
		for(x=lineBlackS[i];x<lineBlackE[i];x++)
			for(y=0;y<nHeight;y++)
			{
				if(m_lpBit[y*nByteWidth+3*x]==0)
				{
					if(y==0)y=0;
					if(y>CharTop[i])CharTop[i]=y;//最大
					if(y<CharBottom[i])
						CharBottom[i]=y;//最小
				}
			}
	}
	CString result=	MatchChar(lineBlackNum,CharTop,CharBottom,lineBlackS,lineBlackE);
//画出横竖4条线
	for(i=1;i<=lineBlackNum;i++)//画出黑色区域  x=0 的数组没有使用
	{
		for(x=lineBlackS[i];x<lineBlackE[i];x++)
		{//上横
			m_lpBit[CharTop[i]*nByteWidth+3*x]=255;
			m_lpBit[CharTop[i]*nByteWidth+3*x+1]=0;
			m_lpBit[CharTop[i]*nByteWidth+3*x+2]=0;
		//下横
			m_lpBit[CharBottom[i]*nByteWidth+3*x]=0;
			m_lpBit[CharBottom[i]*nByteWidth+3*x+1]=255;
			m_lpBit[CharBottom[i]*nByteWidth+3*x+2]=0;
		}
		for(y=CharBottom[i];y<CharTop[i];y++)
		{//左竖
			m_lpBit[y*nByteWidth+3*lineBlackS[i]]=255;
			m_lpBit[y*nByteWidth+3*lineBlackS[i]+1]=0;
			m_lpBit[y*nByteWidth+3*lineBlackS[i]+2]=255;
		//右竖
			m_lpBit[y*nByteWidth+3*lineBlackE[i]]=0;
			m_lpBit[y*nByteWidth+3*lineBlackE[i]+1]=155;
			m_lpBit[y*nByteWidth+3*lineBlackE[i]+2]=255;

		}
	}
	memcpy(lpTempBit,m_lpBit,nByteWidth*nHeight);
	m_lpBit=new BYTE[5*nHeight*nByteWidth];
	for(y=0;y<5*nHeight;y++)
		for(x=0;x<nByteWidth;x++)
		{
			long PointAddress=y*nByteWidth+x;
			if(y>=nHeight)
			{
				m_lpBit[PointAddress]=lpTempByte[(y-nHeight)*nByteWidth+x];
			}
			else
				m_lpBit[PointAddress]=lpTempBit[PointAddress];
		}

	nHeight=5*nHeight;	
	long T2 = ::GetTickCount();
	delete lpTempByte;
	delete lpTempBit;
    CString WinCap,strtemp;
	WinCap.Format("识别字符\r\n  字符是     %s  时间花费:%ims\r\n",result,T2-T1); 
	m_edit1.GetWindowText(strtemp);
	WinCap=WinCap+strtemp; 
	m_edit1.SetWindowText(WinCap); 
	WinCap.Format("识别结果:%s",result); 
	m_result.SetWindowText(WinCap); 
	menuSub->EnableMenuItem(IDD_RECONGNISE,MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
	this->Invalidate(true);		
}

void CMyDlg::OnOnestep() 
{
	if(m_lpBit==NULL)return;
	long T1 = ::GetTickCount();
	OnBinary();
	OnProjection();
	OnProjectiondivide();
	OnRecongnise();
	long T2 = ::GetTickCount();

    CString WinCap,strtemp;
	WinCap.Format("一步执行所有过程:%ims\r\n",T2-T1); 
	m_edit1.GetWindowText(strtemp);
	WinCap=WinCap+strtemp; 
	m_edit1.SetWindowText(WinCap); 

	menuSub->EnableMenuItem(IDD_ONESTEP,MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
	menuSub->EnableMenuItem(IDD_BINARY,MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);

	this->Invalidate(true);		
}

void CMyDlg::OnReloadfile() 
{
	int ReturnNum=ReadBmpFile(FileName,0);
	this->Invalidate(true);	
	CString Wincap;
	Wincap.Format ("重新加载图像数据 文件名%s",FileName);
	m_edit1.SetWindowText(Wincap); 

	menuSub->EnableMenuItem(IDD_BINARY, MF_ENABLED);
	menuSub->EnableMenuItem(IDD_ONESTEP, MF_ENABLED);

	menuSub->EnableMenuItem(IDD_PROJECTION, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
	menuSub->EnableMenuItem(IDD_PROJECTIONDIVIDE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
	menuSub->EnableMenuItem(IDD_RECONGNISE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);


}


int CMyDlg::DelLittleArea8(int AreaOrPerimeter,long* count,int Type)
{
//八邻域物体;AreaOrPerimeter:最小保留的面积或周长,返回count物体最大可能的数量(第一次标号得到),
//Type操作的类型,0:代表面积过滤中的使用 1:代表周长过滤中的应用
//去掉面积或周长小于AreaOrPerimeter的黑色物体
	int x,y,i;
	long PointAddress;
	bool OneNoFinish;
//	int *areaNo;
	int *lpTempNo= new int[nHeight*nWidth];//标号序列
	*count=1;
	OneNoFinish=false;
	//行标号
	for(y=0;y<nHeight;y++)
		for(x=0;x<nWidth;x++)
		{
			lpTempNo[y*nWidth+x]=0;
		}
	for(y=1;y<nHeight-1;y++)
		for(x=1;x<nWidth-1;x++)
		{
			PointAddress=y*nByteWidth+3*x;
			if((OneNoFinish==false)&&(*(m_lpBit+PointAddress)==0)||(m_lpBit[PointAddress-3]==0&&m_lpBit[PointAddress]==0))
			//开始发现是物体标号或物体的连续标号
			{
				OneNoFinish=true;
				lpTempNo[y*nWidth+x]=*count;
			}
			else
				if((OneNoFinish==true)&&*(m_lpBit+PointAddress)==255)//行末尾
				{
					*count=*count+1;
					OneNoFinish=false;
				}
		}
	//上下行判断,从上到下,下行跟上行的编号
	int t1,t2,t3,t4,t5;
	for(y=1;y<nHeight-1;y++)
		for(x=1;x<nWidth-1;x++)
		{//这里是唯一和是邻域有区别的地方
			PointAddress=y*nWidth+x;
			t1=lpTempNo[PointAddress];
			t2=lpTempNo[PointAddress+nWidth-1];
			t3=lpTempNo[PointAddress+nWidth];
			t4=lpTempNo[PointAddress+nWidth+1];

			if(t1!=0)//本像素有标号
				if(((t2!=0)&&(t1!=t2))||((t3!=0)&&(t1!=t3))||((t4!=0)&&(t1!=t4)))//下行对应像素有不同的标号
				{	if((t2!=0)&&(t1!=t2)) t5=t2;
					if((t3!=0)&&(t1!=t3)) t5=t3;	
					if((t4!=0)&&(t1!=t4)) t5=t4;
					for(i=0;i<nWidth;i++)
						if (lpTempNo[y*nWidth+nWidth+i]==t5) lpTempNo[y*nWidth+nWidth+i]=t1;//改下行所有该标号点
				}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -