![](/img/trans.png)
[英]OpenCV Python VideoWriter wrong fps rate for some codecs
[英]python opencv videoWriter fps rounding
我正在尝试测量输入视频文件中的某些事件:“test.mp4”。 这是通过分几个步骤处理视频来完成的,其中每个步骤对视频数据执行一些操作并将中间结果写入新的视频文件。
输入视频的fps为:29.42346629489295 fps
下面我写了一个脚本来测试这个问题。 当我使用此脚本编写新文件时,fps 在输出文件中四舍五入为 29.0 fps,这就是问题所在。
import cv2
import sys
inputfilepath = "test.mp4"
outputfilepath = "testFps.mp4"
video = cv2.VideoCapture(inputfilepath)
fps = video.get(cv2.CAP_PROP_FPS)
framecount = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT))
print("original fps: ", fps)
# fps = 29.4
print("writing fps: ", fps)
writer = cv2.VideoWriter(outputfilepath, 0x00000020, fps, (width, height))
for i in range(framecount):
success, image = video.read()
if not success:
break
writer.write(image)
writer.release()
video.release()
video = cv2.VideoCapture(outputfilepath)
fps = video.get(cv2.CAP_PROP_FPS)
# the next line will not print the same fps as I passed to cv2.VideoWriter(...) above.
print("output fps: ", fps)
video.release()
我试图为 fps 硬编码不同的值。 似乎低于 29.5 fps 的所有内容都四舍五入为零位小数 (29 fps),而高于 29.5 fps 的所有内容都四舍五入为一位小数 (29.x fps)
所以我的问题是:
是否有可能获得任何 mp4 格式的 fps?
output 文件中实际使用了哪个 fps?
如何在 output 文件中获取正确的 fps?
附加信息
我尝试了从 28 fps 到 31 fps 的许多不同值,并绘制了实际的 output 文件帧率与预期的对比图。 这显示了某种分形行为,也许这个提示会激发这里的一些数学向导:)
OpenCV 使用一些工具包来编写。 就我而言,在 iOS 上,OpenCV 使用本机 AVFoundation 库。 似乎 AVFoundation(或 OpenCV api)无法很好地处理具有许多有效数字的 fps 值,例如 29.7787878779,并且在 OpenCV 的 api 或 AVFoundation 中某些东西被错误地舍入。
为了解决这个问题,我在调用 VideoWriter::open 之前对一些有效数字进行了四舍五入
normalizedFPS = round(1000.0 * normalizedFPS) / 1000.0;
希望它也适用于你
我已经看到 30,000 被用作时间尺度建议,所以也许测试一下 1000.0 与 30,000.0
不幸的是 OpenCV 里面有一个 bug。我读和写了一个 46 分钟的电影,有 2 秒丢失了(同样的帧数,但不同的 FPS 写在文件的 header 中)对我来说是一个大问题,因为我试图加入另一个编辑器中的音频信息,您可以看到缺少的 2 秒原始电影是 fps = (60/1.001) = 59.94005994... OpenCv 将此 fps 四舍五入为 60,无论我是否在 2 个地方写了 59.94005994
坏消息——我在 opencv 源代码中找到了这段代码
outfps = cvRound(fps);
bool AVIWriteContainer::initContainer(const String& filename, double fps, Size size, bool iscolor){
outfps = cvRound(fps);
width = size.width;
height = size.height;
channels = iscolor ? 3 : 1;
moviPointer = 0;
bool result = strm->open(filename);
return result;
}
我们必须将此错误升级到 OpenCv 团队(我使用 opencv-460.jar)我将尝试使用其他程序手动更改 header - 这可以挽救一天
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.