RotatedRect ROI in OpenCV
Asked Answered
P

4

8

I have a RotatedRect, I want to do some image processing in the rotated region (say extract the color histogram). How can I get the ROI? I mean get the region(pixels) so that I can do processing.

I find this, but it changes the region by using getRotationMatrix2D and warpAffine, so it doesn't work for my situation (I need to process the original image pixels).
Then I find this suggests using mask, which sounds reasonable, but can anyone teach me how to get the mask as the green RotatedRect below.
The green RotatedRect is the ROI I want to do some processing

Excepts the mask, is there any other solutions ?
Thanks for any hint

Poetics answered 26/10, 2012 at 3:56 Comment(1)
does this help? You just need to use fillPoly to draw your rotated rect. You can get the 4 points bounding it using its size and angle.Guarino
P
7

Here is my solution, using mask:
The idea is construct a Mat mask by assigning 255 to my RotatedRect ROI.

How to know which point is in ROI (which should be assign to 255)?
I use the following function isInROI to address the problem.

/** decide whether point p is in the ROI.
*** The ROI is a rotated rectange whose 4 corners are stored in roi[] 
**/
bool isInROI(Point p, Point2f roi[])
{
    double pro[4];
    for(int i=0; i<4; ++i)
    {
        pro[i] = computeProduct(p, roi[i], roi[(i+1)%4]);
    }
    if(pro[0]*pro[2]<0 && pro[1]*pro[3]<0)
    {
        return true;
    }
    return false;
}

/** function pro = kx-y+j, take two points a and b,
*** compute the line argument k and j, then return the pro value
*** so that can be used to determine whether the point p is on the left or right
*** of the line ab
**/
double computeProduct(Point p, Point2f a, Point2f b)
{
    double k = (a.y-b.y) / (a.x-b.x);
    double j = a.y - k*a.x;
    return k*p.x - p.y + j;
}

How to construct the mask?
Using the following code.

Mat mask = Mat(image.size(), CV_8U, Scalar(0));
for(int i=0; i<image.rows; ++i)
{
    for(int j=0; j<image.cols; ++j)
    {
        Point p = Point(j,i);   // pay attention to the cordination
        if(isInROI(p,vertices))
        {
            mask.at<uchar>(i,j) = 255;
        }
    }
}

Done,
vancexu

Poetics answered 31/10, 2012 at 6:29 Comment(1)
What are vertices? In my case, I have the roi coordinates as rect_points array of Point2f.Cenesthesia
E
5

I found the following post very useful to do the same. http://answers.opencv.org/question/497/extract-a-rotatedrect-area/

The only caveats are that (a) the "angle" here is assumed to be a rotation about the center of the entire image (not the bounding box) and (b) in the last line below (I think) "rect.center" needs to be transformed to the rotated image (by applying the rotation-matrix).

    // rect is the RotatedRect 
    RotatedRect rect;
    // matrices we'll use
    Mat M, rotated, cropped;
    // get angle and size from the bounding box
    float angle = rect.angle;
    Size rect_size = rect.size;
    // thanks to http://felix.abecassis.me/2011/10/opencv-rotation-deskewing/
    if (rect.angle < -45.) {
        angle += 90.0;
        swap(rect_size.width, rect_size.height);
    }
    // get the rotation matrix
    M = getRotationMatrix2D(rect.center, angle, 1.0);
    // perform the affine transformation
    warpAffine(src, rotated, M, src.size(), INTER_CUBIC);
    // crop the resulting image
    getRectSubPix(rotated, rect_size, rect.center, cropped);
Eldwen answered 25/4, 2014 at 20:54 Comment(0)
A
1

If you need a superfast solution, I suggest:

  • crop a Rect enclosing your RotatedRect rr.
  • rotate+translate back the cropped image so that the RotatedRect is now equivalent to a Rect. (using warpAffine on the product of the rotation and the translation 3x3 matrices)
  • Keep that roi of the rotated-back image (roi=Rect(Point(0,0), rr.size())).

It is a bit time-consuming to write though as you need to calculate the combined affine transform.

Aiden answered 26/11, 2012 at 21:8 Comment(0)
C
1

If you don't care about the speed and want to create a fast prototype for any shape of the region, you can use an openCV function pointPolygonTest() that returns a positive value if the point inside:

double pointPolygonTest(InputArray contour, Point2f pt, bool measureDist)

Simple code:

vector<Point2f> contour(4);
contour[0] = Point2f(-10, -10);
contour[1] = Point2f(-10, 10);
contour[2] = Point2f(10, 10);
contour[3] = Point2f(10, -10);    
Point2f pt = Point2f(11, 11);
an double res = pointPolygonTest(contour, pt, false);
if (res>0)
    cout<<"inside"<<endl;
else
    cout<<"outside"<<endl;
Couvade answered 6/2, 2014 at 23:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.