# Fill an image with the content of RotatedRect

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 close merge delete

Sort by ยป oldest newest most voted

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

more

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

( 2013-06-07 03:07:49 -0600 )edit

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

}

more

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.

more

-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.

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

Official site

GitHub

Wiki

Documentation