首页 > 解决方案 > OpenCV-n帧后读取

问题描述

我写了以下代码

import cv2
import datetime
import time
import pandas as pd

cascPath = 'haarcascade_frontalface_dataset.xml'  # dataset
faceCascade = cv2.CascadeClassifier(cascPath)

video_capture = cv2.VideoCapture('video1.mp4')

frames = video_capture.get(cv2.CAP_PROP_FRAME_COUNT) 
fps = int(video_capture.get(cv2.CAP_PROP_FPS)) 

print(frames) #1403 frames
print(fps) #30 fps
# calculate duration of the video 
seconds = int(frames / fps) 
print("duration in seconds:", seconds)  #46 seconds


df = pd.DataFrame(columns=['Time(Seconds)', 'Status'])
start = time.time()
print(start)
n=5
while True:
    
    ret, frame = video_capture.read()
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) #converts frame to grayscale image
    faces = faceCascade.detectMultiScale(
                gray, scaleFactor=1.1,
                minNeighbors=5,
                minSize=(30, 30),
                flags=cv2.FONT_HERSHEY_SIMPLEX
        )
    if len(faces) == 0:
        print(time.time()-start, 'No Face Detected')
        df = df.append({'Time(Seconds)': (time.time()-start) , 'Status':'No Face detected' }, ignore_index=True)
    else: 
        print(time.time()-start, 'Face Detected')
        df = df.append({'Time(Seconds)':(time.time()-start), 'Status':'Face Detected' }, ignore_index=True)

    # Draw a rectangle around the faces
    for (x, y, w, h) in faces:
        cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)


    # Display the resulting frame
    cv2.imshow('Video', frame)
    df.to_csv('output.csv', index = False)
    if cv2.waitKey(1) & 0xFF == ord('q'):
            # print(df.head(2))
            break


# When everything is done, release the capture
video_capture.release()
cv2.destroyAllWindows()

如果你想下载我正在制作的视频,你可以从这里下载

从这里下载 haar 级联 XML 文件

我对此有几个疑问。

  1. 目前它在视频的所有 1403 帧上运行,我想对其进行优化,使其在每一n帧之后运行推理,这是可定制的。在代码中我提到了 n = 5。因此,如果 n = 5。帧数应为 1403/5 = 280
  2. 我的 CSV 中的时间戳不准确,我希望它们与视频相关。基本上,第一列(时间(秒)应指定视频中的时间,状态应确定当时帧的状态(检测到/未检测到),时间(秒)列应在 46 秒左右结束,这是视频的长度。
  3. 我的 cv2.imshow 正在显示一个大约 2 倍速度的视频,我相信我可以通过使用 cv2.imKey() 来控制速度,这应该是 cv2.waitKey 的最佳参数,以便我获得与输出类似的速度视频.

感谢您完成整个问题

标签: pythonopencvmachine-learningimage-processingcomputer-vision

解决方案


如果您想读取每个“n”帧,可以将 VideoCapture.read() 调用包装在这样的循环中:

for a in range(n):
    ret, frame = video_capture.read();

对于 csv 文件中的时间戳,如果它随数据集一起提供,我会相信的。相机可能没有以一致的帧速率进行捕捉。如果您认为帧速率是一致的并且想要自己生成时间戳,您可以跟踪您已经经历了多少帧并将视频长度除以它。(即在第 150 帧,时间戳将为 (150 / 1403) * 46 秒)

cv2.imshow() 只显示与循环运行一样快的帧。这主要是通过 cv2.waitKey(milliseconds) 控制的。如果您认为您在循环中进行的处理所花费的时间可以忽略不计,您可以将 waitKey 中的时间设置为 ((n / 1403) * 46 * 1000)。否则,您应该使用 python 时间模块来跟踪处理需要多长时间并从等待中减去该时间。

编辑:

对不起,我应该对第一部分更清楚。那个 for 循环只有 VideoCapture.read() 行,没有别的。这样,您将读取“n”帧,但只处理每“n”帧中的一个。这并没有取代您已经拥有的整个 while 循环。您只是使用 for 循环来转储要跳过的帧。

哦,您还应该检查 read() 的返回值。

if not ret:
    break;

如果没有该检查,该程序可能会在视频结束时崩溃。


推荐阅读