python opencv cv2.cv.CV_CAP_PROP_FRAME_COUNT获取错误的数字

kli*_*lpr 9 python opencv

import os
import cv2
path='/home/nlpr4/video-data/UCF-101/GolfSwing/v_GolfSwing_g24_c06.avi'
cap=cv2.VideoCapture(path)
video_length=int(cap.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT))

success=True
count=0
while success:
    success,image=cap.read()
    if success==False:
        break
    count=count+1

print video_length,count
Run Code Online (Sandbox Code Playgroud)

输出:

149 
146
Run Code Online (Sandbox Code Playgroud)

为什么这两个数字不同?怎么了?

Wan*_*ang 10

get()CAP_PROP_FRAME_COUNT永远不应该是准确的!如果您检查opencv源代码.你可以找到这个:

int64_t CvCapture_FFMPEG::get_total_frames() const
{
    int64_t nbf = ic->streams[video_stream]->nb_frames;

    if (nbf == 0)
    {
        nbf = (int64_t)floor(get_duration_sec() * get_fps() + 0.5);
    }
    return nbf;
}
Run Code Online (Sandbox Code Playgroud)

这意味着它将首先查看流标题nb_frames,您可以使用ffprobe查看.如果没有这样的字段,则没有比直接解码视频更好的获取帧号的方法.opencv做了一个粗略的估计,get_duration_sec() * get_fps() + 0.5这肯定不是准确性的意思.

因此,要获得正确的帧编号,您必须解码并读取整个流,或者您必须要求视频生成器生成带nb_frames字段的正确流标题.

  • 这个答案是不正确且具有误导性的。这里OpenCV的计算没有任何问题;它获取预期的帧数并将其四舍五入到最接近的整数。这种舍入并没有什么不准确的地方,因为视频的持续时间始终是 1/FPS 的倍数。@ilke444 的答案是真实答案。 (3认同)

ilk*_*444 6

CV_CAP_PROP_FRAME_COUNT给出来自视频标题的“帧数”属性。另一个数字基本上是“我可以从这个视频文件中读取多少帧?”。

如果视频包含无法读取/解码的帧(例如,由于被损坏),OpenCV 会跳过这些帧(在尝试读取它们之后)并为您提供下一个有效帧。因此,您的两个数字之间的差异是无法读取的帧数。

此外,如果您的视频标头已损坏和/或无法被 OpenCV 使用的底层编解码器解析,那么这些数字也可能不同。