图像梯度与几种算子的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时的边缘检测结果
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。