Python OpenCV 365 天學習計劃纺棺,與橡皮擦一起進入圖像領域吧。本篇博客是這個系列的第 46 篇邪狞。
該系列文章導航參考:https://blog.csdn.net/hihell/category_10688961.html
基礎知識鋪墊
關于 Sobel 算子祷蝌、Scharr 算子、laplacian 算子在 這篇博客 中已經(jīng)學習過了帆卓,第二次學習巨朦,可以針對算子卷積核進行一下稍微深入一點的理解。
Sobel 算子
使用該函數(shù)時剑令,卷積核在 X 方向為: 糊啡,在 Y 方向為
上述卷積核時一個 3x3
的矩陣,當其與一個圖像進行卷積計算的時候吁津,如果覆蓋的矩陣是
計算之后會得到如下結(jié)果 棚蓄,結(jié)果越大,差異越明顯碍脏,還有為什么在
與
點梭依,卷積核的值大,簡單理解就是這個點距離中心點近典尾。
先寫一段測試代碼如下:
import cv2 as cv
import numpy as np
src = cv.imread('./star.png')
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(gray, 127, 255, cv.THRESH_BINARY_INV)
# Sobel 算子計算邊緣
sobel_x = cv.Sobel(thresh, -1, 1, 0, ksize=3)
image = np.hstack((gray, thresh, sobel_x))
cv.imshow("image", image)
cv.waitKey()
運行結(jié)果如下:
最后一幅圖片獲取到的是圖形的左側(cè)役拴,原因是這樣導致的。
Sobel 在計算的是時候是右側(cè)減左側(cè)钾埂、下面減上面河闰,查看二值化圖形會發(fā)現(xiàn),右側(cè)減左側(cè)會得到左側(cè)邊緣的原因是勃教,圖形左側(cè)的邊緣兩邊淤击,右側(cè)是白色 255,左側(cè)是黑色 0故源,所以可以得到邊緣,相同的方式汞贸,在圖形右側(cè)邊緣部分绳军,兩邊分別是右側(cè)黑色印机、左側(cè)白色,所以邊緣缺失门驾。
如果希望右側(cè)邊緣也同時出現(xiàn)射赛,需要用到下述函數(shù),將得到的負值獲取絕對值奶是。
另一處代碼修改的地方在代碼注釋部分:
# Sobel 算子計算邊緣
# 注意計算 sobel_x 的函數(shù)傳遞參數(shù)的時候楣责,第二個參數(shù)從 -1 修改為 cv.CV_64F,目的是為了獲取到負值聂沙,方便后面的獲取絕對值操作秆麸。
sobel_x = cv.Sobel(thresh, cv.CV_64F, 1, 0, ksize=3)
sobel_x = cv.convertScaleAbs(sobel_x)
image = np.hstack((gray, thresh, sobel_x))
上述代碼計算的是 X 方向的邊緣沮趣,同理計算一下 Y 方向的邊緣,在合并 X 與 Y 方向的邊緣坷随,即可得到最后的圖像邊緣房铭。
import cv2 as cv
import numpy as np
src = cv.imread('./star.png')
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(gray, 127, 255, cv.THRESH_BINARY_INV)
# Sobel 算子計算邊緣
sobel_x = cv.Sobel(thresh, cv.CV_64F, 1, 0, ksize=3)
sobel_y = cv.Sobel(thresh, cv.CV_64F, 0, 1, ksize=3)
sobel_x = cv.convertScaleAbs(sobel_x)
sobel_y = cv.convertScaleAbs(sobel_y)
sobel_xy = cv.addWeighted(sobel_x, 0.5, sobel_y, 0.5, 0)
image = np.hstack((gray, sobel_xy, sobel_x, sobel_y))
cv.imshow("image", image)
cv.waitKey()
合并之后運行結(jié)果如下缸匪,一般不建議直接計算 X 和 Y 方向的 Sobel,而應該分別計算之后再進行合并类溢。
可以對比一下分開計算再合并與直接計算的效果差異凌蔬。
上述圖片是由下面的代碼運行得到的結(jié)果
import cv2 as cv
import numpy as np
src = cv.imread('./t3.jpg')
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(gray, 127, 255, cv.THRESH_BINARY_INV)
# Sobel 算子分開計算
sobel_x = cv.Sobel(thresh, cv.CV_64F, 1, 0, ksize=3)
sobel_y = cv.Sobel(thresh, cv.CV_64F, 0, 1, ksize=3)
sobel_x = cv.convertScaleAbs(sobel_x)
sobel_y = cv.convertScaleAbs(sobel_y)
sobel_xy = cv.addWeighted(sobel_x, 0.5, sobel_y, 0.5, 0)
# 直接計算
sobel_xy1 = cv.Sobel(thresh, cv.CV_64F, 1, 1, ksize=3)
sobel_xy1 = cv.convertScaleAbs(sobel_xy1)
image = np.hstack((gray, sobel_xy, sobel_xy1))
cv.imshow("image", image)
cv.waitKey(0)
Scharr 算子
該算子有著比 Sobel 更好的精確度,主要因為它的卷積核是下面的數(shù)據(jù)
使用的時候依舊是分開計算
import cv2 as cv
import numpy as np
src = cv.imread('./t3.jpg')
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(gray, 127, 255, cv.THRESH_BINARY_INV)
# Scharr 算子分開計算
scharr_x = cv.Scharr(thresh, cv.CV_64F, 1, 0)
scharr_y = cv.Scharr(thresh, cv.CV_64F, 0, 1)
scharr_x = cv.convertScaleAbs(scharr_x)
scharr_y = cv.convertScaleAbs(scharr_y)
scharr_xy = cv.addWeighted(scharr_x, 0.5, scharr_y, 0.5, 0)
image = np.hstack((gray, scharr_xy))
cv.imshow("image", image)
cv.waitKey(0)
laplacian 算子
概算子的卷積核如下:
laplacian 算子噪點敏感豌骏,在使用的時候需要提前去噪龟梦。
橡皮擦的小節(jié)
希望今天的 1 個小時你有所收獲,我們下篇博客見~
相關閱讀
技術專欄