zoukankan      html  css  js  c++  java
  • 图像轮廓检测


    一、轮廓概念

    轮廓和边缘的区别:

    边缘主要是反映梯度的变化,可以是零零散散的线条;
    轮廓是一个整体;


    findContours 方法说明

    findContours(image, mode, method[, contours[, hierarchy[, offset]]]) -> contours, hierarchy

    • mode:轮廓检索模式

      • RETR_EXTERNAL :只检索最外面的轮廓;
      • RETR_LIST: 检索所有的轮廓,并将其保存到一条链表当中;
      • RETR_CCOMP:检索所有的轮廓,并将他们组织为两层:顶层是各部分的外部边界,第二层是空洞的边界;
      • RETR_TREE:检索所有的轮廓,并重构嵌套轮廓的整个层次; (最常用)
    • method:轮廓逼近方法

      • CHAIN_APPROX_NONE:以Freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列)。
      • CHAIN_APPROX_SIMPLE:压缩水平的、垂直的和斜的部分,也就是,函数只保留他们的终点部分。

    出参:

    • contours:轮廓信息
    • hierarchy:层级

    实现

    import cv2
    import numpy as np
    import matplotlib.pyplot as plt
    lena = cv2.imread('lena.jpg')
     
    gray = cv2.cvtColor(lena, cv2.COLOR_BGR2GRAY)
    plt.imshow(gray)
     
    # 二值化;目的为了更好的进行检测
    ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
    plt.imshow(thresh)
    

    计算轮廓

    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
    
    np.array(contours).shape  # (421,)
    

    绘制轮廓

    '''
    第三个参数:画哪一个轮廓;-1 代表所有轮廓;在有多个轮廓时看起来比较明显。
    第四个参数:BGR 颜色模式;
    第四个参数:绘制线条的宽度
    
    传入 src 图片不能使用原图,否则会在原图上花轮廓;所以这里使用 copy 复制一份;
    '''
    img = gray.copy()
    res = cv2.drawContours(img, contours, -1, (0,0,255), 2)
    plt.imshow(res)
    

    img = gray.copy()
    res = cv2.drawContours(img, contours, -1, (0,0,255), 1)
    plt.imshow(res)
    

    二、轮廓特征

    # 当使用辅助函数计算特征的时候,需要把各个轮廓单独取出来,才能使用
    cnt = contours[1]
    cnt
     
        array([[[210, 261]], 
               [[209, 262]], 
               [[210, 262]], 
               [[211, 262]], 
               [[212, 262]], 
               [[211, 261]]], dtype=int32)
    
    # 面积
    cv2.contourArea(cnt)  # 2.0
     
    # 周长 True-闭合;
    cv2.arcLength(cnt, True) # 6.828427076339722
     
    
    cv2.arcLength(cnt, False) # 5.828427076339722
    

    三、轮廓近似

    A点到B点的曲线,上面一点 C 距离AB直线最远,如果这个距离 d1 小于阈值,则 AB曲线和 AB直线近似;

    否则进一步求 AC 和 CB 的近似线;不断二分下去;

    使用场景:做 外界矩形、外界圆。


    cloud = cv2.imread('pie.png', 0)
    plt.imshow(cloud)
     
    # 计算轮廓
    contours, hierarchy = cv2.findContours(cloud, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
     
    len(contours)  # 3
    

    img1 = cloud.copy()
    res = cv2.drawContours(img1, contours, -1, (0,0,255), 4)
    plt.imshow(res)
    

    cnt = contours[0]
    img2 = cloud.copy()
    res = cv2.drawContours(img2, [cnt], -1, (0,0,255), 4)
    plt.imshow(res)
    

    近似

    epsilon = 0.1 * cv2.arcLength(cnt, True)
    approx = cv2.approxPolyDP(cnt, epsilon, True)
    
    cloud1 = cloud.copy()
    res = cv2.drawContours(cloud1, [approx], -1, (0, 0, 255), 2)
    plt.imshow(res)
    

    边界矩形

    x, y, w, h = cv2.boundingRect(cnt)
    img3 = cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)
    plt.imshow(img3)
    
    
    area = cv2.contourArea(cnt)
    x, y, w, h = cv2.boundingRect(cnt)
    rect_area = w * h
    
    # 轮廓面积与边界矩形比
    extent = float(area) / rect_area
    
    

    外接圆

    (x, y),radius = cv2.minEnclosingCircle(cnt)
    center = (int(x), int(y))
    radius = int(radius)
    img = cv2.circle(img, center, radius, (0, 255, 0), 2)
    
    

  • 相关阅读:
    BEC listen and translation exercise 44
    中译英12
    BEC listen and translation exercise 43
    中译英11
    BEC listen and translation exercise 42
    中译英10
    BEC listen and translation exercise 41
    中译英9
    BEC listen and translation exercise 40
    中译英8
  • 原文地址:https://www.cnblogs.com/fldev/p/14371829.html
Copyright © 2011-2022 走看看