• OpenCV---轮廓发现


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

    轮廓发现

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

    相关API

    findContours 发现轮廓
    
    drawContours绘制轮廓

    操作步骤

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

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

    def contours_demo(image):
        dst = cv.GaussianBlur(image,(9,9),15)  #高斯模糊,消除噪声
        gray = cv.cvtColor(dst,cv.COLOR_BGR2GRAY) #先变灰度图像
        ret, binary = cv.threshold(gray,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU)  #获取二值图像
        cv.imshow("binary image",binary)
    
        # 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 contours",image)
    
    
    src = cv.imread("./lk.png")  #读取图片
    cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)    #创建GUI窗口,形式为自适应
    cv.imshow("input image",src)    #通过名字将图像和窗口联系
    
    contours_demo(src)
    
    cv.waitKey(0)   #等待用户操作,里面等待参数是毫秒,我们填写0,代表是永远,等待用户操作
    cv.destroyAllWindows()  #销毁所有窗口

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

    def contours_demo(image):
        binary = edge_demo(image)
    
        cloneImage,contours,heriachy = cv.findContours(binary,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)    #RETR_TREE包含检测内部
        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 contours",image)
    
    def edge_demo(image):
        dst = cv.GaussianBlur(image,(3,3),0)
        gray = cv.cvtColor(dst,cv.COLOR_BGR2GRAY) #先变灰度图像
    
        edge_output = cv.Canny(gray,50,108)
    
        cv.imshow("detect contours",edge_output)
        return edge_output
    
    src = cv.imread("./lk.png")  #读取图片
    cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)    #创建GUI窗口,形式为自适应
    cv.imshow("input image",src)    #通过名字将图像和窗口联系
    
    contours_demo(src)
    
    cv.waitKey(0)   #等待用户操作,里面等待参数是毫秒,我们填写0,代表是永远,等待用户操作
    cv.destroyAllWindows()  #销毁所有窗口

    相关知识补充

    (一)findContours寻找轮廓

    cv.findContours(binary,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE) 
    def findContours(image, mode, method, contours=None, hierarchy=None, offset=None): # real signature unknown; restored from __doc__
    1.image:输入图像,图像必须为8-bit单通道图像,图像中的非零像素将被视为1,0像素保留其像素值,故加载图像后会自动转换为二值图像。可以通过threshold和canny获取
    2.mode:轮廓检索模式

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

    (二)drawContours绘制轮廓

    cv.drawContours(image,contours,i,(0,0,255),2)
    cv.drawContours(image,contours,i,(0,0,255),-1)
    def drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None): # real signature unknown; restored from __doc__
    1.image:输入输出图像,Mat类型即可 
    2.contours:使用findContours检测到的轮廓数据,每个轮廓以点向量的形式存储
    3.contourIdx:绘制轮廓的只是变量,如果为负值则绘制所有输入轮廓 
    4.color:轮廓颜色 
    5.thickness:绘制轮廓所用线条粗细度,如果值为负值,则在轮廓内部绘制 
  • 相关阅读:
    【Spark亚太研究院系列丛书】Spark实战高手之路-第一章 构建Spark集群(第五步)(13)
    【Spark亚太研究院系列丛书】Spark实战高手之路-第一章 构建Spark集群(第五步)(12)
    【Spark亚太研究院系列丛书】Spark实战高手之路-第一章 构建Spark集群(第五步)(11)
    【Spark亚太研究院系列丛书】Spark实战高手之路-第一章 构建Spark集群(第五步)(10)
    【Spark亚太研究院系列丛书】Spark实战高手之路-第一章 构建Spark集群(第五步)(9)
    【Spark亚太研究院系列丛书】Spark实战高手之路-第一章 构建Spark集群(第五步)(8)
    获取文件CRC和MD5
    Delphi系统托盘组件 TTrayIcon 简介
    如何调试delphi的Access violation at address错误
    Eclipse导入Gradle时报错:SDK location not found. Define location with sdk.dir in the local.properties file or with an ANDROID_HOME environment variable
  • 原文地址:https://www.cnblogs.com/ssyfj/p/9276443.html
Copyright © 2020-2023  润新知