Обнаружение фигур - контурное приближение с помощью OpenCV

Я пишу небольшое приложение для обнаружения фигуры. Что мне нужно сделать в первую очередь, так это найти наиболее значимую фигуру на изображении. Я начал с некоторой предварительной обработки, включая преобразование изображения в оттенки серого, пороговое значение и обнаружение краев. Изображение до и после этих операций представлено ниже

Перед

enter image description here

После

enter image description here

Итак, вы видите, что основная фигура видна (однако она немного разбросана), а также есть некоторые шумы (маленькие деревья и т.д.). Мне нужно сделать так, чтобы как-то извлечь только самую значимую форму (самую большую) - в этом случае это башня. То, что я хотел сделать, это использовать функцию поиска контура в opencv, а затем как-то aproximate найти conturs с полигоном. Тогда я (каким-то образом) вычислил бы площадь гравюр и выберет только самую большую. До сих пор я управлял (только), чтобы найти контуры, используя

cvFindContours(crated,g_storage,&contours);

Я знаю, что есть

cvApproxPoly

однако я не могу получить полезную информацию для результата этой функции. Может ли кто-нибудь сказать мне, можно ли вычислить область контура или приблизить контур с полигоном. Может быть, вам лучше понять, как извлечь только самую значимую фигуру?

Ответы

Ответ 1

Вам не нужно делать обнаружение кромок здесь. Просто порог для двоичного изображения, а затем найдите blobs (cvFindContours). Вы можете использовать cvContourArea для каждого возвращаемого CvSeq, чтобы найти его область.

Ответ 2

Если у вас всегда есть контролируемый фон, я бы пошел на эти шаги (как это предложил также @damian):

  • Бинаризация, т.е. создание изображения, такого как background = 0, и области объекта = 1 (или 255). После этого на вашем изображении будет несколько белых областей. Существует несколько способов сделать это, но если ваш фон контролируется, вы можете использовать фиксированный порог. Обратите внимание, что здесь вы удалили шум внутри объектов. В двоичном изображении вы всегда можете использовать морфологическое открытие/закрытие, чтобы сгладить объекты.
  • Используйте cvFindContours, чтобы найти все объекты: теперь это должно быть проще.
  • Заполните более мелкие контуры цветом фона, используя cvFloodFill.

Ответ 3

Ваша основная проблема заключается в том, что контур башни рассеивается. Трудно воссоздать весь контур из этих маленьких кусочков. Оптимизируйте фазу обнаружения края (попробуйте cvAdaptiveThreshold) или используйте другой подход (возможно, что-то вроде сегментация объектов)

После того, как у вас есть контур в одной части, вы можете проверить его область следующим образом:

CvSeq* convex_hull=cvConvexHull2( contour, storage, CV_CLOCKWISE, 2 );
CvSeq* quad=cvApproxPoly(convex_hull, sizeof(CvContour), storage, CV_POLY_APPROX_DP, cvContourPerimeter(contour)*0.02, 0);
float size=fabs(cvContourArea( quad,CV_WHOLE_SEQ,0 ));

Вам нужно будет настроить параметры. Он использовался для обнаружения прямоугольников.

Ответ 4

Вы можете использовать морфологические операции для подавления "контурного шума" (расширение в вашем случае). Но вы должны помнить, что удобство использования морфологических операций зависит от текущей задачи. Например, если у вас есть два объекта, которые расположены близко друг к другу, расширение может сделать из них один объект.