【Digital|数字图像处理入门(一) 击中击不中

形态学的击中和击不中是形状检测的基本工具。
其基本原理为:(集合X为原二值化图像的像素集合,对X取反求得~X(非X, Y表示), 选择的结构元为s1, 对结构元s1取反的结构元为s2)
首先对用s1对X进行腐蚀得到A1,, 用s2对Y(即~X)进行腐蚀得到A2。最终结果C = A1 & A2。
对本次的样例图片,我们选取以下的结构元s1:
【Digital|数字图像处理入门(一) 击中击不中
文章图片
0 0 1 0 0
0 0 1 0 0
1 1 1 1 1
0 0 1 0 0
0 0 1 0 0【Digital|数字图像处理入门(一) 击中击不中
文章图片

对其取反后的结构元s2为:
1 1 0 1 1
1 1 0 1 1
0 0 0 0 0
1 1 0 1 1
1 1 0 1 1【Digital|数字图像处理入门(一) 击中击不中
文章图片


我们要做就是用s1腐蚀原图像X, 用s2去腐蚀对X取反的图像Y,然后对2个最终的结果相与即可。
公式为:
【Digital|数字图像处理入门(一) 击中击不中
文章图片
【Digital|数字图像处理入门(一) 击中击不中
文章图片



代码如下:其中m_dib为打开的bmp图像,m_dib.GetBits()为获得图像的像素

void CImgDoc::OnHit() { if( m_dib.IsValid() ) { intwidth = m_dib.GetWidth(); intheight = m_dib.GetHeight(); intpitch = ( width*8+31)/32*4; //步长unsigned char* bufNotImg = new unsigned char[height*pitch]; //原图像的反 unsigned char* bufErodeImg = new unsigned char[height*pitch]; //定义好的结构元腐蚀原图像 unsigned char* bufErodeNotImg = new unsigned char[height*pitch]; //取反的结构元腐蚀取反的原图像 unsigned char* bufRes = new unsigned char[height*pitch]; //击中击不中目标图像//初始化 memset(bufNotImg, 0x00, height*pitch); memset(bufErodeImg, 0x00, height*pitch); memset(bufErodeNotImg, 0x00, height*pitch); memset(bufRes, 0x00, height*pitch); //定义的腐蚀结构元 //0 0 1 0 0 //0 0 1 0 0 //1 1 1 1 1 //0 0 1 0 0 //0 0 1 0 0 Pt s1[9]; s1[0].x = 0; s1[0].y = -2; s1[1].x = 0; s1[1].y = -1; s1[2].x = 0; s1[2].y = 0; s1[3].x = 0; s1[3].y = 1; s1[4].x = 0; s1[4].y = 2; s1[5].x = -2; s1[5].y = 0; s1[6].x = -1; s1[6].y = 0; s1[7].x = 1; s1[7].y = 0; s1[8].x = 2; s1[8].y = 0; //将上面的结构元取反,共16个,比较戳的写法,将最中间的点设为原点,其余点即为相对于原点的坐标 Pt s2[16]; s2[0].x = -2; s2[0].y = -2; s2[1].x = -1; s2[1].y = -2; s2[2].x = 1; s2[2].y = -2; s2[3].x = 2; s2[3].y = -2; s2[4].x = -2; s2[4].y = -1; s2[5].x = -1; s2[5].y = -1; s2[6].x = 1; s2[6].y = -1; s2[7].x = 2; s2[7].y = -1; s2[8].x = -2; s2[8].y = 1; s2[9].x = -1; s2[9].y = 1; s2[10].x = 1; s2[10].y = 1; s2[11].x = 2; s2[11].y = 1; s2[12].x = -2; s2[12].y = 2; s2[13].x = -1; s2[13].y = 2; s2[14].x = 1; s2[14].y = 2; s2[15].x = 2; s2[15].y = 2; //1、求取反的图像 for(int y = 0; y < height; y ++) { for(int x = 0; x < width; x ++) { if(m_dib.GetBits()[y*pitch+x]) bufNotImg[y*pitch+x] = 0x0; else bufNotImg[y*pitch+x] = 0xFF; }}//2、经过结构元s1的源图像的腐蚀 //参数:原图像的缓冲区像素,宽度,高度,步长,目标腐蚀图像缓冲区,目标图像步长,结构元,结构元点数 Erode(m_dib.GetBits()+2*pitch+4, width-4, height-4, pitch, bufErodeImg, pitch, s1, 9); //3、经过结构元的反s2的源图像的反图像的腐蚀 Erode(bufNotImg+2*pitch+4, width-4, height-4, pitch, bufErodeNotImg, pitch, s2, 16); //4、经过求第3步的bufErodeImg和第4步的bufErodeNotImg求与 for(int y = 0; y < height; y ++) for(int x = 0; x


【【Digital|数字图像处理入门(一) 击中击不中】

腐蚀的方法如下:(方法略戳,勿喷)
void Erode( const unsigned char* srcBuf, int w, int h, int pitch, unsigned char* dstBuf, int dstPitch, Pt pt[], int nCount ) { for( int y = 0; y < h; y++ ) { for( int x = 0; x < w; x++) { int n = 0; for( int i = 0; i < nCount; i++ ) { if( srcBuf[(y+pt[i].y)*pitch+(x+pt[i].x)] ) n++; } if( n == nCount ) dstBuf[y*dstPitch+x] = 0xFF; } } }



    推荐阅读