-------- 旧 - 查找底部的答案 --------
感谢@Micka 的很多建议,我在路上找到了正确的东西。
使用 cudacodec::VideoWriter 并不那么容易,编译后我无法使用它,因为这个error https://answers.opencv.org/question/187243/opencv-error-the-functionfeature-is-not-implemented/,即使我可以让它运行,部署 PC 也没有 nvidia GPU。
由于我也将使用配备 AMD CPU 的 PC,因此我无法使用 cv::CAP_INTEL_MFX 作为 cv::VideoWriter 的 api-reference 参数。
但还有 cv::CAP_OPENCV_MJPEG,它适用于 MJPG 编解码器(并非所有视频容器都受支持,我使用 .avi,遗憾的是 .mkv 不适用于此配置)。如果用户不使用 MJPG 作为编解码器,我使用 cv::CAP_ANY,然后 opencv 决定使用什么。
So,
cv::VideoWriter videoWriter(path, cv::CAP_OPENCV_MJPEG, fourcc, fps, *size);
即使在我的旧系统上也运行得很好。
不幸的是我之前从未更改过 api-reference 参数,只是从 ffmpeg 更改为 gstreamer,我在opencv的文档 https://docs.opencv.org/3.4/dd/d9e/classcv_1_1VideoWriter.html#af52d129e2430c0287654e7d24e3bbcdc仅最后一行“cv::CAP_FFMPEG 或 cv::CAP_GSTREAMER”。我没有看到有一个“例如”。前...
谢谢@Micka 让我再次阅读。
附:对于我的 cv::imshow 性能问题,我从
cv::namedWindow(WINDOW_NAME, cv::WINDOW_NORMAL);
to
cv::namedWindow(WINDOW_NAME, cv::WINDOW_OPENGL);
显然它使用了 OpenGL,并且做得更好。另外从 cv::Mat 更改为 cv::UMat 可以加快性能,see here https://stackoverflow.com/questions/62243373/too-high-cpu-footprint-of-opencv-text-overlay-on-fhd-video-stream
-------------- 编辑更好的解决方案----------------
由于我在某些系统上使用 OpenCV VideoWriter 时仍然遇到问题,因此我一直在寻找另一种解决方案。现在我用 FFMPEG 编写帧。
对于 FFMPEG,我可以根据我使用的编解码器使用 GPU 或 CPU。
如果 FFMPEG 通过 snapd (Ubuntu 18.04) 安装,则默认启用 cuda:
sudo snap install ffmpeg --devmode
(--devmode 是可选的,但我在特定位置写入文件时遇到问题,这是我修复它的唯一方法)
这是我的代码:
//this string is automatically created in my program, depending on user input and the parameters of the input frames
string ffmpegCommand = "ffmpeg -y -f rawvideo -vcodec rawvideo -framerate 50 -pix_fmt bgr24 -s 1920x1080 -i - -c:v h264_nvenc -crf 14 -maxrate:v 10M -r 50 myVideoFile.mkv";
FILE *pipeout = popen(ffmpegCommand.data(), "w");
int id = metaDataWriter.insertNow(path);
//loop will be stopped from another thread
while (this->isRunning) {
//this->frames is a stack with cv::Mat elements in the right order
//it is filled by another thread
while (!this->frames.empty()) {
cv::Mat mat = frames.front();
frames.pop();
fwrite(mat.data, 1, s, pipeout);
}
}
fflush(pipeout);
pclose(pipeout);
因此使用文件(pipeout)将mat.data写入ffmpeg,ffmpeg本身正在进行编码和文件写入。至参数:
-y = 不询问就覆盖输出文件
-f = 格式,在本例中用于输入原始视频
-vcodec = 输入的编解码器也是原始视频,因为使用的 cv::Mat.data 没有压缩/编解码器
-framerate = 我从采集卡/OpenCv 收到的输入帧率
-pix_fmt = 我的原始数据的格式,在本例中为 bgr24,因此每个通道 8 位,因为我使用常规 OpenCV bgr cv::Mat
-s = 每帧的大小,在我的例子中为 1920x1080
-i = 输入,在这种情况下,我们从 stdinput 读取,您可以在这里看到它“-”,因此文件(管道输出)被 ffmpeg 捕获
-c:v = 输出编解码器,所以这是对视频进行编码,这里使用了h264_nvenc,这是一个GPU编解码器
-r = 帧输出速率,在本例中也是 50 myVideoFile.mkv = 这只是 ffmpeg 生成的文件的名称,您可以更改此文件和路径
更高质量的附加参数:-crf 14 -maxrate:v 10M
这对我来说非常有用,并且使用我的 GPU 硬件加速或与负责 CPU 的另一个编解码器一起使用。
我希望这也能帮助其他开发人员。