計算機視覺中的邊緣檢測

計算機視覺中的邊緣檢測


邊緣檢測是計算機視覺中最重要的概念之一。這是一個很直觀的概念,在一個圖像上運行圖像檢測應該只輸出邊緣,與素描比較相似。我的目
標不僅是清晰地解釋邊緣檢測是怎樣工作的,同時也提供一個新而又容易的方法只需要最小工作來明顯地提高邊緣檢測。


通過獲得這些邊緣,許多計算機算法才得以有可能實現,因爲在一個場景中邊緣包含着絕大部分(至少很多)的信息。

舉個例子,我們都記得 Windows XP 的那個綠色小山坡和藍色天空的背景。


當我們的大腦試圖去理解這個場景時,我們知道這是草地,看起來很統一。然後,我們看到了飄着些許白雲的天空。這些對象的每一個都是分離的,而且它們之間有一個邊緣。這就是場景中爲什麼絕大部分的信息存在與邊緣中。

這也是爲什麼邊緣檢測是計算機視覺中的重要概念。通過把圖像減少到只剩下邊緣,使得對於許多算法更容易識別、學習、或者處理場景。

邊緣檢測:濾波

邊緣檢測的大多數是基於濾波的。通常來說,濾波是一個消除的動作。比如:過濾水,是消除寄生蟲。相似地,當我們嘗試找到圖像邊緣時,我是在嘗試消除掉除圖像邊緣之外的東西。

消除那些不是有用的邊緣的圖像部分,而留下合適的邊緣也是困難所在。我怎麼知道這是不是有用的邊緣,比如,我對 Windows XP 背景運行 Canny edge dectector 程序,效果如下。


你能看到那些小草的細小刀刃似的邊緣,這很讓人討厭,而且沒有真正提供有用的信息。甚至那些雲朵也不是非常清晰。現在,你能在大多數的 Canny edge dectector 上設置一些邊界,這些邊界設置了閾值(或者 非極大值抑制),所有的邊緣必須滿足這個閾值才能劃分爲“重要的”邊緣。與其在 Canny edge 的閾值上區分,不如我們更廣泛地來談談,並且搭建幾個濾波器。

邊緣檢測:高斯濾波器

高斯濾波器是邊緣檢測最基礎的濾波器之一,雖然還有其他的,但是高斯濾波器會貫穿這篇文章。高斯濾波器,正如其名,是一個基於高斯分佈的濾波器。


它看起來像一個拋物線(除了在二維的情況)。通過矩陣乘法,高斯濾波器能被應用到每一個像素上。它實現的是混合效果,讓最中心的像素儘量小基於它相鄰的像素。舉個例子,如對我的貓的圖像運行一個均勻分佈的高斯濾波器,我能夠得到下面的圖像:

5.jpg
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 precision
img = 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 edges
gx = double(imfilter(img,hx,'replicate', 'conv'));
% Leaves y edges
gy = double(imfilter(img,hy,'replicate', 'conv'));
% Take the absolute value, and combine the x and y edges
mag = sqrt((gx .* gx) + (gy .* gy));
% Use non-maxima suppression 
[mag, ] = max(mag, [], 3);

如果我們將它應用我的貓的一張圖片,我我們就得到一下的圖片:


有趣地是,我們同樣也能這種方法應用到 RGB 圖像上去,同樣也會得到彩色的邊緣。

普通的邊緣濾波器應用到貓的RGB圖像
普通的邊緣濾波器應用到貓的RGB圖像

這兩張圖片應該都能代表像素和它相鄰之間像素的顏色的差異,只不過彩色圖像有3層,而黑白圖像只有1層。(層,翻譯不是很好)

邊緣檢測:方向濾波器

爲什麼要限制我們自己僅僅使用絕對的 x 和 y 方向的濾波器呢?讓我們也來構建一些方向濾波器。這個方法(或多或少)來源於 Freeman 和 Adelson 的《The design and use of steerable filters》論文,這個想法使我們能夠把我們的高斯濾波器放置在不同的方向。

根本上,我們把我們的高斯濾波器放置到不同的方向上去,以基於與高斯相關的邊緣的角度來創建不同數值。比如,如果我們把高斯函數放置到45度,應用到45度角的圖像上,應該可以比在0度的高斯函數得到更高的數量級。

在這種情況下,我生成了幾種不同的方向濾波器:

上行x分量,下行y分量
上行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 image
gx = double(imfilter(img,hx,'replicate', 'conv'));
gy = double(imfilter(img,hy,'replicate', 'conv'));
% Run second gaussian filter on image
gx1 = double(imfilter(img,hx1,'replicate', 'conv'));
gy1 = double(imfilter(img,hy1,'replicate', 'conv'));
% Run third gaussian filter on image
gx2 = double(imfilter(img,hx2,'replicate', 'conv'));
gy2 = double(imfilter(img,hy2,'replicate', 'conv'));
% Run fourth gaussian filter on image
gx3 = double(imfilter(img,hx3,'replicate', 'conv'));
gy3 = double(imfilter(img,hy3,'replicate', 'conv'));

% Merge all filters
squareGD = (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 space
colorTransform = makecform('srgb2lab');
img = applycform(rgbImg, colorTransform);

% Make it double to improve representation
img = 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 value
gSquared = sqrt(gx .* gx) + (gy .* gy);

% Apply non-maxima suppression (find best points for edges) 
[mag, ] = max(gSquared, [], 3);

如果我們將 Windows XP 小山坡的背景圖像轉換爲Lab,我們將得到下面的圖像:

Windows XP 背景的Lab空間圖像
Windows XP 背景的Lab空間圖像

然後如果我們施加濾波器(非極大值抑制)將得到下面的圖像,清晰的包含着草地、雲、草地和天空的分界線的圖象。

在Lab 空間上邊緣檢測
在Lab 空間上邊緣檢測

最終,如果我們運行非極大值抑制,那麼我們將得到比本文開頭提到的 Canny邊緣檢測器要好得多的邊緣效果。

Lab 彩色空間邊緣檢測
Lab 彩色空間邊緣檢測

平均來說,這種方法會比普通方法提高 10% 左右的邊緣檢測精度。這是對 The Berkeley Segmentation Dataset and Benchmark 運行 F-measure 測試得到的結果。


邊緣檢測:結語

有無數的方法去做邊緣檢測,這裏講述的方法絕不是最好、最容易實現、最容易解釋的。

我使用這些方法解釋它是因爲我對它們很有興趣。。。加上這是 UIUC的CS543課程《計算機視覺》佈置的作業,所以你也在上這門課,請不要抄襲我的代碼!

我已經把我們所有的實現都放到了 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.


這是本人課餘時間的翻譯,如有錯誤,還請耐心指出,謝謝!
原文鏈接請點擊原文鏈接

發佈了21 篇原創文章 · 獲贊 55 · 訪問量 42萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章