【问题标题】:What's the difference in results of cv::boundingRect() and cv::minAreaRect()?cv::boundingRect() 和 cv::minAreaRect() 的结果有什么区别?
【发布时间】:2021-12-22 22:32:44
【问题描述】:

我尝试阅读文档,但无法理解其中的区别。 当目标是 3x3 正方形时,我期待相同的结果, 但我用 cv::boundingRect() 得到 3x3,用 cv::minAreaRect() 得到 2x2。 我正在使用 OpenCV 4.4。

这是一个示例代码。

char data[25] = {
    0, 0, 0, 0, 0,
    0, 255, 255, 255, 0,
    0, 255, 255, 255, 0,
    0, 255, 255, 255, 0,
    0, 0, 0, 0, 0
};
cv::Mat image = cv::Mat(5, 5, CV_8U, data);

std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
cv::findContours(image, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);

cv::Rect boundingRect = cv::boundingRect(contours[0]);
std::cout << "[cv::boundingRect]" << std::endl;
std::cout << "w, h: " << boundingRect.size().width << " x " << boundingRect.size().height << std::endl;

cv::RotatedRect minAreaRect = cv::minAreaRect(contours[0]);
std::cout << "[cv::minAreaRect]" << std::endl;
std::cout << "w, h: " << minAreaRect.size.width << " x " << minAreaRect.size.height << std::endl;

输出是:

[cv::boundingRect]
w, h: 3 x 3
[cv::minAreaRect]
w, h: 2 x 2

提前致谢。

【问题讨论】:

标签: c++ opencv


【解决方案1】:

OpenCV 存在不一致和草率/没有“定义”,尤其是在那些旧部分中。

其中一些源于不愿意返回小数值来表示线条(轮廓)应该在像素之间。更多的原因是不清楚矩形的“右下角”是 in 的最后一个像素,还是 它的第一个像素......或者如果我们正在考虑位于这些像素的极端角落的

在 OpenCV 中,像素的中心是一个整数坐标。这是肯定的。

在您的示例中,这显然是一个边长为 3 的框,您会期望结果反映该大小。

findContours 为您提供 形状的严格点...它提供了这些边框像素中心。那些将是(1,1), (1,3), (3,3), (3,1)。这是第一个问题。

  • 如果您假设它们是 像素(小方块),您可以算出真正的大小是 3 x 3。
  • 如果将它们视为,则大小必须为 2 x 2。

boundingRect 似乎假定这些值是 像素。它告诉你正确的尺寸。左上角左上角像素,而不是左上角...矩形的右下角不在最后一个内部像素的右下角,而是在它外面的像素的中心。

minAreaRect 似乎假定值是 points。这就解释了它的大小为 2 x 2 的结果。

根据您需要的结果,您必须进行更正。有时这意味着从大小中添加/减去 one。有时这意味着将结果移动 一半 以获得像素的 上的点。

此外,OpenCV 的绘图功能也同样草率地定义。尝试使用LINE_AA 样式绘制一条特定粗细的线,例如 1 或 2...这是一团糟。可能会绘制一个矩形,使线条位于左上角 inside 像素上,而位于右下角像素上 outside

【讨论】:

  • 感谢@Christoph Rackwitz!你把这些事情说清楚了。
【解决方案2】:

很简单,boundingRect() 函数返回一个直立的矩形,或者它的底边平行于 x 轴。 minAreaRect() 函数还考虑围绕您传递给它的对象的轮廓的旋转,这允许它找到相对于总面积而言可能的最小矩形。

例如

boundingRect() 为绿色,minAreaRect() 为红色

【讨论】:

  • 这并不能解释 3x3 正方形的大小差异,正如 OP 所要求的那样
  • 文档指定 boundingRect() 和 minAreaRect() 因为它们是可以互换的......这对于图像处理的新手来说非常混乱。
猜你喜欢
  • 2016-04-16
  • 1970-01-01
  • 1970-01-01
  • 2023-03-29
  • 1970-01-01
  • 2014-06-21
  • 1970-01-01
  • 1970-01-01
  • 2016-11-05
相关资源
最近更新 更多