How to find a black square with any angle of rotation in the image using emgu cv

房东的猫 提交于 2019-11-30 10:34:01

Since you are looking for a very specific object, you can use the following algorithm:

  1. Invert the image, so that the foreground becomes white, and the background black.
  2. Find contours of connected components
  3. For each contours

    a. Compute the minimum area rectangle box

    b. Compute the area of box: barea

    c. Compute the area of the contour: carea

    d. Apply some constraint to be sure your contour is the square you're looking for

The constraints of step 3d are:

  1. The ratio barea / carea should be high (let's say higher then 0.9), meaning that the contour belongs to an almost rectangular blob.

  2. The aspect ratio of box should be almost 1, meaning that the box is basically a square

  3. The size of the square should be almost 30, to reject other smaller or bigger squares in the image.

The result I get running this is:

Here is the code. Sorry, it's C++, but since it's all OpenCV function calls you should be able to port it easily to C#. At least, you can use it as a reference:

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

int main()
{
    // Load image
    Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);

    // Create the output image
    Mat3b out;
    cvtColor(img, out, COLOR_GRAY2BGR);

    // Create debug image
    Mat3b dbg = out.clone();

    // Binarize (to remove jpeg arifacts)
    img = img > 200;

    // Invert image
    img = ~img;

    // Find connected components
    vector<vector<Point>> contours;
    findContours(img.clone(), contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

    vector<RotatedRect> squares;

    // For each contour
    for (int i = 0; i < contours.size(); ++i)
    {
        // Find rotated bounding box
        RotatedRect box = minAreaRect(contours[i]);

        // Compute the area of the contour
        double carea = contourArea(contours[i]);
        // Compute the area of the box
        double barea = box.size.area();

        // Constraint #1
        if ((carea / barea) > 0.9)
        {
            drawContours(dbg, contours, i, Scalar(0, 0, 255), 7);

            // Constraint #2
            if (min(box.size.height, box.size.width) / max(box.size.height, box.size.width) > 0.95)
            {
                drawContours(dbg, contours, i, Scalar(255, 0, 0), 5);

                // Constraint #3
                if (box.size.width > 25 && box.size.width < 35)
                {
                    drawContours(dbg, contours, i, Scalar(0, 255, 0), 3);

                    // Found the square!
                    squares.push_back(box);
                }
            }
        }

        // Draw output
        for (int i = 0; i < squares.size(); ++i)
        {
            Point2f pts[4];
            squares[i].points(pts);

            for (int j = 0; j < 4; ++j)
            {
                line(out, pts[j], pts[(j + 1) % 4], Scalar(0,255,0), 5);
            }
        }
    }

    // Resize for better visualization
    resize(out, out, Size(), 0.25, 0.25);
    resize(dbg, dbg, Size(), 0.25, 0.25);

    // Show images
    imshow("Steps", dbg);
    imshow("Result", out);
    waitKey();

    return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!