RobertJoseph
RobertJoseph

Reputation: 8158

Detect location(s) of objects in an image

I have an input image that looks like this:

input image

Notice that there are 6 boxes with black borders. I need to detect the location (upper-left hand corder) of each box. Normally I would use something like template matching but the contents (the colored area inside the black border) of each box is distinct.

Is there a version of template matching that can configured to ignore the inner area of each box? Is the an algorithm better suited to this situation?

Also note, that I have to deal with several different resolutions... thus the actual size of the boxes will be different from image to image. That said, the ratio (length to width) will always be the same.

Real-world example/input image per request:

input image

Upvotes: 1

Views: 3659

Answers (1)

Miki
Miki

Reputation: 41775

You can do this finding the bounding box of connected components.

To find connected components you can convert to grayscale, and keep all pixels with value 0, i.e. the black border of the rectangles.

enter image description here

Then you can find the contours of each connected component, and compute its bounding box. Here the red bounding boxes found:

enter image description here

Code:

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

int main()
{
    // Load the image, as BGR
    Mat3b img = imread("path_to_image");

    // Convert to gray scale
    Mat1b gray;
    cvtColor(img, gray, COLOR_BGR2GRAY);

    // Get binary mask
    Mat1b binary = (gray == 0);

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

    // For each contour
    for (int i = 0; i < contours.size(); ++i)
    {
        // Get the bounding box
        Rect box = boundingRect(contours[i]);

        // Draw the box on the original image in red
        rectangle(img, box, Scalar(0, 0, 255), 5);
    }

    // Show result
    imshow("Result", img);
    waitKey();

    return 0;
}

From the image posted in chat, this code produces:

enter image description here

In general, this code will correctly detect the cards, as well as noise. You just need to remove noise according to some criteria. Among others: size or aspect ratio of boxes, colors inside boxes, some texture information.

Upvotes: 6

Related Questions