opencv-python(15):轮廓

来源:互联网 发布:诺基亚s60v5软件下载 编辑:程序博客网 时间:2024/05/16 01:09

1.1、寻找轮廓与绘制轮廓

本节会学习cv2.findContours()以及cv2.drawcontours()

寻找轮廓应该首先进行二值化处理,所以应首先变回灰度图。

cv2.findcontours()

原型:

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

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

第二个参数表示轮廓的检索模式,有四种(本文介绍的都是新的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()函数返回两个值,一个是轮廓本身,还有一个是每条轮廓对应的属性。

cv2.drawContours()

原型:

cv2.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset ]]]]])  第一个参数是指明在哪幅图像上绘制轮廓;第二个参数是轮廓本身,在Python中是一个list。第三个参数指定绘制轮廓list中的哪条轮廓,如果是-1,则绘制其中的所有轮廓。后面的参数很简单。其中thickness表明轮廓线的宽度,如果是-1(cv2.FILLED),则为填充模式。绘制参数将在以后独立详细介绍。

  • 第一个参数是指明在哪幅图像上绘制轮廓;
  • 第二个参数是轮廓本身,在Python中是一个list。
  • 第三个参数指定绘制轮廓list中的哪条轮廓,如果是-1,则绘制其中的所有轮廓。后面的参数很简单。其中thickness表明轮廓线的宽度,如果是-1(cv2.FILLED),则为填充模式。绘制参数将在以后独立详细介绍。
代码:

import numpy as npimport cv2im=cv2.imread('C:\\Users\\WLX\\Desktop\\24.png',cv2.IMREAD_COLOR)imgray=cv2.cvtColor(im,cv2.COLOR_RGB2GRAY)#颜色空间转换ret,thresh=cv2.threshold(imgray,175,255,cv2.THRESH_BINARY)#而置换image,contours,hierarchy=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)#轮廓# print(type(contours))# print(type(contours[0]))# print(len(contours))#本例中有两条轮廓,一个是五角星的,一个是矩形的。每个轮廓是一个ndarray,#每个ndarray是轮廓上的点的集合。#print(len(contours[0]))#输出轮廓中存储点的个数,第一个轮廓中只有4个元素,这是因为轮廓中并不是存储轮#廓上所有的点,而是只存储可以用直线描述轮廓的点的个数,比如一个“正立”的矩形,只需4个顶点就能描述轮廓了#print(len(contours[1]))img=cv2.drawContours(im,contours,-1,(0,0,255,),9)#绘制轮廓cv2.imshow('image',image)cv2.imshow('img',img)# img=cv2.drawContours(im,contours,0,(0,0,255),9)#绘制五角星轮廓#img1=cv2.drawContours(im,contours,1,(0,255,0),9)#绘制四边形轮廓# cv2.imshow('img',img)#cv2.imshow('img1',img1)cv2.imwrite('C:\\Users\\WLX\\Desktop\\kkk.png',img)cv2.waitKey(0)cv2.destroyAllWindows()
参考链接:点击打开链接

结果:

轮廓:

轮廓1:


1.2、轮廓特征

1.3、轮廓性质
详细见opencv-python中文教程与OpenCV-python Tutorials,这里仅给出几个程序

寻找最小外接圆:

程序:

#寻找最小外接圆import numpy as npimport cv2im=cv2.imread('C:\\Users\\WLX\\Desktop\\25.png',cv2.IMREAD_COLOR)imgray=cv2.cvtColor(im,cv2.COLOR_RGB2GRAY)ret,thresh=cv2.threshold(imgray,175,255,cv2.THRESH_BINARY)image,contours,hierarchy=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)cnt=contours[0](x,y),radius=cv2.minEnclosingCircle(cnt)center=(int(x),int(y))radius=int(radius)img=cv2.circle(im,center,radius,(0,255,0),2)cv2.imshow('img',img)cv2.waitKey(0)cv2.destroyAllWindows()
结果:

寻找最小外接矩形:

程序:

#寻找最小边界矩形import numpy as npimport cv2im=cv2.imread('C:\\Users\\WLX\\Desktop\\25.png',cv2.IMREAD_COLOR)imgray=cv2.cvtColor(im,cv2.COLOR_RGB2GRAY)ret,thresh=cv2.threshold(imgray,175,255,cv2.THRESH_BINARY)image,contours,hierarchy=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)cnt=contours[0]rect=cv2.minAreaRect(cnt)hh=cv2.boxPoints(rect)#获得矩形的四个角点(左上角角点坐标,宽,高以及旋转角度)box=np.int0(hh)img1=cv2.drawContours(im,[box],-1,(0,255,0),2)cv2.imshow('image',img1)cv2.imwrite('C:\\Users\\WLX\\Desktop\\pp.png',img1)cv2.waitKey(0)cv2.destroyAllWindows()
结果:

1.4、更多函数

凸包:我们可以用cv2.convexHull()来检测一个曲线是否具有凸性缺陷,并能纠正

函数原型:

hull = cv2.convexHull(points[, hull[, clockwise[, returnPoints]]

  • points为传入轮廓
  • hull为输出,通常不需要
  • clockwise设置为真顺时针输出凸包
  • returnPoints默认为真,返回凸包上的点的坐标。如果设置为False,就会返回与凸包点对应的轮廓上的点。
如果要获得凸包,仅仅下面的命令就够了

hull=cv2.convexHull(cnt)
但是如果你为了获得凸性缺陷,需要把returnPoints设置为False。
凸缺陷:

Opencv中有一个函数cv.convexityDefect()可以帮助我们找到凸缺陷。函数调用如下:

hull=cv2.convexHull(cnt,returnPoints=False)defects=cv2.convexityDefects(cnt,hull)#该函数第一个参数为轮廓,第二个参数为凸包
参考:点击打开链接

的该函数返回一个数组,其中每一行包含的值是[起点,终点,最远的点,到最远点的近似距离]

代码:

#凸缺陷import numpy as npimport cv2im=cv2.imread('C:\\Users\\WLX\\Desktop\\27.png',cv2.IMREAD_COLOR)imgray=cv2.cvtColor(im,cv2.COLOR_RGB2GRAY)ret,thresh=cv2.threshold(imgray,175,255,cv2.THRESH_BINARY)image,contours,hierarchy=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)cnt = contours[0]hull=cv2.convexHull(cnt,returnPoints=False)defects=cv2.convexityDefects(cnt,hull)#寻找凸缺陷for i in range(defects.shape[0]):    s,e,f,d = defects[i,0]    start = tuple(cnt[s][0])    end = tuple(cnt[e][0])    far = tuple(cnt[f][0])    cv2.line(im,start,end,[0,255,0],2)    cv2.circle(im,far,5,[0,0,255],-1)cv2.imshow('im',im)cv2.waitKey(0)cv2.destroyAllWindows()
结果:


其余函数见opencv-python中文教程

1.5轮廓的层次结构

见opencv-python中文教程