最近在做关于图像识别的东西,用到了寻找轮廓函数cv2.findContours和绘制轮廓函数cv2.drawContours
先看看cv2.findContours的定义:
如果嫌啰嗦(不想看英语),直接下拉,下面我有写用法与总结
def findContours(image, mode, method, contours=None, hierarchy=None, offset=None): # real signature unknown; restored from __doc__
"""
findContours(image, mode, method[, contours[, hierarchy[, offset]]]) -> contours, hierarchy
. @brief Finds contours in a binary image.
.
. The function retrieves contours from the binary image using the algorithm @cite Suzuki85 . The contours
. are a useful tool for shape analysis and object detection and recognition. See squares.cpp in the
. OpenCV sample directory.
. @note Since opencv 3.2 source image is not modified by this function.
.
. @param image Source, an 8-bit single-channel image. Non-zero pixels are treated as 1's. Zero
. pixels remain 0's, so the image is treated as binary . You can use #compare, #inRange, #threshold ,
. #adaptiveThreshold, #Canny, and others to create a binary image out of a grayscale or color one.
. If mode equals to #RETR_CCOMP or #RETR_FLOODFILL, the input can also be a 32-bit integer image of labels (CV_32SC1).
. @param contours Detected contours. Each contour is stored as a vector of points (e.g.
. std::vector >).
. @param hierarchy Optional output vector (e.g. std::vector), containing information about the image topology. It has
. as many elements as the number of contours. For each i-th contour contours[i], the elements
. hierarchy[i][0] , hierarchy[i][1] , hierarchy[i][2] , and hierarchy[i][3] are set to 0-based indices
. in contours of the next and previous contours at the same hierarchical level, the first child
. contour and the parent contour, respectively. If for the contour i there are no next, previous,
. parent, or nested contours, the corresponding elements of hierarchy[i] will be negative.
. @param mode Contour retrieval mode, see #RetrievalModes
. @param method Contour approximation method, see #ContourApproximationModes
. @param offset Optional offset by which every contour point is shifted. This is useful if the
. contours are extracted from the image ROI and then they should be analyzed in the whole image
. context.
"""
pass
cv2.drawContours的定义:
def drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None): # real signature unknown; restored from __doc__
"""
drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]]) -> image
. @brief Draws contours outlines or filled contours.
.
. The function draws contour outlines in the image if \f$\texttt{thickness} \ge 0\f$ or fills the area
. bounded by the contours if \f$\texttt{thickness}<0\f$ . The example below shows how to retrieve
. connected components from the binary image and label them: :
. @include snippets/imgproc_drawContours.cpp
.
. @param image Destination image.
. @param contours All the input contours. Each contour is stored as a point vector.
. @param contourIdx Parameter indicating a contour to draw. If it is negative, all the contours are drawn.
. @param color Color of the contours.
. @param thickness Thickness of lines the contours are drawn with. If it is negative (for example,
. thickness=#FILLED ), the contour interiors are drawn.
. @param lineType Line connectivity. See #LineTypes
. @param hierarchy Optional information about hierarchy. It is only needed if you want to draw only
. some of the contours (see maxLevel ).
. @param maxLevel Maximal level for drawn contours. If it is 0, only the specified contour is drawn.
. If it is 1, the function draws the contour(s) and all the nested contours. If it is 2, the function
. draws the contours, all the nested contours, all the nested-to-nested contours, and so on. This
. parameter is only taken into account when there is hierarchy available.
. @param offset Optional contour shift parameter. Shift all the drawn contours by the specified
. \f$\texttt{offset}=(dx,dy)\f$ .
. @note When thickness=#FILLED, the function is designed to handle connected components with holes correctly
. even when no hierarchy date is provided. This is done by analyzing all the outlines together
. using even-odd rule. This may give incorrect results if you have a joint collection of separately retrieved
. contours. In order to solve this problem, you need to call #drawContours separately for each sub-group
. of contours, or iterate over the collection using contourIdx parameter.
"""
pass
好吧,一堆英文,看的头蒙。我来总结一下吧
cv2.findContours一共有:
def findContours(image, mode, method, contours=None, hierarchy=None, offset=None):
这么几个参数:
image : 传入的图像,
注意一定要是二值图像,(cv2读图片时,用 cv2.imread(imgpath , 0) 即可,注意第二个参数是0)
mode : 轮廓检索方式
cv2.RETR_TREE:建立一个等级树结构的轮廓
cv2.RETR_EXTERNAL:只检测外轮廓
cv2.RETR_LIST:检测的轮廓不建立等级关系
cv2.RETR_CCOMP:建立两个等级的轮廓,上面一层为外边界,里面一层为内孔的边界信息
method : 轮廓近似方法
cv2.CHAIN_APPROX_NONE: 存储所有边界点
cv2.CHAIN_APPROX_SIMPLE: 压缩垂直、水平、对角方向,只保留端点
cv2.CHAIN_APPROX_TX89_L1: 使用teh-Chini近似算法
cv2.CHAIN_APPROX_TC89_KCOS: 使用teh-Chini近似算法
返回值:注意,在opencv3.2后返回值只有两个:contours, hierarchy,之前的返回值有三个image, contours, hierarchy
一般这样搭配使用:
contours, hierarchy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
当使用cv2.CHAIN_APPROX_NONE存储所有轮廓点时,返回的contours是一个列表,每一项是一个轮廓信息,每一个轮廓信息是一个(n , 1 , 2)维的numpy.ndarray,n是坐标的个数。
利用cv2.drawContours可以将之前找到的轮廓画出来
def drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None):
别看有这么多参数,实际上用的最多的是前几个:
image:
传入的图像,在这张图上画,注意,drawContours本身会直接修改image,不需要返回值,所以在传入图片前先备份一下原图,一般用:img = image * 1,这里image是np.array,乘一相当于复制了一份,注注意:如果img = image这样直接赋值,是没有用的,修改img照样会修改image,这是因为深拷贝与浅拷贝的不同,这里image * 1是一个小技巧,但正规的深拷贝应该用copy这个函数,(还得导包,所以偷个懒,直接乘 1)
contours:
这个是一个列表,注意:是一个列表,是一个列表,是一个列表,可以直接将刚才用findContours找出来的contours给他,也可以是自己给出的一组坐标信息。
contourIdx:顾名思义,就是要画的轮廓下标, -1表示画出全部的轮廓。比如刚才找出来的contours,在将-1给到contourIdx,就会把所有轮廓画出来。
color:画线的颜色:例如(0,0,255)
thickness: 画线的粗细,-1则为填充
一般用法:
cv2.drawContours(img, contours, -1, (255, 255, 255), -1)
注意:如果想画contours中的某个轮廓,一定要取出来放到列表里,像这样:
c = []
c.append(contours[3])
cv2.drawContours(img, c, -1, (255, 255, 255), -1)