Я делаю декодирование видео, чтобы захватить кадр для некоторой постобработки видео. Я использую OpenCV CUDA, поэтому мне действительно нужно видео для чтения из OpenCV CUDA. Тем не менее, я понял:
В NVIDIA Video Codec SDK 8.2.15 говорится, что
Поддержка CUvideosource и связанных API-интерфейсов, включая cuvidCreateVideoSource, cuvidCreateVideoSourceW, cuvidDestroyVideoSource, cuvidSetVideoSourceState, cuvidGetVideoSourceState, cuvidGetSourceVideoFormat, API-интерфейс cuvidGetSource будет удален из будущего. Обратите внимание, что новые примеры приложений декодирования в SDK не используют эти API, но вместо этого используют FFmpeg.
Но чтобы использовать «createVideoReader» в OpenCV Cuda, нам нужно связать «dynlink_nvcuvid.h», который содержит
tcuvidCreateVideoSource *cuvidCreateVideoSource;
tcuvidCreateVideoSourceW *cuvidCreateVideoSourceW;
tcuvidDestroyVideoSource *cuvidDestroyVideoSource;
tcuvidSetVideoSourceState *cuvidSetVideoSourceState;
tcuvidGetVideoSourceState *cuvidGetVideoSourceState;
tcuvidGetSourceVideoFormat *cuvidGetSourceVideoFormat;
tcuvidGetSourceAudioFormat *cuvidGetSourceAudioFormat;
Есть ли обновление от opencv для декодирования видео? Как мы используем FFmpeg в OpenCV для замены "dynlink_nvcuvid.h"? Я пытаюсь использовать декодирование видео NVIDIA, но я застрял при преобразовании видеокадра в GpuMat.
Я использую
Ubuntu 18
Cuda 9.2
OpenCV 3.4.2
Для Cuda-части для декодирования я использовал следующий код:
FFmpegDemuxer demuxer(szInFilePath);
NvDecoder dec(cuContext, demuxer.GetWidth(), demuxer.GetHeight(), true, FFmpeg2NvCodecId(demuxer.GetVideoCodec()));
FramePresenterGL presenter(cuContext, demuxer.GetWidth(), demuxer.GetHeight());
uint8_t *dpFrame = 0;
int nPitch = 0;
int nVideoBytes = 0, nFrameReturned = 0, nFrame = 0;
uint8_t *pVideo = NULL;
uint8_t **ppFrame;
do {
demuxer.Demux(&pVideo, &nVideoBytes);
dec.Decode(pVideo, nVideoBytes, &ppFrame, &nFrameReturned);
if (!nFrame && nFrameReturned)
LOG(INFO) << dec.GetVideoInfo();
for (int i = 0; i < nFrameReturned; i++) {
presenter.GetDeviceFrameBuffer(&dpFrame, &nPitch);
if (dec.GetBitDepth() == 8)
Nv12ToBgra32((uint8_t *)ppFrame[i], dec.GetWidth(), (uint8_t *)dpFrame, nPitch, dec.GetWidth(), dec.GetHeight());
else
P016ToBgra32((uint8_t *)ppFrame[i], 2 * dec.GetWidth(), (uint8_t *)dpFrame, nPitch, dec.GetWidth(), dec.GetHeight());
cv::Size sz(dec.GetWidth(),dec.GetHeight());
cv::Mat mat1(sz,CV_8UC3, ppFrame);
cv::imshow ("test", mat1);
cv::waitKey(0);
}
nFrame += nFrameReturned;
} while (nVideoBytes);
У кого-нибудь есть опыт использования OpenCV CUDA с реальным API видеокодека? Как поместить видеокадр в GpuMat?
Обновление:
Я попытался преобразовать uint8_t, но изображение отображается неправильно, как показано ниже:
Код, который я использовал, обновлен выше. Что я должен изменить, чтобы изображение отображалось правильно? Я пытался https://stackoverflow.com/a/51520728/7939409, но загруженный левый пустой код ниже.
cv::Mat downloadedLeft;
cv::cuda::GpuMat gpuLeft;
cudaMalloc((void **)&ppFrame, gpuLeft.rows*gpuLeft.step);
cudaMemcpyAsync(ppFrame, gpuLeft.ptr<uint8_t>(), gpuLeft.rows*gpuLeft.step, cudaMemcpyDeviceToDevice);
gpuLeft.download(downloadedLeft);
cv::imshow ("test", downloadedLeft);
cv::waitKey(1);