Вопрос по roi, opencv, image-processing, object-detection, c++ – OpenCV извлекает область изображения из вектора квадратов

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 для всех квадратов, обнаруженных в исходном изображении

Как вспомнил Карл, точки, обнаруженные на изображении, могут не представлять идеальный квадрат (как вы можете видеть на рисунке выше), но код, который я только что предложил вам, предполагает, что они это делают.

На самом деле я получаю эту ошибку:

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

Предложение для сценария принять также не идеальные квадраты?

Ваш Ответ

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 с недопустимыми размерами, такими как отрицательные значения ширины и высоты, и поэтому OpenCV выдаетcv::Exception у тебя наMat subimage(image, roi);.

Что вы должны сделать, это написать код, который будет идентифицировать верхнюю левую точку региона и назвать егоp0затем ближайший сосед с правой стороны,p1, затем найдите нижнюю правую точку региона и назовите ееp2и то, что осталосьp3, После этого легко собрать ROI:

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

РЕДАКТИРОВАТЬ:

Я нашелотличное решение читаядокументация v2.3 OpenCV. Это автоматизирует процесс, который я описал ранее, и делает вещи намного проще и понятнее. Вы можете использовать этот трюк, чтобы упорядочить 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;
}
Вам следует также распечатать все значения X и взглянуть на ВСЕ координаты, обнаруженные для ВСЕХ квадратов. Может быть, что-то странное произошло во время обнаружения, и вы смотрите на единичный случай. В любом случае, то, что я объяснил в своем ответе, верно, и теперь это зависит от вас и ваших навыков отладки. karlphillip
Линия, которая вызывает проблемуMat subimage(image, roi);и проблема в том, что размеры обнаруженного квадрата (ака.roiКажется, это не так. Вам нужно вывести эти координаты на экран и посмотреть, действительно ли они имеют смысл, потому что OpenCV считает, что это не так. karlphillip
@Marco Кстати, я только что обновил ответ кодом, который избавит вас от многих хлопот. Он автоматизирует процесс определения точек и организует их в структуру Rect. Это было найдено в документации OpenCV 2.3. Это еще одна причина для меня прекратить использовать имеющуюся там онлайн-документацию (для v2.1) и начать использовать ту, которая поставляется с OpenCV 2.3.x. Думаю, теперь вы можете принять мой ответ как официальный. karlphillip
Более того, с другими изображениями (img401.imageshack.us/img401/9792/64416141.jpg) Я получил:libpng warning: Image width is zero in IHDR libpng error: Invalid IHDR data OpenCV Error: Bad flag (parameter or structure field) (Unrecognized or unsupported array type) in cvGetMat Error: (-206) Unrecognized or unsupported array type in function cvGetMat Marco L.
в то время как этот трюк отлично работает с этим образцом изображения (img12.imageshack.us/img12/4104/26725680.jpg), если я попробую с другим изображением (какimg202.imageshack.us/img202/9962/66647480.jpg но это происходит с МНОГИМИ другими входными изображениями) Я продолжаю получать то же исключение ... Marco L.

Похожие вопросы