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

前端 未结 1 1743
逝去的感伤
逝去的感伤 2020-12-09 14:23

I need to find the coordinates of three black squares in the test form. I took the example code from the site emgu.com and slightly changed it, but he does not find what I n

相关标签:
1条回答
  • 2020-12-09 14:45

    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;
    }
    
    0 讨论(0)
提交回复
热议问题