我希望手图像是手的黑白形状。这是输入和所需输出的示例:c++ - OpenCV图像为黑白形状-LMLPHP

使用阈值无法提供所需的输出,因为手中的某些颜色与背景颜色相同。如何获得所需的输出?

最佳答案

Adaptive thresholdfind contoursfloodfill

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

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

应对各种光照条件的最可靠方法可能是按照顶部的顺序进行所有操作。但是您可能仅能克服阈值或数量/充填量。

顺便说一句,也许最棘手的部分实际上是在寻找轮廓,因为findContours返回一个数组列表/vector/任何(取决于我认为的平台)MatOfPoints。 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;
}

07-28 03:00
查看更多