Задержка OpenCV VideoCapture/V4L2 при захвате нового изображения с веб-камеры

Для проекта компьютерного зрения, над которым я работаю, мне нужно получать изображения с помощью веб-камеры Logitech C920. Для этого я использую OpenCV VideoCapture, но проблема, с которой я сталкиваюсь, заключается в том, что изображение, которое я делаю в определенный момент, не показывает последнее, что видит камера. То есть, если я делаю снимок с временной меткой t, он показывает, что камера видела с временной меткой (t - дельта), так сказать.

Я сделал это, написав программу, которая увеличивает счетчик и показывает его на экране. Я направил камеру на экран и позволил записи. Когда счетчик достигает определенного значения, скажем, 10000, он захватывает изображение и сохраняет его с именем файла «counter_value.png» (например, 10000.png). Таким образом, я смог сравнить текущее значение счетчика с текущим значением, которое видит камера. Я заметил, что большую часть времени задержка составляет около 4-5 кадров, но это не фиксированное значение.

Я видел подобные сообщения об этой проблеме, но ни один из них не помог. Некоторые люди рекомендовали поместить процедуру захвата кадров в отдельный поток и обновить переменную «current_frame» в Mat. Я пробовал это, но по какой-то причине проблема все еще присутствует. Кто-то еще упомянул, что камера хорошо работала в Windows (но мне нужно использовать Linux). Я попытался запустить тот же код в Windows, и действительно, задержка составила всего около 1 кадра (что также могло быть связано с тем, что камера не видела счетчик, потому что экран не обновлялся достаточно быстро).

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

Я новичок в V4L2, и мне действительно нужно решить эту проблему как можно скорее, поэтому мои вопросы к вам, ребята:

  1. Кто-нибудь нашел решение для получения последнего изображения с использованием V4L2 (и, возможно, OpenCV)?
  2. Если нет способа решить ее с помощью V4L2, кто-нибудь знает другую альтернативу решению этой проблемы в Linux?

С уважением,

Михай


person Mihai Morariu    schedule 04.12.2014    source источник


Ответы (2)


Похоже, что всегда будет задержка между вызовом VideoCapture::grab() и фактической съемкой кадра. Это связано с буферизацией кадров, которая выполняется на уровне оборудования/SO, и вы не можете этого избежать.

OpenCV предоставляет метод VideoCapture::get( CV_CAP_PROP_POS_MEC) ), чтобы дать вам точное время захвата кадра, но это возможно только в том случае, если камера его поддерживает.

Недавно в реализации V4L OpenCV была обнаружена проблема: видеокадры-в-linux/" rel="nofollow">http://answers.opencv.org/question/61099/возможно ли-получить-временные метки-кадров-для-живого-потокового-видео -frames-on-linux/

И несколько дней назад было снято исправление: https://github.com/Itseez/opencv/pull/3998

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

person ARrigo    schedule 27.05.2015

Возможно, проблема связана с драйвером Linux UVC, но я использовал Microsoft LifeCam Cinemas для машинного зрения на компьютерах с Ubuntu 12.04 и 14.04 и не видел задержки в 4-5 кадров. Однако я использую их в условиях низкой освещенности, и в этом случае они снижают частоту кадров до 7,5 кадров в секунду.

Еще одна возможная причина — задержка веб-камеры в зависимости от используемого формата. C920, по-видимому, поддерживает H.264 (что поддерживают немногие веб-камеры), поэтому Logitech, возможно, приложила максимум усилий, чтобы это работало хорошо, но OpenCV, похоже, не поддерживает H.264 в Linux; см. этот ответ, какие форматы он поддерживает. На тот же вопрос также есть ответ с взломом ядра (!) для устранения проблемы с драйвером UVC.

PS: чтобы проверить формат, фактически используемый в моем случае, я добавил

fprintf(stderr, ">>> palette: %d\n", capture->palette);

в этой строке в код OpenCV.

person Ulrich Stern    schedule 09.02.2016