• 轮廓检测cv2.findContours()


    轮廓检测

    轮廓检测也是图像处理中经常用到的。OpenCV-Python接口中使用cv2.findContours()函数来查找检测物体的轮廓。

    实现

    使用方式如下:

    import cv2
    img = cv2.imread("./test.jpg")
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
    contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
    cv2.drawContours(img,contours,-1,(0,0,255),3)
    cv2.imshow("img", img)
    cv2.waitKey(0)

    需要注意的是cv2.findContours()函数接受的参数为二值图,即黑白的(不是灰度图),所以读取的图像要先转成灰度的,再转成二值图,参见4、5两行。第六行是检测轮廓,第七行是绘制轮廓。

    结果

    原图如下:

    20201214103632488

    检测结果如下:

    2020121410370882

    注意,findcontours函数会“原地”修改输入的图像。这一点可通过下面的语句验证:

    cv2.imshow("binary", binary)  
    contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)  
    cv2.imshow("binary2", binary)  

    执行这些语句后会发现原图被修改了。

    cv2.findContours()函数

    函数的原型为

    cv2.findContours(image, mode, method[, contours[, hierarchy[, offset ]]])  

    opencv2返回两个值:contours:hierarchy。注:opencv3会返回三个值,分别是img, countours, hierarchy
    参数

    第一个参数是寻找轮廓的图像

    第二个参数表示轮廓的检索模式,有四种(本文介绍的都是新的cv2接口)

        cv2.RETR_EXTERNAL     #表示只检测外轮廓
        cv2.RETR_LIST         #检测的轮廓不建立等级关系
        cv2.RETR_CCOMP        #建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。
        cv2.RETR_TREE         #建立一个等级树结构的轮廓。

    第三个参数method为轮廓的近似办法

    cv2.CHAIN_APPROX_NONE #存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))==1
    cv2.CHAIN_APPROX_SIMPLE #压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息
    cv2.CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS #使用teh-Chinl chain 近似算法

    返回值

    cv2.findContours()函数返回两个值,一个是轮廓本身,还有一个是每条轮廓对应的属性。
    contour返回值

    cv2.findContours()函数首先返回一个list,list中每个元素都是图像中的一个轮廓,用numpy中的ndarray表示。这个概念非常重要。在下面drawContours中会看见。通过

    print (type(contours))  
    print (type(contours[0]))  
    print (len(contours))  

    可以验证上述信息。会看到本例中有两条轮廓,一个是五角星的,一个是矩形的。每个轮廓是一个ndarray,每个ndarray是轮廓上的点的集合。

    由于我们知道返回的轮廓有两个,因此可通过

    cv2.drawContours(img,contours,0,(0,0,255),3)  

    cv2.drawContours(img,contours,1,(0,255,0),3)  

    分别绘制两个轮廓,关于该参数可参见下面一节的内容。同时通过

    print (len(contours[0]))  
    print (len(contours[1]))  

    输出两个轮廓中存储的点的个数,可以看到,第一个轮廓中只有4个元素,这是因为轮廓中并不是存储轮廓上所有的点,而是只存储可以用直线描述轮廓的点的个数,比如一个“正立”的矩形,只需4个顶点就能描述轮廓了。
    hierarchy返回值

    此外,该函数还可返回一个可选的hiararchy结果,这是一个ndarray,其中的元素个数和轮廓个数相同,每个轮廓contours[i]对应4个hierarchy元素hierarchy[i][0] ~hierarchy[i][3],分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,则该值为负数。

    通过

    print (type(hierarchy))  
    print (hierarchy.ndim)  
    print (hierarchy[0].ndim)  
    print (hierarchy.shape)  

    可以看出,hierarchy本身包含两个ndarray,每个ndarray对应一个轮廓,每个轮廓有四个属性。

    轮廓的绘制

    OpenCV中通过cv2.drawContours在图像上绘制轮廓。

    cv2.drawContours()函数

    cv2.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset ]]]]]) 
  • 相关阅读:
    傻瓜教程:asp.net(c#) 如何配置authentication,完成基于表单的身份验证
    ajax与php交互的get和post两种实现方式
    php 存储过程
    一万小时天才理论
    servlet阅读
    post and get
    合并两个有序数组(重新开始)
    Java参数传递问题
    一万小时(如何实现)阅读
    java IO 流的学习(我们到底能走多远系列1)
  • 原文地址:https://www.cnblogs.com/wuyuan2011woaini/p/15846280.html
Copyright © 2020-2023  润新知