Ask Your Question
1

Fill an image with the content of RotatedRect

asked 2013-06-07 01:22:42 -0600

yes123 gravatar image

updated 2013-06-07 01:45:19 -0600

I have:

   Mat myImage;
   RotatedRect(myCenter,mySize,myAngle);

I would like to fill with black the rotated rectangle inside myImage.

Any fast/elegant way to do it?
Note: I would avoid to rotate the image just to fill that rotatedRect

edit retag flag offensive close merge delete

3 answers

Sort by ยป oldest newest most voted
4

answered 2013-06-07 02:43:32 -0600

Ben gravatar image

You can take the rotated rectangle's edges and use fillConvexPoly()

edit flag offensive delete link more

Comments

Thanks to Ben for the nice answer! So you should only compute fillConvexPoly(myImage, rRect.points(vertices), 4, Scalar(0));

Mahdi gravatar imageMahdi ( 2013-06-07 03:07:49 -0600 )edit
1

answered 2013-10-07 14:54:38 -0600

ahundt gravatar image

fillConvexPoly() seems like the right solution. Here is the version I wrote based on Ben's answer:

 // default color is white
inline void drawRotatedRect(cv::Mat& image, cv::RotatedRect rRect, cv::Scalar color = cv::Scalar(255.0, 255.0, 255.0) ) {

   cv::Point2f vertices2f[4];
   cv::Point vertices[4];
   rRect.points(vertices2f);
   for(int i = 0; i < 4; ++i){
     vertices[i] = vertices2f[i];
   }
   cv::fillConvexPoly(image,
                      vertices,
                      4,
                      color);
}


// default color is white
inline void drawRectangle(cv::Mat& image, cv::Point center, cv::Size rectSizePixels, double rotDeg, cv::Scalar color = cv::Scalar(255.0, 255.0, 255.0) ) {

   cv::RotatedRect rRect(center, rectSizePixels, rotDeg); // opencv expects degrees
   drawRotatedRect(image,rRect);

}
edit flag offensive delete link more
0

answered 2013-06-07 02:53:11 -0600

Mahdi gravatar image

updated 2013-06-07 02:55:31 -0600

Here is an answer to this: The idea is to check whether every pixel is in the region respect to rectangle edges:

for(int i=0; i<myImage.rows; ++i)
{
    for(int j=0; j<myImage.cols; ++j)
    {
        if(isInRotatedRect( Point(j,i), rotated_rect))
        {
            myImage.at<uchar>(i,j) = 0;
        }
    }
}

for computing isInRotatedRect:

bool isInRotatedRect(Point p, RotatedRect rRect)
{
    double line_pro[4];
    Point2f vertices[4];
    rRect.points(vertices);
    for(int i=0; i<4; ++i)
    {
        line_pro[i] = computeProduct(p, vertices[i], vertices[(i+1)%4]);
    }
    if(line_pro[1]*line_pro[3]<0 && line_pro[0]*line_pro[2]<0)
    {
        return true;
    }
    return false;
}

//finding whether  point p is at the left or right side of rectangle edge ab.  
double computeProduct(Point p, Point2f a, Point2f b)
{
    double m = (a.y-b.y) / (a.x-b.x);
    double c = a.y - k * a.x;
    return m * p.x - p.y + c;
}

A better and more intuitive way would be rather than doing this for every image make a zero one mask and the cross product original image! This may be more efficient specially in video.

edit flag offensive delete link more

Comments

-1. This is a naive brute-force solution unable to generalize (i.e. different line widths and styles) and simply too complicated and therefore slow.

SR gravatar imageSR ( 2013-06-08 20:15:49 -0600 )edit

Question Tools

Stats

Asked: 2013-06-07 01:22:42 -0600

Seen: 10,318 times

Last updated: Oct 07 '13