相关介绍  http://www.doc88.com/p-7724593025971.html

比较好的介绍  https://www.cnblogs.com/xianglan/archive/2011/01/01/1923779.html

https://www.cnblogs.com/Summerio/p/8284602.html

https://blog.csdn.net/weixinhum/article/details/80261296

//#include "stdafx.h"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <time.h>
#include <iostream>using namespace cv;
using namespace std;/*
* @brief 对输入图像进行细化,骨骼化
* @param src为输入图像,用cvThreshold函数处理过的8位灰度图像格式,元素中只有0与1,1代表有元素,0代表为空白
* @param dst为对src细化后的输出图像,格式与src格式相同,元素中只有0与1,1代表有元素,0代表为空白
*/
void thinImage(Mat & src, Mat & dst)
{int width = src.cols;int height = src.rows;src.copyTo(dst);vector<uchar *> mFlag; //用于标记需要删除的点    while (true){//步骤一   for (int i = 0; i < height; ++i){uchar * p = dst.ptr<uchar>(i);for (int j = 0; j < width; ++j){//获得九个点对象,注意边界问题uchar p1 = p[j];if (p1 != 1) continue;uchar p2 = (i == 0) ? 0 : *(p - dst.step + j);uchar p3 = (i == 0 || j == width - 1) ? 0 : *(p - dst.step + j + 1);uchar p4 = (j == width - 1) ? 0 : *(p + j + 1);uchar p5 = (i == height - 1 || j == width - 1) ? 0 : *(p + dst.step + j + 1);uchar p6 = (i == height - 1) ? 0 : *(p + dst.step + j);uchar p7 = (i == height - 1 || j == 0) ? 0 : *(p + dst.step + j - 1);uchar p8 = (j == 0) ? 0 : *(p + j - 1);uchar p9 = (i == 0 || j == 0) ? 0 : *(p - dst.step + j - 1);if ((p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) >= 2 && (p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) <= 6)//条件1判断{//条件2计算int ap = 0;if (p2 == 0 && p3 == 1) ++ap;if (p3 == 0 && p4 == 1) ++ap;if (p4 == 0 && p5 == 1) ++ap;if (p5 == 0 && p6 == 1) ++ap;if (p6 == 0 && p7 == 1) ++ap;if (p7 == 0 && p8 == 1) ++ap;if (p8 == 0 && p9 == 1) ++ap;if (p9 == 0 && p2 == 1) ++ap;//条件2、3、4判断if (ap == 1 && p2 * p4 * p6 == 0 && p4 * p6 * p8 == 0){//标记    mFlag.push_back(p + j);}}}}//将标记的点删除    for (vector<uchar *>::iterator i = mFlag.begin(); i != mFlag.end(); ++i){**i = 0;}//直到没有点满足,算法结束    if (mFlag.empty()){break;}else{mFlag.clear();//将mFlag清空    }//步骤二,根据情况该步骤可以和步骤一封装在一起成为一个函数for (int i = 0; i < height; ++i){uchar * p = dst.ptr<uchar>(i);for (int j = 0; j < width; ++j){//如果满足四个条件,进行标记    //  p9 p2 p3    //  p8 p1 p4    //  p7 p6 p5    uchar p1 = p[j];if (p1 != 1) continue;uchar p2 = (i == 0) ? 0 : *(p - dst.step + j);uchar p3 = (i == 0 || j == width - 1) ? 0 : *(p - dst.step + j + 1);uchar p4 = (j == width - 1) ? 0 : *(p + j + 1);uchar p5 = (i == height - 1 || j == width - 1) ? 0 : *(p + dst.step + j + 1);uchar p6 = (i == height - 1) ? 0 : *(p + dst.step + j);uchar p7 = (i == height - 1 || j == 0) ? 0 : *(p + dst.step + j - 1);uchar p8 = (j == 0) ? 0 : *(p + j - 1);uchar p9 = (i == 0 || j == 0) ? 0 : *(p - dst.step + j - 1);if ((p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) >= 2 && (p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) <= 6){int ap = 0;if (p2 == 0 && p3 == 1) ++ap;if (p3 == 0 && p4 == 1) ++ap;if (p4 == 0 && p5 == 1) ++ap;if (p5 == 0 && p6 == 1) ++ap;if (p6 == 0 && p7 == 1) ++ap;if (p7 == 0 && p8 == 1) ++ap;if (p8 == 0 && p9 == 1) ++ap;if (p9 == 0 && p2 == 1) ++ap;if (ap == 1 && p2 * p4 * p8 == 0 && p2 * p6 * p8 == 0){//标记    mFlag.push_back(p + j);}}}}//将标记的点删除    for (vector<uchar *>::iterator i = mFlag.begin(); i != mFlag.end(); ++i){**i = 0;}//直到没有点满足,算法结束    if (mFlag.empty()){break;}else{mFlag.clear();//将mFlag清空    }}
}/*
* @brief 对输入图像进行端点和交叉点检测,前提是输入图像已经经过骨骼化提取
*/
void endPointAndintersectionPointDetection(Mat & src)
{int width = src.cols;int height = src.rows;vector<CvPoint> endpoint;vector<CvPoint> intersectionPoint;//遍历骨骼化后的图像,找到端点和交叉点,分别放入容器中for (int i = 0; i < height; ++i){uchar * p = src.ptr<uchar>(i);for (int j = 0; j < width; ++j){//获得九个点对象,注意边界问题uchar p1 = p[j];if (p1 != 1) continue;uchar p2 = (i == 0) ? 0 : *(p - src.step + j);uchar p3 = (i == 0 || j == width - 1) ? 0 : *(p - src.step + j + 1);uchar p4 = (j == width - 1) ? 0 : *(p + j + 1);uchar p5 = (i == height - 1 || j == width - 1) ? 0 : *(p + src.step + j + 1);uchar p6 = (i == height - 1) ? 0 : *(p + src.step + j);uchar p7 = (i == height - 1 || j == 0) ? 0 : *(p + src.step + j - 1);uchar p8 = (j == 0) ? 0 : *(p + j - 1);uchar p9 = (i == 0 || j == 0) ? 0 : *(p - src.step + j - 1);if ((p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) == 1)//端点判断{printf("端点:%d %d\n", i, j);endpoint.push_back(cvPoint(j, i));}else //交叉点判断{int ap = 0;if (p2 == 0 && p3 == 1) ++ap;if (p3 == 0 && p4 == 1) ++ap;if (p4 == 0 && p5 == 1) ++ap;if (p5 == 0 && p6 == 1) ++ap;if (p6 == 0 && p7 == 1) ++ap;if (p7 == 0 && p8 == 1) ++ap;if (p8 == 0 && p9 == 1) ++ap;if (p9 == 0 && p2 == 1) ++ap;if (ap >= 3){printf("交叉点:%d %d\n", i, j);intersectionPoint.push_back(cvPoint(j, i));}}}}//画出端点for (vector<CvPoint>::iterator i = endpoint.begin(); i != endpoint.end(); ++i){circle(src, cvPoint(i->x, i->y), 5, Scalar(255), -1);}//画出交叉点for (vector<CvPoint>::iterator i = intersectionPoint.begin(); i != intersectionPoint.end(); ++i){circle(src, cvPoint(i->x, i->y), 5, Scalar(255));}endpoint.clear();//数据回收 intersectionPoint.clear();
}int main()
{Mat src = imread("5.png", IMREAD_GRAYSCALE);GaussianBlur(src, src, Size(7, 7), 0, 0);//高斯滤波threshold(src, src, 140, 1, cv::THRESH_BINARY_INV);//二值化,前景为1,背景为0Mat dst;thinImage(src, dst);//图像细化(骨骼化)endPointAndintersectionPointDetection(dst);src = src * 255;imshow("原始图像", src);dst = dst * 255;imshow("细化图像", dst);waitKey(0);
}

在源文件的同级目录下放入要编辑的图片(png格式),命名为5.png

编译(需安装opencv):

g++ gujiatiqu.cpp -o gujia `pkg-config opencv --cflags --libs`

g++ -std=c++11  gujiatiqu.cpp -o gujia `pkg-config opencv --cflags --libs`

上面的引号是键盘左上角的`,就是数字键1左边的那个键,谨记!

zhang快速并行细化算法相关推荐

  1. zhang 快速并行细化方法_一种改进的Zhang并行图像细化算法的制作方法

    本发明涉及图像处理技术,具体涉及一种改进的Zhang并行图像细化算法. 背景技术: 图像细化是将图像的线条从多像素宽度减少到单位像素宽度,简称骨架化.细化效果的好坏直接影响后期图像处理的效果.对于二值 ...

  2. 改进zhang方法图像细化(单像素)

    本文主要实现实现了和讲解图像细化算法,引用论文 "牟少敏,杜海洋,苏平,查绪恒,陈光艺.一种改进的快速并行细化算法[J].微电子学与计算机,2013,(第1期)" ,免费下载地址点 ...

  3. 改进Zhang Suen细化算法的C#实现

    本文主要实现了改进Zhang Suen细化算法的C#实现,相关论文 :"牟少敏,杜海洋,苏平,查绪恒,陈光艺.一种改进的快速并行细化算法[J].微电子学与计算机,2013,(第1期)&quo ...

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

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

  5. 并行Zhang细化算法FPA算法

    并行Zhang细化算法 和 FPA算法 ,的规则好像完全一样. //  p9 p2 p3   //  p8 p1 p4   //  p7 p6 p5 前景点为1,背景点为0 条件1:p1为前景点 条件 ...

  6. C#:实现Zhang Suen细化算法(附完整源码)

    C#:实现Zhang Suen细化算法 #region xqpublic Bitmap zhang_thinimage_improve(Bitmap bmp){int imgWidth = bmp.W ...

  7. 图像处理之Zhang Suen细化算法

    在二值图像处理特别是OCR识别与匹配中,都要通过对字符进行细化以便获得图像的骨架,通过zhang-suen细化算法获得图像,作为图像的特征之一,常用来作为识别或者模式匹配. 一:算法介绍 Zhang- ...

  8. 图像和视频的快速去雾算法研究

    王昕, 孙莹莹, 李影昉. 图像和视频的快速去雾算法研究[J]. 影像科学与光化学, 2016, 34(1): 82-87.   WANG Xin, SUN Yingying, LI Yingfang ...

  9. 改进的脱机手写体汉字细化算法

    摘要:基础数据来源于23名同学手写的100个汉字,共计2300个,然后对这组数据进行二值化,去噪,分割,归一化后所得数据. 作者:刘亚宁,2010年9月10日 在进行细化之前首先以说明为什么要将手写体 ...

最新文章

  1. 第四章第四个例题(LRJ)
  2. [architecture]-Generic Timer
  3. (看这一篇就够了)基本数据类型的赋值与引用类型赋值的区别
  4. 在VS2010里可以给JS函数添加代码提示\注释
  5. 设计模式之Builder (创建者模式)的一些个人理解(转)
  6. Spark应用运行流程
  7. 词汇的积累与遣词造句 —— 准确的表达、新鲜的词汇
  8. 试用cmd markdown
  9. ajax send()的作用_AJAX(Asynchronous JavaScript And XML)
  10. 计算机玩游戏特别卡怎么办,电脑玩游戏突然变卡怎么办 玩游戏变卡的解决方法...
  11. 小秘书智能app登录
  12. java校园快递代领系统 小程序
  13. 【东方博宜】【入门】1326--需要安排几位师傅加工零件?
  14. 新型冠状病毒传染模型SI、SIS、SIR、SEIR
  15. 基于滴滴云搭建安全稳定的 Memcached 服务器
  16. [转载]华为老员工看华为(一):不断改进的海外市场
  17. 7-7 六度空间 (30 point(s))
  18. C/C++面试感受和经验以及面试题收藏(转)
  19. 商务部公布跨国公司港澳台企业捐款详情
  20. Latex插入多张图片及图片图题的间隔位置等问题处理

热门文章

  1. python中label有什么用_对Python中TKinter模块中的Label组件实例详解
  2. linux mysql木马_Linux系统木马后门查杀方法
  3. 推荐系统[八]算法实践总结V0:淘宝逛逛and阿里飞猪个性化推荐:召回算法实践总结【冷启动召回、复购召回、用户行为召回等算法实战】
  4. Kali Linux无法联网的解决办法(亲测有效)
  5. winxp计算机名称改了恢复,WinXP如何修改Netbios名和计算机名有什么不同
  6. errors不是exceptions | Gopher Daily (2021.02.05) ʕ◔ϖ◔ʔ
  7. 柳传志一生最大的过错
  8. java中结束进程的方法_java关闭Process
  9. Linux——目录和文件的管理
  10. pikachu之unsafe upfileupload