OpenCV图像转黑白形状

4
我希望手部图像成为黑白的手形。这是输入和期望输出的样例: hand black and white 由于手部内部的一些颜色与背景颜色相同,使用阈值处理无法得到期望的输出。如何获得所需的输出?
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;
}

我已经扩展了我的帖子,并链接到了我描述的函数的文档。 - 1''

1

您可以尝试两件事情:

阈值化后,您可以:

  1. 进行形态学闭运算,

  2. 或者,最简单的方法是:使用cv::findContours,保留最大的轮廓(如果有多个),然后使用cv::fillConvexPoly绘制它,您将得到这个掩码。(fillConvexPoly会为您填充孔洞)


@OgNamdik 你先尝试自己实现了吗?你应该展示一下你做了什么以及卡在哪里了。 - Sassa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接