4

我有一个包含正方形的图像,我需要提取该正方形中包含的区域。应用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][0].x, 
             squares[x][3].y - squares[x][0].y);
    Mat subimage(image, roi);
}

为了为原始图像中检测到的所有正方形生成一个名为 subimage 的新 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

使脚本也接受非完美正方形的建议?

4

1 回答 1

11

我觉得我需要澄清一些关于该代码的事情。

首先,它假设检测到的区域是一个完美的正方形,因为它忽略了里面的一些点squares[x]来创建一个新的Mat

其次,它还假设构成该区域的点是按顺时针方向检测到的,从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,例如负宽度和高度值,这就是 OpenCVcv::ExceptionMat subimage(image, roi);.

你应该做的是编写一个代码来识别区域的左上角并调用它p0,然后它是右侧最近的neightbor 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;
}
于 2011-10-13T14:49:14.880 回答