OpenCV边缘检测(Sobel,Scharr,Laplace,Canny)

对于图像的处理,基本的步骤是这样的:
取得图像数据 —— 将图像进行平滑处理 —— 进行边缘检测,阈值分析 —— 进行形态学的操作 —— 获取某些特征点 —— 分析数据

那么在这里,我就讲解下边缘检测的这部分,然后后续再进行其他的讲解。

在OpenCV中,边缘检测的方法有以下几种:
Sobel
Scharr
Laplace
Canny
其中前三种的边缘检测是带方向的

那么我们就先从Sobel算子开始讲起吧!
先来看看Sobel方法的定义
def Sobel
(src,ddepth,dx,dy,dst=None,ksize=None,scale=None,delta=None,borderType=None)

ddepth:图像的颜色深度,针对不同的输入图像,输出目标图像有不同的深度,具体组合如下:
- 若src.depth() = CV_8U, 取ddepth =-1/CV_16S/CV_32F/CV_64F
- 若src.depth() = CV_16U/CV_16S, 取ddepth =-1/CV_32F/CV_64F
- 若src.depth() = CV_32F, 取ddepth =-1/CV_32F/CV_64F
- 若src.depth() = CV_64F, 取ddepth = -1/CV_64F
dx:int类型的,表示x方向的差分阶数,1或0
dy:int类型的,表示y方向的差分阶数,1或0
kSize:模板大小,前面虽然提到过,不过对于Sobel算子这里要补充下,这里的取值为1,3,5,7,当不输入的时候,默认为3。特殊的,当kSize = 1的时候,采用的模板为1*3或者3*1 而非平时的那些格式。

接下来看Scharr的定义
def Scharr(src, ddepth, dx, dy, dst=None, scale=None, delta=None, borderType=None)
会看到参数和Sobel算子一致,不过,该函数与Sobel的区别在于,Scharr仅作用于大小为3的内核。具有和sobel算子一样的速度,但结果更为精确

接下来我们看下这俩的比较:
OpenCV边缘检测(Sobel,Scharr,Laplace,Canny)_第1张图片

第一列显示的Sobel算子的在默认3*3模板下的图像,第二列显示的是Scahrr算子在默认3*3模板下的图像,会发现有明显的不同,Scharr给出的更为精确。第三列放的原图像和Sobel算子x=1 y=1的情况。 代码如下:

import cv2

img = cv2.imread("C:/Users/DELL/Desktop/img.jpg")

gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

sobel_x = cv2.Sobel(gray, cv2.CV_8U, 1, 0)
sobel_y = cv2.Sobel(gray, cv2.CV_8U, 0, 1)
sobel = cv2.Sobel(gray, cv2.CV_8U, 1, 1)

scharr_x = cv2.Scharr(gray, cv2.CV_8U, 1, 0)
scharr_y = cv2.Scharr(gray, cv2.CV_8U, 0, 1)

cv2.imshow("src", img)
cv2.imshow("Sobel_x", sobel_x)
cv2.imshow("Sobel_y", sobel_y)
cv2.imshow("Sobel", sobel)
cv2.imshow("Scharr_x", scharr_x)
cv2.imshow("Scharr_y", scharr_y)

cv2.waitKey(0)

接下来讲下Laplace
def Laplacian(src,ddepth,dst=None,ksize=None,scale=None,delta=None,borderType=None)
scale:Double类型的,计算拉普拉斯可选比例因子,有默认值1
delta:加到输出像素的值,默认为0
borderType:边界模式。默认值BORDER_DEFAULT

Laplace其实利用Sobel算子的运算,它通过Sobel算子运算出图像在x方向和y方向的导数,来得到我们载入图像的拉普拉斯变换结果。
这里简单看下Laplace的说明,就在方法里面的

 The function calculates the Laplacian of the source image by adding up the second x and y
    .   derivatives calculated using the Sobel operator:

由于这个,我这里特意选取了同样kSize的两种方法做下比较:

OpenCV边缘检测(Sobel,Scharr,Laplace,Canny)_第2张图片

发现Laplace的轮廓更为清晰。
我觉得Laplace算是Sobel的升级版。

代码如下:

import cv2

img = cv2.imread("C:/Users/DELL/Desktop/img.jpg")

gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

laplace = cv2.Laplacian(gray, cv2.CV_8U, ksize=3)
sobel = cv2.Sobel(gray, cv2.CV_8U, 1, 1)

cv2.imshow("Laplace", laplace)
cv2.imshow("Sobel", sobel)

cv2.waitKey(0)

最后讲下Canny函数:
def Canny(image,threshold1,threshold2,edges=None,apertureSize=None,L2gradient=None)

threshold1:int类型的,低阈值
threshold2:int类型的,高阈值
edeges:单通道存储边缘的输出图像
apertureSize:Sobel算子内核(kSize)大小
L2gradiend:Bool类型的,为真表示使用更精确的L2范数进行计算(两个方向的倒数的平方再开放),为假表示用L1范数(直接将两个方向导数的绝对值相加)

由于和阈值相关,那么我们这里就不指定阈值了,使用进度条的方式来调整阈值获得我们想要图像,直接上图,进度值直接看图吧:

OpenCV边缘检测(Sobel,Scharr,Laplace,Canny)_第3张图片

OpenCV边缘检测(Sobel,Scharr,Laplace,Canny)_第4张图片

OpenCV边缘检测(Sobel,Scharr,Laplace,Canny)_第5张图片

会发现,当我们改变阈值后,图像后渐渐过滤掉一些背景,当然,重在阈值的选取上,当阈值选大的时候,也是会将图像的特征完全损坏的。

代码如下:

import cv2

img = cv2.imread("C:/Users/DELL/Desktop/img.jpg")

gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

gauss = cv2.GaussianBlur(gray, (3, 3), 1)

def doCanny(x):
    position = cv2.getTrackbarPos("CannyBar", "Canny")
    canny = cv2.Canny(gauss, position, position*2.5)
    cv2.imshow("Canny", canny)


cv2.namedWindow("Canny")

cv2.createTrackbar("CannyBar", "Canny", 1, 100, doCanny)

cv2.waitKey(0)

你可能感兴趣的:(OpenCV边缘检测(Sobel,Scharr,Laplace,Canny))