Detection of three nested objects of the same shape in the image

I want to determine the purpose of archery with my colors and do it like this:

Original image and analyzed colors:

I get circles using the color range on an RGB image. As you can see, there are also many other drops in the images that I want to get rid of.

I tried to compare all the shapes in all three images with each other in order to find the best match for MatchShape, but this does not lead to the three circles I want.

Any ideas how I can find out which outlines / shapes / objects in the image are actually three circles?

The input image may have an angle / perspective, so I cannot use hough to find circles.

As a result, I need a contour of three circles (external and internal contour), since I need to continue processing this data.

This is actually a continuation of this question: to find the target of archery in an image with different perspectives


Since this is a more specific question, I created a new one. I'm new here.


Follow up answer to Miki's question. One of the results is as follows: Outline of the blue circle and fitting ellipse The outline in the binary image and the resulting ellipse in the original image are different.

I would still like to solve this problem. I think of an algorithm that follows the path of a binary image, and wherever the path is broken, the algorithm continues to use the last known radius until it finds the next pixel of the path. Is there such an algorithm? Or maybe a way to stretch the fitting ellipse at specific points until all parts of the contour are covered?

0
source share
2 answers

You can find the Circle Hough Transform algorithm to find all the circular objects in the red, green, and blue channels and then match them.

You can find the implementation here or use the OpenCV implementation .

0
source

Finding directly ellipses in this image can be quite complicated. You can, however, look here for a few details and code links.


In this case, it is much easier to segment 3 colors: blue, red and yellow, find the outer contours and place them in an ellipse.

So, in this input image:

enter image description here

So, first convert the image to HSV, and then apply some threshold values ​​to restore the masks. Using morphological closure operations, you will get rid of some holes and connect adjacent drops.

blue mask:

enter image description here

red mask:

enter image description here

yellow mask:

enter image description here

Then you can get the outer contours from these masks and save only the largest ones (in case you find that some smaller blob does not belong to the target).

Now you just need to pick up the ellipse for these contours:

enter image description here

Please note that I also tried on the image in your other question . The blue target is deformed, and therefore it is not an ellipse, so setting an ellipse here is not a good choice:

enter image description here

In this case, it is better to use the convex hull of the contours, which will be more reliable than the contour itself if the mask is not perfect (the code is indicated below):

enter image description here

code:

#include <opencv2/opencv.hpp> #include <vector> #include <string> using namespace std; using namespace cv; int main() { // Load image Mat3b img = imread("path_to_image"); // Convert to hsv Mat3b hsv; cvtColor(img, hsv, COLOR_BGR2HSV); // Find masks for different colors Mat1b blue_mask; inRange(hsv, Scalar(90, 150, 150), Scalar(110, 255, 255), blue_mask); Mat1b red_mask; inRange(hsv, Scalar(160, 150, 100), Scalar(180, 255, 255), red_mask); Mat1b yellow_mask; inRange(hsv, Scalar(20, 150, 100), Scalar(30, 255, 255), yellow_mask); // Apply morphological close Mat1b kernel = getStructuringElement(MORPH_ELLIPSE, Size(11,11)); morphologyEx(blue_mask, blue_mask, MORPH_CLOSE, kernel); morphologyEx(red_mask, red_mask, MORPH_CLOSE, kernel); morphologyEx(yellow_mask, yellow_mask, MORPH_CLOSE, kernel); // Find largest blob and draw it vector<Point> blue_contour, red_contour, yellow_contour; { vector<vector<Point>> contours; findContours(blue_mask.clone(), contours, RETR_EXTERNAL, CHAIN_APPROX_NONE); blue_contour = *max_element(contours.begin(), contours.end(), [](const vector<Point>& lhs, const vector<Point>& rhs){ return contourArea(lhs) < contourArea(rhs); }); } { vector<vector<Point>> contours; findContours(red_mask.clone(), contours, RETR_EXTERNAL, CHAIN_APPROX_NONE); red_contour = *max_element(contours.begin(), contours.end(), [](const vector<Point>& lhs, const vector<Point>& rhs){ return contourArea(lhs) < contourArea(rhs); }); } { vector<vector<Point>> contours; findContours(yellow_mask.clone(), contours, RETR_EXTERNAL, CHAIN_APPROX_NONE); yellow_contour = *max_element(contours.begin(), contours.end(), [](const vector<Point>& lhs, const vector<Point>& rhs){ return contourArea(lhs) < contourArea(rhs); }); } // Fit ellipse RotatedRect blue_ellipse = fitEllipse(blue_contour); RotatedRect red_ellipse = fitEllipse(red_contour); RotatedRect yellow_ellipse = fitEllipse(yellow_contour); // Draw ellipses ellipse(img, blue_ellipse, Scalar(255, 0, 0), 3); ellipse(img, red_ellipse, Scalar(0, 0, 255), 3); ellipse(img, yellow_ellipse, Scalar(0, 255, 255), 3); imshow("Result", img); waitKey(); return 0; } 

Code for convex hull:

 // Get convex hulls vector<Point> blue_hull, red_hull, yellow_hull; convexHull(blue_contour, blue_hull); convexHull(red_contour, red_hull); convexHull(yellow_contour, yellow_hull); // Draw convex hulls drawContours(img, vector < vector<Point> > {blue_hull}, 0, Scalar(255,0,0), 3); drawContours(img, vector < vector<Point> > {red_hull}, 0, Scalar(0, 0, 255), 3); drawContours(img, vector < vector<Point> > {yellow_hull}, 0, Scalar(0, 255, 255), 3); 
0
source

Source: https://habr.com/ru/post/1262266/


All Articles