python - 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 文件
我对此有几个疑问。
- 目前它在视频的所有 1403 帧上运行,我想对其进行优化,使其在每一
n
帧之后运行推理,这是可定制的。在代码中我提到了 n = 5。因此,如果 n = 5。帧数应为 1403/5 = 280 - 我的 CSV 中的时间戳不准确,我希望它们与视频相关。基本上,第一列(时间(秒)应指定视频中的时间,状态应确定当时帧的状态(检测到/未检测到),时间(秒)列应在 46 秒左右结束,这是视频的长度。
- 我的 cv2.imshow 正在显示一个大约 2 倍速度的视频,我相信我可以通过使用 cv2.imKey() 来控制速度,这应该是 cv2.waitKey 的最佳参数,以便我获得与输出类似的速度视频.
感谢您完成整个问题
解决方案
如果您想读取每个“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;
如果没有该检查,该程序可能会在视频结束时崩溃。
推荐阅读
- c - 在本地测试 TCP/IP 服务器
- java - 无法从片段内部刷新 recyclveiw?
- ios - 按字母顺序将 NSMutableArray 数据动态排序到 NSDictionary
- c++ - 如何为每个循环传递一个成员函数?
- python - 识别 sqlalchemy.exc.OperationalError
- hadoop - Hive 中的数据透视表并为唯一组合创建多个列
- firebase - iPhone X 上没有出现通知气泡
- javascript - 从 ajax 调用返回到 django 视图的清洁日期字段
- ios - 无法接收任何用户登录的弹出窗口或提示
- c# - 难以通过反射使用 System.IO.Compression.ZipArchive 访问可见属性