2019-09-01 19:51:41 webzhuce 阅读数 441

基本概念

        “骨架”是指一幅图像的骨骼部分,它描述物体的几何形状和拓扑结构,是重要的图像描绘子之一。计算骨架的过程一般称为“细化”或“骨架化”,在包括文字识别、工业零件形状识别以及印刷电路板自动检测在内的很多应用中,细化过程都发挥这关键作用。通常,对我们感兴趣的目标物体进行细化有助于突出目标的形状特点和拓扑结构并且减少冗余的信息。
在这里插入图片描述
这里给出细化算法
在这里插入图片描述

示例演示

        实现基于形态学的细化算法。与上面算法介绍不同,将白色作为前景,黑色作为背景。完整工程代码。

/*
 *only process binary image
 * white is foreground
*/
void Thining(const cv::Mat &src, cv::Mat &dst)
{

    //four conditions
    bool condition1 = false, condition2 = false, condition3 = false, condition4 = false;

    //n*n neighbours
    constexpr int N = 5;
    uchar neighbour[N][N];
    const int kOffset = N / 2;
    src.copyTo(dst);

    bool modified = true;
    while(modified)
    {
        modified = false;
        Mat img;
        dst.copyTo(img);

        for(int i = kOffset; i < (dst.rows - kOffset); i++)
        {
            for(int j = kOffset; j < (dst.cols - kOffset); j++)
            {
                if(dst.at<uchar>(i, j) == 0)
                    continue;

                condition1 = false;
                condition2 = false;
                condition3 = false;
                condition4 = false;

                //get N*N neighbours of current point
                //white : 0, black : 1
                for(int m = 0; m < N; m++)
                {
				    for(int n = 0; n < N; n++)
                    {
                        neighbour[m][n] = dst.at<uchar>(i + n - kOffset, j + m - kOffset) == 255 ? 1 : 0;
                    }
                }

                //2 <= NZ(P1) <=6
                int count = neighbour[1][1] + neighbour[1][2] + neighbour[1][3] +
                        neighbour[2][1] + neighbour[2][3] +
                        neighbour[3][1] + neighbour[3][2] + neighbour[3][3];
                if(count >= 2 && count <=6)
                    condition1 = true;

                //Z0(P1) == 1
                count = 0;
                if(neighbour[1][2] == 0 && neighbour[1][1] == 1)
                    count++;
                if(neighbour[1][1] == 0 && neighbour[2][1] == 1)
                    count++;
                if(neighbour[2][1] == 0 && neighbour[3][1] == 1)
                    count++;
                if(neighbour[3][1] == 0 && neighbour[3][2] == 1)
                    count++;
                if(neighbour[3][2] == 0 && neighbour[3][3] == 1)
                    count++;
                if(neighbour[3][3] == 0 && neighbour[2][3] == 1)
                    count++;
                if(neighbour[2][3] == 0 && neighbour[1][3] == 1)
                    count++;
                if(neighbour[1][3] == 0 && neighbour[1][2] == 1)
                    count++;
                if(count == 1)
                    condition2 = true;

                //P2*P4*P8 = 0 or Z0(P2) != 1
                if(neighbour[1][2] * neighbour[2][1] * neighbour[2][3] == 0)
                    condition3 = true;
                else
                {
                    count = 0;
                    if(neighbour[0][2] == 0 && neighbour[0][1] == 1)
                        count++;
                    if(neighbour[0][1] == 0 && neighbour[1][1] == 1)
                        count++;
                    if(neighbour[1][1] == 0 && neighbour[2][1] == 1)
                        count++;
                    if(neighbour[2][1] == 0 && neighbour[2][2] == 1)
                        count++;
                    if(neighbour[2][2] == 0 && neighbour[2][3] == 1)
                        count++;
                    if(neighbour[2][3] == 0 && neighbour[1][3] == 1)
                        count++;
                    if(neighbour[1][3] == 0 && neighbour[0][3] == 1)
                        count++;
                    if(neighbour[0][3] == 0 && neighbour[0][2] == 1)
                        count++;
                    if(count != 1)
                        condition3 = true;
                }

                //P2*P4*P6 = 0 or Z0(P4) != 1
                if(neighbour[1][2] * neighbour[2][1] * neighbour[3][2] == 0)
                    condition4 = true;
                else
                {
                    count = 0;
                    if(neighbour[1][1] == 0 && neighbour[1][0] == 1)
                        count++;
                    if(neighbour[1][0] == 0 && neighbour[2][0] == 1)
                        count++;
                    if(neighbour[2][0] == 0 && neighbour[3][0] == 1)
                        count++;
                    if(neighbour[3][0] == 0 && neighbour[3][1] == 1)
                        count++;
                    if(neighbour[3][1] == 0 && neighbour[3][2] == 1)
                        count++;
                    if(neighbour[3][2] == 0 && neighbour[2][2] == 1)
                        count++;
                    if(neighbour[2][2] == 0 && neighbour[1][2] == 1)
                        count++;
                    if(neighbour[1][2] == 0 && neighbour[1][1] == 1)
                        count++;
                    if(count != 1)
                        condition4 = true;
                }

                if(condition1 && condition2 && condition3 && condition4)
                {
                    img.at<uchar>(i, j) = 0;
                    modified = true;
                }
                else
                    img.at<uchar>(i, j) = 255;

            } // for columns
        } // for rows
        img.copyTo(dst);
    } //  for while
}

运行结果

在这里插入图片描述

2013-03-21 16:41:26 KTs_3 阅读数 806

细化算法:

假设某图像中的一个3*3区域,对其中各点标记名称P1,P2,P3...P9,分布如下:

P3    P2   P9

P4    P1   P8

P5    P6   P7 

 

这里假设1表示黑色,0表示白色,且中心P1=1(黑色),那么,在同时满足以下4个条件时就删除P1(令P1=0):

(1) 7>NZ(P1)>1;

(2) Z0(P1)=1;

(3) P2*P4*P6=0 OR Z0(P2)!=1;

(4) P2*P4*P8=0 OR Z0(P4)!=1;

其中的NZ(P)表示P点的8领域中1的数目;而Z0(P)可按如下方式计算:

Set  ncount=1;

if  P2=0 and P3=1, then ncount++;

if  P3=0 and P4=1, then ncount++;

if  P4=0 and P5=1, then ncount++;

if  P5=0 and P6=1, then ncount++;

if  P6=0 and P7=1, then ncount++;

if  P7=0 and P8=1,then  ncount++;

if  P8=0 and P9=1,then  ncount++;

if  P9=0 and P2=1,then  ncount++;

Z0(P)=ncount;

#include <iostream>
#include "cv.h"
#include "highgui.h"

using namespace std;
using namespace cv;

Mat ThinImage(Mat img)
{
	int i,j,count,ncount;

	for (i=2;i<img.rows-2;i++)
	{
		for (j=2;j<img.cols-2;j++)
		{
			if(img.at<uchar>(i,j)==255)
			{
			   bool condition1=false,
			        condition2=false,
			        condition3=false,
			        condition4=false;
			//count P(i,j) around #1
			count=0;
			if(img.at<uchar>(i-1,j-1)==255)
				count++;
			if(img.at<uchar>(i-1,j)==255)
				count++;
			if(img.at<uchar>(i-1,j+1)==255)
				count++;
			if(img.at<uchar>(i,j-1)==255)
				count++;
			if(img.at<uchar>(i,j+1)==255)
				count++;
			if(img.at<uchar>(i+1,j-1)==255)
				count++;
			if(img.at<uchar>(i+1,j)==255)
				count++;
			if(img.at<uchar>(i+1,j+1)==255)
				count++;
			if(count<7&&count>1)
				condition1=true;

			//compute ncount
			ncount=0;
			if(img.at<uchar>(i-1,j)==0&&img.at<uchar>(i-1,j-1)==255)
				ncount++;
			if(img.at<uchar>(i-1,j-1)==0&&img.at<uchar>(i,j-1)==255)
				ncount++;
			if(img.at<uchar>(i,j-1)==0&&img.at<uchar>(i+1,j-1)==255)
				ncount++;
			if(img.at<uchar>(i+1,j-1)==0&&img.at<uchar>(i+1,j)==255)
				ncount++;
			if(img.at<uchar>(i+1,j)==0&&img.at<uchar>(i+1,j+1)==255)
				ncount++;
			if(img.at<uchar>(i+1,j+1)==0&&img.at<uchar>(i,j+1)==255)
				ncount++;
			if(img.at<uchar>(i,j+1)==0&&img.at<uchar>(i-1,j+1)==255)
				ncount++;
			if(img.at<uchar>(i-1,j+1)==0&&img.at<uchar>(i-1,j)==255)
				ncount++;
			if(ncount==1)
				condition2=true;

			if (img.at<uchar>(i-1,j)*img.at<uchar>(i,j-1)*img.at<uchar>(i,j+1)==0)
				condition3=true;
			else
			{
				ncount=0;
				i-=1;
				if(img.at<uchar>(i-1,j)==0&&img.at<uchar>(i-1,j-1)==255)
					ncount++;
				if(img.at<uchar>(i-1,j-1)==0&&img.at<uchar>(i,j-1)==255)
					ncount++;
				if(img.at<uchar>(i,j-1)==0&&img.at<uchar>(i+1,j-1)==255)
					ncount++;
				if(img.at<uchar>(i+1,j-1)==0&&img.at<uchar>(i+1,j)==255)
					ncount++;
				if(img.at<uchar>(i+1,j)==0&&img.at<uchar>(i+1,j+1)==255)
					ncount++;
				if(img.at<uchar>(i+1,j+1)==0&&img.at<uchar>(i,j+1)==255)
					ncount++;
				if(img.at<uchar>(i,j+1)==0&&img.at<uchar>(i-1,j+1)==255)
					ncount++;
				if(img.at<uchar>(i-1,j+1)==0&&img.at<uchar>(i-1,j)==255)
					ncount++;
				if(ncount!=1)
					condition3=true;
				i+=1;
			}

			if (img.at<uchar>(i-1,j)*img.at<uchar>(i,j-1)*img.at<uchar>(i+1,j)==0)
				condition4=true;
			else
			{
				ncount=0;
				j-=1;
				if(img.at<uchar>(i-1,j)==0&&img.at<uchar>(i-1,j-1)==255)
					ncount++;
				if(img.at<uchar>(i-1,j-1)==0&&img.at<uchar>(i,j-1)==255)
					ncount++;
				if(img.at<uchar>(i,j-1)==0&&img.at<uchar>(i+1,j-1)==255)
					ncount++;
				if(img.at<uchar>(i+1,j-1)==0&&img.at<uchar>(i+1,j)==255)
					ncount++;
				if(img.at<uchar>(i+1,j)==0&&img.at<uchar>(i+1,j+1)==255)
					ncount++;
				if(img.at<uchar>(i+1,j+1)==0&&img.at<uchar>(i,j+1)==255)
					ncount++;
				if(img.at<uchar>(i,j+1)==0&&img.at<uchar>(i-1,j+1)==255)
					ncount++;
				if(img.at<uchar>(i-1,j+1)==0&&img.at<uchar>(i-1,j)==255)
					ncount++;
				if(ncount!=1)
					condition4=true;
				j+=1;

			}

			if(condition1&&condition2&&condition3&&condition4==true)
				img.at<uchar>(i,j)=0;
			}
		}
	}
 

			
	imshow("ThinImage",img);
	waitKey();
	return img;
}

 

细节:

注意环境复原,i,j 的处理,否则会进入死循环!

 

参考:

《数字图像处理与机器视觉》(人民邮电出版社)

(新手上路,如有错误或不够优化的地方请大方指出,共同提高!)


 

2018-12-24 22:44:22 fengxianghui01 阅读数 2134

        细化(thinning)算法有很多,我们在这里介绍的是一种简单而且效果很好的算法,用它就能够实现从文本抽取骨架的功能。我们的对象是白纸黑字的文本,但在程序中为了处理的方便,还是采用 256 级灰度图,不过只用到了调色板中 0 和 255 两项。

        所谓细化,就是从原来的图中去掉一些点,但仍要保持原来的形状。实际上,是保持原图的骨架。所谓骨架,可以理解为图象的中轴,例如一个长方形的骨架是它的长方向上的中轴线;正方形的骨架是它的中心点;圆的骨架是它的圆心,直线的骨架是它自身,孤立点的骨架也是自身。那么怎样判断一个点是否能去掉呢?显然,要根据它的八个相邻点的情况来判断,我们给几个例子(如图 6.22 所示)。

                                                   

         图 6.22 中,(1)不能删,因为它是个内部点,我们要求的是骨架,如果连内部点也删了,骨架也会被掏空的;(2)不能删,和(1)是同样的道理;(3)可以删,这样的点不是骨架;(4)不能删,因为删掉后,原来相连的部分断开了;(5)可以删,这样的点不是骨架;(6)不能删,因为它是直线的端点,如果这样的点删了,那么最后整个直线也被删了,剩不下什么。总结一下,有如下的判据:(1)内部点不能删除;(2)孤立点不能删除;(3)直线端点不能删除;(4)如果 P 是边界点,去掉 P 后,如果连通分量不增加,则 P 可以删除。

         我们可以根据上述的判据,事先做出一张表,从 0 到 255 共有 256 个元素,每个元素要么是0,要么是 1。我们根据某点(当然是要处理的黑色点了)的八个相邻点的情况查表,若表中的元素是 1,则表示该点可删,否则保留。

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

int main(int* argc, char** argv)
{
	FILE* fp = fopen("./threshold.bmp", "rb");
	if (fp == 0)
		return 0;
	BITMAPFILEHEADER fileHead;
	fread(&fileHead, sizeof(BITMAPFILEHEADER), 1, fp);

	BITMAPINFOHEADER infoHead;
	fread(&infoHead, sizeof(BITMAPINFOHEADER), 1, fp);
	int width = infoHead.biWidth;
	int height = infoHead.biHeight;
	int biCount = infoHead.biBitCount;

	int lineByte = (biCount*width / 8 + 3) / 4 * 4;
	RGBQUAD* pColorTable;
	pColorTable = new RGBQUAD[256];
	fread(pColorTable, sizeof(RGBQUAD), 256, fp);

	unsigned char* pBmpBuf,*pBmpBuf2;
	pBmpBuf = new unsigned char[lineByte*height];
	fread(pBmpBuf, lineByte*height, 1, fp);
	fclose(fp);

	// 新图
	FILE* fop = fopen("thinging.bmp", "wb");
	if (fop == 0)
		return 0;

	pBmpBuf2 = new unsigned char[lineByte*height];
	for (int i = 0; i < height; ++i){
		for (int j = 0; j < width; ++j){
			*(pBmpBuf2 + i*lineByte + j) = *(pBmpBuf + i*lineByte + j);
		}
	}

	// 比较矩阵,0为黑,1为白; 
	// 1:不能;2:不能;3:能;4:不能;5:能;6:不能
	char str[6][8] = { { 0, 0, 0, 0, 0, 0, 0, 0, }, { 255, 0, 255, 0, 0, 255, 0, 0 },
	{ 255, 0, 255, 255, 0, 255, 0, 255 }, { 255, 255, 255, 0, 0, 255, 255, 255 },
	{ 255, 0, 255, 255, 0, 255, 255, 255 }, { 0, 255, 255, 255, 255, 255, 255, 255 } };
	int temp, k;
	char strTemp[8];
	for (int i = 1; i < height-1; ++i){
		for (int j = 1; j < width - 1; ++j){
			k = 0;
			for (int m = -1; m <= 1; ++m){
				for (int n = -1; n <= 1; ++n){
					temp = *(pBmpBuf + (i - m)*lineByte + (j + n));
					strTemp[k] = temp;
					k++;
				}
			}
			for (int k = 0; k < 6; ++k){
				if (strcmp(strTemp, str[k])==0){
					if (k == 3 || k == 5){
						*(pBmpBuf2 + i*lineByte + j) = 255;
					}
				}
			}
		}
	}


	fwrite(&fileHead, sizeof(BITMAPFILEHEADER), 1, fop);
	fwrite(&infoHead, sizeof(BITMAPINFOHEADER), 1, fop);
	fwrite(pColorTable, sizeof(RGBQUAD), 255, fop);
	fwrite(pBmpBuf2, lineByte*height, 1, fop);
	fclose(fop);

	system("pause");
	return 0;
}

 

实验结果:

               原图                     效果图

       

2018-08-07 14:51:11 sm16111 阅读数 1244

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

2017-04-18 14:36:14 Isaac320 阅读数 603

数字图像处理书上图像细化  结构元B对A的细化表示为以下

   

其中

 是结构元B在A中的匹配。


集合A就是你要细化的图像 

结构元B用以下八个





黑圈表示前景色,空白表示背景色,叉表示不考虑   


用B1对A细化后,在用B2对处理后的A细化,。。。到B8细化,一个周期。

然后,循环以上的周期,直到A不再变化。





【opencv】图像细化

阅读数 31415

图像处理 腐蚀 膨胀 细化

博文 来自: Dopamy_BusyMonkey
没有更多推荐了,返回首页