圖像梯度計算



零、梯度理論

可以把圖像看成二維離散函數,圖像梯度就是這個二維離散函數的求導:

梯度一般產生在邊緣位置;


OpenCV 提供了三種不同的梯度濾波器,或者說高通濾波器:Sobel,Scharr和Lapacian。
Sobel,Scharr其實就是求一階或二階導。
Scharr是對Sobel的部分優化。
Laplacian是求二階導。


一、Sobel 算子

一個點附近是什么;

$ G_x 水平, G_y 豎直 $

將附近的點使用權重相加減,得到像素點差異值作為水平/垂直方向的梯度;

以下以 3*3 的核為例

$ G_x = \left[ \begin{matrix} -1 & 0 & +1 \ -2 & 0 & +2 \ -1 & 0 & +1 \end{matrix} \right] * A $

$ G_y = \left[ \begin{matrix} -1 & -2 & -1 \ 0 & 0 & 0 \ +1 & +2 & +1 \end{matrix} \right] * A $


cv2. Sobel 方法

Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]]) -> dst

  • ddepth:圖像的深度
  • dx和dy分別表示水平和豎直方向
  • ksize是Sobel算子的大小

import cv2
import numpy as np
import matplotlib.pyplot as plt

lena = cv2.imread('lena.jpg')
lena_gray = cv2.imread('lena.jpg', 0)
pie = cv2.imread('pie.png')
# cv2.CV_64F 的位數更多,能表示負數的形式  
sobelx = cv2.Sobel(pie, cv2.CV_64F, 1, 0, ksize=3)
plt.imshow(sobelx)
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).


openCV 會對負數做截斷;所以上方沒有顯示右側的梯度;
解決方法:取絕對值

sobelx = cv2.Sobel(pie, cv2.CV_64F, 1, 0, ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
plt.imshow(sobelx)


# 將 0,1 參數切換,計算豎直方向,不計算水平方向
sobely = cv2.Sobel(pie, cv2.CV_64F, 0, 1, ksize=3)
sobely = cv2.convertScaleAbs(sobely)
plt.imshow(sobely)


# 不能取 0,0
sobelx = cv2.Sobel(pie, cv2.CV_64F, 1, 1, ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
plt.imshow(sobelx)


# 計算整體的時候,分別計算 x 和 y,再求和;
# 以上都設置為 1 的效果,沒有這樣求和的效果好;

sobelxy = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0)
plt.imshow(sobelxy)



sobelx = cv2.Sobel(lena_gray, cv2.CV_64F, 1, 0, ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)

sobely = cv2.Sobel(lena_gray, cv2.CV_64F, 0, 1, ksize=3)
sobely = cv2.convertScaleAbs(sobely)

sobelxy = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0)
plt.imshow(sobelxy)



 plt.imshow(np.hstack([lena_gray,sobelxy]))


二、Scharr 算子

Sobel 算子 計算得到的值比較小;對數據更敏感;

$ G_x = \left[ \begin{matrix} -3 & 0 & 3 \ -10 & 0 & 10 \ -3 & 0 & 3 \end{matrix} \right] * A $

$ G_y = \left[ \begin{matrix} -3 & -10 & -3 \ 0 & 0 & 0 \ -3 & -10 & -3 \end{matrix} \right] * A $


scharrx = cv2.Scharr(lena_gray, cv2.CV_64F, 1, 0)
scharry = cv2.Scharr(lena_gray, cv2.CV_64F, 0, 1)

scharrx = cv2.convertScaleAbs(scharrx)
scharry = cv2.convertScaleAbs(scharry)

scharrxy = cv2.addWeighted(scharrx, 0.5, scharry, 0.5, 0)


三、lapkacian 拉普拉斯算子

Laplace Operator

其他算子一般是一階導;拉普拉斯用到了二階導;

用中間點和邊緣四個點比較;

不建議單獨使用;一般和其他算法結合。

$ G = \left[ \begin{matrix} 0 & 1 & 0 \ 1 & -4 & 1 \ 0 & 1 & 0 \end{matrix} \right] * A $


laplacian = cv2.Laplacian(lena_gray, cv2.CV_64F)

laplacian = cv2.convertScaleAbs(laplacian)
 
res = np.hstack((sobelxy, scharrxy, laplacian))
plt.imshow(res)




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM