zoukankan      html  css  js  c++  java
  • 十八 轮廓发现

    推文:OpenCV-Python教程(11、轮廓检测)

    一、轮廓发现

    基于图像边缘提取的基础,寻找对象轮廓的方法,所以边缘提取的阈值选定会影响最终轮廓的发现。

    操作步骤

    • 1.转换图像为二值化图像:threshold方法或者canny边缘提取获取的都是二值化图像
    • 2.通过二值化图像寻找轮廓:findContours
    • 3.描绘轮廓:drawContours

    二、相关函数

    1、findContours寻找轮廓

    直接使用二值化图像 cv.findContours(binary,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)
    使用边缘检测后的图像 def findContours(image, mode, method, contours=None, hierarchy=None, offset=None):

    image:输入图像,图像必须为8-bit单通道图像,图像中的非零像素将被视为1,0像素保留其像素值,故加载图像后会自动转换为二值图像。可以通过threshold和canny获取

    mode:轮廓检索模式

    • RETR_EXTERNAL:表示只检测最外层轮廓,对所有轮廓设置hierarchy[i][2]=hierarchy[i][3]=-1
    • RETR_LIST:提取所有轮廓,并放置在list中,检测的轮廓不建立等级关系
    • RETR_CCOMP:提取所有轮廓,并将轮廓组织成双层结构(two-level hierarchy),顶层为连通域的外围边界,次层位内层边界
    • RETR_TREE:提取所有轮廓并重新建立网状轮廓结构
    • RETR_FLOODFILL:官网没有介绍,应该是洪水填充法

    method:轮廓近似方法

    • CHAIN_APPROX_NONE:获取每个轮廓的每个像素,相邻的两个点的像素位置差不超过1
    • CHAIN_APPROX_SIMPLE:压缩水平方向,垂直方向,对角线方向的元素,值保留该方向的重点坐标,如果一个矩形轮廓只需4个点来保存轮廓信息
    • CHAIN_APPROX_TC89_L1和CHAIN_APPROX_TC89_KCOS使用Teh-Chinl链逼近算法中的一种

    返回值

    ret = cv.findContours(binary, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
    cloneImage,contours,heriachy = cv.findContours(binary,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)    #RETR_TREE包含检测内部
    • 返回一个元组,内部有三个元素
    • <class 'numpy.ndarray'>
    • <class 'list'>
    • <class 'numpy.ndarray'>

    第一个返回值:cloneImage是我们传入的二值化图像

    第二个返回值:contours是一个列表,是轮廓本身,含有轮廓上面的各个点的位置信息

    第三个返回值:heriachy是每条轮廓对应的属性

    2、drawContours绘制轮廓

    def drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None):

    1.image:输入输出图像,Mat类型即可

    2.contours:使用findContours检测到的轮廓数据,每个轮廓以点向量的形式存储

    3.contourIdx:绘制轮廓的只是变量,如果为负值则绘制所有输入轮廓(就是i,仅仅表示一个序号

    4.color:轮廓颜色

    5.thickness:绘制轮廓所用线条粗细度,如果值为负值,则在轮廓内部绘制

    cv.drawContours(image,contours,i,(0,0,255),2)    #绘制轮廓
    cv.drawContours(image,contours,i,(0,0,255),-1)    #填充轮廓

    三、代码实现

    1、使用直接使用阈值方法threshold方法获取二值化图像来选择轮廓

    import cv2 as cv
    import numpy as np
    
    def contours_demo(image):
        # 高斯模糊,消除噪声
        dst = cv.GaussianBlur(image,(9,9),15)
    
        # 先变灰度图像
        gray = cv.cvtColor(dst,cv.COLOR_BGR2GRAY)
    
        #OTSU大律法获取二值图像
        #args
        #   输入图像
        #   阈值(为0是全局自适应阈值, 参数0可改为任意数字但不起作用)
        #   与THRESH_BINARY和THRESH_BINARY_INV阈值类型一起使用设置的最大值。
        #   阈值类型
        ret,binary = cv.threshold(gray,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU)
        cv.imshow('binary image',binary)
    
        #寻找轮廓(直接输入二值图像)
        #args:
        #   输入的二值图像
        #   轮廓检索模式  RETR_TREE:提取所有轮廓并重新建立网状轮廓结构
        #   轮廓近似方法  CHAIN_APPROX_SIMPLE:压缩水平方向,垂直方向,对角线方向的元素,值保留该方向的重点坐标,如果一个矩形轮廓只需4个点来保存轮廓信息
        #return:
        #   传入的二值图像(ndarray)
        #   list:轮廓本身,含有轮廓上面各个点的位置信息
        #   每条轮廓对应的属性(ndarray)
        #cloneimage,contours,heriachy = cv.findContours(binary,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)  #RETR_TREE包含检测内部
        cloneImage, contours, heriachy = cv.findContours(binary, cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)  # RETR_EXTERNAL检测外部轮廓
        for i ,contour in enumerate(contours):
            #cv.drawContours(image,contours,i,(0,0,255),2)      #绘制轮廓
            cv.drawContours(image,contours,i,(0,0,255),-1)      #填充轮廓
            print(i)
        cv.imshow('detect image',image)
    
    src = cv.imread('circle.png')
    cv.imshow('input image',src)
    contours_demo(src)
    cv.waitKey(0)
    cv.destroyAllWindows()

    如果使用绘制轮廓的话:

    2、使用canny边缘检测获取二值化图像

     1 import cv2 as cv
     2 import numpy as np
     3 
     4 #提取边缘信息
     5 def edge_demo(image):
     6     #1、高斯模糊
     7     dst = cv.GaussianBlur(image,(3,3),0)
     8     #2、灰度化
     9     gray = cv.cvtColor(dst,cv.COLOR_BGR2GRAY)
    10     #3、canny边缘提取出来的是二值图像
    11     edge_output = cv.Canny(gray,50,108)
    12 
    13     cv.imshow('edge_info',edge_output)
    14     return edge_output
    15 
    16 #轮廓发现绘制
    17 def contours_demo(image):
    18     binary = edge_demo(image)
    19     # 检测轮廓
    20     # 寻找轮廓(输入canny边缘提取之后的二值图像)
    21     # args:
    22     #   输入的二值图像
    23     #   轮廓检索模式  RETR_TREE:提取所有轮廓并重新建立网状轮廓结构
    24     #   轮廓近似方法  CHAIN_APPROX_SIMPLE:压缩水平方向,垂直方向,对角线方向的元素,值保留该方向的重点坐标,如果一个矩形轮廓只需4个点来保存轮廓信息
    25     # return:
    26     #   传入的二值图像(ndarray)
    27     #   list:轮廓本身,含有轮廓上面各个点的位置信息
    28     #   每条轮廓对应的属性(ndarray)
    29     cloneimage,contours,heriachy = cv.findContours(binary,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)  #RETR_TREE包含检测内部
    30     for i,contour in enumerate(contours):
    31         #cv.drawContours(image,contours,i,(0,0,255),2)  #绘制轮廓
    32         cv.drawContours(image,contours,i,(0,0,255),-1)  #填充轮廓
    33         print(i)
    34     cv.imshow('detect contours',image)
    35 
    36 img = cv.imread('contours.png')
    37 cv.imshow('input image',img)
    38 contours_demo(img)
    39 cv.waitKey(0)
    40 cv.destroyAllWindows()

  • 相关阅读:
    C Looooops(扩展欧几里得)题解
    POJ1061 青蛙的约会(扩展欧几里得)题解
    UVA 11426 GCD
    Trailing Zeroes (III) (二分)题解
    BZOJ 1977 次小生成树
    BZOJ 4557 侦查守卫
    codevs 1088 神经网络
    codevs 1135 选择客栈
    BZOJ 3527 力
    BZOJ 1610 连线游戏
  • 原文地址:https://www.cnblogs.com/pacino12134/p/9884392.html
Copyright © 2011-2022 走看看