cv::boundingRect() 和 cv::minAreaRect() 的结果有何不同?
What's the difference in results of cv::boundingRect() and cv::minAreaRect()?
我尝试阅读文档,但无法理解其中的区别。
当目标是 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
提前致谢。
很简单,boundingRect() 函数 returns 一个直立的矩形,或者其底边平行于 x 轴。 minAreaRect() 函数还考虑围绕您传递给它的对象的轮廓的旋转,这允许它找到相对于总面积的最小可能矩形。
例如
boundingRect() 为绿色,minAreaRect() 为红色
OpenCV 存在不一致和 sloppy/no“定义”,尤其是在那些旧部分。
部分原因是不愿使用 return 分数值来表示一条线(轮廓)应该 在像素之间 。更多的原因是不清楚矩形的“右下角”是中的最后一个像素,还是外的第一个像素它...或者如果我们正在考虑位于这些像素极端角上的 点 。
在OpenCV中,像素的中心是一个整数坐标。肯定是这样。
在您的示例中,显然是一个边长为 3 的盒子,您希望结果反映该尺寸。
findContours
给你严格 在 形状中的点...它给那些边界 centers 像素。那些将是 (1,1), (1,3), (3,3), (3,1)
。这是第一个问题。
- 如果您假设它们是 像素(小方块),您可以计算出真实尺寸是 3 x 3。
- 如果考虑 点 ,大小必须为 2 x 2。
boundingRect
似乎假定值是 像素 。它会告诉您正确的尺寸。左上角是 on 左上角像素,而不是它的左上角...并且矩形的右下角不在最后一个内部的右下角像素,但在它外面的像素中心。
minAreaRect
似乎假定值是 点 。这解释了其大小为 2 乘以 2 的结果。
根据您需要结果的目的,您必须进行更正。有时这意味着 adding/subtracting 一个 从大小。有时这意味着将结果移动 一半 以获得像素 角 上的点。
此外,OpenCV 的绘图函数定义同样草率。尝试用 LINE_AA
样式绘制一条特定粗细的线,比如 1 或 2……这很乱。可能会绘制一个矩形,使该线位于左上角 inside 像素,右下角像素仅 outside.
我尝试阅读文档,但无法理解其中的区别。 当目标是 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
提前致谢。
很简单,boundingRect() 函数 returns 一个直立的矩形,或者其底边平行于 x 轴。 minAreaRect() 函数还考虑围绕您传递给它的对象的轮廓的旋转,这允许它找到相对于总面积的最小可能矩形。
例如
boundingRect() 为绿色,minAreaRect() 为红色
OpenCV 存在不一致和 sloppy/no“定义”,尤其是在那些旧部分。
部分原因是不愿使用 return 分数值来表示一条线(轮廓)应该 在像素之间 。更多的原因是不清楚矩形的“右下角”是中的最后一个像素,还是外的第一个像素它...或者如果我们正在考虑位于这些像素极端角上的 点 。
在OpenCV中,像素的中心是一个整数坐标。肯定是这样。
在您的示例中,显然是一个边长为 3 的盒子,您希望结果反映该尺寸。
findContours
给你严格 在 形状中的点...它给那些边界 centers 像素。那些将是 (1,1), (1,3), (3,3), (3,1)
。这是第一个问题。
- 如果您假设它们是 像素(小方块),您可以计算出真实尺寸是 3 x 3。
- 如果考虑 点 ,大小必须为 2 x 2。
boundingRect
似乎假定值是 像素 。它会告诉您正确的尺寸。左上角是 on 左上角像素,而不是它的左上角...并且矩形的右下角不在最后一个内部的右下角像素,但在它外面的像素中心。
minAreaRect
似乎假定值是 点 。这解释了其大小为 2 乘以 2 的结果。
根据您需要结果的目的,您必须进行更正。有时这意味着 adding/subtracting 一个 从大小。有时这意味着将结果移动 一半 以获得像素 角 上的点。
此外,OpenCV 的绘图函数定义同样草率。尝试用 LINE_AA
样式绘制一条特定粗细的线,比如 1 或 2……这很乱。可能会绘制一个矩形,使该线位于左上角 inside 像素,右下角像素仅 outside.