OpenCV中的旋转矩形ROI

8
我有一个 RotatedRect ,我想在旋转的区域中进行一些图像处理(比如提取颜色直方图)。我怎样才能获得ROI?我的意思是获取该区域(像素),以便我可以进行处理。
我发现this,但它使用getRotationMatrix2DwarpAffine改变了区域,因此对于我的情况无法使用(我需要处理原始图像像素)。 然后我找到this建议使用mask,这听起来很合理,但是有人可以教我如何获取绿色的旋转矩形作为掩模吗? The green RotatedRect is the ROI I want to do some processing 除了掩模之外,是否还有其他解决方案? 感谢任何提示

1
这个链接有帮助吗?你只需要使用fillPoly来绘制旋转矩形。你可以通过其大小和角度获取包围它的4个点。 - Hammer
4个回答

7
这是我的解决方案,使用掩膜
构建一个Mat掩膜,将255分配给我的旋转矩形ROI
如何知道哪个点在ROI中(应分配给255)?
我使用以下函数isInROI来解决这个问题。
/** 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;
}

如何构造遮罩层
使用以下代码。

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

完成,
vancexu

什么是顶点?在我的情况下,我有roi坐标作为Point2f数组的rect_points。 - Mojo Jojo

5
我发现以下帖子非常有用,可以完成同样的任务。 http://answers.opencv.org/question/497/extract-a-rotatedrect-area/ 唯一需要注意的是,(a)这里的“角度”被假定为整个图像的中心(而不是边界框)的旋转,(b)在下面的最后一行中(我认为),需要将“rect.center”转换为旋转图像(通过应用旋转矩阵)。
    // 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);

1

如果您不关心速度,并且想要为任何形状的区域创建快速原型,您可以使用一个名为pointPolygonTest()的openCV函数,如果点在内部返回正值:

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

简单的代码:

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;

1

如果您需要一个超快速的解决方案,我建议:

  • 裁剪一个包含您旋转矩形rr的矩形。
  • 将裁剪后的图像旋转+平移回来,使得旋转矩形现在等同于一个矩形。(使用旋转和平移3x3矩阵的乘积上的warpAffine函数)
  • 保留旋转回来的图像的ROI(roi=Rect(Point(0,0), rr.size()))。

虽然需要计算组合仿射变换,但这需要一些时间来编写。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接