mult1plexer 1 Report post Posted January 25, 2019 Здравствуйте. Столкнулся с проблемой получения кадра с веб камеры и видео. Как оказалось opencv использует программное декодирование видео потока. В результате чего не могу получить 60fps и убрать нагрузку с процессора. Через проигрыватель, который идет с K-Lite Codec Pack все воспроизводится так как надо. Кто нибудь решал такую проблему или может есть другой способ получать кадры с видео? 1 Share this post Link to post Share on other sites
fotomer 16 Report post Posted January 26, 2019 А что вы собираетесь делать с полученной cv::Мат картинкой? Многие алгоритмы вообще онлайн не работают на обычном железе. Share this post Link to post Share on other sites
Pechkin80 2 Report post Posted January 26, 2019 Сам думал сделать, но руки не доходят. Вопрос важный и по делу. Так как h.264 может аппратно декодироваться. Но и для остальных кодеков аппаратные возможности лучше испоьзовать на 100 процентов. Share this post Link to post Share on other sites
mult1plexer 1 Report post Posted January 26, 2019 3 часа назад, fotomer сказал: А что вы собираетесь делать с полученной cv::Мат картинкой? Многие алгоритмы вообще онлайн не работают на обычном железе. что значит не работают онлайн? не понял этот тезис Share this post Link to post Share on other sites
Nuzhny 238 Report post Posted January 29, 2019 Попробуй принудительно изменить backend у capture: CAP_FFMPEG, CAP_DSHOW или CAP_VFW. Они выбираются по очереди, какой первый подойдёт. Возможно, что у тебя первый в списке как раз не аппаратный. Share this post Link to post Share on other sites
Pechkin80 2 Report post Posted January 29, 2019 Для линукса по идеи нужен GStreamer. Интересная статья по теме: https://blog.zhaw.ch/high-performance/2017/10/24/boost-your-gstreamer-pipeline-with-the-gpu-plugin/ Share this post Link to post Share on other sites
mult1plexer 1 Report post Posted January 29, 2019 8 часов назад, Nuzhny сказал: Попробуй принудительно изменить backend у capture: CAP_FFMPEG, CAP_DSHOW или CAP_VFW. Они выбираются по очереди, какой первый подойдёт. Возможно, что у тебя первый в списке как раз не аппаратный. это я первым делом сделал. как я понял у меня через directshow идет, с gstreamer не удалось запустить завершается 0xc000007b ошибкой 8 часов назад, Pechkin80 сказал: Для линукса по идеи нужен GStreamer. Интересная статья по теме: https://blog.zhaw.ch/high-performance/2017/10/24/boost-your-gstreamer-pipeline-with-the-gpu-plugin/ я пока под windows запускаю. Share this post Link to post Share on other sites
Nuzhny 238 Report post Posted January 30, 2019 Можно у Capture посмотреть свойство CAP_PROP_BACKEND. Share this post Link to post Share on other sites
mult1plexer 1 Report post Posted January 30, 2019 15 часов назад, Nuzhny сказал: Можно у Capture посмотреть свойство CAP_PROP_BACKEND. что это даст? камера работает только с DSHOW в opencv, в VLC тоже самое только через DSHOW Share this post Link to post Share on other sites
Pechkin80 2 Report post Posted January 30, 2019 51 минуту назад, mult1plexer сказал: что это даст? камера работает только с DSHOW в opencv, в VLC тоже самое только через DSHOW А что за камера ? Камера работает по протоколу обычно и не привязана к кодеку. Если только совсем какойто ширпотреб. Share this post Link to post Share on other sites
Nuzhny 238 Report post Posted January 31, 2019 Веб-камеры используются не по протоколу, а через драйвер. Может оказаться, для неё есть DirectShow драйвер и всё. Но тут ещё вопрос, используется ли DirectShow или сейчас всё реализовано через MSMF. Всё - это dshow и vfw. Думаю, что плайеры работают через DXVA, которое позволяет сразу декодировать и отображать видео. Сходу даже не уверен, можно ли его использовать в OpenCV. Share this post Link to post Share on other sites
mult1plexer 1 Report post Posted January 31, 2019 20 часов назад, Pechkin80 сказал: А что за камера ? Камера работает по протоколу обычно и не привязана к кодеку. Если только совсем какойто ширпотреб. китайские нонейм модули без опознавательных знаков 13 часа назад, Nuzhny сказал: Веб-камеры используются не по протоколу, а через драйвер. Может оказаться, для неё есть DirectShow драйвер и всё. Но тут ещё вопрос, используется ли DirectShow или сейчас всё реализовано через MSMF. Всё - это dshow и vfw. Думаю, что плайеры работают через DXVA, которое позволяет сразу декодировать и отображать видео. Сходу даже не уверен, можно ли его использовать в OpenCV. так в этом и суть, что MPC-HC от k-lite захватывает нормально не через DirectShow. Значит как минимум это можно как то поменять. В opencv проблема даже в FHD сделать захват, FPS падает до 7-10. А по дефолту открывает в 640х480 Share this post Link to post Share on other sites
ppop21285 6 Report post Posted February 4, 2019 Для аппаратного декодирования h.264/h.265/mpeg4/MJPEG можно взять библиотеки из проекта ffmpeg. Там есть реализаций кодеков с использованием SDK от NVIDIA, AMD и INTEL, также есть варианты для мобильных устройств. В ffmpeg есть свой модуль для работы с камерами. OpenCV версий 3 и 4 можно собрать с поддержкой ffmpeg для декодирования. Применяя аппаратный декодер и OpenCV модули с поддержкой NVIDIA Cuda и/или OpenCL, есть возможность построить алгоритмы без копирования декодированного потока в хост память. DirectX и OpenGL поверхности в памяти GPU могут являться источником для OpenCl/Cuda матриц в OpenCV не покидая GPU. 1 Share this post Link to post Share on other sites
Nuzhny 238 Report post Posted February 5, 2019 ffmpeg тут ничего нового не придумал, а просто предоставляет обёртку над DirectShow. Я уже давно этой темы не касался, надеюсь, что не навру. Веб камеры в Windows работают через DirectShow драйвер (или WMF) и тут ничего не попишешь. Я очень сомневаюсь, что у них есть что-то своё. Соответственно, при отображении видео используется DXVA - аппаратное декодирование с выводом видео на экран. При этом кадры даже не поступают в оперативную память, а отправляются сразу на аппаратный декодер, встроенный в процессор или видеокарту. Это даже не CUDA или OpenCL, а отдельные специализированные чипы внутри процессора или видеокарты: Intel Quick Sync Video, Nvidia NVENC или AMD Video Coding Engine. Ffmpeg, например, умеет декодировать сетевое видео или файлы и на CUDA - cuvid. Но это уже будет грузить видеокарту, в отличие от полностью аппаратного Nvidia NVENC. Как всё это применить к вебкамерам я, к сожалению, не в курсе. Share this post Link to post Share on other sites
ppop21285 6 Report post Posted February 5, 2019 Полностью справедливо для камер только с DirectShow/WMF драйвером. Некоторые имеют еще собственный драйвер и SDK, особенно с вариантами для Windows и Linux. Часто, такие камеры выдают полное разрешение и частоту кадров только в сжатом видео потоке ( Mjpeg/h.264) – видел китайcкую камеру 5Mp/60Hz/h.264 120Mbit поток, подключённую по USB2… Такие случаи как раз для аппаратного декодирования. В SDK Intel Quick Sync Video, Nvidia NVENC есть примеры копирования декодированного кадра в OpenCL/Cuda память. Share this post Link to post Share on other sites
Pechkin80 2 Report post Posted February 5, 2019 3 часа назад, Nuzhny сказал: ffmpeg тут ничего нового не придумал, а просто предоставляет обёртку над DirectShow. Я уже давно этой темы не касался, надеюсь, что не навру. Веб камеры в Windows работают через DirectShow драйвер (или WMF) и тут ничего не попишешь. Я очень сомневаюсь, что у них есть что-то своё. Соответственно, при отображении видео используется DXVA - аппаратное декодирование с выводом видео на экран. При этом кадры даже не поступают в оперативную память, а отправляются сразу на аппаратный декодер, встроенный в процессор или видеокарту. Это даже не CUDA или OpenCL, а отдельные специализированные чипы внутри процессора или видеокарты: Intel Quick Sync Video, Nvidia NVENC или AMD Video Coding Engine. Ffmpeg, например, умеет декодировать сетевое видео или файлы и на CUDA - cuvid. Но это уже будет грузить видеокарту, в отличие от полностью аппаратного Nvidia NVENC. Как всё это применить к вебкамерам я, к сожалению, не в курсе. Примение CUDA ИМХО сомнительное дело впринцепи. Если CUDA используется для задач обработки изображений, то использование CUDA ещё и для декодирования будет приводить к частостому сбросу всего кеша GPU и снижению производительности. Я вот тоже слышал что для этого специальный чип внутри процессора или карты есть + SSE/MMX, но как убедиться что FFMPRG или GSTREAMER всё сделал поуму для декодирования ? Я может залез не в свою тему, но как там обстоят дело с подключением камеры за 3 бакса ИМХО не самое главное. Но в любом профессиональном решении с нормальной IP камерой этот впрос не может быть обойдён стороной. Share this post Link to post Share on other sites
Nuzhny 238 Report post Posted February 5, 2019 С ip камерами как раз всё проще. Их можно пачкой на CUDA декодировать, а потом обрабатывать изображения, не выгружая декодированные кадры из видеопамяти. Можно отдавать их, например в TensorFlow. Share this post Link to post Share on other sites
Pechkin80 2 Report post Posted February 5, 2019 1 час назад, Nuzhny сказал: С ip камерами как раз всё проще. Их можно пачкой на CUDA декодировать, а потом обрабатывать изображения, не выгружая декодированные кадры из видеопамяти. Можно отдавать их, например в TensorFlow. Хм, можно попдробнее.... Это такой интерфейс есть чтоб получать данные уже загруженные в GPU , но декодированные? Для декодирования и обработки изображений разные библиотеки используются. Я не знаком с TensorFlow, но я пологаю. что могут потребоваться какието предварительные действия, до применения TensorFlow которых нет в TensorFlow. Очень подозрительно просто что TensorFlow представляется волшебной палочкой. Всё универсальное не всегда самоелучшее. Share this post Link to post Share on other sites
Nuzhny 238 Report post Posted February 5, 2019 Получать можно в том же ffmpeg: 1. Если не собран, то собрать ffmpeg с поддержкой cuvid. Проверка: ./ffmpeg -hwaccels 2. При создании AVCodec вызвать avcodec_find_decoder_by_name("h264_cuvid") или avcodec_find_decoder_by_name("mjpeg_cuvid"). 3. Перед вызовом avcodec_decode_video2 устанавливать decCtx->pix_fmt = AV_PIX_FMT_CUDA 4. Тут уже нам возвращают указатель на видеопамять в AVFrame, можно копировать её к себе и обрабатывать: 4.1. Учитываем, что в данном случае у нас кадр не YUV420, а NV12: cudaMemcpy(data, picture->data[0], height * picture->linesize[0], cudaMemcpyDefault) 4.2. Хочется RGB? Вызываем nppiNV12ToBGR_709HDTV_8u_P2C3R 4.3. Хочется засунуть в OpenCV? Вот: cv::cuda::GpuMat* gpuFrame = new cv::cuda::GpuMat(height, width, CV_8UC1, picture->data[0], picture->linesize[0]) Выгрузить из GPU memory и сохранить? Вот: cv::Mat frame; gpuFrame->download(frame); 4.4. Хочется отобразить кадр без копирования в ОЗУ? Создаём OpenGL окно: cv::namedWindow("wnd name", cv::WINDOW_OPENGL) Это про декодирование на CUDA и обработку кадра средствами OpenCV без копирования в системную память. Про TensorFlow: тут надо использовать С++ API, на Питончике такой возможности нет. Добавили такую возможность недавно в версии 1.12: вот обсуждение. 1 Share this post Link to post Share on other sites
Pechkin80 2 Report post Posted February 5, 2019 1 час назад, Nuzhny сказал: Получать можно в том же ffmpeg: 1. Если не собран, то собрать ffmpeg с поддержкой cuvid. Проверка: ./ffmpeg -hwaccels 2. При создании AVCodec вызвать avcodec_find_decoder_by_name("h264_cuvid") или avcodec_find_decoder_by_name("mjpeg_cuvid"). 3. Перед вызовом avcodec_decode_video2 устанавливать decCtx->pix_fmt = AV_PIX_FMT_CUDA 4. Тут уже нам возвращают указатель на видеопамять в AVFrame, можно копировать её к себе и обрабатывать: 4.1. Учитываем, что в данном случае у нас кадр не YUV420, а NV12: cudaMemcpy(data, picture->data[0], height * picture->linesize[0], cudaMemcpyDefault) 4.2. Хочется RGB? Вызываем nppiNV12ToBGR_709HDTV_8u_P2C3R 4.3. Хочется засунуть в OpenCV? Вот: cv::cuda::GpuMat* gpuFrame = new cv::cuda::GpuMat(height, width, CV_8UC1, picture->data[0], picture->linesize[0]) Выгрузить из GPU memory и сохранить? Вот: cv::Mat frame; gpuFrame->download(frame); 4.4. Хочется отобразить кадр без копирования в ОЗУ? Создаём OpenGL окно: cv::namedWindow("wnd name", cv::WINDOW_OPENGL) Это про декодирование на CUDA и обработку кадра средствами OpenCV без копирования в системную память. Про TensorFlow: тут надо использовать С++ API, на Питончике такой возможности нет. Добавили такую возможность недавно в версии 1.12: вот обсуждение. Спасибо, интересно будет поробовать. Тогда получаеться VideoCapture class из OpenCV не используем ? Он ведь вроде как сам работает с FFMPEG ? И управление видеопотоком тоже надо будет через FFMPEG реализовывать. Или сам VideoCapture OpenCV прпатчить для более эффективной работы ? Share this post Link to post Share on other sites
Nuzhny 238 Report post Posted February 5, 2019 Пропатчить так просто не получится, там весь интерфейс придётся менять для всех бэкендов. Кажется, что надо писать самому на ffmpeg, можно взять код работы с ним из OpenCV в качестве базового. С другой стороны есть cudacodec из opencv_contrib, который, вроде, делает как раз необходимое. Но я его не проверял, ничего не могу сказать. Share this post Link to post Share on other sites
Pechkin80 2 Report post Posted February 6, 2019 Nuzhny, Большое спасибо за ваши ответы. Но у меня так бывает что к теме я возвращаюсь через несколько месяцев. Share this post Link to post Share on other sites
mult1plexer 1 Report post Posted February 6, 2019 В 05.02.2019 at 00:32, ppop21285 сказал: Для аппаратного декодирования h.264/h.265/mpeg4/MJPEG можно взять библиотеки из проекта ffmpeg. Там есть реализаций кодеков с использованием SDK от NVIDIA, AMD и INTEL, также есть варианты для мобильных устройств. В ffmpeg есть свой модуль для работы с камерами. OpenCV версий 3 и 4 можно собрать с поддержкой ffmpeg для декодирования. Применяя аппаратный декодер и OpenCV модули с поддержкой NVIDIA Cuda и/или OpenCL, есть возможность построить алгоритмы без копирования декодированного потока в хост память. DirectX и OpenGL поверхности в памяти GPU могут являться источником для OpenCl/Cuda матриц в OpenCV не покидая GPU. В 05.02.2019 at 12:21, Nuzhny сказал: С ip камерами как раз всё проще. Их можно пачкой на CUDA декодировать, а потом обрабатывать изображения, не выгружая декодированные кадры из видеопамяти. Можно отдавать их, например в TensorFlow. из gpu есть Mali T860 Share this post Link to post Share on other sites
2expres 7 Report post Posted March 10, 2019 В 29.01.2019 at 09:25, Nuzhny сказал: Попробуй принудительно изменить backend у capture: CAP_FFMPEG, CAP_DSHOW или CAP_VFW. Они выбираются по очереди, какой первый подойдёт. Возможно, что у тебя первый в списке как раз не аппаратный. У меня процессор Intel Pentium n3710 с графическим ядром INTEL HD GRAPHICS. Если верить данной таблице https://www.wikizero.com/en/Intel_Graphics_Technology, то данное графическое ядро позволяет декодировать 2k 30 кадров в секунду. Открываю файл 1080p, кодек h264 с принудительно заданным backend ffmpeg: cv::VideoCapture cam( "2.mp4", cv::CAP_FFMPEG); Загрузка процессора от 25 до 60%. Открываю данный файл, используя Microsoft Media Foundation: cv::VideoCapture cam( "2.mp4", cv::CAP_MSMF); Загрузка процессора от 10 до 25%. Почему так происходит?! Насколько я читал ffmpeg использует аппаратное декодирование. Share this post Link to post Share on other sites
Nuzhny 238 Report post Posted March 11, 2019 ffmpeg сам по себе может что-то и не уметь, если его специально не собрали с поддержкой этого аппаратного ускорения. Хотя логично было бы его включать для интеловских процессоров. Если у тебя есть просто собранный отдельно ffmpeg (или скачанный), то можешь посмотреть, что он умеет и повыбирать разные кодеки из командной строки. Например, команда "ffmpeg -hwaccels" выведен список доступных аппаратных кодеков. Share this post Link to post Share on other sites