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

WaitKey(ms) или Sleep(ms), но без визуализации.

Recommended Posts

Коллеги, прошу подсказки. Мониторил форум, не нашел ответов...

Задача.
Считать покадрово видеофайлики с минимум нагрузкой на ЦП. Работа решения планируется на одноплатных ПК без визуализации, то есть в фоновом режиме.

Если считывать кадр и добавить задержку таким способом, нагрузка на ЦП в пределах 0.5%

cv::imshow("ing", img);
cv::waitKey(1000/fps);

Если считывать кадр и добавить задержку так, нагрузка на ЦП в пределах 5.5%

Sleep(1000/fps);

 

Пробовал кучу вариантов.
- Анализ в разных потоках, причем пробовал даже делегировать потоки относительно основного процесса.
- Делал считывание кадров через FFmpeg, типа.

...

avcodec_decode_video2(codec_context, frame, &frame_finished, &packet);

if (frame_finished) {
struct SwsContext * img_convert_ctx;
img_convert_ctx = sws_getCachedContext(NULL, codec_context->width, codec_context->height, codec_context->pix_fmt, codec_context->width, codec_context->height, AV_PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);

sws_scale(img_convert_ctx, ((AVPicture*)frame)->data, ((AVPicture*)frame)->linesize, 0, codec_context->height, ((AVPicture *)pFrameRGB)->data, ((AVPicture *)pFrameRGB)->linesize);

cv::Mat img(frame->height, frame->width, CV_8UC3, pFrameRGB->data[0]); //dst->data[0]);

av_free_packet(&packet);

sws_freeContext(img_convert_ctx);

Sleep(40);
или
cv::imshow("img", img);
cv::waitKey(40);
}
...

- Считывал кадры тоже по разному.

Mat frame;
cap >> frame; 

и так.

cap.grab();
if (!cap.retrieve(frame) || frame.empty())
{continue;}



В общем хоть убей, но при добавление инструкции 

cv::imshow("img", img);
cv::waitKey(40);

Загрузка ЦП оптимальна, но это не то, что нужно в плане реализации., так как планируется работа без визуализации. То есть в конечном итоге желательно установить задержку в Sleep(ms), с сохранением минимальной нагрузки на ЦП.

 

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

Приоритет: Считать все кадры с минимум нагрузки на ЦП.

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


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

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

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


Ссылка на сообщение
Поделиться на других сайтах
23 минуты назад, iskees сказал:

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

Он и так в цикле, можно конечно поставить Sleep(500), но тогда получим два кадра в сек., что неправильно. Необходимо получать количество кадров равное количеству кадров в видеофайле.

Идеально работает связка cv::imshow и cv::waitKey, но это не то....так как визуализации в фоновой программе нет.

- Может есть информация, что такого есть в cv::imshow и cv::waitKey, чего нет в Sleep()?

- Почему cv::imshow и cv::waitKey дает минимум нагрузки на проц, а Sleep() очень ресурсоёмкий?.. 

PS

Запускал по разному и в разных потоках.

PSS

Проверил Sleep() в цикле, дает 0% нагрузки.

 

 

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


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

windows под intel i7, сборка в студии

linux под ARM, сборка через cmake ( cmake -DCMAKE_BUILD_TYPE=Release

 сборка и там и там, только в release.

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


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

А стандартный вариант:

std::this_thread::sleep_for(40ms);

 

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


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

Тоже самое.

Может cv::waitKey() как то блокирует события в основном потоке и система ждет освобождения ресурсов на уровне получения кадра?. Может еще flush делает какой-то ))

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


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

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

Пути уменьшения нагрузки 2: увеличивать время простоя или оптимизация узких мест.

P.S. Кстати, если тебе RGB изображение не нужно, то можно оставаться в рамках YUV и убрать sws_scale, нагрузка снизится. Я вообще слабо представляю зачем может понадобиться RGB и откуда он берётся. С камеры получаем raw, который близок к RGB, но не он, а по факту Bayer. Если мы получаем видео с веб-камеры, то там может быть RGB. Если из h264 или jpeg, то уже YUV. Это явно твой случай.

Далее идёт анализ. Куча алгоритмов работают с grayscale картинками. Как мы получаем их? Правильно, конвертируем YUV -> RGB -> Gray. Но можно было просто взять первый Y канал из YUV безо всякого копирования памяти. То есть в привычном сценарии делается две (!!!) лишних конвертации с копированием памяти и потерей данных при этом.

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


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

Отлично.

Пойду пробовать варианты.

Интересно самому стало.

Спасибо.

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


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

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

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

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

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

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

Войти

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

Войти сейчас


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

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

×