First time here? Check out the FAQ!

Ask Your Question
1

Fill an image with the content of RotatedRect

asked Jun 7 '13

yes123 gravatar image

updated Jun 7 '13

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

Preview: (hide)

3 answers

Sort by » oldest newest most voted
4

answered Jun 7 '13

Ben gravatar image

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

Preview: (hide)

Comments

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

Mahdi gravatar imageMahdi (Jun 7 '13)edit
1

answered Oct 7 '13

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

}
Preview: (hide)
0

answered Jun 7 '13

Mahdi gravatar image

updated Jun 7 '13

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.

Preview: (hide)

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 (Jun 9 '13)edit

Question Tools

Stats

Asked: Jun 7 '13

Seen: 10,619 times

Last updated: Oct 07 '13