4

我希望手的图像是手的黑白形状。这是输入和所需输出的示例:黑白手

使用阈值不会提供所需的输出,因为手内的某些颜色与背景颜色相同。我怎样才能得到想要的输出?

4

2 回答 2

5

自适应阈值查找轮廓填充

基本上,自适应阈值会将您的图像变成黑白,但会根据每个像素周围的本地条件获取阈值级别 - 这样,您应该避免使用普通阈值时遇到的问题。事实上,我不确定为什么有人会想要使用正常的阈值。

如果这不起作用,另一种方法是找到图像中最大的轮廓,将其绘制到单独的矩阵上,然后用黑色填充其中的所有内容。(Floodfill 就像 MSPaint 中的桶工具 - 它从特定像素开始,并填充与该像素相关的所有内容,该像素与您选择的另一种颜色相同。)

可能对各种照明条件最稳健的方法是按顶部的顺序进行所有操作。但是您可能只能摆脱阈值或计数/洪水填充。

顺便说一句,也许最棘手的部分实际上是找到轮廓,因为 findContours 返回 MatOfPoints 的 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;
}
于 2012-09-22T16:06:10.753 回答
1

您可以尝试两件快速的事情:

设置阈值后,您可以:

  1. 做一个形态闭合,

  2. 或者,最简单的:cv::findContours,如果大于一个,则保持最大,然后使用它绘制它cv::fillConvexPoly,您将获得此蒙版。(fillConvexPoly会为你填补漏洞)

于 2012-09-22T16:34:33.533 回答