OpenCV图像细化的一个例子
转自:http://blog.csdn.net/zfdxx369/article/details/9091953?utm_source=tuicool
本文是zhang的一篇经典图像细化论文,效果很好,采用并行计算,速度非常快;
下文是 "智慧视觉"在CSDN上对这篇论文程序的一个改造,亲测可用!
由于OpenCV没有自带的图像细化函数,网上提供的基本是基于1.0接口的,于是乎动手搞成2.0 Mat类型接口的,方便好用。细化方法当中,当属经典的Zhang并行快速细化算法,细化之后的轮廓走势与原图保持得相对较好.
//将 DEPTH_8U型二值图像进行细化 经典的Zhang并行快速细化算法
void thin(const Mat &src, Mat &dst, const int iterations)
{
const int height =src.rows -1;
const int width =src.cols -1; //拷贝一个数组给另一个数组
if(src.data != dst.data)
{
src.copyTo(dst);
} int n = 0,i = 0,j = 0;
Mat tmpImg;
uchar *pU, *pC, *pD;
BOOL isFinished =FALSE; for(n=0; n<iterations; n++)
{
dst.copyTo(tmpImg);
isFinished =FALSE; //一次 先行后列扫描 开始
//扫描过程一 开始
for(i=1; i<height; i++)
{
pU = tmpImg.ptr<uchar>(i-1);
pC = tmpImg.ptr<uchar>(i);
pD = tmpImg.ptr<uchar>(i+1);
for(int j=1; j<width; j++)
{
if(pC[j] > 0)
{
int ap=0;
int p2 = (pU[j] >0);
int p3 = (pU[j+1] >0);
if (p2==0 && p3==1)
{
ap++;
}
int p4 = (pC[j+1] >0);
if(p3==0 && p4==1)
{
ap++;
}
int p5 = (pD[j+1] >0);
if(p4==0 && p5==1)
{
ap++;
}
int p6 = (pD[j] >0);
if(p5==0 && p6==1)
{
ap++;
}
int p7 = (pD[j-1] >0);
if(p6==0 && p7==1)
{
ap++;
}
int p8 = (pC[j-1] >0);
if(p7==0 && p8==1)
{
ap++;
}
int p9 = (pU[j-1] >0);
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==0)&&(p4*p6*p8==0))
{
dst.ptr<uchar>(i)[j]=0;
isFinished =TRUE;
} // if((p2*p4*p8==0)&&(p2*p6*p8==0))
// {
// dst.ptr<uchar>(i)[j]=0;
// isFinished =TRUE;
// } }
}
} } //扫描过程一 结束 dst.copyTo(tmpImg);
//扫描过程二 开始
for(i=1; i<height; i++) //一次 先行后列扫描 开始
{
pU = tmpImg.ptr<uchar>(i-1);
pC = tmpImg.ptr<uchar>(i);
pD = tmpImg.ptr<uchar>(i+1);
for(int j=1; j<width; j++)
{
if(pC[j] > 0)
{
int ap=0;
int p2 = (pU[j] >0);
int p3 = (pU[j+1] >0);
if (p2==0 && p3==1)
{
ap++;
}
int p4 = (pC[j+1] >0);
if(p3==0 && p4==1)
{
ap++;
}
int p5 = (pD[j+1] >0);
if(p4==0 && p5==1)
{
ap++;
}
int p6 = (pD[j] >0);
if(p5==0 && p6==1)
{
ap++;
}
int p7 = (pD[j-1] >0);
if(p6==0 && p7==1)
{
ap++;
}
int p8 = (pC[j-1] >0);
if(p7==0 && p8==1)
{
ap++;
}
int p9 = (pU[j-1] >0);
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==0)&&(p4*p6*p8==0))
// {
// dst.ptr<uchar>(i)[j]=0;
// isFinished =TRUE;
// } if((p2*p4*p8==0)&&(p2*p6*p8==0))
{
dst.ptr<uchar>(i)[j]=0;
isFinished =TRUE;
} }
}
} } } //一次 先行后列扫描完成
//如果在扫描过程中没有删除点,则提前退出
if(isFinished ==FALSE)
{
break;
}
} }
}
OpenCV图像细化的一个例子的更多相关文章
- opencv 图像细化
图像细化多用于机器人视觉,OCR字符识别等领域,细化后的图像经过去毛刺就成为了我们常说的图像的骨架. 该图像细化代码依据论文: T. Y. ZHANG and C. Y. SUEN A Fast P ...
- 【opencv】图像细化
[原文:http://blog.csdn.net/qianchenglenger/article/details/19332011] 在我们进行图像处理的时候,有可能需要对图像进行细化,提取出图像的骨 ...
- opencv图像的基本操作3
1.获取像素并修改 读取一副图像,根据像素的行和列的坐标获取它的像素值,对于RGB图像而言,返回RGB的值,对于灰度图则返回灰度值 import cv2 import numpy img = cv2. ...
- OpenCV图像处理中“投影技术”的使用
本文区分"问题引出"."概念抽象"."算法实现"三个部分由表及里具体讲解OpenCV图像处理中"投影技术" ...
- opencv——图像直方图与反向投影
引言 在图像处理中,对于直方图这个概念,肯定不会陌生.但是其原理真的可以信手拈来吗? 本文篇幅有点长,在此列个目录,大家可以跳着看: 分析图像直方图的概念,以及opencv函数calcHist()对于 ...
- <学习opencv>图像和大型阵列类型
OPenCV /*=========================================================================*/ // 图像和大型阵列类型 /* ...
- SSE图像算法优化系列三十二:Zhang\Guo图像细化算法的C语言以及SIMD指令优化
二值图像的细化算法也有很多种,比较有名的比如Hilditch细化.Rosenfeld细化.基于索引表的细化.还有Opencv自带的THINNING_ZHANGSUEN.THINNING_GUOHALL ...
- OpenCV图像金字塔:高斯金字塔、拉普拉斯金字塔与图片尺寸缩放
这篇已经写得很好,真心给作者点个赞.题目都是直接转过来的,直接去看吧. Reference Link : http://blog.csdn.net/poem_qianmo/article/detail ...
- 【OpenCV新手教程之十三】OpenCV图像金字塔:高斯金字塔、拉普拉斯金字塔与图片尺寸缩放
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/26157633 作者:毛星云(浅墨) ...
随机推荐
- web.xml 中的listener、 filter、servlet 加载顺序及其详解
在项目中总会遇到一些关于加载的优先级问题,近期也同样遇到过类似的,所以自己查找资料总结了下,下面有些是转载其他人的,毕竟人家写的不错,自己也就不重复造轮子了,只是略加点了自己的修饰. 首先可以肯定的是 ...
- VS单元测试
弄了好久才明白 ,但是收获确实挺大的,话不多说,直接上图. 1 打开VS建立项目 2 建立一个类 3 点击创建单元测试 4 在运行模块里重新输入代码 5 在空白处 点击鼠标右键 选择运行测试 6 测试 ...
- ORACLE判别字段是否包含中文
在ORACLE数据库中如何查找那些字段里面包含中文的数据记录呢,有时候就是有这样的特殊需求,下面整理了一些判别字段中包含中文记录的几个方法 1:使用ASCIISTR函数判别 ASCIISTR函数说 ...
- java获取注册ip
String ip = request.getHeader("x-forwarded-for"); if (ip == null || ip.length() == 0 || &q ...
- hdu 5641 King's Phone
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5641 题目类型:水题 题目思路:将点x到点y所需要跨过的点存入mark[x][y]中(无需跨过其它点存 ...
- Linux的文件权限与目录配置
用户与用户组(Linux是一个多用户多任务的系统) 文件所有者 设置适当的权限,其他人无法看到自己的文件 用户组概念 属于同一个用户组的可以看到这个团体的公共信息,每个账户都可以有多个用户组的 ...
- DNS相关知识
1 DNS解析过程详解 2 DNS原理总结及其解析过程详解 3 DNS原理及其解析过程[精彩剖析] 4 DNS域名解析原理 5 dig挖出DNS的秘密 6 nslookup通往DNS的桥梁 7 DNS ...
- 附加数据库后无法创建发布,error 2812 解决
日前,由于业务需要,我要把一个数据库直接迁移到新的实例上 用的方法比较古老,就是直接停旧服务器,将数据文件复制到新服务器上,附加数据库 当然这个附加没有什么可说的了,但是在附加后需要将原来库上的发布重 ...
- redis 源码阅读 内部数据结构--字符串
redis的内部数据结构主要有:字符串,双端链表,字典,跳跃表. 这里主要记录redise字符串的设计.相关的源码位于:src/sds.h 和 src/sds.c. 一 字符串 sds的结构体 s ...
- QT210 android2.3 和android4.0 烧写编译日记
QT210下载烧录编译android2.3过程 工作环境:ubuntu12.04.5 | QT210开发板光盘 | QT210开发板 android2.3编译环境:gcc version 4.4.7 ...