OPENCV之寻找并绘制轮廓以及提取轮廓重心坐标 您所在的位置:网站首页 坐标系中重心公式 OPENCV之寻找并绘制轮廓以及提取轮廓重心坐标

OPENCV之寻找并绘制轮廓以及提取轮廓重心坐标

2023-08-31 18:20| 来源: 网络整理| 查看: 265

OPENCV之寻找并绘制轮廓以及提取轮廓重心坐标 1、寻找轮廓

声明:在寻找图像轮廓之前需要对图像进行阈值分割或者Canny、拉普拉斯等边缘检测算子处理。

寻找轮廓的算子:

findContours(InputOutputArray image, OutputArrayOfArrays contours,OutputArray hierarchy, int mode, int method, Point offset = Point());

(1)单通道图像,可以是灰度图,常用的是二值图像;

(2)contours是一个双重向量(向量内每个元素保存了一组由连续的Point构成的点的集合的向量),每一组点集就是一个轮廓,有多少轮廓,contours就有多少元素。其定义为“vector contours”;

(3)hierarchy也是一个向量,向量内每个元素保存了一个包含4个int整型的数组。其定义为“vector hierarchy”,其中是Vec的别名,定义了一个“向量内每一个元素包含了4个int型变量”的向量。

        hierarchy向量内每一个元素的4个int型变量——hierarchy[i][0] ~hierarchy[i][3],分别表示第 i个轮廓的后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号。如果当前轮廓没有对应的后一个轮廓、前一个轮廓、父轮廓或内嵌轮廓的话,则hierarchy[i][0] ~hierarchy[i][3]的相应位被设置为 默认值-1。

(4)轮廓的检索方式,opencv提供了四种方法,解释如下:

                 CV_RETR_EXTERNAL:只检测最外围轮廓,包含在外围轮廓内的内围轮廓被忽略;

                CV_RETR_LIST:检测所有的轮廓,包括内围、外围轮廓,但是检测到的轮廓不建立等级关系,彼此之间独立,没有等级关系,这就意味着这个检索模式下不存在父轮廓或内嵌轮廓,所 以hierarchy向量内所有元素的第3、第4个分量都会被置为-1,具体下文会讲到;

                CV_RETR_CCOMP: 检测所有的轮廓,但所有轮廓只建立两个等级关系,外围为顶层,若外围内的内围轮廓还包含了其他的轮廓信息,则内围内的所有轮廓均归属于顶层;

                CV_RETR_TREE: 检测所有轮廓,所有轮廓建立一个等级树结构。外层轮廓包含内层轮廓,内层轮廓还可以继续包含内嵌轮廓。

(5)轮廓的近似方法,opencv提供了四种方法,解释如下:

                CV_CHAIN_APPROX_NONE:保存物体边界上所有连续的轮廓点到contours向量内;

                CV_CHAIN_APPROX_SIMPLE:仅保存轮廓的拐点信息,把所有轮廓拐点处的点保存入contours向量内,拐点与拐点之间直线段上的信息点不予保留;

                CV_CHAIN_APPROX_TC89_L1:使用teh-Chinl chain 近似算法;

                CV_CHAIN_APPROX_TC89_KCOS:使用teh-Chinl chain 近似算法。

(6)Point偏移量,所有的轮廓信息相对于原始图像对应点的偏移量,相当于在每一个检测出的轮廓点上加上该偏移量,并且Point还可以是负值!

详细解释可参考: findContours函数参数详解

2、绘制轮廓

绘制轮廓的算子:

drawContours( InputOutputArray image, InputArrayOfArrays contours,int contourIdx, const Scalar& color, int thickness = 1, int lineType = LINE_8, InputArray hierarchy = noArray(), int maxLevel = INT_MAX, Point offset = Point() );

 (1)目标图像;

(2)所有的输入轮廓。每个轮廓都被存储为一个点向量,其定义与findContours的参数2相同;

(3)指示要绘制哪条轮廓的索引数。如果它是负的,就画出所有的轮廓线;

(4)指定绘制轮廓的颜色;

(5)指定轮廓线的粗细。如果它是负的,则绘制轮廓内部(经测试,为负值情况下轮廓内部完全被涂成设定的轮廓线颜色);

(6)指定轮廓线的类型,参考LineTypes,一般设定为8,即LINE_8;

(7)层次结构的可选信息。只在你想画某些指定的轮廓的时候才需要进行设置;

(8)绘制轮廓的最大数量。如果它是0,则只绘制指定的轮廓线。如果为1,则绘制轮廓线和所有嵌套轮廓线。如果它是2,则绘制轮廓线、所有嵌套轮廓线、所有嵌套到嵌套轮廓线等。该参数只有在存在层次结构时才被考虑在内。(与轮廓检索方式即findContours的参数4有关)

(9)轮廓点的偏移量。

3、提取轮廓重心坐标

说明:形状轮廓重心坐标的提取主要是利用图像的矩来计算。

什么是图像的矩?把图像的像素看做密度函数f(x,y),对该像素点求期望E,即是图像的矩(原点矩)。公式如下:

原点矩:

 图像的矩主要表征了图像区域的几何特征,又称几何矩,由于具有旋转、平移、尺度等不变的特兴奋,所以又称为不变矩。一般来说,一阶矩和零阶矩可以计算某个形状的重心,二阶矩可以计算形状的方向。

关于矩以及图像矩的详细解释可以参考:矩、中心矩、质心、patch方向

提取重心坐标方法:

//声明一个图像的矩 Moments M; //计算要绘制轮廓的矩 M = moments(contours[i]); //求取轮廓重心的X坐标 double cX = double(M.m10 / M.m00); //求取轮廓重心的Y坐标 double cY = double(M.m01 / M.m00);

关于m10、m01、m00的解释:

关于重心坐标的求解过程的详细解释可以参考: 中心距求解

4、示例

示例代码:

Mat img = imread("C:\\Users\\SUNSONG\\Desktop\\图片\\Image_02.PNG"); Mat gray_img, thresh_img; //灰度 cvtColor(img, gray_img, COLOR_BGR2GRAY); threshold(gray_img, thresh_img, 0, 255, THRESH_TRIANGLE); //开运算 Mat ellipse = getStructuringElement(MORPH_ELLIPSE, Size(13, 13)); morphologyEx(thresh_img, thresh_img, MORPH_OPEN, ellipse, Point(-1, -1), 2); ************以上为图像处理过程**************************************** //寻找轮廓 vector contours; vector hierarchy1; findContours(thresh_img, contours, hierarchy1, RETR_LIST, CHAIN_APPROX_NONE, Point()); //获取某一轮廓重心点 Moments M; M = moments(contours[0]); double cX = double(M.m10 / M.m00); double cY = double(M.m01 / M.m00); //绘制轮廓 drawContours(img, contours, 0, Scalar(0, 255, 0), 2, 8, hierarchy1); //显示轮廓重心并提取坐标点 circle(img, Point2d(cX, cY), 1, Scalar(0, 255, 0), 2, 8); putText(img, "center", Point2d(cX - 20, cY - 20), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0), 1, 8); cout


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有