如何验证OpenCV中的矩形是否在cv :: Mat内?

17

在OpenCV中是否有类似cv::Mat::contains(cv::Rect)的东西?

背景: 在将对象检测为轮廓并尝试使用cv::boundingRect访问ROI时,我的应用程序崩溃了。好的,这是因为靠近图像边界的对象的边界矩形可能不完全在图像内。

现在通过以下检查跳过未完全位于图像内的对象:

if(
  cellRect.x>0 && 
  cellRect.y>0 && 
  cellRect.x + cellRect.width < m.cols && 
  cellRect.x + cellRect.width < m.rows) ...

我希望有一个专门的OpenCV函数来完成这个任务,其中cellRect是对象的边界矩形,m是图像。

3个回答

30

简单的方法是使用AND (即&) 操作符。

假设您想检查cv :: Rect rect是否在cv :: Mat mat中:

bool is_inside = (rect & cv::Rect(0, 0, mat.cols, mat.rows)) == rect;

可能不是最快的解决方案,但很有趣。(rect&rect_mat)将创建一个新的Mat对象,并且==将比较所有单元格。这肯定比获取和比较4个数字x,y,w,h要慢。 - Valentin H
4
不是创建一个新的 Mat,而是创建一个新的 Rect,它基本上只是4个数字 (x、y、宽度、高度)。所以它应该相对较快。 :P - herohuyongtao
1
好的,明白了!现在看起来确实很优雅! - Valentin H
括号在运算符 & 周围是很重要的。如果没有它,我会得到一个无意义的错误。 - Burak

5

您可以创建一个代表图像的矩形(x、y坐标为0,宽度和高度等于图像的宽度和高度),并检查它是否包含您轮廓的边界矩形。为了实现这一点,您需要使用矩形交集 - 在OpenCV中非常简单,只需使用rect1 & rect2即可。希望这段代码能使其更加清晰易懂:

cv::Rect imgRect = cv::Rect(cv::Point(0,0), img.size());
cv::Rect objectBoundingRect = ....;
cv::Rect rectsIntersecion = imgRect & objectBoundingRect;
if (rectsIntersecion.area() == 0)
  //object is completely outside image
else if (rectsIntersecion.area() == objectBoundingRect.area()) 
  //whole object is inside image
else 
  //((double)rectsIntersecion.area())/((double)objectBoundingRect.area()) * 100.0 % of object is inside image

有趣!我从未直观地理解&在OpenCV中代表交集。好知道!看起来似乎没有像Rect :: contains(Rect)这样的内置函数?为什么?对我来说,这似乎是一个非常常见和有用的功能。 - Valentin H
3
我认为不存在这样的函数,因为一个矩形可以完全包含另一个矩形、完全不包含或部分包含(在0-100%之间的任何部分)。如果您想检查rect1是否完全包含rect2,只需使用此代码bool contains = (rect1&rect2).area() == rect2.area()。请注意,如果rect2.area()为0(因此宽度或高度将等于0),则此代码将返回true,如果您不希望如此,请使用此代码:bool contains = rect2.area() && (rect1&rect2).area() == rect2.area()。希望这是您所需要的 :) - cyriel

-1

这里有一种方法可以判断一个矩形是否包含另一个矩形。 您可以从cv::Mat first中获取大小信息,然后使用以下方法:

public bool rectContainsRect(Rectangle containerRect, Rectangle subRect)
{
    if( containerRect.Contains(new Point(subRect.Left, subRect.Top)) 
        && containerRect.Contains(new Point(subRect.Right, subRect.Top))
        && containerRect.Contains(new Point(subRect.Left, subRect.Bottom))
        && containerRect.Contains(new Point(subRect.Right, subRect.Bottom)))
    {
        return true;
    }
    return false;
}

你在开玩笑吗? - Muhammet Ali Asan

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