细化算法它的原理也很简单:

我们对一副二值图像进行骨架提取,就是删除不需要的轮廓点,只保留其骨架点。假设一个像素点,我们定义该点为p1,则它的八邻域点p2->p9位置如下图所示,该算法考虑p1点邻域的实际情况,以便决定是否删除p1点。假设我们处理的为二值图像,背景为黑色,值为0,要细化的前景物体像素值为1。

算法的描述如下:

  

首先复制源图像到目地图像,然后建立一个临时图像,接着执行下面操作:

1. 把目地图像复制给临时图像,对临时图像进行一次扫描,对于不为0的点,如果满足以下四个条件,则在目地图像中删除该点(就是设置该像素为0),这里p2,…,p9是对应位置的像素灰度值(其为1或者0)。

a. 2<= p2+p3+p4+p5+p6+p7+p8+p9<=6

大于等于2会保证p1点不是端点或孤立点,因为删除端点和孤立点是不合理的,小于等于6保证p1点是一个边界点,而不是一个内部点。等于0时候,周围没有等于1的像素,所以p1为孤立点,等于1的时候,周围只有1个灰度等于1的像素,所以是端点(注:端点是周围有且只能有1个值为1的像素)。

b. p2->p9的排列顺序中,01模式的数量为1,比如下面的图中,有p2p3 => 01, p6p7=>01,所以该像素01模式的数量为2。

之所以要01模式数量为1,是要保证删除当前像素点后的连通性。比如下面的图中,01模式数量大于1,如果删除当前点p1,则连通性不能保证。

c. P2*p4*p6 = 0

d. p4*p6*p8 = 0

在第一次子迭代中,只是移去东南的边界点,而不考虑西北的边界点,注意p4,p6出现了2次,就是说它们有一个为0,则c,d就满足。

2. 接下来,把目地图像再次复制到临时图像,接着对临时图像进行一次扫描,如果不为0的点它的八邻域满足以下4个条件,则在目地图像中删除该点(就是设置该像素为0)

a. 2<= p2+p3+p4+p5+p6+p7+p8+p9<=6

b. p2->p9的排列顺序中,01模式的数量(这里假设二值图非零值为1)为1。

c. p2*p4*p8 = 0

d. p2*p6*p8 = 0

第二次迭代则相反,会移去西北的边界点,注意p2,p8出现了2次,就是说它们有一个为0,则c,d就满足。

执行完上面两个步骤后,就完成了一次细化算法,我们可以多次迭代执行上述过程,得到最终的骨架图。

细化算法代码如下:

以上部分原理是转载(迈克老狼2012)http://www.cnblogs.com/mikewolf2002/p/3321732.html

接下来发布的是在我电脑上通过的测试代码:

编译环境为win7+VS2015+OpenCV3.0

 void cvThin(IplImage* src, IplImage* dst, int iterations)
{
//此时的src是一个二值化的图片
CvSize size = cvGetSize(src);
cvCopy(src, dst); int n = , i = , j = ;
for (n = ; n < iterations; n++)//开始进行迭代
{
IplImage* t_image = cvCloneImage(dst);
for (i = ; i < size.height; i++)
{
for (j = ; j < size.width; j++)
{
if (CV_IMAGE_ELEM(t_image, uchar, i, j) == )
{
int ap = ;
int p2 = (i == ) ? : CV_IMAGE_ELEM(t_image, uchar, i - , j);
int p3 = (i == || j == size.width - ) ? : CV_IMAGE_ELEM(t_image, uchar, i - , j + );
if (p2 == && p3 == )
{
ap++;
} int p4 = (j == size.width - ) ? : CV_IMAGE_ELEM(t_image, uchar, i, j + );
if (p3 == && p4 == )
{
ap++;
} int p5 = (i == size.height - || j == size.width - ) ? : CV_IMAGE_ELEM(t_image, uchar, i + , j + );
if (p4 == && p5 == )
{
ap++;
} int p6 = (i == size.height - ) ? : CV_IMAGE_ELEM(t_image, uchar, i + , j);
if (p5 == && p6 == )
{
ap++;
} int p7 = (i == size.height - || j == ) ? : CV_IMAGE_ELEM(t_image, uchar, i + , j - );
if (p6 == && p7 == )
{
ap++;
} int p8 = (j == ) ? : CV_IMAGE_ELEM(t_image, uchar, i, j - );
if (p7 == && p8 == )
{
ap++;
} int p9 = (i == || j == ) ? : CV_IMAGE_ELEM(t_image, uchar, i - , j - );
if (p8 == && p9 == )
{
ap++;
}
if (p9 == && p2 == )
{
ap++;
} if ((p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) > && (p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) < )
{
if (ap == )
{
if (!(p2 && p4 && p6))
{
if (!(p4 && p6 && p8))
{
CV_IMAGE_ELEM(dst, uchar, i, j) = ;//设置目标图像中像素值为0的点
}
}
}
} }
}
} cvReleaseImage(&t_image); t_image = cvCloneImage(dst);
for (i = ; i < size.height; i++)
{
for (int j = ; j < size.width; j++)
{
if (CV_IMAGE_ELEM(t_image, uchar, i, j) == )
{
int ap = ;
int p2 = (i == ) ? : CV_IMAGE_ELEM(t_image, uchar, i - , j);
int p3 = (i == || j == size.width - ) ? : CV_IMAGE_ELEM(t_image, uchar, i - , j + );
if (p2 == && p3 == )
{
ap++;
}
int p4 = (j == size.width - ) ? : CV_IMAGE_ELEM(t_image, uchar, i, j + );
if (p3 == && p4 == )
{
ap++;
}
int p5 = (i == size.height - || j == size.width - ) ? : CV_IMAGE_ELEM(t_image, uchar, i + , j + );
if (p4 == && p5 == )
{
ap++;
}
int p6 = (i == size.height - ) ? : CV_IMAGE_ELEM(t_image, uchar, i + , j);
if (p5 == && p6 == )
{
ap++;
}
int p7 = (i == size.height - || j == ) ? : CV_IMAGE_ELEM(t_image, uchar, i + , j - );
if (p6 == && p7 == )
{
ap++;
}
int p8 = (j == ) ? : CV_IMAGE_ELEM(t_image, uchar, i, j - );
if (p7 == && p8 == )
{
ap++;
}
int p9 = (i == || j == ) ? : CV_IMAGE_ELEM(t_image, uchar, i - , j - );
if (p8 == && p9 == )
{
ap++;
}
if (p9 == && p2 == )
{
ap++;
}
if ((p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) > && (p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) < )
{
if (ap == )
{
if (p2*p4*p8 == )
{
if (p2*p6*p8 == )
{
CV_IMAGE_ELEM(dst, uchar, i, j) = ;
}
}
}
}
} } }
cvReleaseImage(&t_image);
} }

细化结果因为我的图不方便展示,大家可以参考迈克老狼2012的哦,效果是很像的,他采用的mat类,而我采用的iplimage类。

OpenCV细化算法简单解析的更多相关文章

  1. 手指静脉细化算法过程原理解析 以及python实现细化算法

    原文作者:aircraft 原文地址:https://www.cnblogs.com/DOMLX/p/8672489.html 文中的一些图片以及思想很多都是参考https://www.cnblogs ...

  2. OpenCV学习(18) 细化算法(6)

    本章我们在学习一下基于索引表的细化算法. 假设要处理的图像为二值图,前景值为1,背景值为0. 索引表细化算法使用下面的8邻域表示法: 一个像素的8邻域,我们可以用8位二进制表示,比如下面的8邻域,表示 ...

  3. OpenCV学习(13) 细化算法(1)

    程序编码参考经典的细化或者骨架算法文章: T. Y. Zhang and C. Y. Suen, "A fast parallel algorithm for thinning digita ...

  4. OpenCV学习(17) 细化算法(5)

    本章我们看下Pavlidis细化算法,参考资料http://www.imageprocessingplace.com/downloads_V3/root_downloads/tutorials/con ...

  5. OpenCV学习(16) 细化算法(4)

    本章我们学习Rosenfeld细化算法,参考资料:http://yunpan.cn/QGRjHbkLBzCrn 在开始学习算法之前,我们先看下连通分量,以及4连通性,8连通性的概念: http://w ...

  6. OpenCV学习(14) 细化算法(2)

          前面一篇教程中,我们实现了Zhang的快速并行细化算法,从算法原理上,我们可以知道,算法是基于像素8邻域的形状来决定是否删除当前像素.还有很多与此算法相似的细化算法,只是判断的条件不一样. ...

  7. c++opencv中线条细化算法

    要达到的效果就是将线条尽量细化成单像素,按照论文上的Hilditch算法试了一下,发现效果不好,于是自己尝试着写了一下细化的算法,基本原理就是从上下左右四个方向向内收缩. 1.先是根据图片中的原则确定 ...

  8. Adaboost 算法实例解析

    Adaboost 算法实例解析 1 Adaboost的原理 1.1 Adaboost基本介绍 AdaBoost,是英文"Adaptive Boosting"(自适应增强)的缩写,由 ...

  9. 2. Attention Is All You Need(Transformer)算法原理解析

    1. 语言模型 2. Attention Is All You Need(Transformer)算法原理解析 3. ELMo算法原理解析 4. OpenAI GPT算法原理解析 5. BERT算法原 ...

随机推荐

  1. 国内物联网平台(1):百度物接入IoT Hub

    国内物联网平台(1) ——百度物接入IoT Hub 马智 物接入IoT Hub - 架构 全托管的云服务,帮助建立设备与云端之间安全可靠的双向连接 支撑海量设备的数据收集.监控.故障预测等各种物联网场 ...

  2. kylin 连接 hortonworks 中的 hive 遇到的问题

    用 hortonworks(V3.1.0.0) 部署了 ambari (V2.7.3),用 ambari 部署了 hadoop 及 hive. 1.  启动 kylin(V2.6)时,遇到如下问题: ...

  3. CI框架源码学习笔记7——Utf8.php

    愉快的清明节假期结束了,继续回到CI框架学习.这一节我们来看看Utf8.php文件,它主要是用来做utf8编码,废话不多说,上代码. class CI_Utf8 { /** * Class const ...

  4. dedecms有缩略图则显示缩略图,没有则显示随机缩略图

    随着html5以及扁平化等新的设计概念的深入人心,缩略图功能则成了一般网页模版制作不可或缺的一个功能,dedecms默认的的缩略图调用标签[field:imglink/] 或者 [field:litp ...

  5. luogu2948 滑雪课

    题解里面全是dp的大神本蒟蒻瑟瑟发抖奉上一篇记忆化搜索... 其实嘛,记忆化搜索还是很安全透彻清真人品的,一般递推不好实现dp可以用记忆化搜索 然后本题先预处理一个mint[i]代表当前能力值为i,参 ...

  6. 资深专家深度剖析Kubernetes API Server第2章(共3章)

    欢迎来到深入学习Kubernetes API Server的系列文章的第二部分.在上一部分中我们对APIserver总体,相关术语及request请求流进行探讨说明.在本部分文章中,我们主要聚焦于探究 ...

  7. javascript事件委托//就是父级事件给子级

    <!DOCTYPE html><html><head> <title></title> <style type="text/ ...

  8. [JSOI2009]瓶子和燃料 BZOJ2257 数学

    题目描述 jyy就一直想着尽快回地球,可惜他飞船的燃料不够了.有一天他又去向火星人要燃料,这次火星人答应了,要jyy用飞船上的瓶子来换.jyy的飞船上共有 N个瓶子(1<=N<=1000) ...

  9. asp.net mvc 中的 controller和asp.net web api 的apicontroller有什么区别?(转)

    本质上区别不大,一个返回html/text类型的response,一个返回json/text或者xml/text类型的response,对于api环境而言,apicontroller更智能一点,他可以 ...

  10. windows安装redis并设置别名

    最近两天不知什么原因导致win10的redis 无法通过 双击 redis-server.exe 文件启动 redis服务:于是从新安装并且 通过命令行启动服务,并且设置别名,每次方便启动服务 1.下 ...