- Visual C++数字图像模式识别典型案例详解
- 冯伟兴 梁洪 王臣业编著
- 812字
- 2025-03-16 03:50:50
5.4.2 人脸识别与分割
编程实现
[1] 在视图类里添加消息映射函数Onboundary()以实现轮廓提取。Onboundary()函数代码如代码5-5所示。
代码5-5 Onboundary()函数
void CDemoView::Onboundary() { CDemoDoc *pDoc=GetDocument(); ImageDib *pDib=pDoc->GetPDib(); int i,j,thd; CSize size=pDib->GetDimensions(); int lineByte=(size.cx+3)/4*4; long pixel_scales=0; for(i=0;i<size.cx;i++){ for(j=0;j<size.cy;j++){ pixel_scales+=*(pDib->m_pImgData+j*lineByte+i); } } thd=pixel_scales/(size.cx*size.cy); GrayTrans graytrans(size,pDib->m_nBitCount, pDib->m_lpColorTable, pDib-> m_pImgData); graytrans.Binary(thd); //调用Binary()对图像进行二值化 //建立一个新视图,显示分割结果 CMainFrame* pFrame = (CMainFrame *)(AfxGetApp()->m_pMainWnd); pFrame->SendMessage(WM_COMMAND, ID_FILE_NEW); CDemoView* pView=(CDemoView*)pFrame->MDIGetActive()->GetActiveView(); CDemoDoc* pDocNew=pView->GetDocument(); ImageDib *dibNew=pDocNew->GetPDib(); dibNew->ReplaceDib(graytrans.GetDimensions(),graytrans.m_nBitCountOut, graytrans.m_lpColorTableOut, graytrans.m_pImgDataOut); pView->OnInitialUpdate(); pDocNew->SetModifiedFlag(TRUE); pDocNew->UpdateAllViews(pView); } void CDemo1View::Onboundary() { CDemo1Doc *pDoc=GetDocument(); ImageDib *pDib=pDoc->GetPDib(); //只处理灰度图像 if(pDib->m_nBitCount!=8){ ::MessageBox(0, "只处理灰度图像", MB_OK,0); return ; } int i,j,thd; CSize size=pDib->GetDimensions(); int lineByte=(size.cx+3)/4*4; long pixel_scales=0; for(i=0;i<size.cx;i++){ for(j=0;j<size.cy;j++){ pixel_scales+=*(pDib->m_pImgData+j*lineByte+i); } } thd=pixel_scales/(size.cx*size.cy); GrayTrans graytrans(size,pDib->m_nBitCount, pDib->m_lpColorTable, pDib-> m_pImgData); //调用Binary()对图像进行二值化 graytrans.BinaryImage(thd); //建立一个新视图,显示分割结果 CMainFrame* pFrame = (CMainFrame *)(AfxGetApp()->m_pMainWnd); pFrame->SendMessage(WM_COMMAND, ID_FILE_NEW); CDemo1View* pView=(CDemo1View*)pFrame->MDIGetActive()->GetActiveView(); CDemo1Doc* pDocNew=pView->GetDocument(); ImageDib *dibNew=pDocNew->GetPDib(); dibNew->ReplaceDib(graytrans.GetDimensions(),graytrans.m_nBitCountOut,gray trans.m_lpColorTableOut, graytrans.m_pImgDataOut); pView->OnInitialUpdate(); pDocNew->SetModifiedFlag(TRUE); pDocNew->UpdateAllViews(pView); }
[2] 上述代码中调用了GrayTrans类中的BinaryImage ()函数,已进行图像的二值化处理,其具体代码如代码5-6所示。
代码5-6 BinaryImage()函数
void GrayTrans::BinaryImage(int threshold) { //对于灰度图像 if(m_nBitCount==8){ //释放旧的输出图像数据及颜色表缓冲区 if(m_pImgDataOut!=NULL){ delete []m_pImgDataOut; m_pImgDataOut=NULL; } if(m_lpColorTableOut!=NULL){ delete []m_lpColorTableOut; m_lpColorTableOut=NULL; } //输出图像的每像素位数、颜色表长度 m_nBitCountOut=m_nBitCount; m_nColorTableLengthOut=ComputeColorTabalLength(m_nBitCountOut); //申请输出图像颜色表缓冲区,并将输入图像颜色表复制至输出图像颜色表中 m_lpColorTableOut=new RGBQUAD[m_nColorTableLengthOut]; memcpy(m_lpColorTableOut,m_lpColorTable,sizeof(RGBQUAD)*m_ nColorTableLengthOut); //输出图像的宽高,与输入图像相等 m_imgWidthOut=m_imgWidth; m_imgHeightOut=m_imgHeight; //图像每行像素所占字节数,输入图像与输出图像每行像素所占字节数相等 int lineByte=(m_imgWidth*m_nBitCount/8+3)/4*4; //申请输出图像位图数据缓冲区 m_pImgDataOut=new unsigned char[lineByte*m_imgHeight]; //循环变量,图像的坐标 int i,j; //二值化 for(i=0;i<m_imgHeight;i++){ for(j=0;j<m_imgWidth;j++){ if(*(m_pImgData+i*lineByte+j)<threshold) *(m_pImgDataOut+i*lineByte+j)=0; else *(m_pImgDataOut+i*lineByte+j)=255; } } } else { if(m_pImgDataOut!=NULL){ delete []m_pImgDataOut; m_pImgDataOut=NULL; } if(m_lpColorTableOut!=NULL){ delete []m_lpColorTableOut; m_lpColorTableOut=NULL; } //灰值化后,每像素位数为8比特 m_nBitCountOut=8; //颜色表长度 m_nColorTableLengthOut=ComputeColorTabalLength(m_nBitCountOut); //申请颜色表缓冲区,生成灰度图像的颜色表 if(m_nColorTableLengthOut!=0){ m_lpColorTableOut=new RGBQUAD[m_nColorTableLengthOut]; for(int i=0; i<m_nColorTableLengthOut;i++){ m_lpColorTableOut[i].rgbBlue=i; m_lpColorTableOut[i].rgbGreen=i; m_lpColorTableOut[i].rgbRed=i; m_lpColorTableOut[i].rgbReserved=0; } } //输入图像每像素字节数,彩色图像为3字节/像素 int pixelByteIn=3; //输入图像每行像素所占字节数,必须是4的倍数 int lineByteIn=(m_imgWidth*pixelByteIn+3)/4*4; //输出图像的宽高,与输入图像相等 m_imgWidthOut=m_imgWidth; m_imgHeightOut=m_imgHeight; //输出图像每行像素所占字节数,必须是4的倍数 int lineByteOut=(m_imgWidth*m_nBitCountOut/8+3)/4*4; //申请输出图像位图数据缓冲区 m_pImgDataOut=new unsigned char[lineByteOut*m_imgHeight]; //循环变量,图像的坐标 int m,n; //根据灰值化公式为输出图像赋值 for(m=0;m<m_imgHeight;m++){ for(n=0;n<m_imgWidth;n++) *(m_pImgDataOut+m*lineByteOut+n)=0.11**(m_pImgData+m* lineByteIn+n*pixelByteIn+0) +0.59**(m_pImgData+m*lineByteIn+n*pixelByteIn+1) +0.30**(m_pImgData+m*lineByteIn+n*pixelByteIn+2)+0.5; } //输出图像每行像素所占字节数,输入图像与输出图像每行像素所占字节数不等 int i,j; //二值化 for(i=0;i<m_imgHeight;i++){ for(j=0;j<m_imgWidth;j++) if(*(m_pImgDataOut+i*lineByteOut+j)<threshold) *(m_pImgDataOut+i*lineByteOut+j)=0; else *(m_pImgDataOut+i*lineByteOut+j)=255; } } }