一、目标轮廓的获取与绘制
通常,使用findContours() 函数是为了获取一张图像内目标对象的所有轮廓,并且在 OpenCV4.x 版本中,findContours() 函数的返回值发生了变化。参数列表不列举了,下面直接给出最常用的一种语法:
// python
contours, _ = cv2.findContours(label, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
// C++
vector<std::vector<cv::Point>> contours;
cv::findContours(label, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
label:输入图,最好是二值图
cv2.RETR_EXTERNAL: 只检测最外层轮廓
cv2.CHAIN_APPROX_SIMPLE:压缩水平方向、垂直方向和对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保持轮廓信息。
调试阶段,为了直观显示出轮廓,可使用drawContours()函数进行轮廓绘制。
cv::drawContours(img, contours, -1, cv::Scalar(71, 206, 255), 1);
cv::imshow("output_contours", img);
第三个参数为要绘制的轮廓数量,负数-1则表示全部绘制
第四个参数为轮廓的颜色
第五个参数为轮廓的粗细
后面还有参数,但都采用默认值即可
此外,还可以使用 rectangle函数 来绘制矩形边框,fillPoly函数 来填充目标区域。
二、轮廓的信息(面积和周长)
检测完所有最外层轮廓后,通常还需要筛选、去除掉一些不需要的轮廓。其中,轮廓的面积是一个常用的判别值,
OpenCV提供了contourArea()函数来直接计算面积:
// python
contours, _ = cv2.findContours(label, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for contour in contours:
area = cv2.contourArea(contour)
if (area < 1000):
continue
// C++
vector<std::vector<cv::Point>> contours;
cv::findContours(label, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
for (int i = 0; i < contours.size(); i++)
{
double area = cv::contourArea(contours[i]);
if (area > 1000)
{
continue;
}
}
此外,OpenCV还提供了一个计算轮廓周长的函数arcLength(),用法和计算面积函数是一样的。但实际用处不大,毕竟轮廓的周长并不能说明什么。
三、轮廓外接形状的三种表达方式
获得目标轮廓后,有三种处理方式:1)最小外接斜矩阵。 2)最大外接正矩阵。 3)逼近多边形。 前两种是最为常用的处理方式,毕竟矩阵信息在后续处理中比较方便。
目标轮廓的使用在图像分割项目中很常见,因为分割的标签图是一个可以完美检测目标轮廓的二值图。三种处理使用的函数和常用方式如下:文章来源:https://www.toymoban.com/news/detail-740810.html
image = cv2.imread('C:/Users/train/view4_20230616130920_2.jpg')
label = cv2.imread('C:/Users/mask/view4_20230616130920_2.png',0)
contours, _ = cv2.findContours(label, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for contour in contours:
# 1、最小外接斜矩阵(带角度)
# rect = cv2.minAreaRect(contour) # 计算轮廓的最小外接矩形
# box = cv2.boxPoints(rect) # 获取旋转矩形的四个顶点坐标
# box = np.int0(box) # 将顶点坐标转换为整数
#
# (cx,cy), (boxW, boxH), angle = rect # (中心点),(宽高),角度
#
# cv2.drawContours(image, [box], -1, (0,255,0), 2) # 要绘制的轮廓必须是一个列表,所以是[box]
# cv2.fillPoly(label, np.array([contour]), 255) # 将目标轮廓区域填充为白色
# 2、最大外接正矩阵
x, y, width, height = cv2.boundingRect(contour) # (左上角坐标,宽,高)
cv2.rectangle(image, (x, y), (x + width, y + height), (0, 255, 0), 2)
# 3、多边形
# epsilon = 0.01 * cv2.arcLength(contour, True) # 常用轮廓的周长(或弧长)的百分比作为 epsilon 的值
# approx = cv2.approxPolyDP(contour, epsilon, True) # epsilon表示逼近后的多边形与原始轮廓之间的最大距离,True表示将轮廓视为闭合
# cv2.drawContours(image, [approx], 0, (0, 255, 0), 2)
cv2.imshow("Contours", image)
cv2.imshow("Contours——mask", label)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.minAreaRect函数获取最小外接斜矩阵,它的返回值为:(中心点),(宽高),角度。若只需要获取矩形坐标,可使用cv2.boxPoints函数来得到矩形的四个顶点坐标。
该函数获得返回的角度有一个应用,就是之前博客讲的仿射变换,它返回的中心点和角度可以作为仿射变换矩阵的参数:M = cv2.getRotationMatrix2D((cx, cy), angle, 1) ,这样我们可以将有角度的目标进行仿射变换旋转,让其处于水平方向。文章来源地址https://www.toymoban.com/news/detail-740810.html
到了这里,关于OpenCV(应用) —— 目标轮廓的相关应用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!