import cv2
import numpy as np
import matplotlib.pyplot as plt
def cv_show(name, mat):
cv2.imshow(name, mat)
cv2.waitKey(0)
cv2.destroyAllWindows()
对周围各点赋予权重,再计算梯度
计算垂直方向梯度的权重【水平方向则是它的转置矩阵】
### 函数原型
void cv::Sobel(InputArray src,
OutputArray dst,
int ddepth,
int dx,
int dy,
int ksize = 3,
double scale = 1,
double delta = 0,
int borderType = BORDER_DEFAULT
)
### 在python中使用
dst = cv2.Sobel(src, ddepth, dx, dy, dst, ksize, scale, delta, borderType)
src | 原图像 |
dst | 处理后的图像,大小类型须和原图像相同 |
ddepth | 输出图像深度 |
dx | 置1则计算x方向的梯度 |
dy | 置1则计算y方向的梯度 |
ksize | 参考的像素点范围,必须是1, 3, 5, or 7. |
scale | 计算导数值的可选比例因子;默认情况下,不应用缩放 |
delta | 结果偏移量 |
borderType | 像素外推方法 |
img = cv2.imread('C://Users//rwhite//Pictures//opencv//test.jpg', cv2.IMREAD_GRAYSCALE)
dstx = cv2.Sobel(img, cv2.CV_64F, dx = 1, dy = 0, ksize=3)
dsty = cv2.Sobel(img, cv2.CV_64F, dx = 0, dy = 1, ksize=3)
cv2.imwrite('C://Users//rwhite//Pictures//opencv//dstx.jpg', dstx)
cv2.imwrite('C://Users//rwhite//Pictures//opencv//dsty.jpg', dsty)
sobel算子对梯度的计算遵循“右边像素减左边像素”。以x轴方向的梯度计算为例。
白色圆圈的左半边均为白色像素(右边像素)减去黑色像素(左边像素),所以左半边的梯度都为正数,即显示为白色轮廓。
而白色圆圈的右半边是黑色像素(右边像素)减去白色像素(左边像素),结果为负数,会自动截取为0,所以显示为一片黑色。
因此,为了得到完整的梯度图,需要对计算结果取绝对值。
#上述代码再增加两个步骤
dstx = cv2.convertScaleAbs(dstx)
dsty = cv2.convertScaleAbs(dsty)
最后在对x方向和y方向的梯度进行整合:
dst = cv2.addWeighted(dstx, 0.5, dsty, 0.5, 0)
Ps:不建议使用sobel算子同时计算x和y方向上的梯度(即同时将dx和dy置1),效果较差:
计算方式与sobel算子相同,但对周围像素点的权重不同。
scharr对周围像素点更为敏感,能捕捉到更多信息。
函数使用方法也与sobel算子相同。
计算方式与sobel算子相同,但对周围像素点的权重不同。
对噪音点会比较敏感。
函数使用方法与sobel算子相似,不同在于不用设置dx和dy。