Python,OpenCV:在文件末尾停止捕获

Python,OpenCV:在文件末尾停止捕获,python,python-3.x,opencv,video-capture,Python,Python 3.x,Opencv,Video Capture,(使用OpenCV 4.1) 我正在尝试从视频中捕获截图。我的意图是让脚本每五分钟捕获一帧,最多捕获20帧 我的测试视频有20分钟长。一旦脚本循环4次,我希望它退出。但是,它循环第5次,并从视频结束后捕获2秒。然后它循环第6次,并捕获与第4次循环相同的帧。它不断重复最后两个循环,直到捕捉到20帧 如何让脚本识别它已到达视频的结尾并停止 注意:捕获的最后一帧可能不是视频中的最后一帧。例如,如果视频长度为23分钟,则捕获的最后一帧应接近20分钟标记 import datetime import sy

(使用OpenCV 4.1)

我正在尝试从视频中捕获截图。我的意图是让脚本每五分钟捕获一帧,最多捕获20帧

我的测试视频有20分钟长。一旦脚本循环4次,我希望它退出。但是,它循环第5次,并从视频结束后捕获2秒。然后它循环第6次,并捕获与第4次循环相同的帧。它不断重复最后两个循环,直到捕捉到20帧

如何让脚本识别它已到达视频的结尾并停止

注意:捕获的最后一帧可能不是视频中的最后一帧。例如,如果视频长度为23分钟,则捕获的最后一帧应接近20分钟标记

import datetime
import sys
import time

from cv2 import cv2


def milsec_to_hr_min_sec(milliseconds):  # Returned from CAP_PROP_POS_MSEC
    ms = int(milliseconds)
    seconds = str(int((ms / 1000) % 60))
    minutes = str(int((ms / (1000 * 60)) % 60))
    hours = str(int((ms / (1000 * 60 * 60)) % 24))
    return hours, minutes, seconds


def FrameCapture(path):  # Extract frame
    cap = cv2.VideoCapture(path)
    framerate = cap.get(cv2.CAP_PROP_FPS)
    count = 1
    framecount = 0

    # checks whether frames were extracted
    while True:
        while count < 21 and framecount < cap.get(cv2.CAP_PROP_FRAME_COUNT):
            # Capture frame every 5 minutes
            framecount = count * framerate * 60 * 5
            cap.set(1, framecount)

            # capture frame at timestamp
            success, image = cap.read()
            if success:
                cv2.imwrite(
                    path + " (screencap #%d).jpg" % count, image,
                )
                # Convert timestamp to hr:min:sec
                hours, minutes, seconds = milsec_to_hr_min_sec(
                    cap.get(cv2.CAP_PROP_POS_MSEC)
                )
                print(
                    str(success)
                    + " "
                    + "Captured: screencap #{} at timestamp ".format(count)
                    + hours
                    + "h "
                    + minutes
                    + "m "
                    + seconds
                    + "s"
                )
                count += 1
                if cv2.waitKey(1) & 0xFF == ord("q"):
                    break
            else:
                break

    # When everything done, release the capture
    cap.release()
    cv2.destroyAllWindows()
    print("Finished capture")


# Driver Code
if __name__ == "__main__":

    # Calling the function
    fn = "\\full\path\to\file"
    FrameCapture(fn)
导入日期时间
导入系统
导入时间
从cv2导入cv2
def密耳秒至小时分钟秒(毫秒):从CAP PROP POS返回毫秒
ms=int(毫秒)
秒=str(整数((毫秒/1000)%60))
分钟=str(整数((毫秒/(1000*60))%60))
小时=str(整数((毫秒/(1000*60*60))%24))
返回时、分、秒
def帧捕获(路径):#提取帧
cap=cv2.视频捕获(路径)
帧速率=cap.get(cv2.cap\u PROP\u FPS)
计数=1
帧数=0
#检查是否提取了帧
尽管如此:
当计数<21且帧数

请原谅我的脚本的粗俗性。我用从搜索中找到的零件将它们拼凑在一起。

有两种方法:

  • 循环执行
    while(true)
    循环和
    break
    while
    frame.empty()
  • 使用以下方法获取帧计数:
    int nFrames=vid\u cap.get(cap\u PROP\u frame\u count)//获取视频中可用的帧数
    ,并使用
    for_loop
    循环帧
此代码将从您的视频中获取所有帧

def get_list_frame_by_video(file_path_video):
    vs = cv2.VideoCapture(file_path_video)
    list_frame = []

    print("____start load video____")
    len_frames = int(vs.get(cv2.CAP_PROP_FRAME_COUNT))
    while True:
        is_cap, frame = vs.read()
        if frame is None:
            continue
        list_frame.append(frame)
        if len_frames == len(list_frame):
            break

    print("____complete load video____")
    return list_frame
在“while”循环开始时,您可以使用以下代码:

ret, frames = cap.read()

if frames is None:

    break

一次脚本循环4次是什么意思?最好也有一些测试数据。请参阅:。您没有检查是否已通过视频结尾。在设置帧数之前,请检查视频中的帧数是否足够多。也就是说,根据测试数据,将while循环条件更改为
while count<21和framecount
@alexander cécile,您是指视频的副本吗?此外,脚本会在每个循环中捕获视频的屏幕截图(count==1,count==2,等等)。因为视频长度为20分钟,脚本每5分钟捕获一帧,所以应该捕获4帧。@GBMedusa是的,只要能让我们正确运行程序就可以。@alkasm我尝试了你的建议,效果很好。在我做了更改之后,我遇到了另一个问题,脚本将按照我的要求停止循环,但它将挂起在第二个(修改的)while循环的开始。我添加了
if count>20或framecount>total_frames-1:break
以离开循环,脚本目前正在运行。谢谢