Я знаю, что название немного расплывчато, но я не знаю, как еще его описать.
CentOS с ffmpeg + OpenCV 2.4.9. Я работаю над простой системой обнаружения движения, которая использует поток с IP-камеры (h264).
Время от времени поток икает и выбрасывает «плохой кадр» (см. Ссылку pic-bad.png ниже). Проблема состоит в том, что эти кадры сильно отличаются от предыдущих кадров и вызывают запуск события «движение», даже если фактическое движение не произошло.
Фотографии ниже объяснят проблему.
Хороший кадр (движение запечатлено):
Плохая рамка (нет движения, просто сломанная рамка):
Плохой кадр попадает случайно. Я думаю, что я могу сделать плохой детектор кадров, анализируя (проходя по петлям) пиксели, идущие вниз из определенной позиции, чтобы увидеть, все ли они одинаковые, но мне интересно, есть ли какой-нибудь другой, более эффективный, «по книге «Подход к обнаружению этих типов плохих кадров и просто пропустить их.
Благодарю вас!
РЕДАКТИРОВАТЬ ОБНОВЛЕНИЕ:
Фрейм захватывается с помощью программы обнаружения движения C ++ через cvQueryFrame(camera);
поэтому я не взаимодействую напрямую с ffmpeg, OpenCV делает это на бэкэнде. Я использую последнюю версию ffmpeg, скомпилированную из git source. Все библиотеки также обновлены (h264 и т. Д., Все скачано и скомпилировано вчера). Данные поступают из потока RTSP (ffserver). Я провел тестирование на нескольких камерах (модели Dahua с 1–3 Мп), и сбои кадров довольно устойчивы во всех них, хотя это не происходит непрерывно, только один раз (например, один раз каждые 10 минут).
При первом подходе мне приходит в голову проверка несоответствия между примером действительного фрейма и тем, который мы проверяем, путем подсчета пикселей, которые не совпадают. Разделив это число на площадь, мы получаем процент, который измеряет различие. Я бы предположил, что выше 0,5 мы можем сказать, что проверенный кадр недействителен, потому что он слишком сильно отличается от примера действительного.
Это предположение подходит только в том случае, если у вас есть статическая камера (она не двигается) и объекты, которые могут двигаться перед ней, находятся не на самом коротком расстоянии (зависит от фокусного расстояния, но если у вас есть, например, широкие линзы, поэтому объекты не должны появляются на расстоянии менее 30 см перед камерой, чтобы предотвратить возникновение ситуации, когда объекты «прыгают» в кадр из ниоткуда и имеют размер, превышающий 50% площади кадра).
Здесь у вас есть функция opencv, которая делает то, что я сказал. Фактически, вы можете отрегулировать коэффициент несоответствия более большим, если считаете, что изменения движения будут происходить быстрее. Обратите внимание, что первый параметр должен быть примером допустимого кадра.
bool IsBadFrame(const cv::Mat &goodFrame, const cv::Mat &nextFrame) {
// assert(goodFrame.size() == nextFrame.size())
cv::Mat g, g2;
cv::cvtColor(goodFrame, g, CV_BGR2GRAY);
cv::cvtColor(nextFrame, g2, CV_BGR2GRAY);
cv::Mat diff = g2 != g;
float similarity = (float)cv::countNonZero(diff) / (goodFrame.size().height * goodFrame.size().width);
return similarity > 0.5f;
}
Вы не упоминаете, используете ли вы командную строку ffmpeg или библиотеки, но в последнем случае вы можете проверить флаг плохого фрейма (я забыл его точное описание) и просто проигнорировать эти фреймы.
Удалить waitKey(50)
или измените его на waitKey(1)
, Я думаю, что opencv не создает новый поток для выполнения захвата. поэтому, когда возникает пауза, это сбивает с толку процедуры управления буфером, вызывая плохие кадры .. может?
У меня есть камеры dahua и я заметил, что с более высокой задержкой наблюдаются плохие кадры. И они уходят полностью с waitKey(1)
, Пауза не обязательно должна исходить от waitKey
, Процедуры вызова также вызывают такие паузы и приводят к плохим кадрам, если они занимают достаточно много времени.
Это означает, что должна быть минимальная пауза между последовательными захватами кадра. Решение было бы использовать два потока для выполнения захвата и обработки отдельно.