2019-10-18 15:51:03 weixin_44225182 阅读数 206

击中击不中变换

原理

击中击不中变换(HMT)需要两个结构元素B1和B2,合成一个结构元素对B=(B1,B2)

一个用于探测图像内部,作为击中部分;另一个用于探测图像外部,作为击不中部分。显然,B1和B2是不应该相连接的,即B1∩B2=Φ。击中击不中变换的数学表达式为:

g(x, y)=hitmiss[f(x, y), B]=erode[f(x, y), B1]AND erode[fc(x, y), B2]

其中,fc(x,y)表示的是f(x,y)的补集。

作用

击中击不中变换就是在A图像上找到和B图像一致的那块区域,举个例子就是:你拿着一张A图片的一部分,你需要在A图像上找到这张图片在A图片上的位置在哪

算法步骤

  1. 这里把A图像作为原图像 B图像是目标形状,这里我们将B作为结构元素
  2. 建立一个比B大的模板W,计算出模板V (W-B),这里是为了满足原理中B1、B2无交集的条件
  3. 用B作为结构元素对A进行腐蚀
  4. 用V作为结构元素对A的补集进行腐蚀
  5. 取两张腐蚀后图片的交集

举例分析
在A图中寻找B图所示的图像目标的位置
在这里插入图片描述
步骤:

1、确定结构元素

既然是寻找图B所示形状,选取H为图B所示的形状。再选一个小窗口W,W包含H,M=W-H。如下图所示:
在这里插入图片描述
2、求H对A的腐蚀结果
在这里插入图片描述
3、求M对A补集的腐蚀
在这里插入图片描述
4.两张腐蚀图片求交集

图片Y中左上角那个红点就是B在A中的位置
在这里插入图片描述
MATLAB实战

t=zeros(500,500);

for i=100:200
for j=100:200
t(i,j)=1;
end
end

for i=70:140
for j=370:440
t(i,j)=1;
end
end

for i=300:400
for j=300:480
t(i,j)=1;
end
end

imshow(t);%构造原图

m=zeros(100,100);

for i=1:100
for j=1:100
m(i,j)=1;
end
end

figure,imshow(m);%构造m结构元素

n=zeros(120,120);

for i=1:120
for j=1:120
n(i,j)=1;
end
end

for i=10:110
for j=10:110
n(i,j)=0;
end
end

figure,imshow(n);%构造n结构元素 与m交集为空

x1=imerode(t,m);
figure,imshow(x1);%原图被m结构元素腐蚀后
x2=imerode(~t,n);
figure,imshow(x2);%原图补集被n结构元素腐蚀后

x3=x1.*x2;
figure,imshow(x3);%求两张腐蚀后图像的交集

结果图

1.原图
原图A
2.m对A腐蚀后
在这里插入图片描述
3.n对A补集腐蚀后
在这里插入图片描述
4.两张腐蚀图求交集后

图中左上角就是B在A中的位置
在这里插入图片描述
总结

  • 这里击中击不中变换还是有点难理解,至于为什么进行两次腐蚀,就可以找到B在A中的位置,这里就不讨论了,反正我们只需要知道进过这样的运算可以得到结果即可(这里其实自己对那个变换公式原理有点不是很理解)
  • 这里有个很大的坑,就是如果按照原理上的图进行变换,是得不到最终答案的。其原因就是在MATLAB中,白色是1,黑色是0。在课本上,定义的结构元素有效值是1,也就是白色,而上面原理包括课本上则是默认黑色进行腐蚀的。所以,为了验证原理,我们只需要将颜色反转即可(黑变白,白变黑)。
  • 这里对腐蚀、膨胀一定要理解清楚,特别是结构体元素有效值为1,MATLAB中1是白色,我被这个坑惨了
  • 击中击不中的用处就是 在图像A中寻找图像B在A中的位置
2019-07-03 10:59:48 weixin_39504171 阅读数 261

图像处理3:击中击不中算法

(1)击中击不中简介:

           击中击不中变换是形态学形状检测的基本工具,是用来查找像素局部模式的形态学运算符,其中局部是指结构元素的大小。

           两个不相交集合B=(B1, B2),称B为复合结构元素。则击中击不中变换为:用B1去腐蚀x,然后用B2去腐蚀X的补集,得到的结果相减就是击中击不中变换。

(2)击中击不中算法原理:

          如果要在一幅图像A上找到B形状的目标:

          ①建立一个比B大的模板W,使用此模板对图像A进行腐蚀,得到图像假设为Process1;

          ②用B减去w,从而得到V模板(W-B),使用V模板对图像A的补集进行腐蚀,得到图像假设为Process2;

          ③Process1与Process2取交集,得到的结果就是B的位置,这里的位置可能不是B的中心位置。

(3)击中击不中算法原理:

        击中击不中算法的原理基于腐蚀运算的一个特性:腐蚀的过程相当于对可以填入结构元素的位置作标记的过程。

        腐蚀过程中,虽然标记点取决于原点在结构元素中的相对位置,但输出图像的形状与此无关,改变原点的位置,只会导致输出结果发生平移。既然腐蚀的过程相当于对可以填入结构元素的位置作标记的过程,可以利用腐蚀来确定目标的位置。

        进行目标检测,既要检测到目标的内部,也要检测到外部,即在一次运算中可以同时捕获内外标记。

        由于以上两点,采用两个结构基元H,M,作为一个结构元素对B= (H, M) ,一个探测目标内部,一个探测目标外部。当且仅当H平移到某一点可填入X的内部, M平移到该点可填入X的外部时,该点才在击中击不中变换的输出中。

(4)击中击不中算法的应用:

        ①物体识别:将击中基元设计成为需要识别的图像的样子,击不中基元设计为击中基元取反后的样子,然后用这两个基元对图像进行检测即可。

        ②图像细化:将图像变细,就像取到了图像的骨架。

(5)击中击不中算法的结构元素:

         选取击中击不中需要两个结构基元E和F,这两个结构基元一个探测图像内部,一个探测图像外部。当被测图像上目标击中"击中元素" ,但击不中"击不中结构元素"时,将该目标输出。

(6)击中击不中算法的Halcon实现:

         hit or miss(Region, StructElement1, StructElement2, RegionHitMiss, Row, Column)

         首先,在输入区域Region上对结构元素结构1StructElement1进行腐蚀,然后在输入区域的补集上对结构元素2StructElement2进行腐蚀,两个结果区域的交集是算法的结果区域。

2018-05-16 21:36:55 wanty_chen 阅读数 261

本文在前文基础上完成以白色为前景的二值图像的击中击不中变换:

1、击中击不中变换

       击中击不中变换是形态学形状检测的基本工具,是用来查找像素局部模式的形态学运算符。‘局部’是指‘结构元素’的大小。

       两个不相交集合B={B1,B2},称B为复合结构元素。则击中击不中变换为:

                                                                  

即:用B1去腐蚀X,然后用B2去腐蚀X的补集,得到的结果相减就是击中击不中变换。(B2是B1的补集)

代码如下:

#include <cstring>
#include <windows.h>
#include"readbmp.h"
#include"savebmp.h"
#include"img_erosion.h"




int main()
{
	int tembuf1[4][4] = { 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0 };
	int tembuf2[4][4];
	int TempH = 4;
	int TempW = 4;
	for (int i = 0; i < TempH; i++)
		for (int j = 0; j < TempW; j++)
			tembuf2[i][j] = 1 - tembuf1[i][j];

	char readPath[] = "D:\\C++_file\\image_deal_C++\\image_morphology\\photo\\lunpan.bmp";
	readBmp(readPath);
	unsigned char *pGrayData;
	//因为转换后多了个颜色表,所以要改变
	bfoffbits += (sizeof(RGBQUAD) * 256);
	//biSizeImg存储的为位图数据占用的字节数,转换为灰度图像后值发生改变,  
	//因为24为真彩色位图数据的一个像素用3各字节表示,灰度图像为1个字节  
	biBitCount = 8;
	int lineBytes = (bmpWidth * biBitCount / 8 + 3) / 4 * 4;
	int oldLineBytes = (bmpWidth * 24 / 8 + 3) / 4 * 4;;
	pGrayData = new unsigned char[lineBytes * bmpHeight];
	//memset(pGrayData, 0, bmpInfoHeader.biSizeImage);

	//-------------------------------定义灰度图像的颜色表--------------------//  

	pColorTable = new RGBQUAD[256];
	for (int i = 0; i < 256; i++)
	{
		(*(pColorTable + i)).rgbBlue = i;
		(*(pColorTable + i)).rgbGreen = i;
		(*(pColorTable + i)).rgbRed = i;
		(*(pColorTable + i)).rgbReserved = 0;
	}
	//--------------------------------将RGB转换为灰度值------------------------//  
	int red, green, blue;
	BYTE gray;
	//char gray_1;
	int threshold = 128;

	for (int i = 0; i < bmpHeight; i++)
	{
		for (int j = 0; j < bmpWidth; j++)
		{
			red = *(pBmpBuf + i*oldLineBytes + 3 * j + 2);
			green = *(pBmpBuf + i*oldLineBytes + 3 * j + 1);
			blue = *(pBmpBuf + i*oldLineBytes + 3 * j);
			gray = (BYTE)((77 * red + 151 * green + 28 * blue) >> 8);
			//gray_1 = red*0.299 + green*0.587 + blue*0.114;
			*(pGrayData + i*lineBytes + j) = gray;

			if (*(pGrayData + i*lineBytes + j)>threshold)
				*(pGrayData + i*lineBytes + j) = 0;
			else
				*(pGrayData + i*lineBytes + j) = 255;

		}

	}
	unsigned char *p_erosion1;
	p_erosion1 = img_erosion(pGrayData, bmpHeight, bmpWidth, biBitCount, *tembuf1, TempH, TempW);
	
	for (int i = 0; i<bmpHeight; i++)//取反
	{
		for (int j = 0; j<bmpWidth; j++)
		{
			*(pGrayData + i*lineBytes + j) = 255 - *(pGrayData + i*lineBytes + j);
		}
	}
	unsigned char *p_erosion2;
	p_erosion2 = img_erosion(pGrayData, bmpHeight, bmpWidth, biBitCount, *tembuf2, TempH, TempW);


	unsigned char *p_hitmiss;
	p_hitmiss = new unsigned char[lineBytes * bmpHeight];
	for (int i = 0; i<bmpHeight; i++)//求交集
	{
		for (int j = 0; j<bmpWidth; j++)
		{
			if ((*(p_erosion1 + i*lineBytes + j) == 0) &&( *(p_erosion2 + i*lineBytes + j) == 0))
				*(p_hitmiss + i*lineBytes + j) = 0;
			else
				*(p_hitmiss + i*lineBytes + j) =255;

		}
	}

	
	char writePath[] = "D:\\C++_file\\image_deal_C++\\image_morphology\\photo\\hit_miss.bmp";
	saveBmp(writePath, p_hitmiss, bmpWidth, bmpHeight, biBitCount, pColorTable);
	printf("击中击不中运算完成,请查看bmp文件。\n\n");
	delete[] p_hitmiss;
	delete[] p_erosion1;
	delete[] p_erosion2;
	return 0;
}

其中,img_erosion.h为将前文的腐蚀代码改写为子程序。

示例如下:


       对erzhi_white.bmp进行第一次腐蚀后得到p_erosion1.bmp,第二次腐蚀后得到p_erosion2.bmp,求交集得到最终的击中击不中变换hit_miss.bmp。


2013-11-18 17:54:11 zone_programming 阅读数 9067

形态学的击中和击不中是形状检测的基本工具。

其基本原理为:(集合X为原二值化图像的像素集合,对X取反求得~X(非X, Y表示), 选择的结构元为s1, 对结构元s1取反的结构元为s2)

首先对用s1对X进行腐蚀得到A1,, 用s2对Y(即~X)进行腐蚀得到A2。最终结果C = A1 & A2。

对本次的样例图片,我们选取以下的结构元s1:

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                              

对其取反后的结构元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                        

我们要做就是用s1腐蚀原图像X, 用s2去腐蚀对X取反的图像Y,然后对2个最终的结果相与即可。

公式为:    

                       


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

void CImgDoc::OnHit()
{
	if( m_dib.IsValid() )
	{
        int  width = m_dib.GetWidth();
		int  height = m_dib.GetHeight();
		int  pitch = ( 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 <width; x ++)
				bufRes[y*pitch+x] = bufErodeImg[y*pitch+x] & bufErodeNotImg[y*pitch+x];

		CDib::SaveImg8("G:\\bufNotImg.bmp", bufNotImg, width, height, pitch);
		CDib::SaveImg8("G:\\bufErodeImg.bmp", bufErodeImg, width, height, pitch);
		CDib::SaveImg8("G:\\bufErodeNotImg.bmp", bufErodeNotImg, width, height, pitch);
		CDib::SaveImg8("G:\\bufRes.bmp", bufRes, width, height, pitch);

		delete[] bufRes;
		delete[] bufErodeNotImg;
		delete[] bufErodeImg;
		delete[] bufNotImg;
	}

}


腐蚀的方法如下:(方法略戳,勿喷)
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;
		}
	}
}


2019-09-28 10:53:27 u013289254 阅读数 28

    要想学习本章内容,则需要提前看一下我的另外一篇博客:图像的腐蚀与膨胀之c++实现(qt + 不调包),本章内容将从击中/不击中运算和细化处理这两个方面介绍

1.击中/不击中运算

    图像的腐蚀是可以除去目标图像中与结构元素几何特征不符的部分,保留符合特定集合特征的图像,利用多个结构元素的依次腐蚀,就可以对目标图像进行多种条件过滤。比如A被S(S时有S1和S2模板组成且无交集)击中,可以理解成A中具有S1几何特征的部分除去A中具有S2几何特征的差集。

QImage* MainWindow::Hit(QImage* image)
{
	QImage* newImage = new QImage(image->width(), image->height(), QImage::Format_ARGB32);
	QImage* newImage1 = new QImage(image->width(), image->height(), QImage::Format_ARGB32);
	QImage* newImage2 = new QImage(image->width(), image->height(), QImage::Format_ARGB32);
	int kernel[7][7] = {
		{ 0,0,0,0,0,0,1 },
		{ 0,0,0,0,0,1,1 },
		{ 0,0,0,0,1,1,1 },
		{ 0,0,0,1,1,1,1 },
		{ 0,0,1,1,1,1,1 },
		{ 0,1,1,1,1,1,1 },
		{ 1,1,1,1,1,1,1 } };
	int kernel1[7][7] = {
		{ 1,1,1,1,0,0,0 },
		{ 1,1,1,0,0,0,0 },
		{ 1,1,0,0,0,0,0 },
		{ 1,0,0,0,0,0,0 },
		{ 0,0,0,0,0,0,0 },
		{ 0,0,0,0,0,0,0 },
		{ 0,0,0,0,0,0,0 }
	};
	int sizeKernel = 7;
	QColor color;
	QColor newcolor;
	int r = 0;
	int g = 0;
	int b = 0;
	/*用kernel腐蚀操作*/
	for (int y = sizeKernel / 2; y < image->height() - sizeKernel / 2; y++)
	{
		for (int x = sizeKernel / 2; x < image->width() - sizeKernel / 2; x++)
		{
			int kr = 255;
			int kg = 255;
			int kb = 255;
			for (int j = -sizeKernel / 2; j <= sizeKernel / 2; j++)
			{
				for (int i = -sizeKernel / 2; i <= sizeKernel / 2; i++)
				{
					color = QColor(image->pixel(x + i, y + j));
					while (color.red() < kr && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
					{
						kr = color.red();
					}
					while (color.green() < kg && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
					{
						kg = color.green();
					}
					while (color.blue() < kb && kernel[sizeKernel / 2 + i][sizeKernel / 2 + j])
					{
						kb = color.blue();
					}
				}
			}
			newImage->setPixel(x, y, qRgb(kr, kg, kb));
		}
	}

	/*kernel1腐蚀操作*/
	for (int y = sizeKernel / 2; y < image->height() - sizeKernel / 2; y++)
	{
		for (int x = sizeKernel / 2; x < image->width() - sizeKernel / 2; x++)
		{
			int kr = 255;
			int kg = 255;
			int kb = 255;
			for (int j = -sizeKernel / 2; j <= sizeKernel / 2; j++)
			{
				for (int i = -sizeKernel / 2; i <= sizeKernel / 2; i++)
				{
					color = QColor(image->pixel(x + i, y + j));
					while (color.red() < kr && kernel1[sizeKernel / 2 + i][sizeKernel / 2 + j])
					{
						kr = color.red();
					}
					while (color.green() < kg && kernel1[sizeKernel / 2 + i][sizeKernel / 2 + j])
					{
						kg = color.green();
					}
					while (color.blue() < kb && kernel1[sizeKernel / 2 + i][sizeKernel / 2 + j])
					{
						kb = color.blue();
					}
				}
			}
			newImage1->setPixel(x, y, qRgb(kr, kg, kb));
		}
	}

	/*一一检测像素,将符合模板kernel但不符合kernel1的像素填写白色*/
	for (int y = 0; y<image->height(); y++)
	{
		for (int x = 0; x<image->width(); x++)
		{
			color = QColor(newImage->pixel(x, y));
			newcolor = QColor(newImage1->pixel(x, y));
			if (color.red() > 100 && newcolor.red() < 100)
			{
				r = 255;
			}
			else
			{
				r = 0;
			}
			if (color.green() > 100 && newcolor.green() < 100)
			{
				g = 255;
			}
			else
			{
				g = 0;
			}
			if (color.blue() > 100 && newcolor.blue() < 100)
			{
				b = 255;
			}
			else
			{
				b = 0;
			}
			newImage2->setPixel(x, y, qRgb(r, g, b));
		}
	}
	delete newImage;
	delete newImage1;
	return newImage2;
}

2.细化处理

    图像的细化的操作实际是一个逐渐腐蚀的过程,每次从图像的边缘腐蚀掉一个像素,直到不能腐蚀为止。算法的关键是任何在每次腐蚀中判断像素点是否可以清除。细化有两条准则:1)细化不能缩短图像骨架的长度;2)细化不能将图像分解成不同部分。其两条准则的详细步骤如下:

    1)计算当前像素邻域内8个方向的可见像素数目,如果少于2个像素,则删除此像素会缩短图像骨架长度;若多于6个像素,则删除此像素会改变骨架的几何形状

    2)计算当前像素周围邻域内的区域数目,如果多余1个,那么删除中心像素会将目标图像分解成不同部分

/*图像的细化*/
QImage* MainWindow::Thining(QImage* image)
{
	QImage* newImage = new QImage(image->width(), image->height(), QImage::Format_ARGB32);
	int count;
	int finish = 0;
	int nb[5][5];
	int r = 0;
	int b = 0;
	int g = 0;
	QColor color;
	/*二值化*/

	for (int y = 0; y<image->height(); y++)
	{
		for (int x = 0; x<image->width(); x++)
		{
			color = QColor(image->pixel(x, y));


			color = QColor(image->pixel(x, y));
			if (color.red()< 100)
			{
				r = 0;
			}
			else
			{
				r = 255;
			}
			if (color.green()< 100)
			{
				g = 0;
			}
			else
			{
				g = 255;
			}
			if (color.blue() < 100)
			{
				b = 0;
			}
			else
			{
				b = 255;
			}
			newImage->setPixel(x, y, qRgb(r, g, b));
		}
	}
	while (!finish)
	{
		finish = 1;
		for (int y = 2; y< image->height() - 2; y++)
		{
			for (int x = 2; x< image->width() - 2; x++)
			{
				color = QColor(newImage->pixel(x, y));
				if (color.red() == 0)
				{
					continue;
				}
				int  t1 = 0;
				int  t2 = 0;

				for (int j = 0; j < 5; j++)
				{
					for (int i = 0; i < 5; i++)
					{
						color = QColor(newImage->pixel(x + i - 2, y + j - 2));
						if (color.red() == 255)
						{
							nb[j][i] = 1;
						}
						else
						{
							nb[j][i] = 0;
						}
					}
				}
				/*条件1*/
				count = nb[1][1] + nb[1][2] + nb[1][3] + nb[2][1] + nb[2][3] + nb[3][1] + nb[3][2] + nb[3][3];
				if (count >= 2 && count <= 6)
				{
					t1 = 1;
				}
				else
				{
					continue;
				}
				/*条件2*/
				count = 0;
				if (nb[1][2] == 0 && nb[1][1] == 1)
					count++;
				if (nb[1][1] == 0 && nb[2][1] == 1)
					count++;
				if (nb[2][1] == 0 && nb[3][1] == 1)
					count++;
				if (nb[3][1] == 0 && nb[3][2] == 1)
					count++;
				if (nb[3][2] == 0 && nb[3][3] == 1)
					count++;
				if (nb[3][3] == 0 && nb[2][3] == 1)
					count++;
				if (nb[2][3] == 0 && nb[1][3] == 1)
					count++;
				if (nb[1][3] == 0 && nb[1][2] == 1)
					count++;
				if (count == 1)
				{
					t2 = 1;
				}
				else
				{
					continue;
				}
				if (t1*t2 == 1)
				{
					newImage->setPixel(x, y, qRgb(0, 0, 0));
					finish = 0;
				}
			}
		}
		finish = 1;
	}

	return newImage;
}

3.参考资料

    数字图像处理——技术详解与Visual C++实践(左飞等著),写代码与写博客的时间相差两年,至于还参考其他的资料不,我已经忘记了,如若需要,我可以补上去

没有更多推荐了,返回首页