2012-09-22 154 views

回答

5

Adaptive thresholdfind contoursfloodfill

基本上,自適應閾值會將圖像變成黑白圖像,但會根據每個像素周圍的局部條件採取閾值級別 - 這樣,您應該避免使用普通閾值時遇到的問題。事實上,我不確定爲什麼有人會想要使用正常的門檻。

如果這不起作用,另一種方法是找到圖像中最大的輪廓,將其繪製到單獨的矩陣上,然後用黑色將其中的所有內容充滿。 (Floodfill就像MSPaint中的剷鬥工具 - 它從一個特定像素開始,並填充與該像素相連的所有與您選擇的另一種顏色相同的顏色)。

可能是針對各種照明的最穩健的方法條件是在頂部的序列中完成它們。但是,您可能只能通過門檻或計數/填充來逃脫。

順便說一下,也許最棘手的部分實際上是找到輪廓,因爲findContours返回一個ArrayOfPoints的ArrayList/vector/whatever(取決於我認爲的平臺)。 MatOfPoint是Mat的子類,但不能直接繪製 - 您需要使用drawContours。下面是一些代碼爲OpenCV4Android,我知道作品:

private Mat drawLargestContour(Mat input) { 
    /** Allocates and returns a black matrix with the 
    * largest contour of the input matrix drawn in white. */ 

    List<MatOfPoint> contours = new ArrayList<MatOfPoint>();   
    Imgproc.findContours(input, contours, new Mat() /* hierarchy */, 
      Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE); 
    double maxArea = 0; 
    int index = -1; 
    for (MatOfPoint contour : contours) { // iterate over every contour in the list 
     double area = Imgproc.contourArea(contour); 
     if (area > maxArea) { 
      maxArea = area; 
      index = contours.indexOf(contour); 
     } 
    } 

    if (index == -1) { 
     Log.e(TAG, "Fatal error: no contours in the image!"); 
    } 

    Mat border = new Mat(input.rows(), input.cols(), CvType.CV_8UC1); // initialized to 0 (black) by default because it's Java :) 
    Imgproc.drawContours(border, contours, index, new Scalar(255)); // 255 = draw contours in white 
    return border; 
} 
+0

我可以看到你的示例代碼嗎? –

+0

我已經擴展了我的文章並鏈接到我描述的功能的文檔。 –

1

兩個快速的東西,你可以嘗試:

閾值處理後,您可以:

  1. 執行形態閉合,

  2. 或最直接的:cv::findContours,如果它不止一個,則保持最大,然後繪製它使用cv::fillConvexPoly,你會得到這個面具。 (fillConvexPoly將填補你的空洞)

+0

你可以發佈一個示例代碼嗎?我還是個初學者。 –

+0

@OgNamdik你是否嘗試首先實現它?你應該顯示你做了什麼以及你卡在哪裏。 – Sassa