基于distanceTransform-距离变换的区域中心提取

合集下载

基于边界距离场的管腔中心路径自动提取算法

基于边界距离场的管腔中心路径自动提取算法

取 中心 路 径 . 验 结 果 表 明 , 确 的边 界距 离 场 使 得 提 取 的 中心 路 径 更 加 精 确 , 快 速 算 法 的 应 用 提 高 了 该 算 法 的 实 精 而
效 率 , 得 的结 果 可 直 接用 作 虚 拟 内 窥 镜 的 漫 游 路 径 . 获
关键 词 虚 拟 内窥 镜 ; 界 距 离 场 ; 边 中心 路 径 提 取
0 引

得类似 的观 察效 果 , 虚拟 内窥 镜 漫 游数 字 器官 的 在
过程 中 , 虚拟 相机最 好也 能 够沿 着一 定 的路径 行 走 .
虚拟 内 窥 镜 技 术 随 着 高 分 辨 医 学 图 像 ( T, C MRI ) 出现 , 等 的 以及 虚 拟 现 实技 术 的 不 断 完 善 和 提高, 已得 到迅 速发展 , 同时也 成 为虚 拟现 实技 术走
ag rt m h e trieo h u ua be t se tatdfo t eMS te . ee p r n a eut h w lo ih t ec n el ft et b lr jc x r ce rm h T re Th x e i t l s l s o n o i me r s
统 中的关 键技 术之 一. 实现 漫游 路径 的 自动 规划一 般 可分 为拓 扑逻辑
细化 法 和距离 变换 法 2种 . 扑 逻 辑细 化 法 通过 反 拓 复剥 除物 体 的最 外层 体 素 , 到 只剩 下 一 个 体 素作 直 为该 物体 的 骨 架 . 然 这 种 算 法 的 思 想 非 常 简 单 , 虽 但是其 计 算 量 非 常 大 _ , 使 是 其 快 速 算 法 _ , 2 即 J 3 也 ]
J n ,2 0 ue 06

基于距离变换与路径规划的骨架提取算法

基于距离变换与路径规划的骨架提取算法
s∈ S
那么 p1 就是局部距离变换 最 大 值 点,所 有 最 大 值点的集合为 Lmax。图 5是根 据 图 3得 出 的 距 离 变 换局部最大值的图像。
定义 2:距离 变 换 梯 度 的 模 同 样 反 应 骨 架 点 的 情况。假 设 p2 象 素 的 距 离 变 换 梯 度 的 模 的 值 为 ‖f(p2)‖,p2 的 8邻 域 象 素 点 为 集 合 S,如 果 满 足以下条件:
基于骨架提取 的 重 要 性,在 文 献 中 提 出 了 大 量 的骨架提取算法。这些骨架提取算法大致可以分为 四 类 [3]:① 中 轴 变 换 (medicalaxistransform)[4-5]; ② 细化算 法 (thinningalgorithm)[6-8];③ 距 离 变 换 (distancetransform)[9-12];④ 路 径 规 划 算 法 (path planningalgorithm)[9,13-14]。
中轴在数学术语中可以用最大内切圆的相关术 语定义,一个对称点 是 两 个 或 多 个 有 着 相 等 长 度 的 圆盘法线的交点。其中圆盘法线是从对称点到边界 的最短长度的线段。由于一个目标内点的最大内切 圆在边界上至少有 两 个 切 点,所 以 每 个 对 称 点 有 两 个或多个圆盘法线。中轴变换实现起来较为困难, 中轴变换用于识别 的 最 大 缺 点 就 是:边 界 上 的 很 小 变化会使得对称轴人为产生冗余的长分支。细化算 法的基本思想是通过利用分层单向或双向迭代的方 法更改目标边缘的 点 为 背 景 点,直 到 目 标 变 成 了 一 些单象素宽的曲线所构成的结合。尽管细化算法可 以很好地保留物体 的 拓 扑 形 状,但 是 生 成 的 骨 架 依 赖于初始条件,且 迭 代 过 程 耗 时 较 大。 文 献 讨 [8] 论 了接近 300种细 化 算 法,近 年 来 也 提 出 了 许 多 新 的 细化算法,如势 能 场、水 平 集、主 曲 线 评 价 法 等。 传 统的距离变换算法通过在高一维空间中生成的距离 曲面形成的脊线来建立骨架。它们的主要特点是骨 架 位 置 准 确 ,外 形 顺 滑 ,缺 点 在 于 容 易 受 到 边 缘 噪 声 的干扰且难以保证骨架的准确性。而路径规划算法 通过寻找两点间的 最 短 路 径,通 过 定 义 骨 架 的 起 始 点与终止点,两点 间 的 最 短 路 径 即 是 骨 架。 路 径 规 划算法可以将物体的拓扑性与连续性很好地保留。

基于distanceTransform-距离变换的区域中心提取

基于distanceTransform-距离变换的区域中心提取

基于distanceTransform-距离变换的区域中⼼提取这⼏天在做⼀个⼿势识别的项⽬,其中最的关键⼀步是提取⼿掌中⼼。

获得⼿掌重⼼通常的做法是计算整个⼿部的重⼼,并以该重⼼位置近似⼿掌重⼼,这种⽅法只适⽤于没有⼿指伸出或只有⼀个⼿指伸出的情况,否则获得的⼿掌重⼼位置将严重偏离真实位置。

距离变换的基本含义是计算⼀个图像中⾮零像素点到最近的零像素点的距离,也就是到零像素点的最短距离。

因此可以基于距离变换提取⼿掌重⼼。

算法基本思想:(1)将⼿掌图像⼆值化,⼿掌内的区域设为⽩⾊,外部区域设为⿊⾊。

(2)将⼆值化后的图像经过distanceTransform变换,得到dist_image,其中每个像素点的值是该像素点到其最近的零像素点的距离。

(3)找到dist_image的最⼤值(即圆的半径R),并记录下位置(即圆⼼坐标)。

代码如下:[cpp]view plaincopy1. #include "opencv2/opencv.hpp"2. #include <opencv2/core/core.hpp>3. #include <opencv2/highgui/highgui.hpp>4. #include <opencv2/imgproc/imgproc.hpp>5. #include <vector>6. using namespace cv;7. using namespace std;8.9. pair<Point,double> DetectInCircles(vector<Point> contour,Mat src)10. {11.12. Mat dist_image;13. distanceTransform(src,dist_image,CV_DIST_L2,3);14. int temp=0,R=0,cx=0,cy=0;15. int d;16. for (int i=0;i<src.rows;i++)17. for (int j=0;j<src.cols;j++)18. {19. /* checks if the point is inside the contour. Optionally computes the signed distance from the point to the contour boundary*/20. d = pointPolygonTest(contour, Point2f(j, i), 0);21. if (d>0)22. {23. temp=(int)dist_image.ptr<float>(i)[j];24. if (temp>R)25. {26. R=temp;27. cy=i;28. cx=j;29. }30.31. }32. }33.34.35. return make_pair(Point(cx,cy),R);36.37. }38.39. int main()40. {41. // Read input binary image41. // Read input binary image42. Mat src= imread("D:\\mycode\\6.jpg",1);43. Mat image;44. cvtColor(src,image,CV_BGR2GRAY);45. vector<vector<Point>> contours;46.47. //findContours的输⼊是⼆值图像48. findContours(image,49. contours, // a vector of contours50. CV_RETR_EXTERNAL, // retrieve the external contours51. CV_CHAIN_APPROX_NONE); // retrieve all pixels of each contours52.53. // Print contours' length轮廓的个数54. cout << "Contours: " << contours.size() << endl;55. vector<vector<Point>>::const_iterator itContours= contours.begin();56. for ( ; itContours!=contours.end(); ++itContours) {57.58. cout << "Size: " << itContours->size() << endl;//每个轮廓包含的点数59. }60. //找到最⼤轮廓61. int index=0,maxArea=0;62. for(unsigned int i=0;i<contours.size();i++)63. {64. int area=contourArea(contours[i]);65. if (area>maxArea)66. {67. index=i;68. maxArea=area;69. }70. }71. // draw black contours on white image72. Mat result(image.size(),CV_8U,Scalar(0));73. drawContours(result,contours, //画出轮廓74. -1, // draw all contours75. Scalar(255), // in black76. 2); // with a thickness of 277.78.79. pair<Point,double> m=DetectInCircles(contours[index],image);80.81. cout<<m.first.x<<" "<<m.first.y<<" "<<m.second<<endl;82. circle(src,m.first,3,Scalar(0,0,255),2);83. circle(src,m.first,m.second,Scalar(0,0,255),1);84. namedWindow("result");85. imshow("result",src);86. waitKey(0);87.88. return 0;89. }结果:原图 dist_image 结果其中有⼀点需要注意:[cpp]view plaincopy1. distanceTransform(InputArray src, OutputArray dst, int distanceType, int maskSize)2.3. Parameters:4. src – 8-bit, single-channel (binary) source image.5. dst – Output image with calculated distances. It is a 32-bit floating-point, single-channel6. image of the same size as src .7. distanceType – Type of distance. It can be CV_DIST_L1, CV_DIST_L2 , or CV_DIST_C .8. maskSize – Size of the distance transform mask. It can be 3, 5, or CV_DIST_MASK_PRECISE9. (the latter option is only supported by the first function). In case of the CV_DIST_L1 or10. CV_DIST_C distance type, the parameter is forced to 3 because a 3 3 mask gives the same11. result as 5 5 or any larger aperture.12. labels – Optional output 2D array of labels (the discrete Voronoi diagram). It has the type13. CV_32SC1 and the same size as src . See the details below.dst为单通道的32-bit 浮点型矩阵,读取元素时需要⽤image.ptr<float>(i)[j],⽤imshow显⽰的时候需要⽤normalize(dist_image, magI, 0, 1, CV_MINMAX); 将float类型的矩阵转换到可显⽰图像范围 (float [0, 1]).。

opencv实现机器视觉检测和计数的方法

opencv实现机器视觉检测和计数的方法

opencv实现机器视觉检测和计数的⽅法引⾔在机器视觉中,有时需要对产品进⾏检测和计数。

其难点⽆⾮是对于产品的图像分割。

由于之前⽹购的维⽣素⽚,有时候忘了今天有没有吃过,就想对瓶⼦⾥的药⽚计数...在学习opencv以后,希望实现对于维⽣素⽚分割计数算法。

本次实战在基于形态学的基础上⼜衍⽣出基于距离变换的分⽔岭算法,使其实现的效果更具普遍性。

基于形态学的维⽣素⽚检测和计数整体思路:读取图⽚形态学处理(在⼆值化前进⾏适度形态学处理,效果俱佳)⼆值化提取轮廓(进⾏药⽚分割)获取轮廓索引,并筛选所需要的轮廓画出轮廓,显⽰计数opencv实现:int main(int argc, char** argv){Mat src, src_binary,dst,src_distance;src = imread("D:/opencv练习图⽚/维⽣素⽚机器视觉检测和计数.png");imshow("原图⽚", src);Mat kernel = getStructuringElement(MORPH_RECT, Size(16, 16), Point(-1, -1));morphologyEx(src, dst, MORPH_OPEN, kernel);imshow("形态学",dst);cvtColor(dst, dst, COLOR_RGB2GRAY);threshold(dst, src_binary, 100, 255, THRESH_OTSU);imshow("⼆值化", src_binary);vector<vector<Point>> contours;findContours(src_binary, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE, Point(0, 0));RNG rng(12345);double area;Point2i PL;for (size_t i = 0; i < contours.size(); i++){area = contourArea(contours[i]);if (area < 500)continue;PL = contours[i].front();Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));drawContours(src, contours, i, color, 2, 8);putText(src, to_string(i), PL, FONT_HERSHEY_COMPLEX, 1, color, 2);}imshow("计数结果", src);waitKey(0);return 0;}效果展⽰:由上图可以看的,原图在经过形态学处理后,可以去除很多细节,简化后续的药⽚分割操作。

基于TensorFlow的掌纹识别方法研究

基于TensorFlow的掌纹识别方法研究

基于TensorFlow的掌纹识别方法研究作者:王全来源:《价值工程》2018年第33期摘要:使用掌纹作为生物特征进行身份认证是近年来一门兴起的技术,本文提出一种基于TensorFlow的掌纹识别方法。

该方法首先应用TensorFlow Object Detection API使用Google ML Engine云计算技术对获取到的手掌图像进行训练,利用得到的模型在本地完成手掌检测;然后通过手掌检测获得的ROI,使用OpenCV得部分掌纹;最后采用TensorFlow自行编写的卷积神经网络,对提取到的掌纹图像进行训练,得到训练模型进行分类预测。

实验表明,该方法对比PCA、LBP等算法、得到了较高的识别率。

Abstract: Using palmprint as biometrics for identity authentication is a rising technology in recent years. This paper proposes a palmprint recognition method based on TensorFlow. The method first uses the TensorFlow Object Detection API to train the acquired palm image using Google ML Engine cloud computing technology. The palm can be detected locally by using the model. And then the ROI obtained by palm detection. Use OpenCV to get partial palmprint. Finally, the convolutional neural network constructed by TensorFlow is used. The extracted palmprint image is trained to obtain a training model for classification prediction. Experiments show that this method,compared with PCA, LBP and other algorithms, obtains a higher recognition rate.关键词:掌纹识别;卷积神经网络;手掌检测;掌纹提取Key words: palmprint recognition;convolutional neural networks;palm detection;palmprint extraction中图分类号:TP391 文献标识码:A 文章编号:1006-4311(2018)33-0169-030 引言掌纹识别是一种新颖的生物识别技术。

图像处理距离变换算法

图像处理距离变换算法

图像处理距离变换算法距离定义满⾜以下函数条件D(p,q)>=0,当且仅当p=q时D(p,q)=0;D(p,q)=D(q,p)D(p,r)<=D(p,q)+D(q,r)欧式距离D[(i,j),(k,h)]=((i-k)^2+(j-h)^2)^(1/2);城市街区距离只允许横向以及纵向的移动D[(i,j),(k,h)]=|i-k|+|j-h|;棋盘距离允许横向、纵向以及对⾓线上的移动D[(i,j),(k,h)]=max{|i-k|,|j-h|}算法实现步骤1.按照⼀种距离度量D,D是D4或D8,对⼤⼩为M*N的图像的⼀个⼦集S计算距离变换,建⽴⼀个M*N的数组F并作初始化:⼦集S中元素置为0,其他置为⽆穷。

2.按⾏遍历图像,从上到下,从左到右。

对于上⽅和左⾯的邻接像素设F(p)=min[F(p),D(p,q)+F(q)]。

3.按⾏遍历图像,从下到上,从右到左。

对于下⽅和右⾯的邻接像素设F(p)=min[F(p),D(p,q)+F(q)]。

4.数组F中得到的是⼦集S的斜切。

具体函数初始化函数void DistanceTransformD4(vector<vector<int>> &src, vector<vector<int>> &f){int cols = src[0].size();int rows = src.size();//初始化for (int i = 0; i < rows; ++i)for (int j = 0; j < cols; ++j)if (src[i][j] == 1)f[i][j] = 0;elsef[i][j] = INT_MAX - 2;//简单的防⽌溢出//按⾏遍历图像,从上到下,从左到右for (int i = 0; i < rows; ++i)for (int j = 0; j < cols; ++j)D4AL(i, j, rows, cols, f);//按⾏遍历图像,从下到上,从右到左for (int i = rows - 1; i >= 0; --i)for (int j = cols - 1; j >= 0; --j)D4BR(i, j, rows, cols, f);}左变换函数void D4AL(int i,int j, int rows, int cols, vector<vector<int>> &f){//上if (InArea(i - 1, j, rows, cols))f[i][j] = min(f[i][j], 1 + f[i - 1][j]);//左上if (InArea(i - 1, j - 1, rows, cols))f[i][j] = min(f[i][j], 2 + f[i - 1][j - 1]);//左if (InArea(i, j - 1, rows, cols))f[i][j] = min(f[i][j], 1 + f[i][j - 1]);//左下if (InArea(i + 1, j - 1, rows, cols))f[i][j] = min(f[i][j], 2 + f[i + 1][j - 1]);}右变换函数void D4BR(int i, int j, int rows, int cols, vector<vector<int>> &f) {//下if (InArea(i + 1, j, rows, cols))f[i][j] = min(f[i][j], 1 + f[i + 1][j]);//右下if (InArea(i + 1, j + 1, rows, cols))f[i][j] = min(f[i][j], 2 + f[i + 1][j + 1]);//右if (InArea(i, j + 1, rows, cols))f[i][j] = min(f[i][j], 1 + f[i][j + 1]);//右上if (InArea(i - 1, j + 1, rows, cols))f[i][j] = min(f[i][j], 2 + f[i - 1][j + 1]);}判断是否出界函数bool InArea(int i, int j, int rows, int cols){if (i<0 || i>=rows)return false;if (j<0 || j>=cols)return false;return true;}。

distancetransform用法

distancetransform用法

distancetransform用法distancetransform是一种图像处理算法,它可以计算每个像素点到离它最近的像素点的距离。

这个算法在很多应用中都有广泛的应用,比如目标检测、图像分割、形态学操作等等。

本文将介绍distancetransform的用法,并给出实例说明。

distancetransform 的基本原理是在输入图像中寻找相邻像素点之间的最短距离的过程。

算法的核心思想有两个关键点:- 首先,需要定义一个距离函数。

常用的距离函数有欧几里得距离(常用于灰度图像)和曼哈顿距离(常用于二值图像)等等,本文采用欧几里得距离。

- 其次,需要前向和后向一次扫描来确保每个像素点到离它最近的像素距离被计算。

这个算法的基本流程如下:- 首先,对输入图像进行阈值处理,将其二值化。

- 然后,对二值图像进行距离变换。

- 最后,对距离转换的结果进行处理,可进行形态学操作。

dst=cv2.distanceTransform(src, distType, maskSize)其中,src表示输入图像,distType表示距离转换类型,maskSize表示距离转换的卷积核大小。

- distType - 它指定距离变换的类型。

常用的类型有:- cv2.DIST_L1:曼哈顿距离- cv2.DIST_L2:欧几里得距离- cv2.DIST_C:切比雪夫距离- maskSize - 指定距离转换的卷积核大小。

常用的值为3或5。

dst是距离转换结果的输出数组。

3. 实例分析首先,我们需要准备一张图像。

在这个简单的示例中,我们使用一张长度和宽度都为200像素的灰度图像。

下面是我们将要使用的代码:import cv2import numpy as npfrom matplotlib import pyplot as pltimage = cv2.imread('image.jpg',0)plt.imshow(image,cmap='gray')plt.show()然后,我们需要将灰度图像二值化。

distancetransform函数

distancetransform函数

Distancetransform函数介绍在计算机视觉和图像处理领域中,distancetransform函数是一种常用的图像处理工具。

它用来计算二值图像中每个像素点到最近边界的距离。

这个函数的核心思想是根据像素点的位置来计算其与最近边界的距离,从而为图像提供更丰富的信息。

背景在许多图像处理的应用中,我们需要了解图像中各个像素点与图像边界的距离。

例如,在边缘检测算法中,我们常常需要知道每个像素点到最近边界的距离,以便进一步分析图像的边缘结构。

而在路径规划算法中,我们需要计算每个像素点到障碍物边界的距离,以便寻找到最短路径。

在这些应用中,distancetransform函数起到了关键的作用。

distancetransform函数的原理distancetransform函数的核心原理是计算每个像素点到最近边界的距离。

其主要思想可以归纳为以下几步:1.首先,需要将输入的二值图像进行一定的预处理操作。

例如,可能需要对图像进行二值化处理,将图像中的灰度值转换为二值(0和1)。

2.然后,根据二值图像中的像素点信息,计算每个像素点到最近边界的距离。

这个过程可以使用多种算法来实现,常见的有腐蚀操作、曼哈顿距离、欧氏距离等。

3.最后,将计算得到的距离信息存储在一个新的图像中,并返回该图像作为函数的输出结果。

distancetransform函数的算法实现distancetransform函数的实现可以使用多种算法。

以下是常见的一些算法:1. 腐蚀操作腐蚀操作是一种简单且有效的计算距离的方法。

它的基本思想是遍历图像中的每个像素点,对于每个像素点,计算它到最近边界的距离。

具体步骤如下:1.初始化一个与输入图像相同大小的距离图像,并将其中的元素值设置为一个较大的值(例如,无穷大)。

2.从左上角开始遍历图像中的每个像素点,对于每个像素点,计算它到最近边界的距离。

3.对于每个像素点,将其与邻域像素点的距离进行比较,取最小值作为该像素点的距离值。

opencv python 几何中心 距离变换

opencv python 几何中心 距离变换

opencv python 几何中心距离变换在OpenCV中,可以使用几何中心和距离变换来对图像进行处理。

1. 几何中心:可以使用函数`cv2.moments()`来计算图像的几何中心。

首先,需要将图像转换为灰度图像,然后使用`cv2.threshold()`函数对图像进行二值化处理。

接下来,可以使用`cv2.moments()`函数计算图像的矩,并使用矩计算图像的几何中心。

以下是一个示例代码:```pythonimport cv2import numpy as np# 读取图像image = cv2.imread('image.jpg')# 转换为灰度图像gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 二值化处理ret, binary = cv2.threshold(gray, 127, 255,cv2.THRESH_BINARY)# 计算图像的矩moments = cv2.moments(binary)# 计算图像的几何中心cX = int(moments["m10"] / moments["m00"])cY = int(moments["m01"] / moments["m00"])# 在图像上标出几何中心cv2.circle(image, (cX, cY), 5, (0, 255, 0), -1)# 显示图像cv2.imshow('image', image)cv2.waitKey(0)cv2.destroyAllWindows()```2. 距离变换:可以使用函数`cv2.distanceTransform()`来进行距离变换。

首先,将图像转换为灰度图像,并对图像进行二值化处理。

然后,可以使用`cv2.distanceTransform()`函数计算图像中每个像素距离最近的背景像素的距离。

opencv中距离变换原理

opencv中距离变换原理

opencv中距离变换原理opencv中的距离变换是一种图像处理技术,用于计算图像中每个像素点到离它最近的边界点的距离。

这种技术广泛应用于目标检测、图像分割和形态学等领域。

距离变换可以帮助我们定量地描述图像中的边界信息,从而实现更精确的图像分析和处理。

距离变换的原理是基于图像中的像素值和像素点之间的距离关系。

在距离变换过程中,首先需要对图像进行二值化处理,将目标区域设为白色,背景区域设为黑色。

然后,根据像素点的位置和像素值,计算每个像素点到离它最近的边界点的距离。

在opencv中,距离变换可以通过函数distanceTransform()实现。

这个函数接受一个二值化图像作为输入,然后根据距离变换的原理,计算每个像素点到离它最近的边界点的距离,并将距离值保存在输出图像中。

距离变换的原理可以简单描述为以下几个步骤:1. 首先,将图像进行二值化处理,得到目标区域和背景区域。

2. 对目标区域中的每个像素点,计算它到离它最近的边界点的距离。

如果像素点本身就是边界点,则距离为0。

3. 对背景区域中的每个像素点,计算它到离它最近的边界点的距离。

如果像素点本身就是边界点,则距离为0。

4. 将计算得到的距离值保存在输出图像中,可以用不同的灰度级表示不同的距离值。

距离变换的结果可以用来进行图像分析和处理。

例如,可以根据距离变换的结果进行边界提取,通过设置阈值可以得到不同的边界宽度。

此外,距离变换还可以用于形态学操作,如骨架提取和形态学重建等。

距离变换的优势在于它能够提供更准确的边界信息,进而提高图像分析和处理的精度。

它可以帮助我们定量地描述图像中的边界信息,并且能够应用于各种不同的图像处理任务中。

总结起来,opencv中的距离变换是一种计算图像中每个像素点到离它最近的边界点的距离的图像处理技术。

它的原理是基于像素值和像素点之间的距离关系,通过二值化图像和距离计算来实现。

距离变换的结果可以应用于边界提取、形态学操作等各种图像处理任务中,提高图像分析和处理的精度。

图像处理09对象检测--分水岭算法

图像处理09对象检测--分水岭算法

图像处理09对象检测--分⽔岭算法对象测量对象测量可以帮助我们进⾏矩阵计算:获取弧长与⾯积多边形拟合计算图⽚对象中⼼多边形拟合步骤:读取图⽚转换成灰度图⼆值化轮廓检测计算轮廓周长多边形拟合格式:cv2.approxPolyDP(curve, epsilon, closed, approxCurve=None)1参数:curve: 输⼊轮廓epsilon: 逼近曲率, 越⼩表⽰相似逼近越厉害closed: 是否闭合import cv2from matplotlib import pyplot as plt# 读取图⽚image = cv2.imread("tx.png")image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# ⼆值化ret, thresh = cv2.threshold(image_gray, 127, 255, cv2.THRESH_OTSU)# 计算轮廓contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)# 轮廓近似perimeter = cv2.arcLength(contours[0], True)approx = cv2.approxPolyDP(contours[0], perimeter * 0.1, True)# 绘制轮廓result1 = cv2.drawContours(image.copy(), contours, 0, (0, 0, 255), 2)result2 = cv2.drawContours(image.copy(), [approx], -1, (0, 0, 255), 2)# 图⽚展⽰f, ax = plt.subplots(1, 2, figsize=(12, 8))# ⼦图ax[0].imshow(cv2.cvtColor(result1, cv2.COLOR_BGR2RGB))ax[1].imshow(cv2.cvtColor(result2, cv2.COLOR_BGR2RGB))# 标题ax[0].set_title("contour")ax[1].set_title("approx")plt.show()计算对象中⼼cv2.moments()可以帮助我们得到轮距, 从⽽进⼀步计算图⽚对象的中⼼.格式:cv2.moments(array, binaryImage=None)1参数:array: 轮廓binaryImage: 是否把 array 内的⾮零值都处理为 1, 默认为 Noneimport numpy as npimport cv2# 读取图⽚image = cv2.imread("tx.png")image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# ⼆值化ret, thresh = cv2.threshold(image_gray, 0, 255, cv2.THRESH_OTSU)# 获取轮廓contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 遍历每个轮廓for i, contour in enumerate(contours):# ⾯积area = cv2.contourArea(contour)# 外接矩形x, y, w, h = cv2.boundingRect(contour)# 获取论距mm = cv2.moments(contour)print(mm, type(mm)) # 调试输出 (字典类型)# 获取中⼼cx = mm["m10"] / mm["m00"]cy = mm["m01"] / mm["m00"]# 获取cv2.circle(image, (np.int(cx), np.int(cy)), 3, (0, 255, 255), -1)cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2)# 图⽚展⽰cv2.imshow("result", image)cv2.waitKey(0)cv2.destroyAllWindows()# 保存图⽚cv2.imwrite("result1.jpg", image)分⽔岭算法分⽔岭算法 (Watershed Algorithm) 是⼀种图像区域分割算法. 在分割的过程中, 分⽔岭算法会把跟临近像素间的相似性作为重要的根据.分⽔岭分割流程:1. 读取图⽚2. 转换成灰度图3. ⼆值化4. 距离变换5. 寻找种⼦6. ⽣成 Marker7. 分⽔岭变换连通域连通域 (Connected Components) 指的是图像中具有相同像素且位置相邻的前景像素点组成的图像区域.cv2.connectedComponents(image, labels=None, connectivity=None, ltype=None)1参数:image: 输⼊图像, 必须是 uint8 ⼆值图像labels 图像上每⼀像素的标记, ⽤数字 1, 2, 3 表⽰分⽔岭算法会根据 markers 传⼊的轮廓作为种⼦, 对图像上其他的像素点根据分⽔岭算法规则进⾏判断, 并对每个像素点的区域归属进⾏划定. 区域之间的分界处的值被赋值为 -1. cv2.watershed(image, markers)参数:image: 输⼊图像markers: 种⼦, 包含不同区域的轮廓import numpy as npimport cv2from matplotlib import pyplot as pltdef watershed(image):"""分⽔岭算法"""# 卷积核kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))# 均值迁移滤波blur = cv2.pyrMeanShiftFiltering(image, 10, 100)# 转换成灰度图image_gray = cv2.cvtColor(blur, cv2.COLOR_BGR2GRAY)# ⼆值化ret1, thresh1 = cv2.threshold(image_gray, 0, 255, cv2.THRESH_OTSU)# 开运算open = cv2.morphologyEx(thresh1, cv2.MORPH_OPEN, kernel, iterations=2)# 膨胀dilate = cv2.dilate(open, kernel, iterations=3)# 距离变换dist = cv2.distanceTransform(dilate, cv2.DIST_L2, 3)dist = cv2.normalize(dist, 0, 1.0, cv2.NORM_MINMAX)print(dist.max())# ⼆值化ret2, thresh2 = cv2.threshold(dist, dist.max() * 0.6, 255, cv2.THRESH_BINARY)thresh2 = np.uint8(thresh2)# 分⽔岭计算unknown = cv2.subtract(dilate, thresh2)ret3, component = cv2.connectedComponents(thresh2)print(ret3)# 分⽔岭计算markers = component + 1markers[unknown == 255] = 0result = cv2.watershed(image, markers=markers)image[result == -1] = [0, 0, 255]# 图⽚展⽰image_show((image, blur, image_gray, thresh1, open, dilate), (dist, thresh2, unknown, component, markers, image)) return imagedef image_show(graph1, graph2):"""绘制图⽚"""# 图像1original, blur, gray, binary1, open, dilate = graph1# 图像2dist, binary2, unknown, component, markers, result = graph2f, ax = plt.subplots(3, 2, figsize=(12, 16))# 绘制⼦图ax[0, 0].imshow(cv2.cvtColor(original, cv2.COLOR_BGR2RGB))ax[0, 1].imshow(cv2.cvtColor(blur, cv2.COLOR_BGR2RGB))ax[1, 0].imshow(gray, "gray")ax[1, 1].imshow(binary1, "gray")ax[2, 0].imshow(open, "gray")ax[2, 1].imshow(dilate, "gray")# 标题ax[0, 0].set_title("original")ax[0, 1].set_title("image blur")ax[1, 0].set_title("image gray")ax[1, 1].set_title("image binary1")ax[2, 0].set_title("image open")ax[2, 1].set_title("image dilate")plt.show()f, ax = plt.subplots(3, 2, figsize=(12, 16))# 绘制⼦图ax[0, 0].imshow(dist, "gray")ax[0, 1].imshow(binary2, "gray")ax[1, 0].imshow(unknown, "gray")ax[1, 1].imshow(component, "gray")ax[2, 0].imshow(markers, "gray")ax[2, 1].imshow(cv2.cvtColor(result, cv2.COLOR_BGR2RGB))# 标题ax[0, 0].set_title("image distance")ax[0, 1].set_title("image binary2")ax[1, 0].set_title("image unknown")ax[1, 1].set_title("image component")ax[2, 0].set_title("image markers")ax[2, 1].set_title("result")plt.show()if __name__ == "__main__":# 读取图⽚image = cv2.imread("girl.png")# 分⽔岭算法result = watershed(image)# 保存结果cv2.imwrite("result.png", result)。

前沿距离水平测度方法

前沿距离水平测度方法

前沿距离水平测度方法前沿距离是一种常用的目标距离度量方法,用于衡量图像、模式或数据点之间的相似性或差异性。

它是将目标的边界与参考对象进行比较,从而计算它们之间的距离。

前沿距离的测度方法有很多,下面介绍一些常见的方法:1.像素计数法(PixelCountingMethod):这是最简单的前沿距离测度方法之一,它通过计算目标和参考对象之间的像素差异来度量距离。

具体来说,将目标像素和参考像素逐个比较,并计算它们之间的差异像素数量作为距离度量。

2.距离变换法(DistanceTransformMethod):距离变换是一种将二值化图像转化为灰度图像的方法,其中每个像素的灰度值表示该像素到最近目标边界的距离。

通过计算目标和参考对象图像的距离变换图像之间的差异,可以得到前沿距离。

3.轮廓匹配法(ContourMatchingMethod):这种方法将目标和参考对象的边界提取出来,然后通过计算两个轮廓之间的差异来度量距离。

常见的轮廓差异度量指标有欧氏距离、曼哈顿距离、Hausdorff距离等。

4.形状上下文法(ShapeContextMethod):形状上下文是一种用于描述和比较轮廓形状的特征向量。

通过计算目标和参考对象的形状上下文之间的差异,可以得到前沿距离。

这种方法在形状匹配和目标识别中被广泛应用。

5.神经网络法(NeuralNetworkMethod):近年来,随着深度学习的兴起,神经网络在前沿距离测度中也得到了应用。

通过训练一个神经网络,将目标图像和参考对象图像作为输入,输出它们之间的距离。

这种方法在一些特定的任务中表现出了很好的效果。

总之,前沿距离是一种重要的距离度量方法,具有广泛的应用领域,如图像处理、模式识别、计算机视觉等。

不同的方法适用于不同的场景,选择合适的方法能够有效地衡量目标之间的相似性或差异性。

halcon 聚类算法

halcon 聚类算法

Halcon 聚类算法1. 简介Halcon是一款广泛应用于机器视觉领域的软件库,提供了丰富的图像处理和分析功能。

其中,聚类算法是Halcon中重要的一部分,用于将数据集划分为不同的群组。

本文将介绍Halcon中常用的聚类算法及其应用。

2. K-Means 聚类算法K-Means是一种常见的聚类算法,它通过将数据集划分为K个簇来实现聚类。

该算法具有简单、高效的特点,并且在实际应用中广泛使用。

2.1 算法原理K-Means算法基于以下几个步骤:1.随机选择K个初始聚类中心。

2.将每个样本点分配到距离最近的聚类中心。

3.根据每个簇内样本点的均值更新聚类中心。

4.重复步骤2和3,直到收敛或达到最大迭代次数。

2.2 Halcon中使用K-Means算法在Halcon中,可以使用kmeans_clustering函数来执行K-Means聚类算法。

该函数需要指定输入数据集、簇数目以及其他参数。

以下是使用Halcon进行K-Means聚类的示例代码:read_image(Image, 'image.jpg')convert_image_type(Image, 'byte')reduce_domain(Image, ImageReduced)features := create_feature_set()add_features_object(features, ImageReduced, 7)kmeans_clustering(features, 4, KMeansHandle)get_clusters(KMeansHandle, Clusters)上述代码首先读取图像并将其转换为灰度图像,然后使用reduce_domain函数减少领域以提高聚类性能。

接下来,创建一个特征集并将图像添加到特征集中。

最后,使用kmeans_clustering函数执行聚类并获取聚类结果。

3. DBSCAN 聚类算法DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一种基于密度的聚类算法,它能够发现任意形状的簇,并且对噪声数据具有较好的鲁棒性。

【CN110083300A】一种基于距离变化的手势数据提取方法【专利】

【CN110083300A】一种基于距离变化的手势数据提取方法【专利】

(19)中华人民共和国国家知识产权局(12)发明专利申请(10)申请公布号 (43)申请公布日 (21)申请号 201910275266.X(22)申请日 2019.04.08(71)申请人 南京航空航天大学地址 210016 江苏省南京市秦淮区御道街29号(72)发明人 许舒晨 孙永荣 孙亚飞 赵伟 (74)专利代理机构 南京经纬专利商标代理有限公司 32200代理人 刘莎(51)Int.Cl.G06F 3/0488(2013.01)G06F 3/042(2006.01)(54)发明名称一种基于距离变化的手势数据提取方法(57)摘要本发明公开了一种基于距离变化的手势数据提取方法,通过获取手势形状的极值点,以手势形状的极值点作为骨架,提取相同数目的有效触点来表示触点数目差异较大的不同手势,提取的有效触点最大程度保持手势的原形状。

权利要求书2页 说明书4页 附图4页CN 110083300 A 2019.08.02C N 110083300A权 利 要 求 书1/2页CN 110083300 A1.一种基于距离变化的手势数据提取方法,每一条所述手势数据均是数量不固定的坐标式的触点数据集合,所述坐标式的触点数据使用神经网络进行识别,其特征在于,该方法包括如下步骤:步骤1,获取触控屏的手势数据,对每一条手势数据分别进行预处理;步骤2,对每一条预处理后的手势数据,寻找其中的极值点;步骤3,对每一条预处理后的手势数据,计算除手势起始点外所有触点到手势起始点之间的折线距离;步骤4,根据预提取点数目,计算每个预提取点到手势起始点之间的折线距离;步骤5,在每一条预处理后的手势数据中,选取正式提取点;步骤6,在步骤5得到的正式提取点中插入极值点,得到的触点集合即为最终有效触点集合;步骤7,输出最终有效触点,完成手势数据提取。

2.根据权利要求1所述的一种基于距离变化的手势数据提取方法,其特征在于,步骤1的每一条手势数据中,每个触点包含其坐标信息和采集时间信息,坐标信息为该触点相对触控屏左下角的X坐标和Y坐标,由采集时间信息确定集合中的触点顺序以判断手势的方向。

《图像处理实例》之中轴线提取

《图像处理实例》之中轴线提取

《图像处理实例》之中轴线提取中轴线算法这是的作者原创,我只是对其理解之后改进和说明,欢迎⼤家使⽤这个⼩软件!如果有需要C++版本的朋友,可以博⽂结尾留邮箱!⾸先上效果图:算法的流程: 第⼀步: 距离变换 第⼆步: 把距离变换的图像进⾏像素值的排列(排列返回像素的位置信息) 第⼆步: 从⼩到⼤进⾏像素的查表操作 注释:这⾥为什么叫中轴线提取?因为提取的过程是绝对的按照对称来的,距离变换的结果就是前景到背景的距离,所以结果是绝对的集合中⼼。

Python代码:1import numpy as np2from skimage.data import horse, camera3import matplotlib.pyplot as plt4import scipy.ndimage as ndimg5from numba import jit6import cv27from scipy.ndimage import label, generate_binary_structure89 strc = np.ones((3, 3), dtype=np.bool)101112# check whether this pixcel can be removed13def check(n):14 a = [(n >> i) & 1 for i in range(8)]15 a.insert(4, 0) # make the 3x3 unit16# if up, down, left, right all are 1, you cannot make a hole17# if a[1] & a[3] & a[5] & a[7]:return False18 a = np.array(a).reshape((3, 3))19# segments20 n = label(a, strc)[1]21# if sum is 0, it is a isolate point, you cannot remove it.22# if number of segments > 2, you cannot split them.23return n < 224return a.sum() > 1 and n < 225if a.sum() == 1 or n > 2: return 226if a.sum() > 1 and n < 2: return 127return 0282930 lut = np.array([check(n) for n in range(256)])31 lut = np.dot(lut.reshape((-1, 8)), [1, 2, 4, 8, 16, 32, 64, 128]).astype(np.uint8)32'''33lut = np.array([200, 206, 220, 204, 0, 207, 0, 204, 0, 207, 221, 51, 1, 207, 221, 51, 34 0, 0, 221, 204, 0, 0, 0, 204, 1, 207, 221, 51, 1, 207, 221, 51], dtype=np.int8) 35'''363738 @jit39def skel2dp(data, idx, lup):40 h, w = data.shape41 data = data.ravel()42for id in idx:4344if data[id] == 0: continue45 i2 = id - w46 i8 = id + w47 i1 = i2 - 148 i3 = i2 + 149 i4 = id - 150 i6 = id + 151 i7 = i8 - 152 i9 = i8 + 153 c = (data[i1] > 0) << 0 | (data[i2] > 0) << 1 \54 | (data[i3] > 0) << 2 | (data[i4] > 0) << 3 \55 | (data[i6] > 0) << 4 | (data[i7] > 0) << 5 \56 | (data[i8] > 0) << 6 | (data[i9] > 0) << 757if (lup[c // 8] >> c % 8) & 1: data[id] = 058return 0596061def mid_axis(img):62 dis = ndimg.distance_transform_edt(img)63 idx = np.argsort(dis.flat).astype(np.int32)64 skel2dp(dis, idx, lut)65return dis666768from time import time69 img = ~horse()*25570#img = cv2.imread('123.jpg')71#img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)72#ret2, img = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)73 dis = ndimg.distance_transform_edt(img)74 plt.imshow(dis)75 idx = np.argsort(dis.flat).astype(np.int32)76 a = skel2dp(dis, idx, lut)77#mid_axis(img.copy())78 t1 = time()79 a = mid_axis(img)80 t2 = time()81print(t2 - t1)82 plt.imshow(a)83 plt.show()C++代码:1void center_axis(InputArray _src, Mat& dst)2 {3 typedef struct MyStruct4 {5 Point position;6float num;7 }MyStruct;8int wjy_array[] = { 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1,91, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1,100, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1,111, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1,121, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,141, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1,150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,160, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1,171, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1,180, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1,191, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,201, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,211, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,221, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0,231, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0 };24 uchar lut[] = { 200, 206, 220, 204, 0, 207, 0, 204, 0, 207, 221, 51, 1, 207, 221, 51,250, 0, 221, 204, 0, 0, 0, 204, 1, 207, 221, 51, 1, 207, 221, 51 };26 Mat src = _src.getMat();27//Mat dst = _dst.getMat();28 distanceTransform(src, src, DIST_L2, DIST_MASK_3, 5);29 normalize(src, src, 0, 255, NORM_MINMAX);30 Mat img_row = src.reshape(0, 1);31 vector<MyStruct> my_vector;32for (size_t j = 0; j < img_row.cols; j++)33 {34if (img_row.at<float>(0, j) == 0) continue;35 MyStruct my_struct;36 my_struct.num = saturate_cast<float>(img_row.at<float>(0, j));37 my_struct.position = Point(saturate_cast<int>(j % src.cols), saturate_cast<int>(j / src.cols));38 my_vector.push_back(my_struct);39 }40for (size_t i = 0; i < my_vector.size(); i++)41 {42if (my_vector[i].num == 0) continue;43for (size_t j = i; j < my_vector.size(); j++)44 {45 MyStruct temp;46if (my_vector[i].num >= my_vector[j].num)47 {48if (my_vector[j].num == 0) continue;49 temp = my_vector[j];50 my_vector[j] = my_vector[i];51 my_vector[i] = temp;52 }53 }54 }55for (size_t i = 0; i < my_vector.size(); i++)56 {57if (my_vector[i].position.y == 158 || my_vector[i].position.x == 159 || my_vector[i].position.y == src.rows - 160 || my_vector[i].position.x == src.cols - 161 || src.at<float>(my_vector[i].position.y, my_vector[i].position.x) == 0) continue;62else63 {64char num[] = { 1,1,1,1,1,1,1,1 };65 num[0] = src.at<float>(my_vector[i].position.y - 1, my_vector[i].position.x - 1)66 > 0 ? 1 : 0;67 num[1] = src.at<float>(my_vector[i].position.y - 1, my_vector[i].position.x)68 > 0 ? 1 : 0;69 num[2] = src.at<float>(my_vector[i].position.y - 1, my_vector[i].position.x + 1)70 > 0 ? 1 : 0;71 num[3] = src.at<float>(my_vector[i].position.y, my_vector[i].position.x - 1)72 > 0 ? 1 : 0;73 num[4] = src.at<float>(my_vector[i].position.y, my_vector[i].position.x + 1)74 > 0 ? 1 : 0;75 num[5] = src.at<float>(my_vector[i].position.y + 1, my_vector[i].position.x - 1)76 > 0 ? 1 : 0;77 num[6] = src.at<float>(my_vector[i].position.y + 1, my_vector[i].position.x)78 > 0 ? 1 : 0;79 num[7] = src.at<float>(my_vector[i].position.y + 1, my_vector[i].position.x + 1)80 > 0 ? 1 : 0;81int sum = num[0] + num[1] * 2 + num[2] * 4 + num[3] * 882 + num[4] * 16 + num[5] * 32 + num[6] * 64 + num[7] * 128;83 src.at<float>(my_vector[i].position.y, my_vector[i].position.x) = ((lut[uchar(sum / 8)] >> sum % 8) & 1) != 1 ? 255 : 0;84 }85 }86 dst = src.clone();87 dst.convertTo(dst, CV_8UC1);88 }。

距离图像局部特征提取方法综述

距离图像局部特征提取方法综述
are
mnge images and their representations including the methods
are
are
introduced,
sud’ace
no瑚al,
the
cun,ature
the local feature detection And the local feature
万方数据
模式识别与人工智能
25卷



色图像和二维灰度图像∽J.从数学角度看,二维彩 色图像(colored Image)是一个五维矢量[M。,可;,R。,
近年来,随着三维(3D)成像技术如激光雷达和 结构光主动成像等的快速发展,距离图像的获得变 得越来越便捷.距离图像反映物体的三维空间几何 形状信息,相对于二维图像而言,其不受光照、视点 和尺度变化等¨屯。因素的影响,有望克服二维图像 目标识别中存在的诸多瓶颈,目前已在人脸识 别∞。j、人耳识别∽J、人头识别∽j、三维模型建 模n0]、自主驾驶Ⅲ1以及导航与制导‘12—41等领域得 到广泛关注,成为新的研究热点.
242.6
SurVey of Local Feature Extraction
On
Range hnages
GUO Yu—Lanl”,LU Minl,TAN Zhi.Gu01,WAN Jian一Ⅵkil
1(c0Z如ge矿Eze甜ron记&iewe口nd胁i凡卯矗增,肫fio乃oz‰如e瑙渺矿D咖瑚e‰^加觇fy,
为面片数. 受自遮挡的影响,一个视点下获得的距离图像
分割且三维数据完整,因而应用范围受限.局部特征
对遮挡和背景干扰有很强的适应性¨7I,被广泛应用
于距离图像配准、三维建模和目标识别中,成为当前 研究的热点,因而本文将只对局部特征提取方法进
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

基于distanceTransform-距离变换的区域中心提取
这几天在做一个手势识别的项目,其中最的关键一步是提取手掌中心。

获得手掌重心通常的做法是计算整个手部的重心,并以该重心位置近似手掌重心,这种方法只适用于没有手指伸出或只有一个手指伸出的情况,否则获得的手掌重心位置将严重偏离真实位置。

距离变换的基本含义是计算一个图像中非零像素点到最近的零像素点的距离,也就是到零像素点的最短距离。

因此可以基于距离变换提取手掌重心。

算法基本思想:
(1)将手掌图像二值化,手掌内的区域设为白色,外部区域设为黑色。

(2)将二值化后的图像经过distanceTransform变换,得到dist_image,其中每个像素点的值是该像素点到其最近的零像素点的距离。

(3)找到dist_image的最大值(即圆的半径R),并记录下位置(即圆心坐标)。

代码如下:
[cpp] view plaincopy#include "opencv2/opencv.hpp"
#include &lt;opencv2/core/core.hpp&gt; #include
&lt;opencv2/highgui/highgui.hpp&gt; #include
&lt;opencv2/imgproc/imgproc.hpp&gt; #include
&lt;vector&gt; using namespace cv; using namespace std; pair&lt;Point,double&gt; DetectInCircles(vector&lt;Point&gt; contour,Mat src)
{ Mat dist_image;
distanceTransform(src,dist_image,CV_DIST_L2,3);
int temp=0,R=0,cx=0,cy=0; int d; for (int
i=0;i&lt;src.rows;i++) for (int j=0;j&lt;src.cols;j++) { /* checks if the point is inside the contour. Optionally computes the signed distance from the point to the contour boundary*/ d = pointPolygonTest(contour, Point2f(j, i), 0); if (d&gt;0)
{ temp=(int)dist_image.ptr&lt;float&gt;(i )[j]; if (temp&gt;R)
{ R=temp;
cy=i;
cx=j; }
} }
return make_pair(Point(cx,cy),R); } int main() { // Read input binary image
Mat src= imread("D:\\mycode\\6.jpg",1); Mat image; cvtColor(src,image,CV_BGR2GRAY);
vector&lt;vector&lt;Point&gt;&gt; contours;
//findContours的输入是二值图像
findContours(image, contours, // a vector of contours CV_RETR_EXTERNAL, // retrieve the external contours
CV_CHAIN_APPROX_NONE); // retrieve all pixels of each contours // Print contours' length轮廓的个数cout &lt;&lt; "Contours: " &lt;&lt; contours.size() &lt;&lt; endl; vector&lt;vector&lt;Point&gt;&gt;::const_iterator
itContours= contours.begin(); for ( ;
itContours!=contours.end(); ++itContours)
{ cout &lt;&lt; "Size: " &lt;&lt;
itContours-&gt;size() &lt;&lt; endl;//每个轮廓包含的点
数} //找到最大轮廓int
index=0,maxArea=0; for(unsigned int
i=0;i&lt;contours.size();i++) { int
area=contourArea(contours[i]); if
(area&gt;maxArea) { index=i; maxArea=area; } } // draw black contours on white image Mat
result(image.size(),CV_8U,Scalar(0));
drawContours(result,contours, //画出轮廓
-1, // draw all contours Scalar(255), // in black 2); // with a thickness of 2
pair&lt;Point,double&gt;
m=DetectInCircles(contours[index],image);
cout&lt;&lt;m.first.x&lt;&lt;" "&lt;&lt;m.first.y&lt;&lt;"
"&lt;&lt;m.second&lt;&lt;endl;
circle(src,m.first,3,Scalar(0,0,255),2);
circle(src,m.first,m.second,Scalar(0,0,255),1); namedWindow("result"); imshow("result",src); waitKey(0); return 0; } 结果:
原图dist_image 结果
其中有一点需要注意:
[cpp] view plaincopydistanceTransform(InputArray src, OutputArray dst, int distanceType, int maskSize)
Parameters:src – 8-bit, single-channel (binary) source image. dst – Output image with calculated distances. It is a 32-bit floating-point, single-channel image of the same size as src . distanceType – Type of distance. It can be CV_DIST_L1, CV_DIST_L2 , or CV_DIST_C . maskSize – Size of the distance transform mask. It can be 3, 5, or CV_DIST_MASK_PRECISE (the latter option is only supported by the first function). In case of the CV_DIST_L1 or CV_DIST_C distance type, the parameter is forced to 3 because a 3 3 mask gives the same result as 5 5 or any larger aperture. labels – Optional output 2D array of labels (the discrete Voronoi diagram). It has the type
CV_32SC1 and the same size as src . See the details below. dst为单通道的32-bit 浮点型矩阵,读取元素时需要用image.ptr&lt;float&gt;(i)[j],用imshow显示的时候需要用normalize(dist_image, magI, 0, 1, CV_MINMAX); 将float类型的矩阵转换到可显示图像范围(float [0, 1]).
另外还有一个博客值得参考:
/wuhaibing_cver/article/details/8602461。

相关文档
最新文档