OpenCV功能检测器 - ROI掩膜可获得更好的性能?

时间:2016-06-05 19:20:55

标签: c++ performance opencv image-processing

在OpenCV中,可以通过掩码指定感兴趣的区域作为特征检测器算法的输入。从我的角度来看,我希望获得巨大的性能提升,但是投资回报率很低的简单测试无法证实这一点。

在OpenCV中使用掩码时,期望获得更好的性能是否合理?或者是否需要修剪图像?

2 个答案:

答案 0 :(得分:2)

很可能掩码只是删除掩码外的所有关键点,因此OpenCV仍然要解析整个图像。

您可以缩小图像尺寸以提高速度

答案 1 :(得分:1)

我不确定这是否是您正在寻找的东西(特别是因为这是在Java中),但请查看this file,特别是第121行的功能。

这是为了您的方便:

    MatOfRect diceDetections = new MatOfRect(); // Essentially an array of locations where our dice features were detected. (Stupid wrappers)

    // Note that detectMultiScale has thrown an unknown exception before (literally, unknown). This is to prevent crashing.
    try {
        diceCascade.detectMultiScale(image, diceDetections, 1.1, 4, 0, new Size(20, 20), new Size(38, 38));
    } catch (Exception e) {
        e.printStackTrace();
    }

    // Debug, used for console output
    String curDetect = "";

    // Iterates for every Dice ROI
    for (int i = 0; i < diceDetections.toArray().length; i++) {

        Rect diceRect = diceDetections.toArray()[i];

        // Draws rectangles around our detected ROI
        Point startingPoint = new Point(diceRect.x, diceRect.y);
        Point endingPoint = new Point(diceRect.x + diceRect.width, diceRect.y + diceRect.height);
        Imgproc.rectangle(image, startingPoint, endingPoint, new Scalar(255, 255, 0));

        MatOfRect pipDetections = new MatOfRect();

        try {
            /*
             * Now this is interesting. We essentially create a sub-array of the image, with our dice ROI as the image. Then we perform the detection on the image. This gives us the relative
             * positions of our pip ROIs to the dice ROI. Later on, we can draw the circles around the pip ROI, with the centers' positions adjusted by adding the dice ROI positions, so that it
             * renders properly. This is an amazing trick, as it not only eliminates false positives in non-dice ROIs, but it reduces how many pixels the classifier has to analyze to only at most
             * 38 x 38 pixels (because of the size restraints provided while detecting dice ROIs). This means we can set the precision to an insane level, without performance loss.
             */
            pipCascade.detectMultiScale(image.submat(diceRect), pipDetections, 1.01, 4, 0, new Size(2, 2), new Size(10, 10));
        } catch (Exception e) {
            e.printStackTrace();
        }

        // Gets the number of detected pips and draws a cricle around the ROI
        int numPips = 0;
        for (int y = 0; y < pipDetections.toArray().length; y++) {
            Rect pipRect = pipDetections.toArray()[y]; // Provides the relative position of the pips to the dice ROI
            /*
             * Finds the absolute center of a pip. diceRect.x and diceRect.y provides the top-left position of the dice ROI. pipRect.x and pipRect.y provides the top-left position of the pip ROI.
             * Normally, to find a center of an object with size (w, h) with the top-left point (x, y), we divide the width and height by two, and then add on the x pos to the width and y pos to
             * the height. Now, since pipDetections only provide relative positioning to the dice ROI, we also need to add the dice position to find our absolute center position (aka relative to
             * the entire image).
             */
            Point center = new Point(diceRect.x + pipRect.x + pipRect.width / 2, diceRect.y + pipRect.y + pipRect.height / 2);
            Imgproc.ellipse(image, center, new Size(pipRect.width / 2, pipRect.height / 2), 0, 0, 360, new Scalar(255, 0, 255), 1, 0, 0);

            numPips++;
        }

简而言之,我有两个分类器,一个用于识别骰子(第129行),另一个用于识别骰子上的点(黑点)。它得到一个骰子ROI数组,然后对于数组中的每个项目,取一个图像的子矩阵(位于ROI),并使pip分类器扫描该矩阵而不是整个图像(第156行)。但是,如果您尝试显示检测结果(在我的示例中为点数),则需要将其偏移到您所在的ROI的位置,因此在第171和172行进行工作。

我确信这可以达到您所寻求的相同性能增益,但不一定以相同的方式(子映像与屏蔽)。