从标题就可以看出我们写这篇文章的意义了,我们的目的就是为了通过对图像进行处理,绘制出图像中物体的轮廓。从而为后面,我们计算一些特殊图形的周长,面积打下基础。轮廓可以简单认为成将连续的点(连着边界)连在一起的曲线,具有相同 的颜色或者灰度。轮廓在形状分析和物体的检测和识别中很有用。为了更加准确,要使用二值化图像。在寻找轮廓之前,要进行阈值化处理或者 Canny 边界检测查找轮廓的函数会修改原始图像。如果你在找到轮廓之后还想使用原始图像的话,你应该将原始图像存储到其他变量中。在 OpenCV 中,查找轮廓就像在黑色背景中超白色物体。要找的物体应该是白色而背景应该是黑色。
效果图
感觉效果不是很好,应该是我的参数没调整好,如果有知道的,望告知。
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()
如果有对代码不是很理解的,可以看下面的代码中函数解释。
函数原型:
void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT);
参数详解如下:
void findContours(
InputArray image,
OutputArrayOfArrays contours,
OutputArray hierarchy,
int mode,
int method,
Point offset = Point()
);
函数各个参数的意义如下:
取值一: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还可以是负值!
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.