图像梯度与几种算子的opencv实现

水花花花花花 2024-09-04 16:31:02 阅读 72

1、 Sobel算子函数

OpenCV使用Sobel 算子的方法是cv2.Sobel()

<code>dst = cv2.Sobel(src,ddepth,dx,dy,ksize,scale,delta,borderType)

参数:

src 原图像

ddepth 输出图像的深度,具体关系:

输入图像深度(src.depth()) 输出图像深度(ddepth)
cv2.CV_8U -1/cv2.CV_16S/cv2.CV_32F/cv2.CV_64F
cv2.CV_16U/cv2.CV_16S -1/cv2.CV_32F/cv2.CV_64F
cv2.CV_32F -1/cv2.CV_32F/cv2.CV_64F
cv2.CV_64F -1/cv2.CV_64F

dx:x方向上的求导阶数

dy:y方向上的求导阶数

ksize:Sobel核的大小。该值为-1时,会使用Scharr算子进行运算

scale:计算导数时采用的缩放因子,默认为1,是没有缩放的

delta:加在目标图像dst上的值,默认为0

borderType:边界样式,默认值为cv2.BORDER_DEFAULT。

关于参数ddepth

该值为-1时,让处理结果与原始图像保持一致,但是直接将ddepth设置为-1,得到的结果可能是错误的。计算梯度值可能出现负数,当处理的图像是8位图类型,ddepth的值为-1时,运算结果也是8位图类型,负数会自动截断为0,发生信息丢失。为了避免信息丢失,要先使用更高的数据类型cv2.CV_64F,再通过取绝对值将其映射到cv2.CV_8U类型。所以,通常将ddepth值设置为“cv2.CV_8U”,并使用函数cv2.convertScaleAbs()对函数cv2.Sobel()的计算结果取绝对值。

注意:x方向和y方向的边缘叠加时,应先令dx=1,dy=0,得到一个结果;再令dx=0,dy=1,得到一个结果。将两个结果相加,而不是同时令dx=1和dy=1。

import cv2

#读取图像

img = cv2.imread('图片路径',0)

#计算x方向边缘信息

sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5)

#计算y方向边缘信息

sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=5)

#求绝对值

sobelx = cv2.convertScaleAbs(sobelx)

sobely = cv2.convertScaleAbs(sobely)

#x方向和y方向的边缘叠加

sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)

#显示图像

cv2.imshow("origin image",img)

cv2.imshow("x",sobelx)

cv2.imshow("y",sobely)

cv2.imshow("xy",sobelxy)

cv2.waitKey(0)

cv2.destroyAllWindows()

 

2、 Scharr算子

OpenCV使用Scharr算子的函数是cv2.Scharr()

<code>dst = cv2.Scharr(src,ddepth,dx,dy,scale,delta,borderType)

参数:

src 原图像

ddepth 输出图像的深度,该值与函数cv2.Sobel()中的参数ddepth的含义相同。

dx x方向上的求导阶数

dy y方向上的求导阶数

scale 计算导数时采用的缩放因子,默认为1,是没有缩放的

delta 加在目标图像dst上的值,默认为0

borderType 边界样式,默认值为cv2.BORDER_DEFAULT。

在cv2.Sobel()中,ksize=-1时,则会使用Scharr算子。所以下面两个语句等价:

dst = cv2.Scharr(src,ddepth,dx,dy)dst = cv2.Sobel(src,ddepth,dx,dy,-1)

注意:

参数ddepth的值应该设置为“cv2.CV_64F”,并对函数cv2.Scharr()的计算结果取绝对值。

dx和dy不能同时为1,否则语句是错误的。

计算x方向和y方向的边缘叠加时,应先令dx=1,dy=0,得到一个结果;再令dx=0,dy=1,得到一个结果。将两个结果相加,而不是同时令dx=1和dy=1。

代码示例:

import cv2

#读取图像

img = cv2.imread('img.png',0)

#计算水平方向边缘信息

scharrx = cv2.Scharr(img,cv2.CV_64F,1,0)

#计算垂直方向边缘信息

scharry = cv2.Scharr(img,cv2.CV_64F,0,1)

#求绝对值

scharrx = cv2.convertScaleAbs(scharrx)

scharry = cv2.convertScaleAbs(scharry)

#水平方向和垂直方向的边缘叠加

scharrxy = cv2.addWeighted(scharrx,0.5,scharry,0.5,0)

#显示图像

cv2.imshow("origin image",img)

cv2.imshow("x",scharrx)

cv2.imshow("y",scharry)

cv2.imshow("xy",scharrxy)

cv2.waitKey(0)

cv2.destroyAllWindows()

结果:x方向:

 y方向:

x方向和y方向的边缘叠加

3、 Laplacian算子

OpenCV使用Laplacian算子的函数是cv2.Laplacian()

<code>dst = cv2.Laplacian(src,ddepth,ksize,scale,delta,borderType)

参数:

src 原图像

ddepth 输出图像的深度,该值与函数cv2.Sobel()中的参数ddepth的含义相同。

ksize 计算二阶导数的核尺寸大小,必须为正的奇数。

scale 计算导数时采用的缩放因子,默认为1,是没有缩放的

delta 加在目标图像dst上的值,默认为0

borderType 边界样式,默认值为cv2.BORDER_DEFAULT。

该函数分别对x和y方向进行二次求导:

注意:当ksize=1时,计算时采用如下3×3的核:

代码:

<code>import cv2

#读取图像

img = cv2.imread('5907dfd8407ca2407d082c90bf6d290.png',0)

#计算边缘信息

laplace = cv2.Laplacian(img,cv2.CV_64F)

#求绝对值

laplace = cv2.convertScaleAbs(laplace)

#显示图像

cv2.imshow("origin image",img)

cv2.imshow("laplace",laplace)

cv2.waitKey(0)

cv2.destroyAllWindows()

4、 Canny函数

OpenCV使用函数cv2.Cannyl()实现Canny边缘检测

<code>edges = cv2.Canny(image,threshold1,threshold2,apertureSize,L2gradient)

参数:

image 输入图像,必须为8位图像

threshold1 第一个阈值

threshold2 第二个阈值

apertureSize Sobel算子的大小

L2gradient 计算图像梯度幅度的表示。默认值为False,使用L1范数计算;如果为True,则使用更精确的L2范数计算。

图片

代码示例:

<code>import cv2

#读取图像,为8位灰度图像

img = cv2.imread('img.png',cv2.IMREAD_GRAYSCALE)

#canny边缘检测

#去噪

img = cv2.GaussianBlur(img,(3,3),0)

#threshold1为128,threshold2为200时的边缘检测结果

canny1 = cv2.Canny(img, 128, 200)

#threshold1为32,threshold2为128时的边缘检测结果

canny2 = cv2.Canny(img, 32, 128)

#显示图像

cv2.imshow("origin image",img)

cv2.imshow("canny1",canny1)

cv2.imshow("canny2",canny2)

cv2.waitKey(0)

cv2.destroyAllWindows()

 threshold1为128,threshold2为200时的边缘检测结果

threshold1为32,threshold2为128时的边缘检测结果 



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。