图像梯度
图像梯度¶
图像梯度代表图像灰度值变化的速度,对于一副图像而言,其边缘部分两侧灰度值相差较大,梯度值大,所以对一副图像求梯度可以突出图像边缘的信息。由于像素值为离散值,所以其梯度其是就是差分运算,其本质上也就是一种空间滤波。
sobel算子¶
其掩膜结构为:
- 水平梯度
G_x = \left[
\begin{matrix}
-1 & 0 & 1 \newline
-2 & 0 & 2 \newline
-1 & 0 & 1
\end{matrix}
\right]
-
垂直梯度 $$ G_y = \left[ \begin{matrix} -1 & -2 & -1 \newline 0 & 0 & 0 \newline 1 & 2 & 1 \end{matrix} \right] $$
-
合成
G=\sqrt{G_{x}^{2}+G_{y}^{2}}
opencv中提供了cv2.Sobel()来实现Sobel算子的运算:
dst=cv2.Sobel(src,ddepth,dx,dy,[,ksize[,scale[,delta[,borderType]]]])
参数说明: dst:目标输出图像 src:原始输入图像 ddepth:图像深度,默认值-1与原始图像相同深度,但注意原始图像一般为cv2.CV_8U,则由于求梯度的时候会出现负值的情况,其会将负值直接置为0,此时会丢失图像许多信息,所以要将其一般转化为更高位灰度去求梯度,再对结果求绝对值。ddepth一般取cv2.CV_64F。 dx:代表x方向上求导 dy:代表y方向上求导 ksize:掩模大小 scale:求导之后值的缩放因子,默认为1,即不会缩放 delta:表示偏置在目标图像上的值,用于调节亮度 borderType:边界处理类型
示例代码:
import cv2 as cv
img = cv.imread("img/brain.jpg",cv.IMREAD_GRAYSCALE)
cv.imshow("src",img)
# sobel算子 参数1:图像, 参数2:图像的深度 -1表示和原图相同, 参数3: x方向求导的阶数 参数4: y方向求导的阶数
x_sobel = cv.Sobel(img, cv.CV_32F, 1, 0)
# 将图像转成8位int
x_sobel = cv.convertScaleAbs(x_sobel)
cv.imshow("x sobel",x_sobel)
# sobel算子
y_sobel = cv.Sobel(img, cv.CV_16S, 0, 1)
# 将图像转成8位int
y_sobel = cv.convertScaleAbs(y_sobel)
cv.imshow("y_sobel",y_sobel)
# 将x,y方向的内容叠加起来
x_y_sobel = cv.addWeighted(x_sobel, 0.5, y_sobel, 0.5,0)
cv.imshow("x,y sobel",x_y_sobel)
cv.waitKey(0)
cv.destroyAllWindows()
scharr算子¶
其基本思想与sobel算子一样,只是两者所使用掩模的结构不一样,在运算中,其梯度近似的结果比sobel更精确,其算子如下:
- 水平梯度
G_x = \left[
\begin{matrix}
-3 & 0 & 3 \newline
-10 & 0 & 10 \newline
-3 & 0 & 3
\end{matrix}
\right]
- 垂直梯度
G_y = \left[
\begin{matrix}
-3 & -10 & -3 \newline
0 & 0 & 0 \newline
3 & 10 & 3
\end{matrix}
\right]
在opencv中提供的函数为cv2.Scharr():
dst=cv2.Scharr(src,ddepth,dx,dy,[,ksize[,scale[,delta[,borderType]]]])
laplace算子¶
其是对像素点求二阶导,即二阶差分,其对噪声点的锐化更加突出。 opencv提供的函数为cv2.Laplacian(),
dst=cv2.Laplacian(src,ddepth,[,ksize[,scale[,delta[,borderType]]]])
各参数意义与sobel一样,只是其求二阶导,无需指定对dx,与dy方向是否求导。
示例代码:
import cv2 as cv
img = cv.imread("img/grbq.jpg",cv.IMREAD_GRAYSCALE)
cv.imshow("src",img)
# 使用拉普拉斯算子
dst = cv.Laplacian(img,cv.CV_32F)
# 取绝对值,将数据转到uint8类型
dst = cv.convertScaleAbs(dst)
cv.imshow("dst",dst)
cv.waitKey(0)
cv.destroyAllWindows();