📄 轧板标号检测演示dlg.cpp
字号:
}
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 + -