如何使用 OpenCV (Python) 读取视频文件而不循环 (Mac OS)?

use*_*184 5 python opencv

我正在用 python 编写一个简单的 OpenCV 脚本来进行一些机器学习。我想向它提供一系列视频文件,它将对其进行处理,然后退出并吐出一些参数。但是,当我使用 cv2.VideoCapture 打开视频文件时,它会无限循环。如何检测视频何时结束?

**编辑** 所以一些人注意到,当读取到达文件末尾时,应该返回一个空帧。我尝试寻找它,它可以在我的 Linux 机器上运行,但不能在我的 mac 上运行。在 Mac 上,它只是循环并继续进行,就好像文件没有结束一样。有任何想法吗?

下面显示了阅读循环的代码,除非我按 esc 键,否则它会无限循环。

cam = cv2.VideoCapture(sourceVideo)            
while True:
    ret, img = cam.read()                      
    cv2.imshow('detection', img)
    print ret
    if (0xFF & cv2.waitKey(5) == 27) or img.size == 0:
        break
Run Code Online (Sandbox Code Playgroud)

请注意,ret 始终返回 True,并且 img 始终是有效数据。我是否有可能不应该使用 VideoCapture() 进行这种阅读?我不想使用旧的 cv 命令,因为我需要使用 cv2 使用的 NumPy 数组。

** 编辑 ** 好的,找到了合理的解决方案。我发现至少还有一个人在 Mac OS 中遇到了类似的问题:OpenCV capture Loops video/Does not detector last frame

我的猜测是,Mac 操作系统中的 OpenCV 设置或文件格式存在问题。

正确的解决方案通常是检查返回帧的类型,因此这应该有效:

    cam = cv2.VideoCapture(sourceVideo)            
    while True:
        ret, img = cam.read()                      
        if (type(img) == type(None)):
            break

        cv2.imshow('detection', img)
        print ret
        if (0xFF & cv2.waitKey(5) == 27) or img.size == 0:
            break
Run Code Online (Sandbox Code Playgroud)

但是,如果您遇到我的问题,则不会检测到最终帧。无论如何,有一个合理的解决方法,即检查文件中的帧数并简单地进行跟踪。

    framecount = cam.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT)

    frames = 0
    while frames < framecount:
        ret, img = cam.read()  
        frames += 1     

        if (type(img) == type(None)):
            break

        cv2.imshow('detection', img)
        print ret
        if (0xFF & cv2.waitKey(5) == 27) or img.size == 0:
            break
Run Code Online (Sandbox Code Playgroud)

Bjo*_*hak 2

不要忘记添加检查视频文件是否已成功打开。

if( !cam.isOpened() )
  throw "Error when reading image file";
Run Code Online (Sandbox Code Playgroud)

通过将帧输送到循环中的 cv::Mat 中来抓取帧

Mat frame;

for( ; ; )
{
    cam >> frame;
    if(!frame)
        break;
    imshow("w", frame);
    waitKey(20);
}
Run Code Online (Sandbox Code Playgroud)

帧为假后,循环应正确终止。

为了也完全终止循环,你可以这样做

cam.get(CV_CAP_PROP_FRAME_COUNT)
Run Code Online (Sandbox Code Playgroud)

以获得确切的帧数。无法获取没有循环的视频,因为它是增量读取的。不过,您可以将其包装到一个单独的函数中。