這里需要區(qū)分開邊緣檢測和輪廓檢測
邊緣檢測并非萬能,邊緣檢測雖然能夠檢測出邊緣,但邊緣是不連續(xù)的,檢測到的邊緣并不是一個(gè)整體。圖像輪廓是指將邊緣連接起來形成的一個(gè)整體,用于后續(xù)的計(jì)算。
OpenCV 提供了查找圖像輪廓的函數(shù) cv2.findContours(),該函數(shù)能夠查找圖像內(nèi)的輪廓信息,而函數(shù)cv2.drawContours()能夠?qū)⑤喞L制出來。
一、圖像梯度
圖像梯度是指圖像中灰度強(qiáng)度變化的方向和幅度。梯度計(jì)算對于許多計(jì)算機(jī)視覺和圖像處理任務(wù)非常重要,如邊緣檢測、特征提取等。
圖像梯度通常使用Sobel、Scharr或其他卷積核進(jìn)行計(jì)算。這些卷積核可以在圖像上進(jìn)行卷積操作,以便檢測圖像中的水平和垂直邊緣。梯度的方向表示灰度變化最快的方向,而梯度的幅度表示這個(gè)變化的強(qiáng)度。
·
圖像梯度是指圖像中像素值變化的快慢和方向。在圖像處理中,常用于檢測圖像中的邊緣和輪廓。圖像梯度的計(jì)算可以通過一階或二階導(dǎo)數(shù)的方法來實(shí)現(xiàn)。
1.1 介紹
-
一階導(dǎo)數(shù)(梯度):
- 水平方向梯度(Gx): 表示圖像在水平方向上的變化率。
- 垂直方向梯度(Gy): 表示圖像在垂直方向上的變化率。
-
梯度幅值: 通過Gx和Gy的組合計(jì)算,通常使用歐幾里得范數(shù)(平方和的平方根)表示:
-
梯度方向:
- 梯度方向角度(θ): 通過arctan(Gy/Gx)計(jì)算,表示梯度的方向。
-
邊緣檢測:
- 基于圖像梯度的邊緣檢測算法,如Sobel、Prewitt、Roberts等,通過卷積運(yùn)算來獲取圖像梯度。
-
Canny邊緣檢測:
- Canny邊緣檢測是一種常用的邊緣檢測方法,它利用圖像梯度的幅值和方向來檢測邊緣。
-
圖像增強(qiáng):
- 圖像梯度也可以用于圖像增強(qiáng),通過調(diào)整圖像梯度的幅值和方向來改善圖像的視覺效果。
在實(shí)際圖像處理中,圖像梯度是一個(gè)重要的特征,它不僅用于邊緣檢測,還可以應(yīng)用于目標(biāo)檢測、圖像分割和其他計(jì)算機(jī)視覺任務(wù)。通過分析圖像梯度,可以獲取關(guān)于圖像結(jié)構(gòu)和內(nèi)容的有用信息。
1.2 涉及函數(shù)
-
Sobel算子:
-
cv2.Sobel(src, ddepth, dx, dy, ksize)
: 對圖像進(jìn)行Sobel算子的卷積操作,其中dx
和dy
表示求導(dǎo)的階數(shù),ksize
是卷積核的大小。
-
-
Scharr算子:
-
cv2.Scharr(src, ddepth, dx, dy)
: 類似于Sobel,用于對圖像進(jìn)行Scharr算子的卷積操作。
-
-
Laplacian算子:
-
cv2.Laplacian(src, ddepth)
: 對圖像進(jìn)行Laplacian算子的卷積操作,用于增強(qiáng)圖像中的高頻信息。
-
-
Canny邊緣檢測:
-
cv2.Canny(image, threshold1, threshold2)
: 使用Canny邊緣檢測算法,threshold1
和threshold2
是梯度閾值,用于定義邊緣的強(qiáng)弱。
-
-
角度和幅值計(jì)算:
-
cv2.phase(x, y)
: 計(jì)算輸入圖像梯度的相位角度。 -
cv2.magnitude(x, y)
: 計(jì)算輸入圖像梯度的幅值。
-
-
圖像梯度計(jì)算:
-
cv2.Sobel()
,cv2.Scharr()
, 和cv2.Laplacian()
的輸出可以通過cv2.magnitude()
和cv2.phase()
計(jì)算幅值和相位。
-
-
圖像增強(qiáng):
- 借助梯度信息可以進(jìn)行圖像增強(qiáng),例如通過調(diào)整梯度的幅值來實(shí)現(xiàn)銳化。
-
圖像顯示:
-
cv2.imshow(window_name, image)
: 用于顯示圖像,可以用來顯示梯度圖等中間結(jié)果。
-
二、高頻強(qiáng)調(diào)濾波器
在OpenCV中,梯度濾波器或高通濾波器通常用于突出圖像中的邊緣和細(xì)節(jié)。這些濾波器是一種高頻強(qiáng)調(diào)濾波器,可以通過卷積操作來應(yīng)用于圖像。、
-
Sobel濾波器:
- Sobel濾波器是一種常用的梯度濾波器,用于在圖像中檢測邊緣。它分為水平和垂直兩個(gè)方向。
sobelx = cv2.Sobel(src, cv2.CV_64F, 1, 0, ksize=3) sobely = cv2.Sobel(src, cv2.CV_64F, 0, 1, ksize=3)
這里,
1
和0
分別表示水平和垂直方向,ksize
是卷積核的大小。 -
Scharr濾波器:
- Scharr濾波器類似于Sobel,但對邊緣的響應(yīng)更強(qiáng)。你可以使用
cv2.Scharr()
函數(shù)來應(yīng)用Scharr濾波器。
scharrx = cv2.Scharr(src, cv2.CV_64F, 1, 0) scharry = cv2.Scharr(src, cv2.CV_64F, 0, 1)
- Scharr濾波器類似于Sobel,但對邊緣的響應(yīng)更強(qiáng)。你可以使用
-
Laplacian濾波器:
- Laplacian濾波器用于增強(qiáng)圖像的高頻部分,通常用于邊緣檢測。
laplacian = cv2.Laplacian(src, cv2.CV_64F)
-
Canny邊緣檢測:
- Canny邊緣檢測是一種綜合了梯度信息的方法,包括非極大值抑制和雙閾值處理。
edges = cv2.Canny(src, threshold1, threshold2)
其中,
threshold1
和threshold2
是梯度閾值,用于定義邊緣的強(qiáng)弱。
這些濾波器可以幫助突出圖像中的邊緣信息,對于圖像處理中的特定任務(wù),你可以根據(jù)需要選擇合適的濾波器。
2.1 Sobel 算子
2.1.1 Sobel 理論基礎(chǔ)
Sobel算子是一種常用的邊緣檢測算法,用于計(jì)算圖像中像素點(diǎn)的梯度強(qiáng)度。在Sobel算子中,中心點(diǎn)相連的系數(shù)為2,是為了更好地捕捉圖像中的邊緣信息。
Sobel算子包含兩個(gè)3x3的卷積核(一個(gè)用于檢測水平邊緣,另一個(gè)用于檢測垂直邊緣)
- 水平方向Sobe檢測核:
-1 -2 -1
0 0 0
1 2 1
水平方向Sobel算子的卷積核主要關(guān)注圖像中水平方向的變化。它通過將權(quán)重分配給中間列和左右列的像素,來檢測圖像中的水平邊緣。
- 垂直方向Sobel檢測核:
-1 0 1
-2 0 2
-1 0 1
垂直方向Sobel算子的卷積核主要關(guān)注圖像中垂直方向的變化。它通過將權(quán)重分配給中間行和上下行的像素,來檢測圖像中的垂直邊緣。
- 梯度計(jì)算:
假設(shè)要計(jì)算圖像中某個(gè)像素位置的值,例如該位置為圖像中的中心點(diǎn)(i,j)位置。卷積操作的計(jì)算步驟如下:
-
將Sobel算子的中心(1,1)位置與圖像中以該點(diǎn)為中心的3x3區(qū)域進(jìn)行對應(yīng)元素相乘,并將結(jié)果相加。
-
(1)對于水平邊緣檢測核:
(-1 * I(i-1, j-1)) + (-2 * I(i, j-1)) + (-1 * I(i+1, j-1)) + (0 * I(i-1, j)) + (0 * I(i, j)) + (0 * I(i+1, j)) + (1 * I(i-1, j+1)) + (2 * I(i, j+1)) + (1 * I(i+1, j+1))
其中,I(i, j) 表示圖像中像素位置為 (i, j) 的值。
簡化:
P5x = (P3-P1) + 2·(P6-P4) + (P9-P7)
- (2) 垂直邊緣檢測核的計(jì)算公式:
(-1 * I(i-1, j-1)) + (0 * I(i, j-1)) + (1 * I(i+1, j-1)) +
(-2 * I(i-1, j)) + (0 * I(i, j)) + (2 * I(i+1, j)) +
(-1 * I(i-1, j+1)) + (0 * I(i, j+1)) + (1 * I(i+1, j+1))
簡化:
P5y = (P7-P1) + 2·(P8-P2) + (P9-P3)
Sobel算子的應(yīng)用可以幫助檢測圖像中的邊緣,因?yàn)樵谶吘壧?,圖像的強(qiáng)度發(fā)生明顯的變化,導(dǎo)致梯度的幅值較大。Sobel算子在實(shí)際圖像處理中廣泛應(yīng)用,尤其是在計(jì)算機(jī)視覺和圖像分析領(lǐng)域,為后續(xù)的邊緣檢測和圖像特征提取提供了基礎(chǔ)。
2.1.2 Sobel 算子及函數(shù)使用
dst = cv2.Sobel(src, ddepth, dx, dy[, ksize[, scale[, delta[, borderType]]]])
其中參數(shù)的含義如下:
-
src
: 輸入圖像,通常是灰度圖像。 -
ddepth
: 輸出圖像的深度(數(shù)據(jù)類型)。通常使用cv2.CV_64F
或-1
(讓處理結(jié)果與原始圖像保持一致)。
當(dāng) ddepth 設(shè)置為 -1 時(shí),如果 Sobel 濾波器的計(jì)算導(dǎo)致了負(fù)數(shù),這些負(fù)數(shù)將被截?cái)酁?0。這可能導(dǎo)致信息的丟失,因?yàn)樨?fù)數(shù)通常在圖像處理中是有意義的。
為了避免信息丟失,推薦使用更高的數(shù)據(jù)類型來進(jìn)行計(jì)算,例如 cv2.CV_64F,即64位浮點(diǎn)型。這樣,計(jì)算結(jié)果將以浮點(diǎn)數(shù)的形式保存,包括負(fù)數(shù)。然后,可以通過取絕對值或其他操作將其映射為需要的數(shù)據(jù)類型,例如 cv2.CV_8U,即8位無符號整數(shù)。
-
dx
和dy
: 分別表示在 x 和 y 方向上的導(dǎo)數(shù)的階數(shù),通常是 0 或 1。 -
ksize
: 可選參數(shù),表示 Sobel 濾波器的大小,通常是 1、3、5 或 7。默認(rèn)值是 3。
當(dāng)該值為-1 時(shí),則會使用 Scharr 算子進(jìn)行運(yùn)算。 -
scale
: 可選參數(shù),用于縮放導(dǎo)數(shù)的比例因子。默認(rèn)值是 1,是沒有縮放的。 -
delta
: 可選參數(shù),表示可選的增加到輸出圖像的值,用于調(diào)整圖像的亮度。默認(rèn)值是 0。 -
borderType
: 可選參數(shù),表示圖像邊界的處理方式。默認(rèn)值是cv2.BORDER_DEFAULT
。
這個(gè)函數(shù)的作用是應(yīng)用 Sobel 濾波器,計(jì)算圖像中每個(gè)像素點(diǎn)的梯度。dx
和 dy
參數(shù)決定了計(jì)算的梯度方向,常見的取值為 0、1,表示水平和垂直方向的梯度。ksize
參數(shù)用于指定 Sobel 濾波器的大小。
絕對值的原因:為了讓偏導(dǎo)數(shù)正確地顯示出來,需要將值為負(fù)數(shù)的近似偏導(dǎo)數(shù)轉(zhuǎn)換為正數(shù)。即,要將偏導(dǎo)數(shù)取絕對值,以保證偏導(dǎo)數(shù)總能正確地顯示出來。
`
如果不取絕對值,梯度的正負(fù)將分別表示變化的方向。但在實(shí)際應(yīng)用中,我們更關(guān)心圖像中是否存在邊緣以及邊緣的強(qiáng)度,而不太在意邊緣的具體方向。因此,為了簡化計(jì)算并準(zhǔn)確表示邊緣的變化強(qiáng)度,常常使用絕對值來忽略方向信息。設(shè)想在二維圖像中有兩個(gè)線條 A 和 B,A 線條是一條黑到白的線,B 線條是一條白到黑的線。
若針對 A 線條所在列,右側(cè)像素值減去左側(cè)像素值所得近似偏導(dǎo)數(shù)的值為-1。 ? 針對 B 線條所在列,右側(cè)像素值減去左側(cè)像素值所得近似偏導(dǎo)數(shù)的值為 1。針對 A 線條所在行,下方像素值減去上方像素值所得近似偏導(dǎo)數(shù)為-1。 ? 針對 B 線條所在行,下方像素值減去上方像素值所得近似偏導(dǎo)數(shù)為 1。
示例:
import cv2
import numpy as np
# 讀取圖像
image = cv2.imread('input_image.jpg', cv2.IMREAD_GRAYSCALE)
# 應(yīng)用 Sobel 濾波器計(jì)算水平方向的梯度
sobelx = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=3)
# 應(yīng)用 Sobel 濾波器計(jì)算垂直方向的梯度
sobely = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=3)
這將分別計(jì)算圖像中每個(gè)像素點(diǎn)的水平和垂直方向的梯度。你可以根據(jù)需要進(jìn)一步處理這些梯度圖像,例如計(jì)算梯度幅值和方向,用于邊緣檢測或其他圖像處理任務(wù)。
(1)對參數(shù)取絕對值
cv2.convertScaleAbs()
是 OpenCV 中用于線性縮放和截?cái)嗟暮瘮?shù)。它的目的是將輸入數(shù)組進(jìn)行線性縮放并進(jìn)行截?cái)?,最后將結(jié)果轉(zhuǎn)換為無符號8位整數(shù)(cv2.CV_8U
)類型。
該函數(shù)的基本語法如下:
#該函數(shù)的作用是將原始圖像 src 轉(zhuǎn)換為 256 色位圖
import cv2
dst = cv2.convertScaleAbs(src [, alpha[, beta]])
其中:
src
: 輸入數(shù)組,即待處理的圖像或數(shù)據(jù)。alpha
: 縮放因子,用于乘以輸入數(shù)組的每個(gè)元素。默認(rèn)值為 1。beta
: 偏移量,用于在縮放后對每個(gè)元素進(jìn)行加法運(yùn)算。默認(rèn)值為 0。
import cv2
import numpy as np
# 讀取圖像
image = cv2.imread('input_image.jpg', cv2.IMREAD_GRAYSCALE)
# 縮放和平移圖像,然后取絕對值
alpha = 1.5
beta = 20
result = cv2.convertScaleAbs(image, alpha=alpha, beta=beta)
# 顯示原圖和處理后的圖像
cv2.imshow('Original Image', image)
cv2.imshow('Result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()
(2)控制dx,dy方向的求導(dǎo)階數(shù)
需要注意的是,dx和dy的值不能同時(shí)為0,因?yàn)橹辽僖谝粋€(gè)方向上進(jìn)行梯度計(jì)算,否則Sobel算子無法發(fā)揮作用。
1. 計(jì)算 x 方向邊緣(梯度):
-
dx=1, dy=0
,表示只計(jì)算圖像中每個(gè)像素點(diǎn)在 x 方向上的梯度。這有助于檢測圖像中水平方向的邊緣。
注意里面的ddepth的不同和求導(dǎo)的數(shù)字1和2造成的差別:
*
ddepth=-1
ddepth=cv2.CV_64F
2. 計(jì)算 y 方向邊緣(梯度):
-
dx=0, dy=1
,表示只計(jì)算圖像中每個(gè)像素點(diǎn)在 y 方向上的梯度。這有助于檢測圖像中垂直方向的邊緣。
3. 參數(shù) dx
和參數(shù) dy
的值均為 1
-
dx=1, dy=1
,表示同時(shí)計(jì)算圖像中每個(gè)像素點(diǎn)在 x 和 y 方向上的梯度。這將產(chǎn)生一個(gè)包含綜合梯度信息的結(jié)果,用于檢測邊緣的強(qiáng)度和方向。
出現(xiàn)零星的微小白點(diǎn),每個(gè)點(diǎn)的大小為一個(gè)像素。
4. 計(jì)算 x 方向和 y 方向的邊緣疊加:
- 通過組合不同的參數(shù),如
dx=1, dy=0
和dx=0, dy=1
,可以實(shí)現(xiàn)計(jì)算 x 方向和 y 方向的邊緣的疊加,得到更全面的邊緣信息。
dx= cv2.Sobel( src , ddepth , 1 , 0 )
dy= cv2.Sobel( src , ddepth , 0 , 1 )
dst=cv2.addWeighted( src1 , alpha , src2 , beta , gamma )
2.1.3通過實(shí)際例子表示
(1)簡單圖像
為了保留更多的有效信息,利用“cv2.CV_64F”,參數(shù) dx
和 dy 的值設(shè)置為“dx=1, dy=0”后執(zhí)行該函數(shù),再對該函數(shù)的結(jié)果計(jì)算絕對值并進(jìn)行對比
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
img = cv.imread('img8/testSobelimg.jpg', cv.IMREAD_GRAYSCALE)
sobelx = cv.Sobel(img, cv.CV_64F, 1, 0)
testsoblex = cv.Sobel(img, -1, 1, 0)
print(sobelx)
sobelxbeside = cv.convertScaleAbs(sobelx)
#%%
sobely = cv.Sobel(img, cv.CV_64F, 0, 1)
testsobley = cv.Sobel(img, -1, 0, 1)
print(sobely)
sobelybeside = cv.convertScaleAbs(sobely)
#%%
sobelxy = cv.Sobel(img, -1, 1, 1)
print(sobelxy)
Sobelxyy = cv.Sobel(img, -1, 1, 1)
plt.imshow(sobelxy, cmap='gray')
#%%
sobelxy = cv.addWeighted(sobelx, 1, sobely, 1, 0)
print(sobelxy)
plt.imshow(sobelxy, cmap='gray')
Sobelxybeside = cv.convertScaleAbs(sobelxy)
#%%
Sobelx = cv.convertScaleAbs(sobelxy)
print(Sobelx)
plt.imshow(Sobelx, cmap='gray')
#%% md
#%%
plt.figure(figsize=(12, 8))
plt.subplot(3, 3, 1), plt.imshow(img, cmap='gray'), plt.title('原始圖像')
plt.subplot(3, 3, 2), plt.imshow(sobelx, cmap='gray'), plt.title('sobelx')
plt.subplot(3, 3, 3), plt.imshow(sobely, cmap='gray'), plt.title('sobely')
plt.subplot(3, 3, 4), plt.imshow(Sobelxyy, cmap='gray')
plt.subplot(3, 3, 5), plt.imshow(sobelxbeside, cmap='gray'), plt.title('sobelxbeside')
plt.subplot(3, 3, 6), plt.imshow(sobelybeside, cmap='gray'), plt.title('sobelybeside')
plt.subplot(3, 3, 7), plt.imshow(Sobelxybeside, cmap='gray')
plt.subplot(3, 3, 8), plt.imshow(testsoblex, cmap='gray'), plt.title('testsoblex')
plt.subplot(3, 3, 9), plt.imshow(testsobley, cmap='gray'), plt.title('testsobley')
plt.show()
(2)復(fù)雜的,實(shí)際的相片
我們可以看到ddepth是-1和cv_64F的區(qū)別,在人物和這個(gè)細(xì)微
2.1.4 近似值
2.2 Scharr 算子
為了彌補(bǔ)Sobel不太精準(zhǔn)的情況,我們可以用 Scharr 算子并看作對 Sobel 算子的改進(jìn):
dst = cv2.Scharr( src, ddepth, dx, dy[, scale[, delta[, borderType]]] )
# 最好ddepth-cv2.cv_64F
dst= cv2.convertScaleAbs(dst)
2.2.1 等價(jià)的函數(shù)。
dst=cv2.Scharr(src, ddepth, dx, dy)
和 cv2.Sobel()中,如果 ksize=-1,則會使用 Scharr 濾波器。
dst=cv2.Sobel(src, ddepth, dx, dy, -1)
2.2.2需要滿足的條件:dx >= 0 && dy >= 0 && dx+dy = 1
參數(shù) ddepth 的值應(yīng)該設(shè)置為“cv2.CV_64F”,并對函數(shù)
cv2.Scharr()的計(jì)算結(jié)果取絕對值,才能保證得到正確的處理結(jié)果。
2.2.3 Sobel 算子和 Scharr 算子的比較
Sobel算子和Scharr算子都是用于圖像邊緣檢測的濾波器,它們在一些方面有相似之處,但也存在一些差異。以下是Sobel算子和Scharr算子的比較:
-
靈敏度:
-
Sobel算子:
Sobel算子對邊緣的響應(yīng)相對較強(qiáng),但相對來說,對噪聲的敏感性也較高。 -
Scharr算子:
Scharr算子在對邊緣的響應(yīng)上更加平滑,對噪聲的敏感性相對較低。
-
-
計(jì)算復(fù)雜度:
-
Sobel算子:
Sobel算子的計(jì)算較為簡單,適用于一些對計(jì)算資源要求較低的場合。 -
Scharr算子:
Scharr算子的計(jì)算復(fù)雜度相對較高,但在一些對精確性要求較高的場景中可能更為合適。
-
-
性能:
-
Sobel算子:
Sobel算子廣泛應(yīng)用于一般的邊緣檢測任務(wù),性能較好。 -
Scharr算子:
Scharr算子在一些特定的圖像分析任務(wù)中可能表現(xiàn)得更好,尤其是對于強(qiáng)邊緣的檢測。
-
在選擇使用Sobel算子或Scharr算子時(shí),通常會根據(jù)具體的應(yīng)用場景和任務(wù)需求來權(quán)衡它們之間的差異。
2.3 拉普拉斯 Laplacian 算子
它是通過對圖像進(jìn)行二階微分操作來實(shí)現(xiàn)的,能夠突出圖像中像素值變化較大的區(qū)域。拉普拉斯算子通常應(yīng)用于灰度圖像。,需要計(jì)算兩個(gè)方向的梯度值。
前兩個(gè)算子,都是m連通型的(即:對角),現(xiàn)在介紹一個(gè)4連通的。
計(jì)算像素點(diǎn) P5 的近似導(dǎo)數(shù)值,
P5lap = (P2 + P4 + P6 + P8) - 4·P5
計(jì)算結(jié)果的值可能為正數(shù),也可能為負(fù)數(shù)。所以,需要對計(jì)算
結(jié)果取絕對值,以保證后續(xù)運(yùn)算和顯示都是正確的。
2.3.1 函數(shù)
laplacian = cv2.Laplacian(src, ddepth[, ksize[, scale[, delta[, borderType]]]])
laplacian = cv2.Laplacian(o,cv2.CV_64F)laplacian = cv2.convertScaleAbs(laplacian) # 回uint8
-
src
:輸入圖像,通常是灰度圖像。 -
ddepth
:輸出圖像的深度(數(shù)據(jù)類型),通常使用cv2.CV_64F
。 -
ksize
:拉普拉斯算子的卷積核大小,通常為1。 -
scale
:拉普拉斯算子的縮放因子,用于調(diào)整結(jié)果的幅值。 -
delta
:可選的增加到輸出圖像的值,用于調(diào)整圖像的亮度。 -
borderType
:圖像邊界處理類型,默認(rèn)為cv2.BORDER_DEFAULT
。
不用像Sobel算子一樣,需要算x和y方向的再加起來。
三、Canny 邊緣檢測
3.1 Canny 原理
【去噪–計(jì)算梯度的幅度與方向–非極大值抑制–確定邊緣】
Canny 邊緣檢測是一種經(jīng)典的圖像處理技術(shù),通常包括以下幾個(gè)步驟:
-
高斯濾波(Gaussian Blur):
- 首先,圖像會經(jīng)過高斯濾波以平滑噪聲和細(xì)節(jié)。這有助于減少后續(xù)步驟中的誤差和不必要的細(xì)節(jié)。
讓臨近的像素具有更高的重要度。對周圍像素計(jì)算加權(quán)平均值,較近的像素具有較大的權(quán)重值。
-
灰度轉(zhuǎn)換(Grayscale Conversion):
- 將圖像轉(zhuǎn)換為灰度,將彩色圖像轉(zhuǎn)換為單通道灰度圖像。這樣可以簡化處理,并減少計(jì)算復(fù)雜性。
-
計(jì)算梯度(Gradient Calculation):
- 使用卷積操作,如Sobel算子,計(jì)算圖像的梯度。梯度的方向和強(qiáng)度有助于找到圖像中的邊緣。
- 使用卷積操作,如Sobel算子,計(jì)算圖像的梯度。梯度的方向和強(qiáng)度有助于找到圖像中的邊緣。
梯度:
方向:
-
非極大值抑制(Non-maximum Suppression):
- 對梯度圖進(jìn)行非極大值抑制,以保留局部梯度最大的點(diǎn),從而使邊緣更細(xì)化。
-
滯后閾值處理(Hysteresis Thresholding):
- 使用兩個(gè)閾值進(jìn)行滯后閾值處理。通常,有一個(gè)較低的閾值(弱邊緣)和一個(gè)較高的閾值(強(qiáng)邊緣)。根據(jù)梯度強(qiáng)度,將像素標(biāo)記為強(qiáng)邊緣、弱邊緣或非邊緣。強(qiáng)邊緣會被保留,而與強(qiáng)邊緣連接的弱邊緣也會被保留。
設(shè)定閾值:
- 選擇兩個(gè)閾值,一個(gè)是高閾值(maxVal),另一個(gè)是低閾值(minVal)。這兩個(gè)閾值的選擇通常依賴于具體的應(yīng)用和圖像特性。
判斷邊緣屬性:
- 對圖像中的每個(gè)像素進(jìn)行檢查,根據(jù)其梯度值與設(shè)定的閾值之間的關(guān)系,判斷其邊緣的屬性:
- 如果梯度值大于或等于高閾值(maxVal),則將該像素標(biāo)記為強(qiáng)邊緣。
- 如果梯度值介于高閾值和低閾值之間(minVal到maxVal之間),則將該像素標(biāo)記為虛邊緣(需要保留)。
- 如果梯度值小于或等于低閾值(minVal),則抑制該像素,認(rèn)為它不是邊緣。
處理虛邊緣:文章來源:http://www.zghlxwxcb.cn/news/detail-761302.html
- 對于被標(biāo)記為虛邊緣的像素,進(jìn)一步判斷其是否與強(qiáng)邊緣相連。如果與強(qiáng)邊緣相連,則將其標(biāo)記為強(qiáng)邊緣,否則抑制它。 這個(gè)步驟的目標(biāo)是最終確定哪些邊緣是真實(shí)的、強(qiáng)的,哪些是需要保留的虛邊緣,以及哪些應(yīng)該被抑制。這樣的處理可以有效減少噪聲和虛假邊緣,提高Canny邊緣檢測的準(zhǔn)確性。
3.2 Canny 函數(shù)及使用
edges = cv.Canny( image, threshold1, threshold2[, apertureSize[, L2gradient]])
? edges 為計(jì)算得到的邊緣圖像。
? image 為 8 位輸入圖像。
如果為了細(xì)節(jié),就設(shè)置的小一些
? threshold1 表示處理過程中的第一個(gè)閾值。
? threshold2 表示處理過程中的第二個(gè)閾值。文章來源地址http://www.zghlxwxcb.cn/news/detail-761302.html
import cv2
import matplotlib.pyplot as plt
# 讀取圖像
image_path = './'
original_image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
# 高斯濾波,去除噪聲
blurred_image = cv2.GaussianBlur(original_image, (5, 5), 0)
# 使用Canny函數(shù)進(jìn)行邊緣檢測
edges = cv2.Canny(blurred_image, 50, 150) # 50是低閾值,150是高閾值
# 顯示原始圖像、模糊圖像和邊緣圖像
plt.figure(figsize=(10, 6))
plt.subplot(131)
plt.imshow(original_image, cmap='gray')
plt.title('Original Image')
plt.subplot(132)
plt.imshow(blurred_image, cmap='gray')
plt.title('Blurred Image')
plt.subplot(133)
plt.imshow(edges, cmap='gray')
plt.title('Canny Edges')
plt.show()
到了這里,關(guān)于我在Vscode學(xué)OpenCV 圖像處理三(圖像梯度--邊緣檢測【圖像梯度、Sobel 算子、 Scharr 算子、 Laplacian 算子、Canny 邊緣檢測】)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!