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()