Opencv处理图像--细化

Opencv处理图像--细化

细化的算法有很多种,但比较常用的算法是查表法

细化是从原来的图中去掉一些点,但仍要保持原来的形状。

实际上是保持原图的骨架。

代码如上:

#include<iostream>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>


IplImage* ColorSrc ,*ColorSrcCopy;

//#define SHOW

//#define LONG int
//#define BYTE unsigned char
/////////////////////////////////////////////////////////////////////////
//基于索引表的细化细化算法
//功能:对图象进行细化
//参数:lpDIBBits:代表图象的一维数组
//      lWidth:图象高度
//      lHeight:图象宽度
//      无返回值
bool ThiningDIBSkeleton (unsigned char* lpDIBBits, int lWidth, int lHeight)
{	
	//循环变量
	long i;
	long j;
	long lLength;

	unsigned char deletemark[256] = {
		0,0,0,0,0,0,0,1,	0,0,1,1,0,0,1,1,
		0,0,0,0,0,0,0,0,	0,0,1,1,1,0,1,1,
		0,0,0,0,0,0,0,0,	1,0,0,0,1,0,1,1,
		0,0,0,0,0,0,0,0,	1,0,1,1,1,0,1,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,0,0,0,0,0,
		0,0,0,0,0,0,0,0,	1,0,0,0,1,0,1,1,
		1,0,0,0,0,0,0,0,	1,0,1,1,1,0,1,1,
		0,0,1,1,0,0,1,1,	0,0,0,1,0,0,1,1,
		0,0,0,0,0,0,0,0,	0,0,0,1,0,0,1,1,
		1,1,0,1,0,0,0,1,	0,0,0,0,0,0,0,0,
		1,1,0,1,0,0,0,1,	1,1,0,0,1,0,0,0,
		0,1,1,1,0,0,1,1,	0,0,0,1,0,0,1,1,
		0,0,0,0,0,0,0,0,	0,0,0,0,0,1,1,1,
		1,1,1,1,0,0,1,1,	1,1,0,0,1,1,0,0,
		1,1,1,1,0,0,1,1,	1,1,0,0,1,1,0,0
	};//索引表

	unsigned char p0, p1, p2, p3, p4, p5, p6, p7;
	unsigned char *pmid, *pmidtemp;
	unsigned char sum;
	int changed;
	bool bStart = true;
	lLength = lWidth * lHeight;
	unsigned char *pTemp = (unsigned char *)malloc(sizeof(unsigned char) * lWidth * lHeight);
	
	//    P0 P1 P2
	//    P7    P3
	//    P6 P5 P4

	while(bStart)
	{
		bStart = false;
		changed = 0;

		//首先求边缘点(并行)
		pmid = (unsigned char *)lpDIBBits + lWidth + 1;
		memset(pTemp,  0, lLength);
		pmidtemp = (unsigned char *)pTemp + lWidth + 1;
		for(i = 1; i < lHeight -1; i++)
		{
			for(j = 1; j < lWidth - 1; j++)
			{
				if( *pmid == 0)
				{
					pmid++;
					pmidtemp++;
					continue;
				}

				p3 = *(pmid + 1);
				p2 = *(pmid + 1 - lWidth);
				p1 = *(pmid - lWidth);
				p0 = *(pmid - lWidth -1);
				p7 = *(pmid - 1);
				p6 = *(pmid + lWidth - 1);
				p5 = *(pmid + lWidth);
				p4 = *(pmid + lWidth + 1);
				
				sum = p0 & p1 & p2 & p3 & p4 & p5 & p6 & p7;
				if(sum == 0)
				{
					*pmidtemp = 1;
					
					#ifdef SHOW
					cvSet2D(ColorSrc,i,j,cvScalar(0,0,255));
					#endif
				}

				pmid++;
				pmidtemp++;
			}
			pmid++;
			pmid++;
			pmidtemp++;
			pmidtemp++;
		}
		#ifdef SHOW
		cvNamedWindow("color");
		cvShowImage("color",ColorSrc);
		cvWaitKey(0);
		#endif
		
		//现在开始串行删除
		pmid = (unsigned char *)lpDIBBits + lWidth + 1;
		pmidtemp = (unsigned char *)pTemp + lWidth + 1;

		for(i = 1; i < lHeight -1; i++)
		{
			for(j = 1; j < lWidth - 1; j++)
			{
				if( *pmidtemp == 0)
				{
					pmid++;
					pmidtemp++;
					continue;
				}

				p3 = *(pmid + 1);
				p2 = *(pmid + 1 - lWidth);
				p1 = *(pmid - lWidth);
				p0 = *(pmid - lWidth -1);
				p7 = *(pmid - 1);
				p6 = *(pmid + lWidth - 1);
				p5 = *(pmid + lWidth);
				p4 = *(pmid + lWidth + 1);
				
				p1 *= 2;
				p2 *= 4;
				p3 *= 8;
				p4 *= 16;
				p5 *= 32;
				p6 *= 64;
				p7 *= 128;

				sum = p0 | p1 | p2 | p3 | p4 | p5 | p6 | p7;
			//	sum = p0 + p1 + p2 + p3 + p4 + p5 + p6 + p7;
				if(deletemark[sum] == 1)
				{
					*pmid = 0;
					bStart = true;

					#ifdef SHOW
					cvSet2D(ColorSrc,i,j,cvScalar(0,0,0));

					cvNamedWindow("delcolor");
					cvShowImage("delcolor",ColorSrc);
					cvWaitKey(2);
					#endif
				}

				pmid++;
				pmidtemp++;
			}

			pmid++;
			pmid++;
			pmidtemp++;
			pmidtemp++;
		}
		
		#ifdef SHOW
		printf("过了一圈\n");
		#endif
	}

	return true;
}

int main()
{
	//#define WRITERESULT
	//#define WRITEIMAGE

	IplImage* src = cvLoadImage("char2.png",0); //加载图像并灰度化
	cvThreshold(src,src,100,255,CV_THRESH_BINARY);  //二值化图像  
	unsigned char* imagedata ;

	ColorSrc = cvLoadImage("char2.png",1);

	cvNamedWindow("s");
	cvShowImage("s" , src);


	FILE* fp ;

	#ifdef WRITEIMAGE
		fp = fopen("data255.txt","rt+");
	#endif

	imagedata = (unsigned char*)malloc(sizeof(char)*src->width*src->height); //动态分配内存

	int x , y;
	for(y=0;y<src->height;y++)
	{
		unsigned char* ptr  = (unsigned char*)(src->imageData + y*src->widthStep);
		for(x=0;x<src->width;x++)
		{
			imagedata[y*src->width+x] = ptr[x] > 0 ? 1 : 0;

            #ifdef WRITEIMAGE
				if(ptr[x] > 0)
					fprintf(fp,"1");
				else
				{
					fprintf(fp,"0");
				}
            #endif
		}

		#ifdef WRITEIMAGE
			fprintf(fp,"\n");
        #endif
	}

	#ifdef WRITEIMAGE
		fclose(fp);
	#endif

	#ifdef WRITERESULT
		fp = fopen("result.txt","rt+");
	#endif
	
	ThiningDIBSkeleton(imagedata,src->width,src->height);//进行细化操作

	for(y=0;y<src->height;y++)
	{
		unsigned char* ptr  = (unsigned char*)(src->imageData + y*src->widthStep);
		for(x=0;x<src->width;x++)
		{
			ptr[x] = imagedata[y*src->width + x]>0? 255 : 0;

			#ifdef WRITERESULT
				if(ptr[x] > 0)
					fprintf(fp,"1");
				else
				{
					fprintf(fp,"0");
				}
            #endif
		}

		#ifdef WRITERESULT
			fprintf(fp,"\n");
        #endif
	}

	#ifdef WRITERESULT
		fclose(fp);
	#endif

	cvNamedWindow("src");
	cvShowImage("src" , src);
	cvWaitKey(0);

	cvReleaseImage(&src);
	cvReleaseImage(&ColorSrc);
	free(imagedata);

	return 0;
}

   细化前后对比

博客参考https://www.cnblogs.com/zhazhiqiang/p/4487950.html

猜你喜欢

转载自blog.csdn.net/sm16111/article/details/81481138