2012-04-20 300 views
7

我目前正在處理圖像處理項目。我正在使用VC++的Opencv2.3.1。 我寫過這樣的代碼,輸入圖像被過濾爲只有藍色並轉換爲二進制圖像。二進制圖像有一些我不想要的小物體。我想消除這些小物體,所以我使用openCV的cvFindContours()方法來檢測二值圖像中的輪廓。但問題是我無法消除圖像輸出中的小物體。我用cvContourArea()函數,但沒有正常工作..,侵蝕功能也沒有正常工作。輪廓opencv:如何消除二進制圖像中的小輪廓

所以請別人幫我解決這個問題..

我獲得二進制圖像:

enter image description here

,我想獲得結果/輸出圖像:

enter image description here

回答

1

是否確定按小輪廓區域過濾不起作用?它一直爲我工作。我們可以看到你的代碼嗎?

另外,正如sue-ling所說,使用侵蝕劑和擴張劑來大致保存區域是個不錯的主意。要去除小嘈雜的鑽頭,首先使用侵蝕劑,然後填充孔,首先使用擴張劑。

另一方面,如果您不知道它們的功能(documentationfindContours),您可能需要查看cv *函數的新C++版本。在我看來,它們更容易使用。

+0

感謝您的建議,但我沒有得到如何編寫代碼來查找已檢測到的每個斑點/輪廓的區域。我寫的代碼在以下鏈接中。你能否糾正它並回復。 :http://textuploader.com/?p=6&id=YwRl。 – 2012-04-20 02:16:39

+0

哦!我只是忘了,cvutility的頭文件和cpp文件可以在這些鏈接中找到:http://textuploader.com/?p = 6&id = Dtnvj http://textuploader.com/?p=6&id=TSlRQ請將它們包含在源目錄和包含路徑。 – 2012-04-20 02:28:55

+0

我對C api不太熟悉,但看起來你只是計算第一個輪廓的面積。您需要遍歷輪廓,並只繪製區域大於某個閾值的輪廓。如果你只是想找到一個物體,你應該繪製最大面積的輪廓。 – fferen 2012-04-20 03:09:34

0

根據前後圖像判斷,需要確定所有白色區域或斑點的面積,然後應用閾值面積值。這將消除小於該值的所有區域,並且僅留下在第二圖像中看到的大的白色區域。使用cvFindContours函數後,嘗試使用0階矩。這將返回圖像中斑點的區域。這個鏈接可能有助於實現我剛剛描述的內容。 http://www.aishack.in/2010/07/tracking-colored-objects-in-opencv/

+0

感謝您的建議,但Iam沒有得到如何編寫代碼來查找已檢測到的每個斑點/輪廓的區域。 – 2012-04-20 02:09:36

+0

感謝您的建議,但我不知道如何編寫代碼來查找已檢測到的每個斑點/輪廓的區域。我寫的代碼在以下鏈接中。你能否糾正它並回復。 :http://textuploader.com/?p=6&id=YwRl。 – 2012-04-20 02:16:18

+0

哦!我只是忘了,cvutility的頭文件和cpp文件可以在這些鏈接中找到:http://textuploader.com/?p = 6&id = Dtnvj http://textuploader.com/?p=6&id=TSlRQ請將它們包含在源目錄和包含路徑。 – 2012-04-20 02:28:38

10

好吧,我相信你的問題可以與最近推出的OpenCV被the bounding box demo解決。

enter image description here

正如你可能已經注意到了,你有興趣的對象應該是裏面最大的矩形畫面繪製。幸運的是,這段代碼並不複雜,我相信你可以通過調查和實驗來弄明白。

+0

thnx ..我會檢查出來。 – 2012-04-21 23:54:28

7

這是我的消除小輪廓的解決方案。 其基本思想是檢查每個輪廓的長度/面積,然後從矢量容器中刪除較小的一個。

通常你會得到這樣

Mat canny_output; //example from OpenCV Tutorial 
vector<vector<Point> > contours; 
vector<Vec4i> hierarchy; 
Canny(src_img, canny_output, thresh, thresh*2, 3);//with or without, explained later. 
findContours(canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0,0)); 

用Canny()預處理的輪廓,將得到的輪廓段,然而每個段被存儲與邊界像素作爲封閉的環。在這種情況下,你可以檢查長度並刪除小的像

for (vector<vector<Point> >::iterator it = contours.begin(); it!=contours.end();) 
{ 
    if (it->size()<contour_length_threshold) 
     it=contours.erase(it); 
    else 
     ++it; 
} 

沒有坎尼()預處理,你會得到對象的輪廓。 相似,也可以使用區域來定義閾值,以消除小物件,如)所示

vector<Point> contour = contours[i]; 
double area0 = contourArea(contour); 

此contourArea(OpenCV的教程是非零的像素數

0

我相信你可以使用形態學(請閱讀更多here

您需要在右側(您想要消除的那個)圓的半徑附近執行內核大小的侵蝕。然後使用相同的內核來擴大由侵蝕步驟產生的空隙。

FYI侵蝕後使用相同的內核擴張被稱爲開放。

代碼將是這樣的

int erosion_size = 30; // adjust with you application 
Mat erode_element = getStructuringElement(MORPH_ELLIPSE, 
         Size(2*erosion_size + 1, 2*erosion_size+1), 
         Point(erosion_size, erosion_size)); 
erode(binary_img, binary_img, erode_element); 
dilate(binary_img, binary_img, erode_element); 
0

這不是一個快速的方法,但可能在某些情況下有用。 OpencCV 3.0中有一個新功能 - connectedComponentsWithStats。有了它,我們可以獲得連接組件的區域,並消除不必要的。所以我們可以很容易地去除有孔的圓,與實心圓相同的邊界框。