2012-07-04 1 views
6

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

Я делаю классический процесс обнаружения прямоугольника, чтобы найти фидуциальные маркеры, т. Е. CvFindContours(), а затем приближенные квадраты от контуров. В случаях со многими, многие маркеры видны (или катастрофически, когда видна плотная сетка прямоугольников, которые не являются маркерами), вызов только cvFindContours() может занять> 30 мс на iPhone.

Я уже заменил невероятно дорогостоящий C++ cv :: FindContours() с cvFindContours(). В частности, если передан вектор>, версия C++ потратила дольше выделение и заполнение векторов, чем его внутренний cvFindContours() взял!

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

Я уже посмотрел на cvBlobLib (для устранения разногласий я имею в виду это: http://code.google.com/p/cvblob/), чтобы увидеть, предоставили ли он альтернативные алгоритмы, которые могли бы сделать то же самое быстрее. Базовая загрузка источника невероятно медленная, поскольку записывает контуры в std :: list() и тратит почти все свое время на распределение памяти. Замена этого списка на std :: vector с предварительным размером до 256 элементов для устранения исходных копий на push_back() по-прежнему оставляет вам функцию, которая занимает в 3 раза больше, чем cvFindContours(), 66% от этого непосредственно в cvb :: cvLabel (). Таким образом, это не кажется жизнеспособным для этого.

Есть ли у кого-нибудь идеи, как я могу оптимизировать обнаружение многих прямоугольников. Мой расплывчатым handwaving включает в себя:

  1. Существуют ли какие-либо быстрые реализации эквивалентны cvFindContour(), в идеале в виде исходного кода, как я мультиплатформенная, там?

  2. Большинство контуров не требуется, только «успешные» прямоугольники полезны. В частности, их внутренние контуры тогда не полезны. Теоретически, я мог бы вообще не называть cvFindContours и вместо этого вызывать cvStartFindContours/cvFindNextContour, проверяя каждый контур как найденный, а не рекурсивный, если бы нашел прямоугольник, который я ищу, так как subrectangles, следовательно, будут бесполезны?

  3. Есть ли совершенно другой алгоритм обнаружения прямоугольника, который я могу использовать из классического подхода FindContours()/ApproxPoly()?

  4. Есть ли способ «прервать» cvFindContours с полезными областями интереса? Например. обнаружение FAST-угла почти всегда возвращает мои координатные углы маркера даже с очень агрессивным порогом. Есть ли способ использовать этот набор точек для ограничения обнаружения? (К сожалению, я не уверен, насколько это помогает, опять же в случае многих маркеров или плотных линий сетки, не связанных с маркерами, что часто случается в моем приложении.)

  5. В том же духе, что и выше, поскольку Обнаружение BLOB может (если я правильно понимаю) реализовать как рекурсивное наводнение, есть ли какие-либо быстрые векторизованные реализации этого, которые затем могут быть использованы для того, чтобы каким-то образом вытащить интересные прямоугольники Blob и определить контур контура семян?

Любые идеи приветствуются!

+0

Только комментарий к вашей точке 5. Наполнение наводнений обычно не самый эффективный метод обнаружения блоба. Скорее, вы хотите использовать двухпроходные или однопроходные альго, некоторые из которых параллельны. Хорошей отправной точкой является страница Википедии «Маркировка связанных компонентов». –

+0

Любые обновления здесь? Новые идеи? У меня есть аналогичная проблема. – Antonvh

ответ

2

Поскольку ваша цель - обнаружение прямоугольника, а не определение контура, я бы предложил использовать интегральные изображения для вычисления. Объяснение интегральных изображений можно найти here. После вычисления интегрального изображения вашего желаемого изображения вычисление суммы пикселя прямоугольника можно выполнить тремя операциями.

Предполагая, что вы хотите нарисовать прямоугольники вокруг каждого нечерного объекта, вы можете использовать метод следующим образом. Рекурсивно продолжайте разделять изображение и его субимаги на 4 и отбрасывать прямоугольники с суммой пикселя ниже желаемого порога. Вы останетесь со множеством маленьких прямоугольников, аппроксимирующих ваши объекты. Объединение соседних прямоугольников даст быстрое приближение ваших обнаруженных объектов.