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

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

📁 This file (the project file) contains information at the project level and is used to build a sing
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		}
	for(y=nHeight-1;y>=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;
				}
		}
	//统计各标号的周长
	long *PerimeterNo =new long[*count];
	for(x=0;x<*count;x++) *(PerimeterNo+x)=0;

	for(y=1;y<nHeight-1;y++)
		for(x=1;x<nWidth-1;x++)
		{	PointAddress=y*nWidth+x;
			t2=lpTempNo[PointAddress];
			t1=lpTempNo[PointAddress-1];
			//如果与前一点或后一点不同,就是边界点
			if((t1==0)&&(t2!=0))PerimeterNo[t2]=PerimeterNo[t2]+1;//0编号为背景
			if((t1!=0)&&(t2==0))
				if((lpTempNo[PointAddress-2]!=0))PerimeterNo[t1]=PerimeterNo[t1]+1;//0编号为背景,需要防止单元素点、线
			//对应编号的周长数组加上一
		}
	//统计各标号的面积
	long *areaNo =new long[*count];
	for(x=0;x<*count;x++) *(areaNo+x)=0;

	for(y=0;y<nHeight;y++)
		for(x=0;x<nWidth;x++)
		{	PointAddress=y*nWidth+x;
			t1=lpTempNo[PointAddress];
			if(t1!=0)//0编号为背景
				areaNo[t1]=areaNo[t1]+1;//对应编号的面积数组加上一
		}
	//type类别为0,代表有关于面积的操作,取出小面积
	if(Type==0)
	{
		for(y=0;y<nHeight;y++)
			for(x=0;x<nWidth;x++)
			{	PointAddress=y*nWidth+x;
				t1=lpTempNo[PointAddress];			
				if(areaNo[t1]<AreaOrPerimeter) 
				{
					PointAddress=y*nByteWidth+3*x;
					*(m_lpBit+PointAddress)=255;
					*(m_lpBit+PointAddress+1)=255;
					*(m_lpBit+PointAddress+2)=255;
				}
			
			}
	}
	if(Type==1)	//type类别为1,代表有关于周长的操作,取出小周长
	{
		for(y=0;y<nHeight;y++)
			for(x=0;x<nWidth;x++)
			{	PointAddress=y*nWidth+x;
				t1=lpTempNo[PointAddress];			
				if(PerimeterNo[t1]<AreaOrPerimeter) 
				{
					PointAddress=y*nByteWidth+3*x;
					*(m_lpBit+PointAddress)=255;
					*(m_lpBit+PointAddress+1)=255;
					*(m_lpBit+PointAddress+2)=255;
				}
			}
	}
	delete lpTempNo;
	delete areaNo;
	delete PerimeterNo ;
	return 1;
}


CString CMyDlg::MatchChar(int CharNum, int *ytop, int *ybottom, int *xleft, int *xright)
{
//输入图中的字符数量 CharNum
//每个字符的y最大ytop最小坐标ybottom,x的最左xleft最右坐标xright
//和标准模板匹配程序
//首先是大小的归一处理
//其次是和存盘的标准图样比较,得到最大相似度
//输出字符串及字符代表的整数量
	//CString IniDir="C:\\Documents and Settings\\103013\\桌面\\喷码检测\\演示图片\\";//模板文件路径
#define ModeFileNum 18//模板数量
#define UnitWidth 16
#define UnitHeight 32

	CString FileArray[ModeFileNum];//模板文件名
	CString FileAsnum[ModeFileNum];//每个模板文件代表的字符
	FileArray[0]="data//standard_0.bmp";FileAsnum[0]="0 ";
	FileArray[1]="data//standard_1.bmp";FileAsnum[1]="1 ";
	FileArray[2]="data//standard_2.bmp";FileAsnum[2]="2 ";
	FileArray[3]="data//standard_3.bmp";FileAsnum[3]="3 ";
	FileArray[4]="data//standard_4.bmp";FileAsnum[4]="4 ";
	FileArray[5]="data//standard_5.bmp";FileAsnum[5]="5 ";
	FileArray[6]="data//standard_6.bmp";FileAsnum[6]="6 ";
	FileArray[7]="data//standard_7.bmp";FileAsnum[7]="7 ";
	FileArray[8]="data//standard_8.bmp";FileAsnum[8]="8 ";
	FileArray[9]="data//standard_9.bmp";FileAsnum[9]="9 ";
	FileArray[10]="data//standard_10.bmp";FileAsnum[10]="0 ";
	FileArray[11]="data//standard_11.bmp";FileAsnum[11]="1 ";
	FileArray[12]="data//standard_111.bmp";FileAsnum[12]="1 ";
	FileArray[13]="data//standard_15.bmp";FileAsnum[13]="5 ";
	FileArray[14]="data//standard_115.bmp";FileAsnum[14]="5 ";
	FileArray[15]="data//standard_13.bmp";FileAsnum[15]="3 ";
	FileArray[16]="data//standard_12.bmp";FileAsnum[16]="2 ";
	FileArray[17]="data//standard_14.bmp";FileAsnum[17]="4 ";
	//存放模板文件的数据指针
	BYTE pModelByte[ModeFileNum][UnitWidth*UnitHeight];
	int i,x,y,processNo=0;
	CString *Char=new CString[CharNum+1];
	int *LineByte=new int;
	double tempAdd1, tempAdd2,AllAdd1,AllAdd2,AllAdd3;
	float Correlate,maxCorrelate=0;//每个字符和标准模板相似运算的结果
	//统一将所有的模板文件读出来存放到内存
	for(i=0;i<ModeFileNum;i++)
		{
			CString fileName=FileArray[i];
			fileName=IniDir+fileName;
			if (!ReadBmpFile(fileName,LineByte,0))
				return "0";
			for(x=0;x<UnitWidth;x++)
				for(y=0;y<UnitHeight;y++)
				{
					pModelByte[i][y*UnitWidth+x]=m_pmodeByte[y*(*LineByte)+3*x];
				}
	}

	for(processNo=1;processNo<=CharNum;processNo++)
	{
		//先标准化为16×32的大小
		BYTE* pchar=new BYTE[UnitWidth*UnitHeight];

		float Wmultiple=(float)(xright[processNo]-xleft[processNo])/UnitWidth;
		float Hmultiple=(float)(ytop[processNo]-ybottom[processNo])/UnitHeight;//放大和缩小的长宽倍数

		for(y=0;y<UnitHeight;y++)
			for(x=0;x<UnitWidth;x++)
			{
				int oldy=(int)(ybottom[processNo]+y*Hmultiple);
				int oldx=(int)(xleft[processNo]+x*Wmultiple);
				int oldposition=(int)(oldy*nByteWidth+3*oldx);
				pchar[y*UnitWidth+x]=m_lpBit[oldposition];

			}
		//WriteChar(pchar, UnitWidth, UnitHeight,processNo);//将各个标准字符写入到相应文件中,用于参考
		//读取模式,进行匹配
		maxCorrelate=0;
		for(i=0;i<ModeFileNum;i++)
		{
			
			//相似度
			AllAdd1=AllAdd2=AllAdd3=0;
			for(y=0;y<UnitHeight;y++)
			for(x=0;x<UnitWidth;x++)
			{
    			long PointAddress=y*UnitWidth+x;
			
					tempAdd1=(long)pchar[PointAddress];
				tempAdd2=(long)pModelByte[i][PointAddress];
				if((tempAdd1<128)&&(tempAdd2<128))
					AllAdd1++;
				if(tempAdd2<128)
					AllAdd2++;
			}
			Correlate=(float)(AllAdd1/AllAdd2);
			
		/*	tempAdd1=(long)pchar[PointAddress];
			tempAdd2=(long)pModelByte[i][PointAddress];
			AllAdd1+=(255-tempAdd1)*(255-tempAdd2);//计算黑点的数值
			AllAdd2+=(255-tempAdd2)*(255-tempAdd2);
			AllAdd3+=(255-tempAdd1)*(255-tempAdd1);
		}
			AllAdd1=AllAdd1*2;
			Correlate=AllAdd1/(AllAdd2+AllAdd3);*/			
		
			if(Correlate>maxCorrelate)
			{
				maxCorrelate=Correlate;
				Char[processNo]=FileAsnum[i];
			}
		}
	}
	CString result="";
	for(i=1;i<=CharNum;i++)
	{
		result+=Char[i];
	}
	delete LineByte;
	return result;
}

int CMyDlg::ReadBmpFile(CString FileName, int *LineByte, int Type)
{
//读取位图文件,返回图形的长、宽、24色像素的指针
	CFile BmpFile;
	BYTE *m_lpBit;
	int nWidth,nHeight,nByteWidth;
	if (!BmpFile.Open(FileName,CFile::modeRead,NULL))
		return 0; //读取文件失败
	int FileLen=BmpFile.GetLength();
	BYTE *lpFile=NULL;
	lpFile= new BYTE[FileLen];
	//读取文件中全部数据失败
	if(!BmpFile.Read (lpFile,FileLen)){ BmpFile.Close();return 0;} 
	BmpFile.Close(); 
	//文件的头结构指定类型、大小等
	BITMAPFILEHEADER *lpBitmapFileHeader;
	lpBitmapFileHeader=(BITMAPFILEHEADER *)	lpFile;
	//从结构中得到文件的大小
	int filelength= lpBitmapFileHeader->bfSize ;
	//从结构中得到图像数据(不包括调色板数据)在文件中开始地址 
	int DataOffBits=lpBitmapFileHeader->bfOffBits;
	//类型是否为'b'+'m' 
	if (lpBitmapFileHeader->bfType!='B'+'M'*256)  return 0;
	BITMAPINFOHEADER *lpBitmapInfoHeader;
	//得到BITMAPINFOHEADER(BITMAPINFO) 结构的开始地址
	lpBitmapInfoHeader=(BITMAPINFOHEADER *)(lpFile + sizeof(BITMAPFILEHEADER));  
	//unsigned int PointColorNum=1<<(lpBitmapInfoHeader->biBitCount);
	unsigned int PointColorNum=0 ;//图像色彩 真色彩超过12000
	switch(lpBitmapInfoHeader->biBitCount)
	{	case 1://表示图像单色 
			PointColorNum=2;break;
		case 4://表示图像16色 
			PointColorNum=16;break;
		case 8://表示图像256色 
			PointColorNum=256;break;
		case 24://表示图像真色彩 
			PointColorNum=1<<(lpBitmapInfoHeader->biBitCount);break;
		default:
			PointColorNum=1<<(lpBitmapInfoHeader->biBitCount);// 真色彩
	}
	if(lpBitmapInfoHeader->biCompression!=BI_RGB)
	{
		::MessageBox(this->m_hWnd,"有压缩数据,代号:" + (char)(lpBitmapInfoHeader->biCompression),"不能显示为图像",MB_OK);
		return(0);
	}
	unsigned int PaletteSize;//得到调色板的大小,可能有压缩
	if(lpBitmapInfoHeader->biClrUsed==0)//位图中实际使用的颜色数,因为压缩所以和PointColorNum不同
		PaletteSize=PointColorNum;//biClrUsed=0 本位图使用最大的颜色数(biBitCount定)
	else
//		if (lpBitmapInfoHeader->biBitCount<16)
		PaletteSize=lpBitmapInfoHeader->biClrUsed;//颜色数从biClrUsed得到

	if (lpBitmapInfoHeader->biBitCount >=16)PaletteSize=0;//颜色表有0项目

	PaletteSize=PaletteSize*sizeof(RGBQUAD);
	//有关数据定义
	//BYTE *m_lpBit;//像素每点数值的指针
	nWidth=( lpBitmapInfoHeader->biWidth);
	nHeight=( lpBitmapInfoHeader->biHeight);
	nByteWidth= nWidth*3;//真色彩24位3字节显示一点
	if (nByteWidth%4) nByteWidth+=4-(nByteWidth%4);//位图文件每行比需要是4的倍数
	m_lpBit = lpFile+DataOffBits;
	
	if (lpBitmapInfoHeader->biBitCount <24)//有调色板显示<16或=16时则转化成24色真色彩
	{	
		RGBQUAD *pPalette=(RGBQUAD *)(lpFile + sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER));
		int nLen=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+nByteWidth*nHeight;
		//BYTE *lpTemp=lpFile;
		lpFile=new BYTE[nLen];//改变lpFile的地址使m_lpBit和lpTempBit不重叠
		BITMAPFILEHEADER bmh;
		BITMAPINFOHEADER bmi;
		bmh.bfType='B'+'M'*256;
		bmh.bfSize=nLen;
		bmh.bfReserved1=0;
		bmh.bfReserved2=0;
		bmh.bfOffBits=54;//14+40=sizeof(BITMAPINFOHEADER)+sizeof(BITMAPFILEHEADER)
		bmi.biSize=sizeof(BITMAPINFOHEADER);//定值 40
		bmi.biWidth=nWidth;
		bmi.biHeight=nHeight;
		bmi.biPlanes=1;//平面数一定为1
		bmi.biBitCount=24;//转化为真色彩24位
		bmi.biCompression=BI_RGB;//不压缩
		bmi.biSizeImage=0;//BI_RGB类型一定为0
		bmi.biXPelsPerMeter=0;
		bmi.biYPelsPerMeter=0;
		bmi.biClrUsed=0;//颜色数
		bmi.biClrImportant=0;//所有颜色都是重要色
		
		memset(lpFile,0,nLen);//数据赋值0
		memcpy(lpFile,&bmh,sizeof(BITMAPFILEHEADER));
		memcpy(lpFile+sizeof(BITMAPFILEHEADER),&bmi,sizeof(BITMAPINFOHEADER));
	
		BYTE *lpTempBit=lpFile+sizeof(BITMAPINFOHEADER)+sizeof(BITMAPFILEHEADER);
		int x,y;
		unsigned int nBWidth,OldPoint,byteNO,BitNo,Palette,NewPoint;
		nBWidth=nWidth;//*lpBitmapInfoHeader->biBitCount;//一行字节代表的像素点数
		if (nBWidth%(32/lpBitmapInfoHeader->biBitCount)) //文件中实际应该有的字节大小是4的倍数
			nBWidth+=(32/lpBitmapInfoHeader->biBitCount)-(nBWidth%(32/lpBitmapInfoHeader->biBitCount));

		for(y=0;y<nHeight;y++)//图像从左下坐标开始
		{
			for(x=0;x<nWidth;x++)
			{
				OldPoint=y*nBWidth+x;
				switch(lpBitmapInfoHeader->biBitCount)
					{case 1://表示图像单色 
							//if (nBWidth%32) nBWidth+=32-(nBWidth%32);//图像中每行的字节数为4的倍数
							//OldPoint=y*nBWidth+x;
							byteNO=int(OldPoint / 8);
							BitNo=7-(OldPoint % 8);
							Palette=m_lpBit[byteNO];	
							Palette=(Palette>>BitNo) ;
							Palette=(Palette	& 0X01);
							break;
			
					case 4://表示图像16色 
							//if (nBWidth%8) nBWidth+=8-(nBWidth%8);//图像中每行的字节数为4的倍数
							//OldPoint=y*nBWidth+x;
							byteNO=int(OldPoint / 2) ;
							BitNo=(OldPoint % 2)*4;
							Palette=m_lpBit[byteNO];
							Palette=((Palette>>BitNo) & 0x0f);
							break;
					case 8://表示图像256色 
							//if (nBWidth%4) nBWidth+=4-(nBWidth%4);//图像中每行的字节数为4的倍数
							//OldPoint=y*nBWidth+x;
							Palette= m_lpBit[OldPoint];
							break;
					case 16://16位 两字节一点,5bit为一种色彩,blue(低),green(中),red(高),最高5bit无意义
							byteNO=OldPoint / 2;
							if (!(OldPoint%2))
							{
								NewPoint=y*nByteWidth+x*3;//24色
								BYTE Color[2],GetColor;
								Color[0]=m_lpBit[byteNO];
								Color[1]=m_lpBit[byteNO+1];								
								lpTempBit[NewPoint]=(Color[0] & 0x1f)  ;
								GetColor=((Color[0] >>5) & 0x07) +((Color[1]<<3) & 0x18);
								lpTempBit[NewPoint+1]=GetColor  ;
								GetColor=((Color[1]>>2) & 0x1f);
								lpTempBit[NewPoint+2]= GetColor;
							}
					}
				if ((lpBitmapInfoHeader->biBitCount) < 16)
				{
					if (Palette*4 > PaletteSize)  Palette=0;
					NewPoint=y*nByteWidth+x*3;//24色
					lpTempBit[NewPoint]=(pPalette[Palette].rgbBlue) ;
					lpTempBit[NewPoint+1]=(pPalette[Palette].rgbGreen ) ;
					lpTempBit[NewPoint+2]=(pPalette[Palette].rgbRed  ) ;
				}
			}
		}
	}
	m_pmodeByte= lpFile+ sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
	*LineByte=nByteWidth;
	return 1;
}

int CMyDlg::WriteChar(BYTE *pbyte, int Width, int Height, int No)
{
//讲标准化后的字符保存进文件 16*32
	if (pbyte==NULL) return 0;
	BYTE *tempByte=new BYTE[Width*Height*3];
	for(int i=0;i<Width*Height;i++)
	{
		tempByte[i*3]=tempByte[i*3+1]=tempByte[i*3+2]=pbyte[i];
	}
	CTime tt;
	CString FileName;
	FileName.Format("%i.bmp",No);
	
	CFileDialog dlg(FALSE,"bmp",FileName,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,"位图文件|*.bmp||");
	CFile file;
	if (dlg.DoModal()==IDOK)
	{
		if (!file.Open(dlg.GetPathName(),CFile::modeWrite|CFile::modeCreate))
		{
			MessageBox("无法打开指定的文件");
			return 0;
		}
		BITMAPFILEHEADER bmh;
		BITMAPINFOHEADER bmi;
		bmh.bfType='B'+'M'*256;
		bmh.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+Width*3*Height;
		bmh.bfReserved1=0;
		bmh.bfReserved2=0;
		bmh.bfOffBits=54;//14+40=sizeof(BITMAPINFOHEADER)+sizeof(BITMAPFILEHEADER)
		bmi.biSize=sizeof(BITMAPINFOHEADER);//定值 40
		bmi.biWidth=Width;
		bmi.biHeight=Height;
		bmi.biPlanes=1;//平面数一定为1
		bmi.biBitCount=24;//转化为真色彩24位
		bmi.biCompression=BI_RGB;//不压缩
		bmi.biSizeImage=0;//BI_RGB类型一定为0
		bmi.biXPelsPerMeter=0;
		bmi.biYPelsPerMeter=0;
		bmi.biClrUsed=0;//颜色数
		bmi.biClrImportant=0;//所有颜色都是重要色
		//memcpy(pMem+sizeof(BITMAPINFOHEADER),m_lpBit,nLen);
		file.Write(&bmh,sizeof(BITMAPFILEHEADER));
		file.Write(&bmi,sizeof(BITMAPINFOHEADER));
		file.Write(tempByte,Width*Height*3);
		file.Close();
	}
	delete tempByte;
	return 1;
}

int CMyDlg::SetWindow()
{
//设置窗口的布局
	CRect lpRect;
	this->GetWindowRect(&lpRect);
	int ShowW=WindowMinWidth,ShowH=WindowMinHeight;
	if(nWidth>WindowMinWidth)ShowW=nWidth+40;
	if(5*nHeight+300>WindowMinHeight)ShowH=5*nHeight+350;
		this->MoveWindow(lpRect.left,lpRect.top,ShowW,ShowH);
	m_edit1.MoveWindow (10,ShowH-280,ShowW-25,220,true);
	m_edit1.ShowWindow(true); 
	m_result.MoveWindow (ShowW/2-200,ShowH-310,400,30,true);
	m_result.ShowWindow(true); 
	return 1;
}

HBRUSH CMyDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
{
	//绘制控件的颜色
	HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
	if(m_edit1.m_hWnd ==pWnd->m_hWnd )
	{
		pDC->SetTextColor(RGB(255,255,255));
		pDC->SetBkColor (RGB(0,0,255));
	}
	if(m_result.m_hWnd ==pWnd->m_hWnd)
	{
		pDC->SetTextColor(RGB(255,255,255));
		pDC->SetBkColor (RGB(0,0,255));
	}
	// TODO: Return a different brush if the default is not desired
	return hbr;
}

void CMyDlg::OnMouseMove(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	
	CDialog::OnMouseMove(nFlags, point);
}

void CMyDlg::OnAbout() 
{
	CAboutDlg about;
	about.DoModal(); 	
}

void CMyDlg::OnHelp() 
{
	DIAHELP	 help;
	help.DoModal(); 
}

⌨️ 快捷键说明

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