OpenCV从正方形的向量提取图像的区域 [英] OpenCV extract area of an image from a vector of squares

查看:736
本文介绍了OpenCV从正方形的向量提取图像的区域的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含正方形的图片,我需要提取该正方形中包含的区域。
应用 squares.c 脚本(在每个OpenCV分发的示例中可用),我获得一个正方形的向量,然后我需要为每个对象保存一个图像。



用户 karlphillip 建议:

  (size_t x = 0; x< squares.size(); x ++)
{
Rect roi(squares [x] [0] .x,squares [x] [0] .y,
square [x] [1] .x-squares [x] [0] .x,
squares [x] [3] .y-squares [x] [0]。
Mat subimage(image,roi);
}

以生成一个新的Mat原始图像



当karl记住我时,图像中检测到的点可能不是完美的正方形(如上图所示),但是我刚才建议的代码



其实我得到这个错误:

  OpenCV Error:Assertion failed(0< = roi.x&&< = 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

在抛出'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

中止


$ b b

建议让脚本接受非完美的正方形吗?

解决方案

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



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



第二,它还假定以顺时针方向检测到该区域的点,从 p0

$ p $ (p0)第一个 - 第二个图片的左上角



< (p1)
| |
| |
(p3)4th ---- 3rd(p2)

对于所有检测到的区域。这意味着这个代码:

  Rect roi(squares [x] [0] .x,squares [x] .y,
squares [x] [1] .x - squares [x] [0] .x,
squares [x] [3] .y- squares [x] [0] .y );

可能会产生一个ROI无效的ROI,例如负宽度和高度值,这就是为什么OpenCV在 Mat子图像(image,roi); 上抛出 cv :: Exception
$ b

你应该做的是编写一个代码,识别该区域的左上角,并调用 p0 在右侧的neightbor, p1 ,然后找到该区域的右下角,并调用 p2 那么剩下的是 p3 。之后,组装ROI很容易:

  Rect roi(p0.x,p0.y,
p1。 x - p0.x,
p3.y - p0.y);

EDIT



我在阅读文档时发现了优秀解决方案的OpenCV v2.3。它自动化我前面描述的过程,它使事情变得更容易和干净。你可以使用这个技巧将向量中的4个点排序成一个有意义的 Rect 结构:

  //由findSquares()返回并填充的数据。检查示例squares.cs有关此功能的更多信息。 
vector< vector< Point> >正方形;

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;
}


I have an image that contains a square, and I need to extract the area contained in that square. After applying the squares.c script (available in the samples of every OpenCV distribution) I obtain a vector of squares, then I need to save an image for each of them.

The user karlphillip suggested this:

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);
}

in order to generate a new Mat called subimage for all the squares detected in the original image

As karl remembered me, the points detected in the image may not represent a perfect square (as you can see in the image above) but the code I just suggested to you assumes they do.

In fact I get this error:

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

Suggestion for make the script accept also non perfect squares?

解决方案

I feel like I need to clarify a few things about that code.

First, it assumes that the region detected is a perfect square because it ignores some of the points inside squares[x] to create a new Mat.

Second, it also assumes that the points that make the region were detected in the clockwise direction, starting with p0 in the top-left corner of the image:

(p0)  1st----2nd  (p1)
       |      |
       |      |
(p3)  4th----3rd  (p2)

which might not be true for all the regions detected. That means that this code:

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);

probably will generate a ROI with invalid dimensions, such as negative width and height values, and that's why OpenCV throws a cv::Exception at you on Mat subimage(image, roi);.

What you should do, is write a code that will identify the top-left point of the region and call it p0, then it's nearest neightbor on the right side, p1, then find the bottom-right point of the region and call it p2, and then what's left is p3. After this, assembling the ROI is easy:

Rect roi(p0.x, p0.y, 
         p1.x - p0.x, 
         p3.y - p0.y);

EDIT:

I found an excellent solution while reading the documentation of the v2.3 of OpenCV. It automates the process I described earlier and it make things so much easier and clean. You can use this trick to order the 4 Points in the vector to a meaningful Rect structure:

// 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;
}

这篇关于OpenCV从正方形的向量提取图像的区域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆