簡體   English   中英

輪廓 opencv:如何消除二值圖像中的小輪廓

[英]Contours opencv : How to eliminate small contours in a binary image

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

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

我獲得的二進制圖像

在此處輸入圖片說明

我想獲得的結果/輸出圖像

在此處輸入圖片說明

好的,我相信您的問題可以通過 OpenCV 最近推出的邊界框演示來解決。

在此處輸入圖片說明

您可能已經注意到,您感興趣的對象應該在圖片中最大的矩形繪制內。 幸運的是,這段代碼並不是很復雜,我相信你可以通過調查和試驗來弄清楚。

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

通常你會得到這樣的輪廓

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;
}

如果沒有 Canny() 預處理,您將獲得對象的輪廓。 類似的,你也可以使用area來定義一個閾值來消除小物體,如OpenCV教程所示

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

這個contourArea() 是非零像素的數量

您確定按小輪廓區域過濾不起作用嗎? 它總是對我有用。 我們可以看看你的代碼嗎?

此外,正如 sue-ling 所提到的,最好同時使用 erode 和 dilate 來近似保留區域。 要去除小的嘈雜位,請先使用腐蝕,然后填充孔,先使用膨脹。

另外,如果您還不知道cv * 函數的新 C++ 版本( findContours 文檔),您可能想查看它們。 在我看來,它們更容易使用。

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

我相信你可以使用像 erode 和 dilate 這樣的形態學運算符( 在這里閱讀更多)

您需要使用接近右側圓(要消除的圓)半徑的內核大小執行侵蝕。 然后使用相同的內核進行膨脹以填充腐蝕步驟產生的間隙。

僅供參考,使用相同的內核進行腐蝕和膨脹稱為開運算。

代碼將是這樣的

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 );

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM