0
votes

I want to implement the following using OpenCV (I'll post my attempt at the bottom of the post). I am aware that OpenCV has a function for something like this, but I want to try to write my own.

In an image (Mat) (the coordinate system is at the top left, since it is an image) of width width and height height, I want to display a filled ellipsewith the following properties:

  • it should be centered at (width/2, height/2)

  • the image should be binary, so the points corresponding to the ellipse should have a value of 1 and others should be 0

  • the ellipse should be rotated by angle radians around the origin (or degrees, this does not matter all that much, I can convert)

  • ellipse: semi-major axis parameter is a and semi-minor axis parameter is b and these two parameters also represent the size of these axes in the picture, so "no matter" the width and height, the ellipse should have a major axis of size 2*a and a minor axis of size 2*b

Ok, so I've found an equation similar to this (https://math.stackexchange.com/a/434482/403961) for my purpose. My code is as follows.. it does seem to do pretty well on the rotation side, but, sadly, depending on the rotation angle, the SIZE (major axis, not sure about the minor) visibly increases/decreases, which is not normal, since I want it to have the same size, independent of the rotation angle.

NOTE The biggest size is seemingly achieved when the angle is 45 or -45 degrees and the smallest for angles like -90, 0, 90.

Code:

inline double sqr(double x)
{
    return x * x;
}

Mat ellipticalElement(double a, double b, double angle, int width, int height)
{
    // just to make sure I don't use some bad values for my parameters
    assert(2 * a < width);
    assert(2 * b < height);

    Mat element = Mat::zeros(height, width, CV_8UC1);

    Point center(width / 2, height / 2);
    for(int x = 0 ; x < width ; x++)
        for(int y = 0 ; y < height ; y++)
        {
            if (sqr((x - center.x) * cos(angle) - (y - center.y) * sin(angle)) / sqr(a) + sqr((x - center.x) * sin(angle) - (y - center.y) * cos(angle)) / sqr(b) <= 1)
                element.at<uchar>(y, x) = 1;
        }

    return element;
}
1

1 Answers

1
votes

A pesky typo sneaked in your inequality. The first summand must be

sqr((x - center.x) * cos(angle) + (y - center.y) * sin(angle)) / sqr(a)

Note the plus sign instead of minus.