简体   繁体   English

python opencv videoWriter fps 四舍五入

[英]python opencv videoWriter fps rounding

I am trying to measure some event in an input video file: "test.mp4".我正在尝试测量输入视频文件中的某些事件:“test.mp4”。 This is done by processing the video in several steps, where each step performs some operations on the video data and writes the intermediate results to a new video file.这是通过分几个步骤处理视频来完成的,其中每个步骤对视频数据执行一些操作并将中间结果写入新的视频文件。

The fps of the input video is: 29.42346629489295 fps输入视频的fps为:29.42346629489295 fps

Below I have written a script to test the problem.下面我写了一个脚本来测试这个问题。 When I write a new file using this script the fps gets rounded in the outputfile to 29.0 fps, and this is the problem.当我使用此脚本编写新文件时,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()

I have tried to hardcode different values for fps.我试图为 fps 硬编码不同的值。 It seems like everything below 29.5 fps is rounded to zero decimals (29 fps), and everything above gets round to one decimal (29.x fps)似乎低于 29.5 fps 的所有内容都四舍五入为零位小数 (29 fps),而高于 29.5 fps 的所有内容都四舍五入为一位小数 (29.x fps)

So my questions are:所以我的问题是:

Is it possible to get any fps with the mp4 format?是否有可能获得任何 mp4 格式的 fps?

Which fps is actually used in the output file? output 文件中实际使用了哪个 fps?

How can I get the correct fps in the output file?如何在 output 文件中获取正确的 fps?

Additional info附加信息

I tried many different values ranging from 28 fps to 31 fps, and plotted the actual output file framerate vs the expected.我尝试了从 28 fps 到 31 fps 的许多不同值,并绘制了实际的 output 文件帧率与预期的对比图。 This displays some kind of fractral behavior, maybe this hint will inspire some math wizard in here:)这显示了某种分形行为,也许这个提示会激发这里的一些数学向导:)

预期与实际帧率

预期与实际帧率缩放

OpenCV uses some toolkit to do the writing. OpenCV 使用一些工具包来编写。 In my case, on iOS, OpenCV uses the native AVFoundation library.就我而言,在 iOS 上,OpenCV 使用本机 AVFoundation 库。 It seems AVFoundation (or the OpenCV api) can't handle well an fps value with many significant digits, like 29.7787878779, and something was being rounded incorrectly either in OpenCV's api or AVFoundation.似乎 AVFoundation(或 OpenCV api)无法很好地处理具有许多有效数字的 fps 值,例如 29.7787878779,并且在 OpenCV 的 api 或 AVFoundation 中某些东西被错误地舍入。

To fix the issue, I rounded off some of the significant digits before calling VideoWriter::open为了解决这个问题,我在调用 VideoWriter::open 之前对一些有效数字进行了四舍五入

normalizedFPS = round(1000.0 * normalizedFPS) / 1000.0;

Hope it works for you also希望它也适用于你

I've seen 30,000 used as a timescale recommendation, so perhaps test out 1000.0 vs 30,000.0我已经看到 30,000 被用作时间尺度建议,所以也许测试一下 1000.0 与 30,000.0

Unfortunately there is a bug inside OpenCV. I read and write an 46 minutes movie and 2 seconds are missing (same number of frames but a diferent FPS written in the header of the file) For me is a big problem as I tried to join the audio information in another editor and you can see the 2 missing seconds The original movie is fps = (60/1.001) = 59.94005994... and OpenCv is rounding this fps to 60 no matter if I wrote 59.94005994 in 2 places不幸的是 OpenCV 里面有一个 bug。我读和写了一个 46 分钟的电影,有 2 秒丢失了(同样的帧数,但不同的 FPS 写在文件的 header 中)对我来说是一个大问题,因为我试图加入另一个编辑器中的音频信息,您可以看到缺少的 2 秒原始电影是 fps = (60/1.001) = 59.94005994... OpenCv 将此 fps 四舍五入为 60,无论我是否在 2 个地方写了 59.94005994

  1. videoWriter = new VideoWriter( full_file_name, fourCC, fps, scaled_size, true); videoWriter = new VideoWriter( full_file_name, fourCC, fps, scaled_size, true);
  2. videoWriter.set(CAP_PROP_FPS, fps); videoWriter.set(CAP_PROP_FPS, fps);

BAD NEWS - I found this code inside opencv source code坏消息——我在 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;
}

We have to escalate this bug toward OpenCv team (I use opencv-460.jar) I will try to manualy change the header using other programs - this could save the day我们必须将此错误升级到 OpenCv 团队(我使用 opencv-460.jar)我将尝试使用其他程序手动更改 header - 这可以挽救一天

the math computation that explain the missing seconds解释缺失秒数的数学计算excel 找到丢失的秒数 少了2秒

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM