为什么在 openCV 和 python 中将 fps 从 30 加倍到 60 时,生成的视频只有一半的时间?
Why is the resulting video half the time long, when doubling the fps from 30 to 60 in openCV and python?
我的总体目标是使用 Raspberry Pi HQ 摄像头拍摄视频。当使用终端和像 raspivid -w 640 -h 480 -fps 90 -t 10000 -o video.h264
这样的标准 raspivid 命令时,生成的视频没有存储关于 fps(和 frame_count)的正确信息。我使用 openCV 和 python 检查了它,代码如下:
import cv2
cap = cv2.VideoCapture('video.h264')
if cap.isOpened():
fps = cap.get(cv2.CAP_PROP_FPS)
print('fps:', fps) # float `fps`
frame_count = cap.get(cv2.CAP_PROP_FRAME_COUNT)
print('frames count:', frame_count) # float `frame_count`
我预计它是 fps: 90.0 和 frame_count: 900.0,但它是 fps: 25.0 和 frame_count: -192153584101141.0.
经过一番研究,我得出结论,.h264 没有存储正确的 fps 值,而是存储了默认值(在我的例子中为 25.0 fps)。
现在我的下一个尝试是使用 openCV 和 python 来使用 HQ 摄像头捕捉视频。我尝试使用以下代码(在尝试使用 openCV 捕获视频时这几乎是标准的):
import numpy as np
import cv2
#had to use (-1,cv2.CAP_V4L) instead of (0) for it to find my HQ Camera
cap = cv2.VideoCapture(-1,cv2.CAP_V4L)
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('video_out.avi', fourcc, 30.0, (640, 480))
while(cap.isOpened()):
ret, frame = cap.read()
if ret==True:
out.write(frame)
cv2.imshow('frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
cap.release()
out.release()
cv2.destroyAllWindows()
现在录制大约 10 秒时。长视频,然后使用与之前相同的方法对其进行分析,结果符合预期 fps: 30.0 and frame_count: (roughly) 300.0.
现在,在第 8 行中将 fps 从 30 更改为 60,从 out = cv2.VideoWriter('video_out.avi', fourcc, 30.0, (640, 480))
到 out = cv2.VideoWriter('video_out.avi', fourcc, 60.0, (640, 480))
并分析大约 10 秒。之后的长视频结果和预期的不一样。而不是 fps: 60.0 and frame_count: (roughly) 600.0 结果是 fps: 60.0 and frame_count: (roughly) 300.0.此外,视频现在只有 5 秒。长而不是 10 秒。
我得出结论,视频仍然以 30 fps 和 10 秒的速度录制。记录的总数为 300 帧是正确的。但是在 video_out.avi 文件中,fps 被设置为 60 fps,这导致(60 fps)视频只有一半的时间长度,因为总共仍然只有 300 帧可用。
现在剩下的问题是:
我用什么方式更改上面的代码,以便能够捕获 10 秒。 60 fps 的长视频,总共得到 600 帧?
编辑#1
@Tiphel 在他的评论中表示,添加 cap.set(cv2.CAP_PROP_FPS, 10) 可以解决问题;它似乎起作用了。
我现在尝试以某种方式编辑代码,它记录先前定义的时间(例如 5 秒)然后停止。通过这样做,我可以验证一个 60 fps 的视频是否有 5 秒。录制确实有 300 帧。此尝试导致以下代码:
import numpy as np
import cv2
import time
f=open("fps_and_time_passed.txt", "w")
cap = cv2.VideoCapture(-1,cv2.CAP_V4L)
cap.set(cv2.CAP_PROP_FPS, 30)
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('vid_out.avi', fourcc, 30.0, (640, 480))
capture_time=5.0
start_time=time.time()
while(time.time() - start_time < capture_time):
#print time passed in console
#print('time passed: ' + str(time.time()-start_time))
#write time passed in .txt file
f.write('time passed: ' + str(time.time()-start_time) + ' ')
fps=cap.get(cv2.CAP_PROP_FPS)
#print fps in console
#print('fps: ',fps)
#write fps in .txt file
f.write('fps: ' + str(fps) + '\n')
ret, frame = cap.read()
if ret==True:
out.write(frame)
cv2.imshow('frame', frame)
#if cv2.waitKey(1) & 0xFF == ord('q'):
# break
else:
break
f.close()
cap.release()
out.release()
cv2.destroyAllWindows()
分析现在生成的“vid_out.avi”文件后,我预计它是 fps: 30.0 和 frame_count 150.0,但它是 fps: 30.0 和 frame_count: 115.0。
然后我查看了“fps_and_time_passed.txt”文件,令我惊讶的是,我发现大约有 1.4 秒。开始延迟:
time passed: 1.1682510375976562e-05 fps: 30.0
time passed: 1.4038400650024414 fps: 30.0
time passed: 1.4290287494659424 fps: 30.0
time passed: 1.4499273300170898 fps: 30.0
...
time passed: 4.89248514175415 fps: 30.0
time passed: 4.925801515579224 fps: 30.0
time passed: 4.9621946811676025 fps: 30.0
time passed: 4.995436191558838 fps: 30.0
如您所见,延迟在第一个和第二个输出之间。
所以我的新问题是:
如何消除这种延迟?
我认为这是因为您在捕获第一帧之前启动了计时器,所以您最终没有达到所需的持续时间。
我相信如果你计算帧数,根据你想要的视频时长,你会得到想要的输出。
试试像这样的东西:
fps = 30
capture_time = 5.0
n_frames = capture_time * fps
curr_frame = 0
while (curr_frame < n_frames):
ret, frame = cap.read()
if ret==True:
out.write(frame)
cv2.imshow('frame', frame)
else:
break
fps=cap.get(cv2.CAP_PROP_FPS)
#write fps in .txt file
f.write('fps: ' + str(fps) + '\n')
curr_frame+=1
我还没有测试过这个,它可能行不通,但就是这样。
我的总体目标是使用 Raspberry Pi HQ 摄像头拍摄视频。当使用终端和像 raspivid -w 640 -h 480 -fps 90 -t 10000 -o video.h264
这样的标准 raspivid 命令时,生成的视频没有存储关于 fps(和 frame_count)的正确信息。我使用 openCV 和 python 检查了它,代码如下:
import cv2
cap = cv2.VideoCapture('video.h264')
if cap.isOpened():
fps = cap.get(cv2.CAP_PROP_FPS)
print('fps:', fps) # float `fps`
frame_count = cap.get(cv2.CAP_PROP_FRAME_COUNT)
print('frames count:', frame_count) # float `frame_count`
我预计它是 fps: 90.0 和 frame_count: 900.0,但它是 fps: 25.0 和 frame_count: -192153584101141.0.
经过一番研究,我得出结论,.h264 没有存储正确的 fps 值,而是存储了默认值(在我的例子中为 25.0 fps)。
现在我的下一个尝试是使用 openCV 和 python 来使用 HQ 摄像头捕捉视频。我尝试使用以下代码(在尝试使用 openCV 捕获视频时这几乎是标准的):
import numpy as np
import cv2
#had to use (-1,cv2.CAP_V4L) instead of (0) for it to find my HQ Camera
cap = cv2.VideoCapture(-1,cv2.CAP_V4L)
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('video_out.avi', fourcc, 30.0, (640, 480))
while(cap.isOpened()):
ret, frame = cap.read()
if ret==True:
out.write(frame)
cv2.imshow('frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
cap.release()
out.release()
cv2.destroyAllWindows()
现在录制大约 10 秒时。长视频,然后使用与之前相同的方法对其进行分析,结果符合预期 fps: 30.0 and frame_count: (roughly) 300.0.
现在,在第 8 行中将 fps 从 30 更改为 60,从 out = cv2.VideoWriter('video_out.avi', fourcc, 30.0, (640, 480))
到 out = cv2.VideoWriter('video_out.avi', fourcc, 60.0, (640, 480))
并分析大约 10 秒。之后的长视频结果和预期的不一样。而不是 fps: 60.0 and frame_count: (roughly) 600.0 结果是 fps: 60.0 and frame_count: (roughly) 300.0.此外,视频现在只有 5 秒。长而不是 10 秒。
我得出结论,视频仍然以 30 fps 和 10 秒的速度录制。记录的总数为 300 帧是正确的。但是在 video_out.avi 文件中,fps 被设置为 60 fps,这导致(60 fps)视频只有一半的时间长度,因为总共仍然只有 300 帧可用。
现在剩下的问题是:
我用什么方式更改上面的代码,以便能够捕获 10 秒。 60 fps 的长视频,总共得到 600 帧?
编辑#1
@Tiphel 在他的评论中表示,添加 cap.set(cv2.CAP_PROP_FPS, 10) 可以解决问题;它似乎起作用了。 我现在尝试以某种方式编辑代码,它记录先前定义的时间(例如 5 秒)然后停止。通过这样做,我可以验证一个 60 fps 的视频是否有 5 秒。录制确实有 300 帧。此尝试导致以下代码:
import numpy as np
import cv2
import time
f=open("fps_and_time_passed.txt", "w")
cap = cv2.VideoCapture(-1,cv2.CAP_V4L)
cap.set(cv2.CAP_PROP_FPS, 30)
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('vid_out.avi', fourcc, 30.0, (640, 480))
capture_time=5.0
start_time=time.time()
while(time.time() - start_time < capture_time):
#print time passed in console
#print('time passed: ' + str(time.time()-start_time))
#write time passed in .txt file
f.write('time passed: ' + str(time.time()-start_time) + ' ')
fps=cap.get(cv2.CAP_PROP_FPS)
#print fps in console
#print('fps: ',fps)
#write fps in .txt file
f.write('fps: ' + str(fps) + '\n')
ret, frame = cap.read()
if ret==True:
out.write(frame)
cv2.imshow('frame', frame)
#if cv2.waitKey(1) & 0xFF == ord('q'):
# break
else:
break
f.close()
cap.release()
out.release()
cv2.destroyAllWindows()
分析现在生成的“vid_out.avi”文件后,我预计它是 fps: 30.0 和 frame_count 150.0,但它是 fps: 30.0 和 frame_count: 115.0。 然后我查看了“fps_and_time_passed.txt”文件,令我惊讶的是,我发现大约有 1.4 秒。开始延迟:
time passed: 1.1682510375976562e-05 fps: 30.0
time passed: 1.4038400650024414 fps: 30.0
time passed: 1.4290287494659424 fps: 30.0
time passed: 1.4499273300170898 fps: 30.0
...
time passed: 4.89248514175415 fps: 30.0
time passed: 4.925801515579224 fps: 30.0
time passed: 4.9621946811676025 fps: 30.0
time passed: 4.995436191558838 fps: 30.0
如您所见,延迟在第一个和第二个输出之间。
所以我的新问题是:
如何消除这种延迟?
我认为这是因为您在捕获第一帧之前启动了计时器,所以您最终没有达到所需的持续时间。
我相信如果你计算帧数,根据你想要的视频时长,你会得到想要的输出。
试试像这样的东西:
fps = 30
capture_time = 5.0
n_frames = capture_time * fps
curr_frame = 0
while (curr_frame < n_frames):
ret, frame = cap.read()
if ret==True:
out.write(frame)
cv2.imshow('frame', frame)
else:
break
fps=cap.get(cv2.CAP_PROP_FPS)
#write fps in .txt file
f.write('fps: ' + str(fps) + '\n')
curr_frame+=1
我还没有测试过这个,它可能行不通,但就是这样。