翻譯自: Edge Detection in Computer Visiongit
邊緣檢測是計算機視覺中最重要的概念之一。這是一個很直觀的概念,在一個圖像上運行圖像檢測應該只輸出邊緣,與素描比較類似。個人目標不只是清晰地解釋邊緣檢測是怎樣工做的,同時也提供一個新而又容易的方法只須要最小工做來明顯地提升邊緣檢測。github
截圖1: 算法
經過得到這些邊緣,許多計算機算法才得以有可能實現,由於在一個場景中邊緣包含着絕大部分(至少不少)的信息。app
舉個例子,咱們都記得 Windows XP
的那個綠色小山坡和藍色天空的背景。jsp
截圖2: 函數
當咱們的大腦試圖去理解這個場景時,咱們知道這是草地,看起來很統一。而後,咱們看到了飄着些許白雲的天空。這些對象的每個都是分離的,並且它們之間有一個邊緣。這就是場景中爲何絕大部分的信息存在與邊緣中。學習
這也是爲何邊緣檢測是計算機視覺中的重要概念。經過把圖像減小到只剩下邊緣,使得對於許多算法更容易識別、學習、或者處理場景。測試
邊緣檢測的大多數是基於濾波的。一般來講,濾波是一個消除的動做。好比:過濾水,是消除寄生蟲。類似地,當咱們嘗試找到圖像邊緣時,我是在嘗試消除掉除圖像邊緣以外的東西。優化
消除那些不是有用的邊緣的圖像部分,而留下合適的邊緣也是困難所在。我怎麼知道這是否是有用的邊緣,好比,我對 Windows XP 背景運行 Canny edge dectector 程序,效果以下。url
截圖3:
你能看到那些小草的細小刀刃似的邊緣,這很讓人討厭,並且沒有真正提供有用的信息。甚至那些雲朵也不是很是清晰。如今,你能在大多數的 Canny edge dectector
上設置一些邊界,這些邊界設置了閾值(或者 非極大值抑制),全部的邊緣必須知足這個閾值才能劃分爲「重要的」邊緣。與其在 Canny edge
的閾值上區分,不如咱們更普遍地來談談,而且搭建幾個濾波器。
高斯濾波器
是邊緣檢測最基礎的濾波器之一,雖然還有其餘的,可是高斯濾波器
會貫穿這篇文章。高斯濾波器
,正如其名,是一個基於高斯分佈的濾波器。
截圖4:
它看起來像一個拋物線(除了在二維的狀況)。經過矩陣乘法,高斯濾波器
能被應用到每個像素上。它實現的是混合效果,讓最中心的像素儘可能小基於它相鄰的像素。舉個例子,如對個人貓的圖像運行一個均勻分佈的高斯濾波器,我可以獲得下面的圖像:
Mew
的圖片截圖5:
Mew
的圖片應用高斯濾波
截圖6:
你能夠看到圖像變得模糊了,高斯濾波器就是獲取全部像素,讓像素值的成分是與相鄰像素有關。
爲了讓高斯濾波器在邊緣檢測中有效,咱們可使用從 x
和 y
A Computational Approach to Edge Detection 方面求導出來的高斯濾波器。這也許聽起來有點反直覺,或者不知所謂,可是若是咱們看到這種導數高斯濾波器的圖像,這種想法就很清晰了。
截圖7:
當你把一個高斯的 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);
若是咱們將它應用個人貓的一張圖片,我咱們就獲得一下的圖片:
截圖8:
有趣地是,咱們一樣也能這種方法應用到 RGB 圖像上去,一樣也會獲得彩色的邊緣。
RGB
圖片應用濾波器截圖9:
這兩張圖片應該都能表明像素和它相鄰之間像素的顏色的差別,只不過彩色圖像有3
個通道:RGB
,而黑白圖像只有1
個通道。(原譯文翻譯爲層, 這裏改成通道)
爲何要限制咱們本身僅僅使用絕對的 x
和 y
方向的濾波器呢?讓咱們也來構建一些方向濾波器。這個方法(或多或少)來源於 Freeman
和 Adelson
的《The design and use of steerable filters》 論文,這個想法使咱們可以把咱們的高斯濾波器
放置在不一樣的方向。
根本上,咱們把咱們的高斯濾波器
放置到不一樣的方向上去,以基於與高斯相關的邊緣的角度來建立不一樣數值。好比,若是咱們把高斯函數放置到45
度,應用到45
度角的圖像上,應該能夠比在0
度的高斯函數獲得更高的數量級。
在這種狀況下,我生成了幾種不一樣的方向濾波器:
截圖10:
頂部行x份量,底部行y份量
各類各樣的高斯函數產生了相對於 x
和 y
份量上的90
、45
、-45
和 22.5
度的濾波器。這也就產生了不一樣的邊緣大小,儘管這些濾波器應該檢測出相近的邊緣。
截圖11:
我使用的代碼與單個濾波器使用的代碼幾乎相同,可是我不一樣以往地把他們混合在一塊兒。它看起來有點雜亂,可是我經過讓我運行每一個濾波器表達更明白來儘量使它看起來更清晰。
% 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);
若是你靠近點看的話,你能看到數量大小的不一樣,特別是那些皺紋。若是咱們混合了全部圖像,咱們就能獲得一張輕微較好的邊緣檢測。
截圖12:
方向濾波器和非方向濾波器之間並無很大的不一樣,可是咱們也應該看到多種方向的結果有些許的提升。
過去兩年,我在不一樣的彩色域上作了大量的測試和實驗。特別地是,Lab 彩色域
(Lab color space
)是另外一種描述圖像的方式。好比,咱們知道的 RGB
和灰度圖像,或者你甚至可能知道 YUV
空間。 Lab 彩色域
與之很是類似。
我對 Lab
彩色感興趣的緣由是它對產生場景的邊緣有着優異的能力。
Lab
彩色空間的每一個字母表示:
L
—— Luminance 亮度a
—— alpha —— 紅到綠b
—— beta —— 黃到藍截圖13:
事實上,這些顏色通道很是適合發現顏色變化梯度,正如天然而然地黃色不多出現另外一個黃色周圍,紅色和綠色也是如此。(儘管我已經完全證實了)。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
,咱們將獲得下面的圖像:
截圖14:
而後若是咱們施加濾波器(非極大值抑制)將獲得下面的圖像,清晰的包含着草地、雲、草地和天空的分界線的圖象。
Lab 彩色域
上邊緣檢測截圖15:
最終,若是咱們運行非極大值抑制,那麼咱們將獲得比本文開頭提到的 Canny
邊緣檢測器要好得多的邊緣效果。
Lab 彩色域
邊緣檢測截圖16:
平均來講,這種方法會比普通方法提升 10%
左右的邊緣檢測精度。這是對 The Berkeley Segmentation Dataset and Benchmark 運行 F-measure
測試獲得的結果。
截圖17:
有無數的方法去作邊緣檢測,這裏講述的方法毫不是最好、最容易實現、最容易解釋的。
我使用這些方法解釋它是由於我對它們頗有興趣。。。加上這是 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
這是本人課餘時間的翻譯,若有錯誤,還請耐心指出,謝謝! 原文連接請點擊原文連接