OpenCV——轮廓发现

目录

  • 前言
  • 正文
    • 代码
    • 函数
      • cv.GaussianBlur
      • cv.threshold
      • findContours
      • drawContours
  • 参考

前言

从标题就可以看出我们写这篇文章的意义了,我们的目的就是为了通过对图像进行处理,绘制出图像中物体的轮廓。从而为后面,我们计算一些特殊图形的周长,面积打下基础。轮廓可以简单认为成将连续的点(连着边界)连在一起的曲线,具有相同 的颜色或者灰度。轮廓在形状分析和物体的检测和识别中很有用。为了更加准确,要使用二值化图像。在寻找轮廓之前,要进行阈值化处理或者 Canny 边界检测查找轮廓的函数会修改原始图像。如果你在找到轮廓之后还想使用原始图像的话,你应该将原始图像存储到其他变量中。在 OpenCV 中,查找轮廓就像在黑色背景中超白色物体。要找的物体应该是白色而背景应该是黑色。

正文

代码

效果图
OpenCV——轮廓发现_第1张图片
感觉效果不是很好,应该是我的参数没调整好,如果有知道的,望告知。
code:

import cv2 as cv
import numpy as np
# 1. 高斯模糊
# 2. 灰度化
# 3. 二值化
# 4. 找轮廓
# 5. 将轮廓画出来

def edge_demo(image):
    blurred = cv.GaussianBlur(image,(3,3),0)
    gray = cv.cvtColor(blurred,cv.COLOR_BGR2GRAY)
    grad_x = cv.Sobel(gray,cv.CV_16SC1,1,0)
    grad_y = cv.Sobel(gray,cv.CV_16SC1,0,1)

    #edge_output = cv.Canny(grad_x,grad_y,30,150)
    edge_output = cv.Canny(gray,50,150)
    cv.imshow("edge_demo",edge_output)
    return edge_output

def contours_demo(image):
    dst = cv.GaussianBlur(image,(3,3),0)
    gray = cv.cvtColor(dst,cv.COLOR_BGR2GRAY)
    ret ,binary = cv.threshold(gray,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU)
    cv.imshow("threshold image",binary)
    # binary = edge_demo(image)
    contours,heriachy = cv.findContours(binary,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)
    for i,contour in enumerate(contours):
        cv.drawContours(image,contours,i,(0,0,255),3)#-1的值就是可以进行填充
        print(i)
    cv.imshow("detect image",image)



src = cv.imread("../images/circle.png")
cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)
cv.imshow('input image', src)
contours_demo(src)
cv.waitKey(0)  # 等有键输入或者1000ms后自动将窗口消除,0表示只用键输入结束窗口

cv.destroyAllWindows()

如果有对代码不是很理解的,可以看下面的代码中函数解释。

函数

cv.GaussianBlur

OpenCV——轮廓发现_第2张图片

函数原型
void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT);
参数详解如下:

  1. src,输入图像,即源图像,填Mat类的对象即可。它可以是单独的任意通道数的图片,但需要注意,图片深度应该为CV_8U,CV_16U, CV_16S, CV_32F 以及 CV_64F之一。
  2. dst,即目标图像,需要和源图片有一样的尺寸和类型。比如可以用Mat::Clone,以源图片为模板,来初始化得到如假包换的目标图。
  3. ksize,高斯内核的大小。其中ksize.width和ksize.height可以不同,但他们都必须为正数和奇数(并不能理解)。或者,它们可以是零的,它们都是由sigma计算而来。
  4. sigmaX,表示高斯核函数在X方向的的标准偏差。
  5. sigmaY,表示高斯核函数在Y方向的的标准偏差。若sigmaY为零,就将它设为sigmaX,如果sigmaX和sigmaY都是0,那么就由ksize.width和ksize.height计算出来。
    OpenCV——轮廓发现_第3张图片

cv.threshold

OpenCV——轮廓发现_第4张图片

  1. cv2.THRESH_BINARY 大于阈值的部分被置为255,小于部分被置为0。

  2. OpenCV——轮廓发现_第5张图片

  3. cv2.THRESH_OTSU 作为图像自适应二值化的一个很优的算法Otsu大津算法的参数。

findContours

void findContours( 
    InputArray image, 
    OutputArrayOfArrays contours,
    OutputArray hierarchy,
    int mode,
    int method,                              
    Point offset = Point()
);

函数各个参数的意义如下:

  1. 第一个数输入的图像。最好是进行过灰度化的图像、
  2. 定义为“vector contours”,是一个向量,并且是一个双重向量,向量内每个元素保存了一组由连续的Point点构成的点的集合的向量,每一组Point点集就是一个轮廓。 有多少轮廓,向量contours就有多少元素。
  3. Vec4i是Vec的别名,定义了一个“向量内每一个元素包含了4个int型变量”的向量。所以从定义上看,hierarchy也是一个向量,向量内每个元素保存了一个包含4个int整型的数组。向量hiararchy内的元素和轮廓向量contours内的元素是一一对应的,向量的容量相同。hierarchy向量内每一个元素的4个int型变量——hierarchy[i][0] ~hierarchy[i][3],分别表示第i个轮廓的后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号。如果当前轮廓没有对应的后一个轮廓、前一个轮廓、父轮廓或内嵌轮廓的话,则hierarchy[i][0] ~hierarchy[i][3]的相应位被设置为
    默认值-1。
  4. int型的mode,定义轮廓的检索模式:

取值一:CV_RETR_EXTERNAL只检测最外围轮廓,包含在外围轮廓内的内围轮廓被忽略.
取值二:CV_RETR_LIST 检测所有的轮廓,包括内围、外围轮廓,但是检测到的轮廓不建立等级关系,彼此之间独立,没有等级关系,这就意味着这个检索模式下不存在父轮廓或内嵌轮廓, 所以hierarchy向量内所有元素的第3、第4个分量都会被置为-1,具体下文会讲到.
取值三:CV_RETR_CCOMP 检测所有的轮廓,但所有轮廓只建立两个等级关系,外围为顶层,若外围内的内围轮廓还包含了其他的轮廓信息,则内围内的所有轮廓均归属于顶层.
取值四:CV_RETR_TREE, 检测所有轮廓,所有轮廓建立一个等级树结构。外层轮廓包含内层轮廓,内层轮廓还可以继续包含内嵌轮廓。
第五个参数:int型的method,定义轮廓的近似方法:
取值一:CV_CHAIN_APPROX_NONE 保存物体边界上所有连续的轮廓点到contours向量内.
取值二:CV_CHAIN_APPROX_SIMPLE 仅保存轮廓的拐点信息,把所有轮廓拐点处的点保存入contours
向量内,拐点与拐点之间直线段上的信息点不予保留
取值三和四:CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法.
第六个参数:Point偏移量,所有的轮廓信息相对于原始图像对应点的偏移量,相当于在每一个检测出的轮廓点上加上该偏移量,并且Point还可以是负值!

drawContours

void drawContours(InputOutputArray image,
InputArrayOfArrays contours, 
int contourIdx, const Scalar& color, 
int thickness=1, 
int lineType=8,
InputArray hierarchy=noArray(),
int maxLevel=INT_MAX,
Point offset=Point() )

第一:输入的目标图像
第二:表示contours表示的轮廓组。
第三:参数contourIdx表明画第几个轮廓组。
第四:轮廓的颜色。
第五:轮廓的线宽,若为负值,表示进行填充。
第六:lineType线型
第七:轮廓结构信息
第八:maxlevel.

参考

  1. OpenCV学习笔记(十八)——轮廓发现
  2. python+opencv3.3视频教学 基础入门
  3. Opencv之图像固定阈值二值化处理threshold

你可能感兴趣的:(OpenCV,opencv)