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)
    
    

  • 相关阅读:
    Ubuntu里Eclipse关联Jdk
    解决Ubuntu自带编译器不好使问题
    Ubuntu英文变为中文
    两个VirtualBox版本装的语言不一样?
    Hadoop-2.0 目录简介
    Eclipse项目里面看源码和文档
    Eclipse搭建Struts2环境
    2017,崭新的一年!
    cl-closure-template 中文乱码的解决方法
    common-list基础知识--多值的返回与接收
  • 原文地址:https://www.cnblogs.com/fldev/p/14371829.html
Copyright © 2011-2022 走看看