目录

 一、Sobel的使用格式与参数解析

 二、一半不到的圆形轮廓

三、接近完全的圆形轮廓

四、完整的圆形轮廓


本文将以下左图为例,分三步完成对该圆形的边缘检测,结果为右图

opencv判断轮廓是否连续且闭合_Sobel

opencv判断轮廓是否连续且闭合_Sobel_02

 一、Sobel的使用格式与参数解析

OpenCV中Sobel算子的使用方式:cv2.Sobel(src, ddepth, dx, dy)

src为输入图像

ddepth为输出图像的数据类型
dx,dy:当组合为dx=1,dy=0时求x方向的一阶导数,即Gx,当组合为dx=0,dy=1时求y方向的一阶导数,即Gy

检测水平方向:

opencv判断轮廓是否连续且闭合_Sobel_03

检测竖直方向

opencv判断轮廓是否连续且闭合_Sobel_04

 二、一半不到的圆形轮廓

进行最普通的Sobel使用,由于本文使用的图片比较特殊,因此跳过灰度化过程。感兴趣的读者也可以使用未经灰度化的图片使用Sobel算子进行边缘检测,轮廓颜色也许会让你意外。

yuan = cv2.imread('yuan.png')
yuan_x=cv2.Sobel(yuan,-1,dx=1,dy=0)
cv2.imshow('yuan_x',yuan_x)
cv2.waitKey(100000)

运行结果如下 

 

opencv判断轮廓是否连续且闭合_Sobel_05

Gx矩阵的计算本质上是该像素点的右侧减左侧。在该处的Sobel函数中,-1表示与原图像相同的深度,即默认的uint8。对于处于左侧边缘的像素来说,右边是白色(255)左边是黑色(0),那么右减左就是255(白色),但是对于图像左边来说,右边是黑色(0),左边是白色(255),右减左等于-255,然而由于OpenCV中图像矩阵是uint8类型的,取值范围是0-255,那么对于-255他会默认赋予0(黑色)。如果想得到更为完整的圆形轮廓,则可以改用以下代码

三、接近完全的圆形轮廓

yuan = cv2.imread('yuan.png')
yuan_x_64 = cv2.Sobel(yuan,cv2.CV_64F,dx=1,dy=0)
yuan_x_full=cv2.convertScaleAbs(yuan_x_64)
cv2.imshow('yuan_x_full',yuan_x_full)
cv2.waitKey(10000)

运行结果如下 

opencv判断轮廓是否连续且闭合_opencv判断轮廓是否连续且闭合_06

对比两次运行的第二行代码可以发现,该处将Sobel的第二个变量-1更改为cv2.CV_64F,即将默认的int8改为float64,因此可保存负数。之后通过第三行的绝对值变换成功将右侧保留下来的-255更换为255,成功被检测

四、完整的圆形轮廓

从三的结果可以发现,虽然左右都被成功检测,但上下方的轮廓依旧不完整,这很好理解,因为上下方的像素点左右都为黑(0),通过Gx肯定无法得到结果,因此此出我们可以转换思路,通过Gy检测竖直方向的轮廓,然后将两个最终的轮廓图进行叠加,即可得到完整的圆形轮廓

Gy检测竖直方向的轮廓

yuan_y_64 = cv2.Sobel(yuan,cv2.CV_64F,dx=0,dy=1)
yuan_y_full=cv2.convertScaleAbs(yuan_y_64)
cv2.imshow('yuan_y_full',yuan_y_full)
cv2.waitKey(10000)

 运行结果如下

opencv判断轮廓是否连续且闭合_Sobel_07

将xy方向的轮廓叠加

yuan_xy_full=cv2.addWeighted(yuan_x_full,1,yuan_y_full,1,0)
cv2.imshow('yuan_xy_full',yuan_xy_full)
cv2.waitKey(10000)

得到最终结果

opencv判断轮廓是否连续且闭合_Sobel_02