Ask Your Question
1

creating a rotatedRect in a threshold image

asked 2015-06-04 16:33:43 -0600

diegomez_86 gravatar image

updated 2015-09-16 15:21:11 -0600

Hello everybody

I am trying to draw an ellipse based on some points that I assign from a Threshold in an image. This is the image

image description

I used fitEllipse function with parameter, all of the points of all of the pixels in a vector of points, with this I thought I was going to get an ellipse in the center of the image, however I got this one

image description

I would like to get something like this (of course it should be an ellipse, but I'm not an expert in graphical design with paint) in a way of ellipse or if it was possible to get a RotatedRect square like this, then it would be awesome too.

image description

I also tried with contours, however the result is not also that good.

image description

I would like your help guys. this is the code I am using

#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
double thresholdValue = 0;

int main(int argc, char** argv) {

Mat src = imread( "/home/diego/Humanoids/imageGreen0.png", 1 );
Mat imageGreen = Mat::zeros(src.size(), CV_8UC1), threshold_output;
Vec3b result;

for (int i = 0; i < src.rows ; i++)
{
    for (int j = 0; j < src.cols ; j++)
    {
        result = src.at<cv::Vec3b>(i,j);
        int value = result[1];
        imageGreen.at<uchar>(i, j) = value;
    }
}

threshold( imageGreen, threshold_output, thresholdValue, 255, THRESH_BINARY_INV );
vector<Point2f> pointsPixels;
for(int i = 0; i < src.rows; i++)
    for(int j = 0; j < src.cols; j++)
    {
        if((int)threshold_output.at<unsigned char>(i, j) == 255)
        {
            pointsPixels.push_back(Point(j,i));
        }
    }

RotatedRect elipseBottle = fitEllipse(pointsPixels);
ellipse(threshold_output, elipseBottle, Scalar(125), 2, 8 );
imshow("threshold ouput", threshold_output);

 return 0;
}

I would be very thankful to you if you guys could help me with a solution or at least ideas (by now I will keep checking at rotatedRect functions or fitEllipse in case I did something wrong). Thanks a lot.

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
4

answered 2015-06-04 17:55:11 -0600

theodore gravatar image

updated 2015-06-04 19:05:12 -0600

the following code should do the trick:

    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;

    Mat bin;
    threshold(src, bin, 100, 255, CV_THRESH_BINARY);
    findContours( bin, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );

    // merge all contours into one vector
    std::vector<cv::Point> merged_contour_points;
    for (size_t i = 0; i < contours.size(); i++) {
      for (size_t j = 0; j < contours[i].size(); j++) {
        merged_contour_points.push_back(contours[i][j]);
      }
    }

    // get rotated bounding box
    std::vector<cv::Point> hull;
    cv::convexHull(cv::Mat(merged_contour_points),hull);
    cv::Mat hull_points(hull);
    cv::RotatedRect rotated_bounding_rect = minAreaRect(hull_points);
    // get ellipse
    cv::RotatedRect minEllipse = fitEllipse(hull_points);


    Mat drawing = Mat::zeros( src.size(), CV_8UC3 );
    // draw contours
    for( size_t i = 0; i < contours.size(); i++ )
    {
        drawContours( drawing, contours, i, Scalar(255, 255, 255), 1, 8, vector<Vec4i>(), 0, Point() );
    }

    // draw ellipse
    ellipse( drawing, minEllipse, Scalar(0, 255, 0), 1, 8 );

    // draw rotated bounding box
    Point2f rect_points[4]; rotated_bounding_rect.points( rect_points );
    for( int j = 0; j < 4; j++ )
      line( drawing, rect_points[j], rect_points[(j+1)%4], Scalar(0, 0, 255), 1, 8 );

image description image description

image description image description

enjoy :-)

edit flag offensive delete link more

Comments

Good job @theodore! Always like your explanations!

StevenPuttemans gravatar imageStevenPuttemans ( 2015-06-05 03:48:26 -0600 )edit
1

Wow, @theodore, Thanks for your help... it's awesome. Now I will look more at convex hull.

diegomez_86 gravatar imagediegomez_86 ( 2015-06-05 05:00:00 -0600 )edit

@theodore (or anyone who can answer this to me), I forgot to ask something about your code

In these 2 lines I saw that you converted the vectors of points into a matrices. Does it have any convenience for the program or does it produce better results? I tried with just the vectors of points pluse different images (20) and there was no difference (in the image, I don't know about the structure) in the results

 cv::convexHull(cv::Mat(merged_contour_points),hull);
 cv::RotatedRect minEllipse = fitEllipse(hull_points); //

Thanks in advance for your answer

diegomez_86 gravatar imagediegomez_86 ( 2015-06-06 04:46:11 -0600 )edit
2

As seen in the documentation you can choose. Afaik the accessing of a Mat element is a bit more optimized code wise internally than the vector, but in this case a vector<points> should be equally correct. You could test it by running 1000 images with both codes and then average the run time for a single item. It is possible than that this approach is somewhat faster.

StevenPuttemans gravatar imageStevenPuttemans ( 2015-06-06 08:07:22 -0600 )edit
1

Thanks @StevenPuttermans. Then I think I will keep converting the vectors to to Mat then.

diegomez_86 gravatar imagediegomez_86 ( 2015-06-06 09:11:34 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2015-06-04 16:33:43 -0600

Seen: 500 times

Last updated: Jun 04 '15