opencv实现二值图像细化的算法
细化算法通常和骨骼化、骨架化算法是相同的意思,也就是thin算法或者skeleton算法。虽然很多图像处理的教材上不是这么写的,具体原因可以看这篇论文,Louisa Lam, Seong-Whan Lee, Ching Y. Suen,“Thinning Methodologies-A Comprehensive Survey ”,IEEE TRANSACTIONS ON PATTERN ANALYSIS AND MACHINE INTELLIGENCE, VOL. 14, NO. 9, SEPTEMBER 1992 ,总结了几乎所有92年以前的经典细化算法。
函数:void cvThin( IplImage* src, IplImage* dst, int iterations=1)
功能:将IPL_DEPTH_8U型二值图像进行细化
参数:src,原始IPL_DEPTH_8U型二值图像
dst,目标存储空间,必须事先分配好,且和原图像大小类型一致
iterations,迭代次数
参考文献:T. Y. Zhang and C. Y. Suen, “A fast parallel algorithm for thinning digital patterns,” Comm. ACM, vol. 27, no. 3, pp. 236-239, 1984.
void cvThin( IplImage* src, IplImage* dst, int iterations=1)
{
CvSize size = cvGetSize(src);
cvCopy(src, dst);
int n = 0,i = 0,j = 0;
for(n=0; n<iterations; n++)
{
IplImage* t_image = cvCloneImage(dst);
for(i=0; i<size.height; i++)
{
for(j=0; j<size.width; j++)
{
if(CV_IMAGE_ELEM(t_image,byte,i,j)==1)
{
int ap=0;
int p2 = (i==0)?0:CV_IMAGE_ELEM(t_image,byte, i-1, j);
int p3 = (i==0 || j==size.width-1)?0:CV_IMAGE_ELEM(t_image,byte, i-1, j+1);
if (p2==0 && p3==1)
{
ap++;
}
int p4 = (j==size.width-1)?0:CV_IMAGE_ELEM(t_image,byte,i,j+1);
if(p3==0 && p4==1)
{
ap++;
}
int p5 = (i==size.height-1 || j==size.width-1)?0:CV_IMAGE_ELEM(t_image,byte,i+1,j+1);
if(p4==0 && p5==1)
{
ap++;
}
int p6 = (i==size.height-1)?0:CV_IMAGE_ELEM(t_image,byte,i+1,j);
if(p5==0 && p6==1)
{
ap++;
}
int p7 = (i==size.height-1 || j==0)?0:CV_IMAGE_ELEM(t_image,byte,i+1,j-1);
if(p6==0 && p7==1)
{
ap++;
}
int p8 = (j==0)?0:CV_IMAGE_ELEM(t_image,byte,i,j-1);
if(p7==0 && p8==1)
{
ap++;
}
int p9 = (i==0 || j==0)?0:CV_IMAGE_ELEM(t_image,byte,i-1,j-1);
if(p8==0 && p9==1)
{
ap++;
}
if(p9==0 && p2==1)
{
ap++;
}
if((p2+p3+p4+p5+p6+p7+p8+p9)>1 && (p2+p3+p4+p5+p6+p7+p8+p9)<7)
{
if(ap==1)
{
if(!(p2 && p4 && p6))
{
if(!(p4 && p6 && p8))
{
CV_IMAGE_ELEM(dst,byte,i,j)=0;
}
}
}
}
}
}
}
cvReleaseImage(&t_image);
t_image = cvCloneImage(dst);
for(i=0; i<size.height; i++)
{
for(int j=0; j<size.width; j++)
{
if(CV_IMAGE_ELEM(t_image,byte,i,j)==1)
{
int ap=0;
int p2 = (i==0)?0:CV_IMAGE_ELEM(t_image,byte, i-1, j);
int p3 = (i==0 || j==size.width-1)?0:CV_IMAGE_ELEM(t_image,byte, i-1, j+1);
if (p2==0 && p3==1)
{
ap++;
}
int p4 = (j==size.width-1)?0:CV_IMAGE_ELEM(t_image,byte,i,j+1);
if(p3==0 && p4==1)
{
ap++;
}
int p5 = (i==size.height-1 || j==size.width-1)?0:CV_IMAGE_ELEM(t_image,byte,i+1,j+1);
if(p4==0 && p5==1)
{
ap++;
}
int p6 = (i==size.height-1)?0:CV_IMAGE_ELEM(t_image,byte,i+1,j);
if(p5==0 && p6==1)
{
ap++;
}
int p7 = (i==size.height-1 || j==0)?0:CV_IMAGE_ELEM(t_image,byte,i+1,j-1);
if(p6==0 && p7==1)
{
ap++;
}
int p8 = (j==0)?0:CV_IMAGE_ELEM(t_image,byte,i,j-1);
if(p7==0 && p8==1)
{
ap++;
}
int p9 = (i==0 || j==0)?0:CV_IMAGE_ELEM(t_image,byte,i-1,j-1);
if(p8==0 && p9==1)
{
ap++;
}
if(p9==0 && p2==1)
{
ap++;
}
if((p2+p3+p4+p5+p6+p7+p8+p9)>1 && (p2+p3+p4+p5+p6+p7+p8+p9)<7)
{
if(ap==1)
{
if(p2*p4*p8==0)
{
if(p2*p6*p8==0)
{
CV_IMAGE_ELEM(dst, byte,i,j)=0;
}
}
}
}
}
}
}
cvReleaseImage(&t_image);
}
}
//使用举例
#include "cxcore.h"
#include "cv.h"
#include "highgui.h"
int main(int argc, char* argv[])
{
if(argc!=2)
{
return 0;
}
IplImage *pSrc = NULL,*pDst = NULL,*pTmp = NULL;
//传入一个灰度图像
pSrc = cvLoadImage(argv[1],CV_LOAD_IMAGE_GRAYSCALE);
if(!pSrc)
{
return 0;
}
pTmp = cvCloneImage(pSrc);
pDst = cvCreateImage(cvGetSize(pSrc),pSrc->depth,pSrc->nChannels);
cvZero(pDst);
cvThreshold(pSrc,pTmp,128,1,CV_THRESH_BINARY_INV);//做二值处理,将图像转换成0,1格式
//cvSaveImage("c:\\Threshold.bmp",pTmp,0);
cvThin(pTmp,pDst,8);//细化,通过修改iterations参数进一步细化
cvNamedWindow("src",1);
cvNamedWindow("dst",1);
cvShowImage("src",pSrc);
//将二值图像转换成灰度,以便显示
int i = 0,j = 0;
CvSize size = cvGetSize(pDst);
for(i=0; i<size.height; i++)
{
for(j=0; j<size.width; j++)
{
if(CV_IMAGE_ELEM(pDst,uchar,i,j)==1)
{
CV_IMAGE_ELEM(pDst,uchar,i,j) = 0;
}
else
{
CV_IMAGE_ELEM(pDst,uchar,i,j) = 255;
}
}
}
//cvSaveImage("c:\\thin.bmp",pDst);
cvShowImage("dst",pDst);
cvWaitKey(0);
cvReleaseImage(&pSrc);
cvReleaseImage(&pDst);
cvReleaseImage(&pTmp);
cvDestroyWindow("src");
cvDestroyWindow("dst");
return 0;
}
分享到:
相关推荐
OpenCV中实现这一功能的主要函数是`thinning`,它采用了Zhang-Suen算法或Guo-Hall算法,这两种算法都是经典的细化算法。 Zhang-Suen算法是一种迭代方法,它通过查找特定的8邻域结构并进行适当的像素值改变来达到...
在二值图像处理特别是OCR识别与匹配中,都要通过对字符进行细化以便获得图像的骨架,通过zhang-suen细化算法获得图像,作为图像的特征之一,常用来作为识别或者模式匹配。此代码用C++实现了这一算法,配有注释,简洁...
普通的OpenCV C++细化算法. 已封装成C++函数,可直接调用使用。也可用于参考, 根据需要也可自行修改源码。
在本案例中,我们关注的是"Opencv处理条纹的细化算法",这是一个涉及图像骨架提取的过程,常用于形状分析、特征提取以及图像压缩等应用。细化算法通常用于将粗略的图像轮廓转化为更简洁、单像素宽的表示,这有助于...
应用OPENCV编写的,输入一张二值图片,根据细化算法细化成单像素的二值图像。
在这个项目中,可能使用了某种特定的算法来实现这一目的,比如Zhang-Suen算法,这是一种经典的二值图像细化算法,通过迭代操作消除边缘的宽度,保留关键结构。 Zhang-Suen算法的步骤大致如下: 1. 邻域检查:对图像...
对于这些问题,可以通过调整参数、预处理图像或选择不同的细化算法来优化。 总结来说,“002_ThinDemo”项目展示了如何使用OpenCV在VS2019环境中实现图像细化。通过理解和应用这些概念,开发者可以进一步提升他们的...
本主题聚焦于OpenCV 3.0版本中的两个关键功能:图像二值化和细化。这两个技术对于图像预处理至关重要,它们可以提高后续图像分析和识别的效率。 **图像二值化**是将图像转化为黑白两色调的过程,即图像中的每个像素...
该实现(C++实现)是在查表法的基础上进行优化后的结果,结果比较完美,且效率较高,适合学习;详细分析见:https://blog.csdn.net/weixin_47156401/article/details/122287851?spm=1001.2014.3001.5502
通过学习和理解这些例子,你可以更深入地掌握OpenCV在图像处理中的应用,尤其是如何对图像进行二值化处理和细化操作,从而为你的项目或研究提供强有力的支持。记得实践是检验真理的唯一标准,动手操作这些代码,你会...
在实际使用时,我们首先需要读取图像,然后将其转换为灰度图,因为细化算法通常只适用于单通道图像。接着,我们可以调用`cv2.threshold()`或者`cv2.adaptiveThreshold()`函数进行预处理,以去除一些噪声。最后,将...
在这个项目中,我们看到的是一个用C++实现的细化算法,适用于二值图像。下面将详细解释相关的知识点。 1. **细化算法**:细化算法的核心目标是减小图像中线条的宽度而不改变其结构。常见的细化算法有基于迭代的方法...
在图像处理领域,细化算法是一种重要的技术,常用于二值黑白图像分析,特别是骨架提取。骨架,也称为轮廓线或中轴线,是物体形状的一种紧凑表示,它将物体的边界压缩成一条单像素宽的线,保留了物体的主要特征。这种...
Rosenfeld提出的早期细化算法,主要基于二值图像,通过查找连续的黑色像素链和白色像素链来确定边缘。在C/C++编程中,可以使用栈数据结构来存储像素链,实现边缘的检测和细化。 5. 基于参照表的细化算法:这种方法...
sz二值图像细化(骨架化)算法。是根据sz那篇经典论文实现的。算法中没有使用opencv而是使用了Matcom函数库。Matcom是matlab5.x版本的C++库。要用到matlib.h 和matlib.lib这两个文件。
**Deriche算法详解及其OpenCV实现** Deriche边缘检测算法是由R. Deriche在1986年提出的一种基于高斯滤波器的边缘检测方法。它结合了高斯平滑与导数运算,旨在寻找图像中的边缘,同时保持较高的信噪比和较少的假阳性...
本文将深入探讨如何利用OpenCV实现相位相关图像配准,并详细介绍相关知识点。 相位相关是一种非像素级对齐技术,它通过计算两个图像的频域相位差异来确定它们之间的位移。这种方法基于傅里叶变换理论,傅里叶变换...
OpenCV是一个强大的开源计算机视觉库,它提供了多种图像处理和计算机视觉功能,包括SIFT算法的实现。 在OpenCV中实现SIFT算法通常涉及以下几个步骤: 1. **预处理**:首先,对输入图像进行灰度化处理,因为SIFT...
在提供的C源码中,这三个算法可能被实现为独立的功能,用于处理二值图像。源码可能包含以下部分: - 结构元素的定义和初始化,结构元素可以是预定义形状,也可以是自定义形状。 - 对于腐蚀和膨胀,源码可能包含两个...
Zhang-Suen细化算法是一种广泛应用的二值图像细化方法,它通过检测并消除像素的相邻连接来达到细化目的。算法主要包括四个步骤:邻接像素检查、线段端点检测、线段内部节点处理和新节点生成。在C++中实现这个算法时...