connectedComponentsWithStats在Java中返回类型和值

时间:2015-12-26 11:31:21

标签: java opencv

我试图从二进制图像中获取一个或多个blob的质心(最好仅在blob的区域超过阈值时)。

findContours解决方案有效,但并不完美,FeatureDetetector.SIMPLEBLOB替代方案就像我想要的那样,但速度非常慢。

现在我正在尝试connectedComponentsWithStats,但不知道如何解释和使用结果,因为它使用Mats我不会期望它们并且文档不是很大的帮助。

如何访问相关信息,例如centriod x,y和area?

1 个答案:

答案 0 :(得分:5)

质心以及连接区域的边界框保存在生成​​的垫的每一行中。在带标签的图像中,您可以将区域视为连续索引。要提取质心,边界框和区域图像,您可以使用此类。它旨在提取近白色背景中的暗区。跳过背景区域。

请注意,在使用Segmentation对象时必须调用'release'方法。

import org.opencv.core.*;
import org.opencv.imgproc.Imgproc;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Segmentation {

    private Region[] regions = null;
    private Mat labeled = null;

    public Segmentation(Mat image, int bwThreshold) {

        Mat gray = new Mat(image.size(), CvType.CV_8U);

        if (image.type() != CvType.CV_8U) {
            Imgproc.cvtColor(image, gray, Imgproc.COLOR_BGR2GRAY);
        } else {
            image.copyTo(gray);
        }

        Mat bw = Mat.zeros(image.size(), image.type());
        Imgproc.threshold(gray, bw, bwThreshold, 255, Imgproc.THRESH_BINARY_INV);

        createRegions(bw);

        // Free memory
        kernel.release();
        gray.release();
        bw.release();
    }

    public Segmentation(Mat image) {
        this(image, 210);
    }

    private void createRegions(Mat image) {
        labeled = new Mat(image.size(), image.type());

        // Extract components
        Mat rectComponents = Mat.zeros(new Size(0, 0), 0);
        Mat centComponents = Mat.zeros(new Size(0, 0), 0);
        Imgproc.connectedComponentsWithStats(image, labeled, rectComponents, centComponents);

        // Collect regions info
        int[] rectangleInfo = new int[5];
        double[] centroidInfo = new double[2];
        regions = new Region[rectComponents.rows() - 1];

        for(int i = 1; i < rectComponents.rows(); i++) {

            // Extract bounding box
            rectComponents.row(i).get(0, 0, rectangleInfo);
            Rect rectangle = new Rect(rectangleInfo[0], rectangleInfo[1], rectangleInfo[2], rectangleInfo[3]);

            // Extract centroids
            centComponents.row(i).get(0, 0, centroidInfo);
            Point centroid = new Point(centroidInfo[0], centroidInfo[1]);

            regions[i - 1] = new Region(rectangle, centroid);
        }

        // Free memory
        rectComponents.release();
        centComponents.release();
    }

    /**
    * Extract region mask from labeled Mat
    *
    * @param region
    * @return Mat
    */
    public Mat getRegionMask(Region region) {
        int i = Arrays.asList(regions).indexOf(region);
        Mat mask = new Mat(labeled.size(), labeled.type());
        Scalar color = new Scalar(i + 1, i + 1, i + 1);
        Core.inRange(labeled, color, color, mask);
        return mask;
    }

    public Region[] getRegions() {
        return regions;
    }

    public Region getRegion(int index) {
        return regions[index];
    }

    /**
     * Call this method to release private Mat member
     */
    public void release() {
        labeled.release();
    }

    /**
    * Extract original image of the region using the region mask
    * @param image Original image
    * 
    */
    public Mat getRegionImageWithMask(Mat image, Region region) {
        Mat mask = getMask(region);
        Mat result = Mat.zeros(image.size(), image.type());
        result.setTo(new Scalar(255,255,255));
        image.copyTo(result, mask);
        Mat boxImage = new Mat(result, region.getBounding());
        mask.release();
        result.release();
        return boxImage;
    }

    /**
    * Extract original image of the region using the region mask
    * @param image Original image
    * 
    */
    public Mat getRegionImage(Mat image, Region region) {
        return new Mat(image, region.getBounding());;
    }

    public class Region {
        private Rect bounding;
        private Point centroid;

        public Region(Rect bounding, Point centroid) {
            this.bounding = bounding;
            this.centroid = centroid;
        }

        public Rect getBounding() {
            return bounding;
        }

        public Point getCentroid() {
            return centroid;
        }
    }
}