C++ OpenCV从正方形矢量中提取图像的面积
我有一个包含正方形的图像,我需要提取该正方形中包含的区域。 应用squares.c脚本(可在每个OpenCV分布的样本中获得)后,我获得了一个正方形向量,然后需要为每个正方形保存一个图像 用户karlphillip建议:C++ OpenCV从正方形矢量中提取图像的面积,c++,opencv,image-processing,object-detection,roi,C++,Opencv,Image Processing,Object Detection,Roi,我有一个包含正方形的图像,我需要提取该正方形中包含的区域。 应用squares.c脚本(可在每个OpenCV分布的样本中获得)后,我获得了一个正方形向量,然后需要为每个正方形保存一个图像 用户karlphillip建议: for (size_t x = 0; x < squares.size(); x++) { Rect roi(squares[x][0].x, squares[x][0].y, squares[x][1].x - squares[x]
for (size_t x = 0; x < squares.size(); x++)
{
Rect roi(squares[x][0].x, squares[x][0].y,
squares[x][1].x - squares[x][0].x,
squares[x][3].y - squares[x][0].y);
Mat subimage(image, roi);
}
(大小x=0;x
{
矩形roi(正方形[x][0]。x,正方形[x][0]。y,
正方形[x][1].x-正方形[x][0].x,
正方形[x][3].y-正方形[x][0].y);
Mat子图像(图像,roi);
}
为了为原始图像中检测到的所有正方形生成一个称为子图像的新Mat
正如karl记得的那样,图像中检测到的点可能并不代表一个完美的正方形(如上图所示),但我刚才向您建议的代码假设它们是
事实上,我得到了这个错误:
OpenCV Error: Assertion failed (0 <= roi.x && 0 <= roi.width &&
roi.x + roi.width <= m.cols && 0 <= roi.y && 0 <= roi.height &&
roi.y + roi.height <= m.rows) in Mat, file /usr/include/opencv/cxmat.hpp,
line 187
terminate called after throwing an instance of 'cv::Exception'
what(): /usr/include/opencv/cxmat.hpp:187: error: (-215) 0 <= roi.x &&
0 <= roi.width && roi.x + roi.width <= m.cols && 0 <= roi.y &&
0 <= roi.height && roi.y + roi.height <= m.rows in function Mat
Aborted
OpenCV错误:断言失败(0我觉得我需要澄清关于该代码的一些事情
首先,它假设检测到的区域是一个完美的正方形,因为它忽略了正方形[x]
内的一些点来创建一个新的Mat
Second,它还假设在顺时针方向检测到构成该区域的点,从图像左上角的p0
开始:
(p0) 1st----2nd (p1)
| |
| |
(p3) 4th----3rd (p2)
对于检测到的所有区域,这可能不是真的。这意味着此代码:
Rect roi(squares[x][0].x, squares[x][0].y,
squares[x][1].x - squares[x][0].x,
squares[x][3].y - squares[x][0].y);
可能会生成具有无效维度的ROI,例如负宽度和高度值,这就是OpenCV在Mat子图像(图像,ROI);
上向您抛出cv::Exception
的原因
您应该做的是,编写一个代码,识别区域的左上角点,并将其称为p0
,然后它是右侧最近的邻居,p1
,然后找到区域的右下角点并将其称为p2
,然后剩下的是p3
。在此之后,组装ROI很容易:
Rect roi(p0.x, p0.y,
p1.x - p0.x,
p3.y - p0.y);
编辑:
我在阅读OpenCV的v2.3版本时发现了一个非常好的解决方案。它自动化了我前面描述的过程,使事情变得更加简单和干净。您可以使用此技巧将向量中的4个点排序为有意义的Rect
结构:
// Data returned and filled by findSquares(). Check the example squares.cpp for more info on this function.
vector<vector<Point> > squares;
for (size_t i = 0; i < squares.size(); i++)
{
Rect rectangle = boundingRect(Mat(squares[i]));
cout << "#" << i << " rectangle x:" << rectangle.x << " y:" << rectangle.y << " " << rectangle.width << "x" << rectangle.height << endl;
}
//findSquares()返回并填充的数据。有关此函数的详细信息,请查看示例squares.cpp。
矢量平方;
对于(size_t i=0;i 虽然这个技巧对该示例图像()非常有效,但如果我尝试使用不同的图像(例如,但在许多其他输入图像中也会出现这种情况),我会继续收到相同的异常…此外,对于其他图像(),我得到:libpng警告:IHDR libpng中的图像宽度为零错误:无效IHDR数据OpenCV错误:错误标志cvGetMat中的(参数或结构字段)(无法识别或不支持的数组类型)错误:(-206)函数cvGetMat中无法识别或不支持的数组类型
导致问题的行是Mat子图像(图像,roi);
,问题是检测到的正方形的尺寸(aka.roi
)似乎不对。您需要将这些坐标打印到屏幕上,看看它们是否真的有意义,因为OpenCV认为它们没有意义。您还应该打印X的所有值,并查看所有正方形检测到的所有坐标。可能在检测过程中发生了奇怪的事情,您正在查看一个孤立的案例。无论如何,我在回答中解释的是正确的,从现在起,这取决于你和你的调试技巧。@Marco顺便说一句,我刚刚用代码更新了答案,这将为你省去很多麻烦。它自动识别点的过程,并将它们组织成一个Rect结构。这在OpenCV 2.3的文档中找到。这就是我有更多的理由停止使用他们提供的在线文档(用于v2.1),并开始使用OpenCV 2.3.x附带的文档。我想现在你可以接受我的正式答案了。