目录
1 sobel理论基础
1.1 基础理论
目的: 利用卷积核,计算不同方向上的梯度.
- x方向有无边界: 右边- 左边
计算点P5 x方向上的梯度. 根据距离,对卷积核设置不同的系数
- y方向有无边界:下边 - 上边
与x方向类似, 计算点P5 y方向上的梯度.
- 计算近似梯度
进一步简化
对图中点P5,进行梯度计算:
2 sobel算子及其函数使用
2.1 基础理论
- 计算梯度
dst=cv2.Sobel(src, ddepth, dx, dy, [ksize])
其中,参数:
・src – 输入图像;
・ddepth– 图像深度;
→ -1,表示和原图像深度一致,但是计算梯度值时会出现负数,自动截断为0,导致信息丢失
→ cv2.CV_64F,改变输出的数据类型,设置的更高,使之允许存在负数. 在后续操作中绝对值后,再转换为np.uint8类型
・dx – x方向;
→ [dx=1,dy=0]
・dy – y方向;
→ [dx=0,dy=1]
・ [ksize] – 核大小;
→ 须为奇数(如1,3,5),默认为3
→ -1时,自动转换为scharr算子
- 修正梯度结果(负数转正)
dst = cv2.convertScaleAbs(src[,alpha[,beta]])
dst = cv2.convertScaleAbs(src) 简化版
将原始图像转换为256色位图,表示对负数取绝对值 dst = 调整(原始图像*alpha系数 + beta修正值)
- 计算sobel
有2种方式.
・方式1不太严谨,往往会得到错误的结果
・所以一般采用方式2: 分别计算出x,y方向的梯度后相加
方式2 借用cv2.addWeighted
函数计算 x,y 两幅图像的权重和
dst= cv2.addWeighted(src1,alpha,src2,beta,gamma)
其中,参数:
・dst– 计算结果;
・src1 – 源图像1;
・alpha– 源图像1系数;
・src2 – 源图像2;
・beta– 源图像2系数;
・gamma– 修正值;
2.2 代码示例
import cv2
import numpy as np
o = cv2.imread('image\\sobel4.bmp',cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(o,cv2.CV_64F,1,0,ksize=3)
sobely = cv2.Sobel(o,cv2.CV_64F,0,1,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx) # 转回uint8
sobely = cv2.convertScaleAbs(sobely)
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0) # x,y方向两幅图像的权重和 dx + dy
sobelxy11=cv2.Sobel(o,cv2.CV_64F,1,1,ksize=3) # dx=1 ,dy =1
cv2.imshow("original",o)
cv2.imshow("x",sobelx)
cv2.imshow("y",sobely)
cv2.imshow("xy",sobelxy)
cv2.imshow("xy11",sobelxy11)
cv2.waitKey()
cv2.destroyAllWindows()
运行结果
● 示例2
sobelxy11=cv2.Sobel(o,cv2.CV_64F,1,1,
ksize=3)
dx=1 ,dy =1 经常会被忽略,容易出错. 无法正常提取到边界
3 scharr算子函数及其使用
3.1 基础理论
- 目的: 使用3*3sobel算子时,并不够精确. scharr算子计算梯度效果更好
- 相当于sobel算子的改进,但是卷积核的系数不一样
- 运算强度,速度完全等价
cv2.Scharr
函数
dst= cv2.Scharr(src, ddepth, dx, dy)
其中,参数:
・dst– 计算结果;
・src – 源图像;
・ddepth– 图像深度;
→ -1时,表示和原图深度一致,但计算梯度时出现负数,自动截断为0,导致信息丢失 ,鉴于此
→ a) 深度先设置为, cv2.CV_64F 数据类型(可保存负值) 详细官方文档
→ b) cv2.convertScaleAbs(dst) 对a)结果取绝对值后,再转换为np.uint8类型
・dx – x方向: [dx=1,dy=0]
・dy – y方向: [dx=0,dy=1]
- 两个方向梯度
・与sobel类似,两个方向梯度 = dx + dy
→scharrxy = cv2.addWeighted(scharrx,0.5,scharry,0.5,0)
・满足条件: dx>=0 且 dy >=0 且 dx + dy ==1
3.2 代码示例
- x方向梯度
import cv2
import numpy as np
o = cv2.imread('image\\scharr.bmp', cv2.IMREAD_GRAYSCALE)
scharrx = cv2.Scharr(o, cv2.CV_64F, 1, 0) #1,0表示x方向
scharrx = cv2.convertScaleAbs(scharrx) #转回uint8
cv2.imshow("original", o)
cv2.imshow("x", scharrx)
cv2.waitkey()
cv2.destroyAllWindows()
运行结果
- y方向梯度
import cv2
import numpy as np
o = cv2.imread('image\\scharr.bmp', cv2.IMREAD_GRAYSCALE)
scharry = cv2.Scharr(o, cv2.CV_64F, 0, 1) #1,0表示x方向
scharry = cv2.convertScaleAbs(scharry) #转回uint8
cv2.imshow("original", o)
cv2.imshow("y", scharry)
cv2.waitkey()
cv2.destroyAllWindows()
运行结果
- 两个方向梯度
使用函数cv2.addWeighted(scharrx, alpha, scharry, beta, gamma)
scharrxy = cv2.addweighted(scharrx, 0.5, scharry, 0.5, 0)
运行结果
scharrscharr是sobel算子的进化版, 用sobel算子也能达到scharr算子的效果.
4 sobel算子和scharr算子的比较
4.1 基础理论
- sobel算子系数:1,2,1 ; scharr算子3,10,3 ;
- 临近的像素点权重值更高, 所以scharr算子要比sobel算子拥有更高的精确度
4.2 代码示例
示例
import cv2
import numpy as np
o = cv2.imread('image\\lena.bmp', cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(o, cv2.CV_64F, 1, 0, ksize=3)
sobely = cv2.Sobel(o, cv2.CV_64F, 0, 1, ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
sobely = cv2.convertScaleAbs(sobey)
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
scharrx = cv2.Scharr(o,cv2.CV_64F,1,0)
scharry = cv2.Scharr(o,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("original",o)
cv2.imshow("sobelxy",sobelxy)
cv2.imshow("scharrxy",scharrxy)
cv2.waitkey()
cv2.destoryAllWindows()
运行结果
- scharr算子把比较细小的边界也检测出来
- sobel算子仅检测出了比较重的边界, 仅把差值大的像素点检测出来
- 根据不同的应用场景,选择不同的算子
5 laplacian算子及使用
5.1 基础理论
- 拉普拉斯算子类似于二阶sobel倒数,OpenCV里调用sobel算子来计算拉普拉斯算子
- 使用公式
- 使用卷积核
- 和sobel算子,scharr算子的比较
具体含义
cv2.Laplacian
函数
dst= cv2.Laplacian(src,ddepth)
其中,参数:
・dst– 计算结果;
・src – 源图像;
・ddepth– 图像深度;
→通常设置为-1, 表示和原图像一致
→为了防止出现负值时的截断, 可用cv2.CV_64F
5.2 代码示例
示例
import cv2
import numpy as np
o = cv2.imread('image\\lena.bmp', cv2.IMREAD_GRAYSCALE)
laplacian= cv2.Laplacian(o, cv2.CV_64F)
laplacian= cv2.convertScaleAbs(laplacian)
cv2.imshow("original",o)
cv2.imshow("laplacian",laplacian)
cv2.waitkey()
cv2.destoryAllWindows()
结果1
结果2