什么是邊緣檢測(cè)
邊緣檢測(cè)是圖像處理和計(jì)算機(jī)視覺(jué)中,尤其是特征提取中的一個(gè)研究領(lǐng)域慢味。
所謂邊緣,就是圖像中強(qiáng)度發(fā)生突變的區(qū)域墅冷,通常暗示著物體邊界的存在纯路。
灰度變化不明顯的部分會(huì)被過(guò)濾掉
邊緣檢測(cè)的一般流程
先灰度化,再用低通濾波器降噪寞忿,用高通濾波器提取邊緣驰唬,最后二值化。
低通濾波器見(jiàn)前面我發(fā)布的圖像預(yù)處理腔彰,下面講的都是高通濾波器叫编。
濾波器與卷積操作
為了提取到圖像的邊緣,我們需要濾波器的幫助萍桌。這類(lèi)濾波器以矩陣的形式存在宵溅,通常被稱(chēng)為卷積核,就是一些值網(wǎng)格上炎,能夠?qū)D像進(jìn)行修改恃逻。
對(duì)于圖像的每一個(gè)像素點(diǎn),計(jì)算它的鄰域像素和濾波器矩陣的對(duì)應(yīng)元素的乘積藕施,然后加起來(lái)寇损,作為該像素位置的值。這樣就完成了濾波過(guò)程裳食。這種計(jì)算被稱(chēng)為圖像卷積矛市。
卷積核上的每一位乘數(shù)被稱(chēng)為權(quán)值,它們決定了這個(gè)像素的分量有多重诲祸。它們的總和加起來(lái)如果等于1浊吏,不會(huì)改變圖像的灰度強(qiáng)度而昨。如果大于1,會(huì)增加灰度強(qiáng)度找田,使得圖像變亮歌憨。如果小于1,會(huì)減少灰度強(qiáng)度墩衙,使得圖像變暗务嫡。如果和為0,圖像不會(huì)變黑漆改,但也會(huì)非常暗(凸出邊緣)心铃。
濾波器的大小應(yīng)該是奇數(shù),這樣它才有一個(gè)中心挫剑,例如3x3去扣,5x5或者7x7。有中心了樊破,也有了半徑的稱(chēng)呼厅篓,例如5x5大小的核的半徑就是2。
幾種經(jīng)典的過(guò)濾器
1捶码、索貝爾過(guò)濾器
索貝爾過(guò)濾器常用于邊緣檢測(cè)和發(fā)現(xiàn)圖像中的強(qiáng)度模式。向圖像中應(yīng)用索貝爾過(guò)濾器就相當(dāng)于沿著 x 或 y 方向求圖像的(近似)導(dǎo)數(shù)或链。
Sobel_x和 Sobel_y的運(yùn)算符分別如下所示:
接下來(lái)惫恼,我們看看將這兩種過(guò)濾器應(yīng)用到大腦圖像的示例。
在上圖中澳盐,可以看到在 x 和 y 方向計(jì)算的梯度檢測(cè)出大腦的邊緣并選出其他邊緣祈纯。沿著 x 方向計(jì)算的梯度強(qiáng)調(diào)的是接近垂直方向的邊緣,沿著 y 方向計(jì)算的梯度強(qiáng)調(diào)的是接近水平方向的邊緣 叼耙。
大小
索貝爾還會(huì)檢測(cè)哪些邊緣最強(qiáng)腕窥,這一點(diǎn)體現(xiàn)在梯度大小上;大小越大筛婉,邊緣越強(qiáng)簇爆。梯度的大小或絕對(duì)值是單個(gè) x 和 y 梯度平方值的平方根。對(duì)于 x 和 y 方向的梯度爽撒,大小是平方和的平方根入蛆。
方向
在很多情形下,我們需要查找特定方向的邊緣硕勿。例如哨毁,我們可能需要查找僅朝上或朝左的線條。通過(guò)單獨(dú)計(jì)算 x 和 y 方向的圖像梯度方向源武,我們可以判斷該梯度的方向扼褪!
梯度方向是指 y 梯度除以 x 梯度的反正切:
# coding = utf-8
import numpy as np
import matplotlib.pyplot as plt
import cv2 as cv
# 圖像讀取并灰度化
image_stripes = cv.imread('images/stripes.jpg')
image_stripes = cv.cvtColor(image_stripes, cv.COLOR_BGR2RGB)
gray_stripes = cv.cvtColor(image_stripes, cv.COLOR_RGB2GRAY)
sobel_x = np.array([[ -1, 0, 1],
[ -2, 0, 2],
[ -1, 0, 1]])
sobel_y = np.array([[ -1, -2, -1],
[ 0, 0, 0],
[ 1, 2, 1]])
filtered_image1 = cv.filter2D(gray_stripes, -1, sobel_x)
filtered_image2 = cv.filter2D(gray_stripes, -1, sobel_y)
2想幻、拉普拉斯過(guò)濾器
Laplace算子是一種各向同性算子,二階微分算子话浇,在只關(guān)心邊緣的位置而不考慮其周?chē)南袼鼗叶炔钪禃r(shí)比較合適脏毯。
Laplace算子對(duì)孤立象素的響應(yīng)要比對(duì)邊緣或線的響應(yīng)要更強(qiáng)烈,因此只適用于無(wú)噪聲圖象凳枝。存在噪聲情況下抄沮,使用Laplacian算子檢測(cè)邊緣之前需要先進(jìn)行低通濾波。
# coding = utf-8
import numpy as np
import matplotlib.pyplot as plt
import cv2 as cv
# 圖像讀取并灰度化
image_stripes = cv.imread('tools/33.jpg')
image_stripes = cv.cvtColor(image_stripes, cv.COLOR_BGR2RGB)
gray_stripes = cv.cvtColor(image_stripes, cv.COLOR_RGB2GRAY)
laplacian=np.array([[0, 1, 0],
[1,-4, 1],
[0, 1, 0]])
filtered_image = cv.filter2D(gray_stripes, -1, laplacian)
3岖瑰、Canny過(guò)濾器
Canny邊緣檢測(cè)是一種非常流行的邊緣檢測(cè)算法叛买,是John Canny在1986年提出的。它是一個(gè)多階段的算法蹋订,即由多個(gè)步驟構(gòu)成率挣。
首先,圖像降噪露戒。我們知道梯度算子可以用于增強(qiáng)圖像椒功,本質(zhì)上是通過(guò)增強(qiáng)邊緣輪廓來(lái)實(shí)現(xiàn)的,也就是說(shuō)是可以檢測(cè)到邊緣的智什。但是动漾,它們受噪聲的影響都很大。那么荠锭,我們第一步就是想到要先去除噪聲旱眯,因?yàn)樵肼暰褪腔叶茸兓艽蟮牡胤剑匀菀妆蛔R(shí)別為偽邊緣证九。
第二步删豺,計(jì)算圖像梯度,得到可能邊緣愧怜。計(jì)算圖像梯度能夠得到圖像的邊緣呀页,因?yàn)樘荻仁腔叶茸兓黠@的地方,而邊緣也是灰度變化明顯的地方拥坛。當(dāng)然這一步只能得到可能的邊緣蓬蝶。因?yàn)榛叶茸兓牡胤娇赡苁沁吘墸部赡懿皇沁吘壊峦铩_@一步就有了所有可能是邊緣的集合疾党。
第三步,非極大值抑制惨奕。通逞┪唬灰度變化的地方都比較集中,將局部范圍內(nèi)的梯度方向上梨撞,灰度變化最大的保留下來(lái)雹洗,其它的不保留香罐,這樣可以剔除掉一大部分的點(diǎn)。將有多個(gè)像素寬的邊緣變成一個(gè)單像素寬的邊緣时肿。即“胖邊緣”變成“瘦邊緣”庇茫。
第四步,雙閾值篩選螃成。通過(guò)非極大值抑制后旦签,仍然有很多的可能邊緣點(diǎn),進(jìn)一步的設(shè)置一個(gè)雙閾值寸宏,即低閾值(low)宁炫,高閾值(high)〉灰度變化大于high的羔巢,設(shè)置為強(qiáng)邊緣像素,低于low的罩阵,剔除竿秆。在low和high之間的設(shè)置為弱邊緣。進(jìn)一步判斷稿壁,如果其領(lǐng)域內(nèi)有強(qiáng)邊緣像素幽钢,保留,如果沒(méi)有傅是,剔除搅吁。這樣做的目的是只保留強(qiáng)邊緣輪廓的話,有些邊緣可能不閉合落午,需要從滿足low和high之間的點(diǎn)進(jìn)行補(bǔ)充,使得邊緣盡可能的閉合肚豺。
# coding = utf-8
import numpy as np
import matplotlib.pyplot as plt
import cv2 as cv
# 圖像讀取并灰度化
image_stripes = cv.imread('tools/33.jpg')
image_stripes = cv.cvtColor(image_stripes, cv.COLOR_BGR2RGB)
gray_stripes = cv.cvtColor(image_stripes, cv.COLOR_RGB2GRAY)
lower = 50
upper = 100
edges = cv.Canny(gray_stripes, lower, upper)
plt.imshow(edges)
plt.show()