Ask Your Question
2

Angles in ellipse() function

asked 2013-06-03 03:54:17 -0600

Abid Rahman K gravatar image

Hi,

I am trying to draw an ellipse using OpenCV. But I have difficulty in understanding its angle arguments. Even it is not clear from the picture in OpenCV docs.

I tried following line:

cv2.ellipse(img,(256,256),(200,100),0,90,180,(0,0,255),4,cv2.CV_AA)

I got the result as below:

image description

That means startangle is taken from positive x axis in clockwise direction and that is same for endangle.

Now I tried this :

cv2.ellipse(img,(256,256),(200,100),0,45,225,(0,0,255),4,cv2.CV_AA)

I got the output as below :

image description

See, the startangle and endangle is not 45 and 225 here.

What is the problem here? Did I miss something ? Or is it a bug?

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
2

answered 2013-06-03 07:02:05 -0600

Guanta gravatar image

It is not a bug, the reason is that it is measured in arc-angles from an ellipse, not from a circle. I ran in the same troubles some weeks ago. The phenomen is visualized in paragraph (59) of http://mathworld.wolfram.com/Ellipse.html . It follows that you cannot compute the angle via atan2(y-center.y,x-center.x) since the points are not lying on a circle.

I had the problem that I wanted to draw an elliptical arc given the extremal points and all parameters of the ellipse except start and end angle via OpenCV, my solution was to convert the ellipse to a polygon and cut out the area where my extremal-points were located, so after cv::ellipse2poly():

void cutOut(const std::vector<cv::Point> & pts,
            std::vector<cv::Point> & poly, 
            const cv::Point2d & ext1, const cv::Point2d & ext2) const
{
    // whole ellipse
    if ( ext1 == cv::Point2d(0.0,0.0)
         && ext2 == cv::Point2d(0.0,0.0) )
    {
        return;
    }

    // get closest points on ellipse to given extremal points
    double min1 = std::numeric_limits<double>::max();
    double min2 = std::numeric_limits<double>::max();
    int min_ind1, min_ind2;
    for( size_t i = 0; i < pts.size(); i++ ) {
        double n1 = cv::norm(cv::Point2d(pts[i].x,pts[i].y) - ext1);
        if ( n1 < min1 ) {
            min_ind1 = i;
            min1 = n1;
        }
        double n2 = cv::norm(cv::Point2d(pts[i].x,pts[i].y) - ext2);
        if ( n2 < min2 ) {
            min_ind2 = i;
            min2 = n2;
        }
    }

    // copy points to poly
    if ( min_ind2 == min_ind1 ) {
        poly = pts;
    }
    if ( min_ind2 < min_ind1 ) {
        poly.insert(poly.begin(), pts.begin()+min_ind1, pts.end());
        poly.insert(poly.end(),pts.begin(), pts.begin()+min_ind2+1);
    } else {
        poly.insert(poly.begin(), pts.begin()+min_ind1, pts.begin()+min_ind2+1);
    }
}

I guess from this post: http://stackoverflow.com/questions/197649/how-to-calculate-center-of-an-ellipse-by-two-points-and-radius-sizes you can derive a direct solution?!

Please let me know, if you know a better (= mathematical) solution than my quick & dirty hack ;) .

edit flag offensive delete link more

Comments

+1 - Thank you. Hmm. it all looks a little dirty. Actually for drawing functions, circular angles were more better.

Abid Rahman K gravatar imageAbid Rahman K ( 2013-06-05 04:11:26 -0600 )edit

Yeah, I don't like it much either and would appreciate a better solution, too.

Guanta gravatar imageGuanta ( 2013-06-05 05:13:07 -0600 )edit

@Guanta, what you mean - better solution?

volodia gravatar imagevolodia ( 2015-10-08 08:31:44 -0600 )edit

well, I haven't provided a mathematical way to draw only the points necessary, instead you need to compute all points and afterwards cut those points out which you are interested in.

Guanta gravatar imageGuanta ( 2015-10-09 16:44:59 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2013-06-03 03:54:17 -0600

Seen: 17,584 times

Last updated: Jun 03 '13