Перейти к содержимому
Compvision.ru
RinOS

Многопоточность и OpenCV

Recommended Posts

Всем привет! Кто ни будь программировал многопоточные приложения, с OpenCV?

Какие подводные камни? Нормально ли сочетаются такие вещи как OpenCV и многопоточность?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Всем привет! Кто ни будь программировал многопоточные приложения, с OpenCV?

Какие подводные камни? Нормально ли сочетаются такие вещи как OpenCV и многопоточность?

C++ Builder приложение является многопоточным :)

Писал еще приложение работающее с Ethernet отдельным потоком, работает вполне хорошо.

Проблем быть не должно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Всем привет! Кто ни будь программировал многопоточные приложения, с OpenCV?

Какие подводные камни? Нормально ли сочетаются такие вещи как OpenCV и многопоточность?

Проблем с многопоточностью не будет. Да и исходники открыты-то, можно самому убедиться: потоки лишние не создаются, локальный стек потока для внутренних целей также не используется (в отличие от той же Intel jpeg library, будь она неладна).

Однако покотобезопасной, в классическом смысле этого слова, библиотека не является: обращения к одному объекту из разных потоков надо синхронизировать. Но это нормально, скрытые методы синхронизации не есть гут.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Однако покотобезопасной, в классическом смысле этого слова, библиотека не является:

Это плохо((

обращения к одному объекту из разных потоков надо синхронизировать.

К примеру о каких объектах идет речь?

К примеру возьмем функцию cvCanny, десяток потоков вызывают эту функцию, со своими данными (одновременно). Будут ли тут какие нибудь траблы?

У меня в ПО архитектура такая:

Есть программа в ней N потоков, в цикле обращаются к DLL, и вызывают функцию.

Вот схема:

HpvXR4vOVG.gif

Если что то не понятно, поясню!

Так вот, когда вызыватся process через некоторе время сыпяться ексепшены из cxcore.dll ((

Если расставить критические секции перед вызовом process(), то все нормально, но тк эта функция выполняется некотое время, другие потоки ждут, и получается не многопоточность, а последовательно... имхо

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Это плохо((

К примеру о каких объектах идет речь?

К примеру возьмем функцию cvCanny, десяток потоков вызывают эту функцию, со своими данными (одновременно). Будут ли тут какие нибудь траблы?

У меня в ПО архитектура такая:

Есть программа в ней N потоков, в цикле обращаются к DLL, и вызывают функцию.

Вот схема:

HpvXR4vOVG.gif

Если что то не понятно, поясню!

Так вот, когда вызыватся process через некоторе время сыпяться ексепшены из cxcore.dll ((

Если расставить критические секции перед вызовом process(), то все нормально, но тк эта функция выполняется некотое время, другие потоки ждут, и получается не многопоточность, а последовательно... имхо

Похоже что критические секции это единственный путь, но согласен что это уже не многопоточность.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
К примеру о каких объектах идет речь?

К примеру возьмем функцию cvCanny, десяток потоков вызывают эту функцию, со своими данными (одновременно). Будут ли тут какие нибудь траблы?

C cvCanny проблем не будет. Проблемы при многопоточности возникают, если в функции используются static переменные (не помню, есть ли аналог в Делфи), всевозможные глобальные состояния. В cvCanny же всё чисто.

Так вот, когда вызыватся process через некоторе время сыпяться ексепшены из cxcore.dll ((

Если расставить критические секции перед вызовом process(), то все нормально, но тк эта функция выполняется некотое время, другие потоки ждут, и получается не многопоточность, а последовательно... имхо

Если говорить об архитектуре, то она у тебя не многопоточная именно из-за единой функции Process. Как правило, единая функция/объект-менеджер занимается только созданием/удалением объектов. Алгоритм примерно таков:

1. Поток запрашивает о необходимости создания объекта/функции.

2. Запрашиваемый объект/функция создаётся в менеджере, указатель или интерфейс передаётся потоку. Менеджер также хранит у себя данный указатель и идентификатор потока. Этот этап необходимо синхронизировать критическими секциями/мьютексами.

3. Далее поток, минуя менеджер, работает с указателем/интерфейсом. Тут синхронизация не нужна.

4. Когда поток своё отработал, то указатель обнуляется/интерфейс освобождается и менеджер удаляет его сам и убирает из своей таблицы. Данный этап также синхронизируется.

На разных языках сделать такое можно с разными трудозатратами. Зачастую помогает автоматическая сборка мусора, всякие умные указатели в С++ или всё делать вручную.

Портить ситуацию могут глобальные переменные и состояния, несинхронизированный доступ к общим ресурсам.

Про вылеты в cxcore трудно сказать. Я бы скомпилировал её с отладочной информацией и посмотрел в дебаггере место вылета и стек вызовов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
C cvCanny проблем не будет. Проблемы при многопоточности возникают, если в функции используются static переменные (не помню, есть ли аналог в Делфи), всевозможные глобальные состояния. В cvCanny же всё чисто.

Мда...) в одной функции memstorage был объявлен как статик :)

2. Запрашиваемый объект/функция создаётся в менеджере, указатель или интерфейс передаётся потоку. Менеджер также хранит у себя данный указатель и идентификатор потока. Этот этап необходимо синхронизировать критическими секциями/мьютексами.

Классно) подумаю над тем что бы сделать через интерфейс) Спасибо!

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Мда...) в одной функции memstorage был объявлен как статик :)

Есть один рабочий, но немного извращенческий способ решения проблемы. Допустим, у тебя есть dll, которая не предназначена для многопоточного использования.

1. Поставляешь с программой эту xxx.dll.

2. Для каждого своего i-го потока создаёшь физическую копию этой длл: xxx_i.dll. Подключаешь её в этом потоке динамически (LoadLibrary и т.д), статическая линковка не подходит.

3. Поток завершается, делается FreeLibrrary и xxx_i.dll удаляется с диска.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
2. Для каждого своего i-го потока создаёшь физическую копию этой длл: xxx_i.dll. Подключаешь её в этом потоке динамически (LoadLibrary и т.д), статическая линковка не подходит.

Да такая идея, посещала меня) Ну это на крайний случай))

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

А как сделать, чтобы вывод изображения с камеры не было замедленным?

while(1)

{

capimg=cvQueryFrame(video);

...

}

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

Реально ли сделать чтобы 30fps было?

Например организовать с помощью потоков.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Точнее я не так выразился- не "замедленное" движение, а не плавное движение. То есть не все кадры захватываются.

проц 3ГГц камера 30кадров\сек 640х480 пикселей.(Logitech E1000)

ситуация такая - пока openCV обрабатывает участок кода между вызовами QueryFrame, то естественно она теряет кадры если не выполняет этот участок кода хотя бы за 1/30 секунды.

Вот например, когда я вывожу изображение с камеры в MPLAYER, то сообщается сколько фреймов получено, а сколько сброшено :

mplayer -vf mirror -fps 6 tv:// -tv driver=v4l2:device=/dev/video0

v4l2: 62 frames successfully processed, 189 frames dropped.

Mplayer показывает плавные движения.

И сравнил сколько фреймов отработала моя программа с количеством фреймов, захваченные mplayer`ом

программа - 40 фреймов за 10 секунд

mplayer 62 фрейма за 10 секунд

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Если процессор хотя бы двухъядерный, то можно сделать 2 потока.

Вариант 1.

Первый поток выполняет только захват видео и копирует каждый кадр во второй поток, в котором будет производиться обработка.

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

Вариант 2.

Сделать очередь, в которую первый поток будет складывать захваченные кадры. Второй поток, соответственно, будет из неё читать и обрабатывать. Если размер очереди будет превышать некоторые разумные пределы (скажем 150 кадров), то выбрасывать кадры из очереди, но не подряд, а равномерно. Таким образом, пропадание кадров не приведёт к "дёрганию" картинки.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Здравствуйте уважаемые.

Вопрос короткий и по существу:

Имеется скажем 2, 3 или 4 камеры, необходимо работать с каждой в своем потоке.

Кто решал подобный вопрос, как реализовать многопоточность ?

Спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Насколько я знаю, в OpenCV не механизма создания и управления потоками.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Здравствуйте уважаемые.

Вопрос короткий и по существу:

Имеется скажем 2, 3 или 4 камеры, необходимо работать с каждой в своем потоке.

Кто решал подобный вопрос, как реализовать многопоточность ?

Спасибо.

На каждый поток(Например Boost::thread или pthread) создавйте свой Iplimage cvCapture и своё окошко воспроизведения , если вообщих чертах.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

тут так и ничего не сказали про многопоточность(или я не понял).

все таки как она реализована в opencv?

т.е. распараллелены ли функции уже заранее? (у меня все время только 1 ядро загружается)

или надо самому использовать Openmp или какие то треды?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Это другой аспект многопоточности - здесь говорилось о потокобезопасности.

1. OpenMP, вроде, подключить можно. Во всяком случае в коде OpenCV есть максросы _OPENMP и USE_OPENMP. Надо их включить и перекомпилировать OpenCV. Попробуешь?

2. Судя по параметрам CMake, OpenCV может использовать Intel Threading Building Blocks - более удобный аналог OpenMP. Надо их поставить, переконфигурировать с помощью CMake OpenCV и перекомпилировать.

3. Можно самому использовать потоки (например из boost'а).

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

А у меня такой вопрос...

Захватываю видео в основном потоке процесса(который создан изначально) все остальное поотключал, нагрузка на проц 12 процентов

Зпхватываю видео в потоке, остальную всю обработку изображения поотключал, тоже. нагрузка 50 - 60. Это как? работа выполняется одна и таже

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

1. Лучше выложить код, чтобы не гадать.

2. Как передаёшь изображения из потока захвата в поток отрисовки?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

вообщем поэкспериментирую с opencv2.1 перенесу на ноут(т.к. там 4 ядра и есть вебка) попробую перекомпилировать библиотеку интеловским компилятором и с поддержкой IPP и многопоточности.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Компилировал Microsoft'овским компилятором, хотелось бы узнать поподробней, как её откомпилировать с поддержкой многопоточности?

Выкладывать не совсем удобна... т.к есть программа, сама по себе реализующая только момент сопряжения длл'ок, она экспортирует в определённы класс все выходы и входы с библиотек и функцтии по их связыванию,

у библеотеки съёма изображения есть импорт выходная картинка и событие, у библиотеки обрабатывающей есть входные и выходные картинки с событиями, у библиотеки отображающей, только входные

завязка происходит следующим образоб

IplImage * in_1 = &out_2; индексы обозначают библиотеки

И С СОБЫТИЯМИ HANDLE inE_1 = outE_2;

Не это упрощённый вариант могу выложить просто архив, с исходниками, что б помсмотрели

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×