標籤:
邊緣檢測是電腦視覺中最重要的概念之一。這是一個很直觀的概念,在一個映像上運行映像檢測應該只輸出邊緣,與素描比較相似。我的目
標不僅是清晰地解釋邊緣檢測是怎樣工作的,同時也提供一個新而又容易的方法只需要最小工作來明顯地提高邊緣檢測。
通過獲得這些邊緣,許多電腦演算法才得以有可能實現,因為在一個情境中邊緣包含著絕大部分(至少很多)的資訊。
舉個例子,我們都記得 Windows XP 的那個綠色小山坡和藍色天空的背景。
當我們的大腦試圖去理解這個情境時,我們知道這是草地,看起來很統一。然後,我們看到了飄著些許白雲的天空。這些對象的每一個都是分離的,而且它們之間有一個邊緣。這就是情境中為什麼絕大部分的資訊存在與邊緣中。
這也是為什麼邊緣檢測是電腦視覺中的重要概念。通過把映像減少到只剩下邊緣,使得對於許多演算法更容易識別、學習、或者處理情境。
邊緣檢測:濾波
邊緣檢測的大多數是基於濾波的。通常來說,濾波是一個消除的動作。比如:過濾水,是消除寄生蟲。相似地,當我們嘗試找到映像邊緣時,我是在嘗試消除掉除映像邊緣之外的東西。
消除那些不是有用的邊緣的映像部分,而留下合適的邊緣也是困難所在。我怎麼知道這是不是有用的邊緣,比如,我對 Windows XP 背景運行 Canny edge dectector 程式,效果如下。
你能看到那些小草的細小刀刃似的邊緣,這很讓人討厭,而且沒有真正提供有用的資訊。甚至那些雲朵也不是非常清晰。現在,你能在大多數的 Canny edge dectector 上設定一些邊界,這些邊界設定了閾值(或者 非極大值抑制),所有的邊緣必須滿足這個閾值才能劃分為“重要的”邊緣。與其在 Canny edge 的閾值上區分,不如我們更廣泛地來談談,並且搭建幾個濾波器。
邊緣檢測:高斯濾波器
高斯濾波器是邊緣檢測最基礎的濾波器之一,雖然還有其他的,但是高斯濾波器會貫穿這篇文章。高斯濾波器,正如其名,是一個基於高斯分布的濾波器。
它看起來像一個拋物線(除了在二維的情況)。通過矩陣乘法,高斯濾波器能被應用到每一個像素上。它實現的是混合效果,讓最中心的像素盡量小基於它相鄰的像素。舉個例子,如對我的貓的映像運行一個均勻分布的高斯濾波器,我能夠得到下面的映像:
5.jpg
你可以看到映像變得模糊了,高斯濾波器就是擷取所有像素,讓像素值的成分是與相鄰像素有關。
為了讓高斯濾波器在邊緣檢測中有效,我們可以使用從 x 和 y 方面求匯出來的高斯濾波器。這也許聽起來有點反直覺,或者不知所謂,但是如果我們看到這種導數高斯濾波器的映像,這種想法就很清晰了。
當你把一個高斯的 x 和 y 分量求導後,一個大的波峰 和波穀就出現了。如果你明白導數,思考下這種情況,你應該能很快想到。由於高斯函數峰上數值上的巨大變化,從而導致了高斯導數波峰和波穀的出現。
如果我們把上面的寫成代碼,那相當直接(至少對於 Matlab 和 Python 來說):
% Takes the derivative of a 5x5 gaussian, with a sigma [hx, hy] = gradient(fspecial(‘gaussian‘,[5 5],sigma));
這就是了,一行代碼就能得到我們所想要的高斯,然後對x 和 y 分量求導。
邊緣檢測:應用濾波器
我們已經有了兩個高斯濾波器,我們把他們應用到映像中。我們同樣使用非極大值限制,即如果不是極大值的話,就把像素值設定為0。換種說法就是消除雜訊。
應用濾波器的代碼如下:
% Convert an image to double for increased precisionimg = double(img);% Find two derived gaussians with respect to x and y[hx, hy] = gradient(fspecial(‘gaussian‘,[5 5],sigma));% Run the filters over the image, generating a filtered image% Leaves x edgesgx = double(imfilter(img,hx,‘replicate‘, ‘conv‘));% Leaves y edgesgy = double(imfilter(img,hy,‘replicate‘, ‘conv‘));% Take the absolute value, and combine the x and y edgesmag = sqrt((gx .* gx) + (gy .* gy));% Use non-maxima suppression [mag, ] = max(mag, [], 3);
如果我們將它應用我的貓的一張圖片,我我們就得到一下的圖片:
有趣地是,我們同樣也能這種方法應用到 RGB 映像上去,同樣也會得到彩色的邊緣。
普通的邊緣濾波器應用到貓的RGB映像
這兩張圖片應該都能代表像素和它相鄰之間像素的顏色的差異,只不過彩色映像有3層,而黑白映像只有1層。(層,翻譯不是很好)
邊緣檢測:方向濾波器
為什麼要限制我們自己僅僅使用絕對的 x 和 y 方向的濾波器呢?讓我們也來構建一些方向濾波器。這個方法(或多或少)來源於 Freeman 和 Adelson 的《The design and use of steerable filters》論文,這個想法使我們能夠把我們的高斯濾波器放置在不同的方向。
根本上,我們把我們的高斯濾波器放置到不同的方向上去,以基於與高斯相關的邊緣的角度來建立不同數值。比如,如果我們把高斯函數放置到45度,應用到45度角的映像上,應該可以比在0度的高斯函數得到更高的數量級。
在這種情況下,我產生了幾種不同的方向濾波器:
上行x分量,下行y分量
各種各樣的高斯函數產生了相對於x 和 y 分量上的90、45、-45 和 22.5 度的濾波器。這也就產生了不同的邊緣大小,儘管這些濾波器應該檢測出相近的邊緣。
我使用的代碼與單個濾波器使用的代碼幾乎相同,但是我不同以往地把他們混合在一起。它看起來有點雜亂,但是我通過讓我運行每個濾波器表達更明白來儘可能使它看起來更清晰。
% Create four filters[hx, hy] = gradient(fspecial(‘gaussian‘,[5 5],sigma));[hx1, hy1] = altOrientFilter1(hx, hy);[hx2, hy2] = altOrientFilter2(hx, hy);[hx3, hy3] = altOrientFilter3(hx, hy);% Run first gaussian filter on imagegx = double(imfilter(img,hx,‘replicate‘, ‘conv‘));gy = double(imfilter(img,hy,‘replicate‘, ‘conv‘));% Run second gaussian filter on imagegx1 = double(imfilter(img,hx1,‘replicate‘, ‘conv‘));gy1 = double(imfilter(img,hy1,‘replicate‘, ‘conv‘));% Run third gaussian filter on imagegx2 = double(imfilter(img,hx2,‘replicate‘, ‘conv‘));gy2 = double(imfilter(img,hy2,‘replicate‘, ‘conv‘));% Run fourth gaussian filter on imagegx3 = double(imfilter(img,hx3,‘replicate‘, ‘conv‘));gy3 = double(imfilter(img,hy3,‘replicate‘, ‘conv‘));% Merge all filterssquareGD = (gx .* gx) + (gy .* gy);squareGD = squareGD + (gx1 .* gx1) + (gy1 .* gy1);squareGD = squareGD + (gx2 .* gx2) + (gy2 .* gy2);squareGD = squareGD + (gx3 .* gx3) + (gy3 .* gy3);% Run non-maxima supression[mag, ] = max(sqrt(squareGD), [], 3);
如果你靠近點看的話,你能看到數量大小的不同,特別是那些皺紋。如果我們混合了所有映像,我們就能得到一張輕微較好的邊緣檢測。
方向濾波器和非方向濾波器之間並沒有很大的不同,但是我們也應該看到多種方向的結果有些許的提高。
邊緣檢測:提高彩色域
過去兩年,我在不同的彩色域上做了大量的測試和實驗。特別地是,Lab 彩色域是另一種描述映像的方式。比如,我們知道的RGB 和灰階映像,或者你甚至可能知道YUV空間。 Lab 彩色域與之非常相似。
我對Lab 彩色感興趣的原因是它對產生情境的邊緣有著優異的能力。
Lab 彩色空間的每個字母表示:
- L —— Luminance亮度
- a —— alpha —— 紅到綠
- b —— beta —— 黃到藍
事實上,這些色彩通道非常適合發現顏色變化梯度,正自然而然地黃色很少出現另一個黃色周圍,紅色和綠色也是如此。(儘管我已經徹底證明了)。Lab 彩色空間與我們人類怎樣察覺顏色中的亮度有很強的相關性。與RGB相反的是,在Lab 彩色空間中亮度有它自己的分離通道,這使得它能更好地處理顏色的差異,這些差異也是亮度與顏色相關之處。
為了最小化額外的代碼,我們所要做的就是把輸入的映像轉化為Lab彩色空間的映像。你可以做一些最佳化,不過你僅僅做了這額外的一步也能明顯提高適宜的邊緣檢測。
% Convert an image to the Lab color spacecolorTransform = makecform(‘srgb2lab‘);img = applycform(rgbImg, colorTransform);% Make it double to improve representationimg = double(img);% Find x and y derivative of a 9x9 gaussian[hx, hy] = gradient(fspecial(‘gaussian‘,[9 9],sigma));% Apply filters gx = double(imfilter(img,hx,‘replicate‘));gy = double(imfilter(img,hy,‘replicate‘));% Find absolute valuegSquared = sqrt(gx .* gx) + (gy .* gy);% Apply non-maxima suppression (find best points for edges) [mag, ] = max(gSquared, [], 3);
如果我們將 Windows XP 小山坡的背景映像轉換為Lab,我們將得到下面的映像:
Windows XP 背景的Lab空間映像
然後如果我們施加濾波器(非極大值抑制)將得到下面的映像,清晰的包含著草地、雲、草地和天空的分界線的圖象。
在Lab 空間上邊緣檢測
最終,如果我們運行非極大值抑制,那麼我們將得到比本文開頭提到的 Canny邊緣檢測器要好得多的邊緣效果。
Lab 彩色空間邊緣檢測
平均來說,這種方法會比普通方法提高 10% 左右的邊緣檢測精度。這是對 The Berkeley Segmentation Dataset and Benchmark 運行 F-measure 測試得到的結果。
邊緣檢測:結語
有無數的方法去做邊緣檢測,這裡講述的方法絕不是最好、最容易實現、最容易解釋的。
我使用這些方法解釋它是因為我對它們很有興趣。。。加上這是 UIUC的CS543課程《電腦視覺》布置的作業,所以你也在上這門課,請不要抄襲My Code!
我已經把我們所有的實現都放到了 github 上了。包括用 C++ 的 OpenCV 實現。
然而,如果你想跟我的貓照相,這沒什麼問題。
建議閱讀
- PCA: Principal Component Analysis
- Everyday Algorithms: Pancake Sort
- Using Computer Vision to Improve EEG Signals
- Introduction to Markov Processes
- The Cache and Multithreading
參考文獻
[1] Canny, John. “A computational approach to edge detection.” Pattern Analysis and Machine Intelligence, IEEE Transactions on 6 (1986): 679-698.
[2] Freeman, William T., and Edward H. Adelson. “The design and use of steerable filters.” IEEE Transactions on Pattern analysis and machine intelligence 13.9 (1991): 891-906.
這是本人課餘時間的翻譯,如有錯誤,還請耐心指出,謝謝!
原文連結請點擊原文連結
電腦視覺中的邊緣檢測