• OpenCV(应用) —— 目标轮廓的相关应用



    一、目标轮廓的获取与绘制

    通常,使用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个点来保持轮廓信息。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    调试阶段,为了直观显示出轮廓,可使用drawContours()函数进行轮廓绘制

    	cv::drawContours(img, contours, -1, cv::Scalar(71, 206, 255), 1);
    	cv::imshow("output_contours", img);
    
    第三个参数为要绘制的轮廓数量,负数-1则表示全部绘制
    第四个参数为轮廓的颜色
    第五个参数为轮廓的粗细
    后面还有参数,但都采用默认值即可
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    此外,还可以使用 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;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    此外,OpenCV还提供了一个计算轮廓周长的函数arcLength(),用法和计算面积函数是一样的。但实际用处不大,毕竟轮廓的周长并不能说明什么。

    三、轮廓外接形状的三种表达方式

    获得目标轮廓后,有三种处理方式:1)最小外接斜矩阵。 2)最大外接正矩阵。 3)逼近多边形。 前两种是最为常用的处理方式,毕竟矩阵信息在后续处理中比较方便。

      目标轮廓的使用在图像分割项目中很常见,因为分割的标签图是一个可以完美检测目标轮廓的二值图。三种处理使用的函数和常用方式如下:

    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()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

      cv2.minAreaRect函数获取最小外接斜矩阵,它的返回值为:(中心点),(宽高),角度。若只需要获取矩形坐标,可使用cv2.boxPoints函数来得到矩形的四个顶点坐标。
      该函数获得返回的角度有一个应用,就是之前博客讲的仿射变换,它返回的中心点和角度可以作为仿射变换矩阵的参数:M = cv2.getRotationMatrix2D((cx, cy), angle, 1) ,这样我们可以将有角度的目标进行仿射变换旋转,让其处于水平方向。

  • 相关阅读:
    【CV】第 16 章:结合计算机视觉和强化学习
    C++中或运算符(||)执行的逻辑及顺序
    令人拍案叫绝的算法学习网站,算法入门到精通,算法面试冲刺资料这里都有
    python 之计算矩阵乘法
    ISO20000认证流程是什么,ISO20000认证好处
    第十五章 插口层
    使用doctest代码测试和Sphinx自动生成文档
    基于LSTM和SVM的设备故障诊断(Matlab代码实现)
    【C++面向对象】8. 继承
    CSDN周年纪念日练习汇总帖
  • 原文地址:https://blog.csdn.net/qq_43199575/article/details/133904265