08-图像梯度

1.sobel算子的理论基础
sobel算子的核心是用来检测边缘信息的,一般认为,邻域的像素对当前像素产生的影响不是等价的,所以距离不同的像素具有不同的权值,对算子结果产生的影响也不同。一般来说,距离越远,产生的影响越小

sobel算子的原理,对原始图像像素分别计算在x和y方向的梯度,然后计算该像素的近似梯度值(soble算子),如果大于某一阈值,则认为该像素点为边缘点,以此来确定边缘信息

1> 计算P5水平方向上的梯度
2> 计算P5垂直方向上的梯度
3> 计算近似梯度值(soble算子)

 

 

 sobel算子函数及其使用
dst = cv2.Sobel(src,ddepth,dx,dy,[ksize])
1> src:原始图像
2> ddepth:处理结果图像深度(通常情况下设置为-1,让处理结果与原始图像保持一致),然而在实际操作中,计算梯度值会出现负数,为了避免负数会自动截断为0,使信息丢失,我们通常使用更高的cv2.CV_64F数据类型,取绝对值后再转换为cv2.CV_8U数据类型
3> dx:x轴方向
4> dy:y轴方向
5> ksize:核大小

dst = cv2.convertScaleAbs(src[,alpha[,beta]])
是为了将原始图像src转换为256色位图,目标图像 = 调整(原始图像*alpha + beta)
dst = cv2.addWeighted(src1,alpha,src2,beta,gamma)
1> src1:源图像1
2> alpha:源图像1的系数
3> src2:源图像2
4> beta:源图像2的系数
5> gamma:修正值
是为了计算两幅图像的权重和,目标图像 = 调整(源图像1*alpha + 源图像2*beta + gamma)

import cv2
import numpy as np

img = cv2.imread(r"image\sobel.bmp",cv2.IMREAD_GRAYSCALE)

# 1.计算x方向上的梯度
# 使用更高的cv2.CV_64F数据类型(包含负数)
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0)
# 取绝对值后再转换为cv2.CV_8U数据类型
sobelx = cv2.convertScaleAbs(sobelx)

# 2.计算y方向上的梯度
sobely = cv2.Sobel(img,cv2.CV_64F,0,1)
sobely = cv2.convertScaleAbs(sobely)

# 3.计算近似梯度值(soble算子)
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)

cv2.imshow("original",img)
cv2.imshow("x",sobelx)
cv2.imshow("y",sobely)
cv2.imshow("xy",sobelxy)

cv2.waitKey(0)
cv2.destroyAllWindows()

2.scharr算子
虽然Sobel算子可以有效的提取图像边缘,但是对图像中较弱的边缘提取效果较差。Scharr算子是对Sobel算子差异性的增强,两者在检测图像边缘的原理和使用方式上相同,但是scharr算子准确度更高,在梯度检测时用的也更多

Scharr算子通过将权重系数放大来增大像素值间的差异,其在X方向和Y方向上的梯度如下:

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

1> src:原始图像
2> ddepth:处理结果图像深度。同上,使用更高的cv2.CV_64F数据类型,取绝对值后再转换为cv2.CV_8U数据类型
3> dx:x轴方向
4> dy:y轴方向
dst = cv2.convertScaleAbs(src[,alpha[,beta]])
是为了将原始图像src转换为256色位图,目标图像 = 调整(原始图像*alpha + beta),最后将结果取绝对值,并转换为cv2.CV_8U数据类型
dst = cv2.addWeighted(src1,alpha,src2,beta,gamma)
1> src1:源图像1
2> alpha:源图像1的系数
3> src2:源图像2
4> beta:源图像2的系数
5> gamma:修正值
是为了计算两幅图像的权重和,目标图像 = 调整(源图像1*alpha + 源图像2*beta + gamma)

需要注意的是:
dst = cv2.Scharr(src,ddepth,dx,dy) 等价于 dst = cv2.Sobel(src,ddepth,dx,dy,-1)

sobel算子和scharr算子的比较:

 

import cv2
import numpy as np

img = cv2.imread(r"image\scharr.bmp",cv2.IMREAD_GRAYSCALE)

# 1.计算x方向上的梯度
# 使用更高的cv2.CV_64F数据类型(包含负数)
scharrx = cv2.Scharr(img,cv2.CV_64F,1,0)
# 取绝对值后再转换为cv2.CV_8U数据类型
scharrx = cv2.convertScaleAbs(scharrx)

# 2.计算y方向上的梯度
scharry = cv2.Sobel(img,cv2.CV_64F,0,1)
scharry = cv2.convertScaleAbs(scharry)

# 3.计算近似梯度值(soble算子)
scharrxy = cv2.addWeighted(scharrx,0.5,scharry,0.5,0)

cv2.imshow("original",img)
cv2.imshow("x",scharrx)
cv2.imshow("y",scharry)
cv2.imshow("xy",scharrxy)

cv2.waitKey(0)
cv2.destroyAllWindows()

 

3.laplacian算子
Laplacian算子具有各方向同性的特点,能够对任意方向的边缘进行提取,具有无方向性的优点,因此使用Laplacian算子提取边缘不需要分别检测X方向的边缘和Y方向的边缘,只需要一次边缘检测即可

Laplacian算子是一种二阶导数算子,对噪声比较敏感

dst = cv2.Laplacian(src,ddepth)
1> src:原始图像
2> ddepth:处理结果图像深度。同上,使用更高的cv2.CV_64F数据类型,取绝对值后再转换为cv2.CV_8U数据类型
dst = cv2.convertScaleAbs(src[,alpha[,beta]])
是为了将原始图像src转换为256色位图,目标图像 = 调整(原始图像*alpha + beta),最后将结果取绝对值,并转换为cv2.CV_8U数据类型

laplacian算子与sobel算子、scharr算子的比较:

import cv2
import numpy as np

img = cv2.imread(r"image\laplacian.bmp",cv2.IMREAD_GRAYSCALE)

# 计算梯度
# 使用更高的cv2.CV_64F数据类型(包含负数)
laplacian = cv2.Laplacian(img,cv2.CV_64F)
# 取绝对值后再转换为cv2.CV_8U数据类型
laplacian = cv2.convertScaleAbs(laplacian)

cv2.imshow("original",img)
cv2.imshow("laplacian",laplacian)

cv2.waitKey(0)
cv2.destroyAllWindows()

 

 

 

 

 

 

posted @ 2021-09-16 15:06  马铃薯1  阅读(201)  评论(0编辑  收藏  举报