OpenCV图像为黑白形状

时间:2012-09-22 16:03:42

标签: c++ image image-processing opencv shape

我希望手形图像是手的黑白形状。这是输入和所需输出的示例:hand black and white http://imageshack.us/a/img853/4017/handtobw.jpg

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

2 个答案:

答案 0 :(得分:5)

Adaptive thresholdfind contoursfloodfill

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

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

针对各种照明条件的最强大的方法可能是按照顶部的顺序完成所有这些操作。但是你可能只能通过门槛或者countours / floodfill逃脱。

顺便说一下,也许最棘手的部分实际上是找到轮廓,因为findContours会返回一个关于MatOfPoints的arraylist / vector /(取决于我认为的平台)。 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将填补您的漏洞)