检测图像中类似形状的三个嵌套对象 [英] Detect three nested objects of similar shape in an image

查看:228
本文介绍了检测图像中类似形状的三个嵌套对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



原始图片和已分析的颜色:





在RGB图像上使用颜色范围的圆。正如你所看到的,图像上还有许多其他的斑点,我想要消除。



我试图比较所有三个图像中的所有形状



任何想法如何找到哪些轮廓/形状/对象上图片实际上是三个圆?



输入图片可能有一个角度/视角,因此我不能使用hough来查找圈子。



我需要的结果是三个圆圈(外轮廓和内轮廓)的轮廓,因为我需要对该数据进行进一步处理。



这实际上是这个问题的后续:



因此,您首先将图片转换为HSV,然后应用一些阈值来恢复面具。



蓝色面具:使用形态关闭操作将会移除一些 p>



红色面具:





黄色面具:





然后,您可以从这个面具中检索外部轮廓,只保留最大的



现在你只需要在这些轮廓上加一个椭圆:





请注意,我也对图片进行了尝试

在这种情况下,可以更好地使用轮廓的凸包,如果掩码不完美,代码将比轮廓本身更加鲁棒(代码如下) :





代码:

  #include< opencv2 / opencv.hpp> 
#include< vector>
#include< string>

using namespace std;
using namespace cv;

int main()
{
// Load image
Mat3b img = imread(path_to_image);

//转换为hsv
Mat3b hsv;
cvtColor(img,hsv,COLOR_BGR2HSV);

//查找不同颜色的掩码
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);

//应用形态close
Mat1b kernel = getStructuringElement(MORPH_ELLIPSE,Size(11,11));
morphoEx(blue_mask,blue_mask,MORPH_CLOSE,kernel);
morphologyEx(red_mask,red_mask,MORPH_CLOSE,kernel);
morphologyEx(yellow_mask,yellow_mask,MORPH_CLOSE,kernel);

//找到最大的blob并绘制它
vector< Point> blue_contour,red_contour,yellow_contour;
{
vector< vector< Point>>轮廓;
findContours(blue_mask.clone(),contoururs,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>>轮廓;
findContours(red_mask.clone(),contoururs,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>>轮廓;
findContours(yellow_mask.clone(),contoururs,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);});
}

//适合椭圆形
RotatedRect blue_ellipse = fitEllipse(blue_contour);
RotatedRect red_ellipse = fitEllipse(red_contour);
RotatedRect yellow_ellipse = fitEllipse(yellow_contour);

//绘制椭圆
椭圆(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;
}

凸包代码:

  //获取凸包
向量< Point> blue_hull,red_hull,yellow_hull;
convexHull(blue_contour,blue_hull);
convexHull(red_contour,red_hull);
convexHull(yellow_contour,yellow_hull);

//绘制凸包
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)


I want to detect an archery target by its colors and made it that far:

Original image and analyzed colors:

I'm getting the circles using color range on a RGB image. As you can see, there are also many other blobs on the images which I want to get rid of.

I tried to compare all shapes in all three images with each other to find the best match by matchShape, but it doesn't result in those three circles I want.

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

The input image might have an angle/perspective, so I can't use hough to find circles.

What I need as a result is a contour of the three circles (outer and inner contour), as I need to do further processing with that data.

This is actually a follow-up of that question: find archery target in image of different perspectives


As it is a more specific question, I created a new one. I'm new here


A follow-up to Miki's answer. One of the results looks like this: Contour of blue circle and fitting ellipse The contour in the binary image and the resulting ellipse in the original image are different.

I would still like to solve that problem. I'm thinking of an algorithm that goes along the contour of the binary image and wherever the contour is broken the algorithm keeps going using the last known radius until it finds the next pixel of the contour. Is there such an algorithm? Or maybe a method to stretch the fitting ellipse at specific points until all parts of the contour are covered?

解决方案

Finding directly the ellipses in that image can be quite tricky. You can, however, have a look here for a few info and references to code.


In this case, it's much easier to segment the 3 color: blue, red and yellow, find the outer contours, and fit an ellipse to them.

So, on this input image:

So, you first convert your image to HSV, and then apply some thresholds to recover the masks. Using morphological close operations will get rid of some holes, and link nearby blobs.

blue mask:

red mask:

yellow mask:

Then, you can retrieve the external contours from this masks, and keep only the largest (in case you find some smaller blob not belonging to the target).

Now you just need to fit an ellipse to these contours:

Please note that I tried also on the image in your other question. Blue target is deformed and so it's not an ellipse, so fitting an ellipse is not a good choice here:

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

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);

这篇关于检测图像中类似形状的三个嵌套对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆