我正在使用OpenCV从一台采用MPEG压缩的Vivotek摄像机的视频输出中读取帧。 我尝试使用下面显示的函数从特定位置开始播放视频,其中“start”是我想要跳过的帧数。
inputVideo.set(CV_CAP_PROP_POS_FRAMES, start);
然而,我在这方面遇到了问题,因为捕获的帧是不正确的,它发生在开始帧之前。
我正在使用opencv版本2.4.2。
请问有人能帮忙解决这个问题吗?
我正在使用OpenCV从一台采用MPEG压缩的Vivotek摄像机的视频输出中读取帧。 我尝试使用下面显示的函数从特定位置开始播放视频,其中“start”是我想要跳过的帧数。
inputVideo.set(CV_CAP_PROP_POS_FRAMES, start);
然而,我在这方面遇到了问题,因为捕获的帧是不正确的,它发生在开始帧之前。
我正在使用opencv版本2.4.2。
请问有人能帮忙解决这个问题吗?
虽然有点晚,但是关于同一主题的搜索(不仅限于Vivotek摄像机,还包括在openCV中出现mpeg问题):
请参见类似的问题:
desired position key frame (this is where the cursor will stop)
| | | |
| > | |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
使用OpenCV 2.4.8 / VS2013和轨迹栏的示例代码:
测试了MPG格式[MPEG1/MPEG2]:帧位置设置正常工作
double currentPos = capture.get(CV_CAP_PROP_POS_FRAMES);
std::cout << "CV_CAP_PROP_POS_FRAMES = " << currentPos << std::endl;
// position_slider 0 - 100
double noFrame = position_slider*nbFrames / 100;
// solution 1
bool success = capture.set(CV_CAP_PROP_POS_FRAMES, noFrame);
// solution 2
double frameRate = capture.get(CV_CAP_PROP_FPS);
double frameTime = 1000.0 * noFrame / frameRate;
bool success = capture.set(CV_CAP_PROP_POS_MSEC, frameTime);
if (!success) {
std::cout << "Cannot set frame position from video file at " << noFrame << std::endl;
return;
}
currentPos = capture.get(CV_CAP_PROP_POS_FRAMES);
if (currentPos != noFrame) {
std::cout << "Requesting frame " << noFrame << " but current position == " << currentPos << std::endl;
}
success = capture.read(frame_aux);
if (!success) {
std::cout << "Cannot get frame from video file " << std::endl;
return;
}
imshow("test", frame_aux);
CV_CAP_PROP_POS_FRAMES
属性无法按您想要的方式工作。long totalFrameNumber = capture.get(CV_CAP_PROP_FRAME_COUNT);
获取总帧数。CV_CAP_PROP_POS_FRAMES
为0,第二次设置。CV_CAP_PROP_POS_FRAMES
设置为0时,它确实会丢失一些帧数,大约每个视频丢失10帧。我想这是因为关键帧不在视频的第一帧中,因此FFMPEG跳过一些帧到第一个关键帧。但是某些视频格式(如.avi)不会出现这样的问题。我希望我的真实经验可以为其他人节省很多时间(好吧,我花了一些时间找到这个页面,但已经足够了)。CV_CAP_PROP_POS_FRAMES
来获取特定帧。最好选择设置CV_CAP_PROP_POS_MSEC
:)如果您愿意升级到OpenCV 3.0,以下两个用例可能对您有所帮助。这些可能适用于早期版本,但我没有尝试过。如果您希望捕获介于帧a和帧b之间的所有帧,请参考第二个用例,并将“desired_frames”替换为:
desired_frames = range(a,b)
import cv2
import math
import numpy as np
#################### Setting up the file ################
videoFile = "Jumanji.mp4"
vidcap = cv2.VideoCapture(videoFile)
success,image = vidcap.read()
#################### Setting up parameters ################
seconds = 5
fps = vidcap.get(cv2.CAP_PROP_FPS) # Gets the frames per second
multiplier = fps * seconds
#################### Initiate Process ################
while success:
frameId = int(round(vidcap.get(1))) #current frame number, rounded b/c sometimes you get frame intervals which aren't integers...this adds a little imprecision but is likely good enough
success, image = vidcap.read()
if frameId % multiplier == 0:
cv2.imwrite("FolderSeconds/frame%d.jpg" % frameId, image)
vidcap.release()
print "Complete"
#################### Setting up the file ################
videoFile = "Jumanji.mp4"
vidcap = cv2.VideoCapture(videoFile)
success,image = vidcap.read()
#################### Setting up parameters ################
#OpenCV is notorious for not being able to good to
# predict how many frames are in a video. The point here is just to
# populate the "desired_frames" list for all the individual frames
# you'd like to capture.
fps = vidcap.get(cv2.CAP_PROP_FPS)
est_video_length_minutes = 3 # Round up if not sure.
est_tot_frames = est_video_length_minutes * 60 * fps # Sets an upper bound # of frames in video clip
n = 5 # Desired interval of frames to include
desired_frames = n * np.arange(est_tot_frames)
#################### Initiate Process ################
for i in desired_frames:
vidcap.set(1,i-1)
success,image = vidcap.read(1) # image is an array of array of [R,G,B] values
frameId = vidcap.get(1) # The 0th frame is often a throw-away
cv2.imwrite("FolderFrames/frame%d.jpg" % frameId, image)
vidcap.release()
print "Complete"
基本上就是这样了。
(major_ver, minor_ver, subminor_ver) = (cv2.__version__).split('.')
major_ver
对我来说很奇怪,我在前面加了一个assert
inputVideo.set(CV_CAP_PROP_POS_FRAMES, start);
移除那个 assert
就解决了问题。
pyav
代替。https://pyav.org - Peter