Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Opencv视频捕获集CV\u CAP\u PROP\u POS\u帧不工作_Opencv - Fatal编程技术网

Opencv视频捕获集CV\u CAP\u PROP\u POS\u帧不工作

Opencv视频捕获集CV\u CAP\u PROP\u POS\u帧不工作,opencv,Opencv,我使用opencv从使用mpeg压缩的Vivotek摄像机输出的视频中读取帧。我正在尝试使用该功能从特定位置启动视频,如下所示,其中start是我要跳过的帧数 inputVideo.set(CV_CAP_PROP_POS_FRAMES, start); 然而,我有一个问题,这是因为不正确的帧被捕获之前发生的帧开始 我使用的是opencv版本2.4.2 有人能帮我解决这个问题吗?有点晚了,但搜索同一个主题(不针对Vivotek Camera,但更多关于openCV的mpeg问题): 视频是经

我使用opencv从使用mpeg压缩的Vivotek摄像机输出的视频中读取帧。我正在尝试使用该功能从特定位置启动视频,如下所示,其中start是我要跳过的帧数

inputVideo.set(CV_CAP_PROP_POS_FRAMES, start); 
然而,我有一个问题,这是因为不正确的帧被捕获之前发生的帧开始

我使用的是opencv版本2.4.2


有人能帮我解决这个问题吗?

有点晚了,但搜索同一个主题(不针对Vivotek Camera,但更多关于openCV的mpeg问题):

  • 视频是经过编码的
  • OpenCV使用FFMPEG
  • 编码使用关键帧
  • 跳过某些帧时,编码无法提供所需的确切帧
见类似问题:

  • 使用带有轨迹栏的openCV 2.4.8/VS2013的示例代码:

  • 使用AVI格式测试[MPEG4视频(H264)]:设置帧位置效果良好
  • 使用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);
    
    double currentPos=capture.get(CV\u CAP\u PROP\u POS\u帧);
    
    正如BlouBlou所说,当你用FFMPEG阅读一些高压缩视频格式时,它使用“关键帧”技术来解码视频。因此,设置
    CV\u CAP\u PROP\u POS\u FRAMES
    属性将无法按您所需工作

    我测试了5个mpeg视频以读取其中的所有帧。使用
    longtotalframenumber=capture.Get(CV\u CAP\u PROP\u frame\u count)获取总帧数

    然后我把每个视频读了两遍,第一次不设置
    CV\u CAP\u PROP\u POS\u FRAMES
    为0,第二次设置它

    当您将
    CV\u CAP\u PROP\u POS\u frames
    设置为0时,它确实删除了一些帧,每个视频大约10帧。我猜是因为关键帧不在视频的第一帧中,所以FFMPEG会将一些帧跳过到第一个关键帧。但是一些视频格式,如.avi,不会出现这样的问题。我希望我的真实经历能为其他人节省很多时间(我花在寻找这个页面上的时间不长,但足够了)


    无论如何,当您面对mpeg格式的视频时,强烈建议不要使用
    CV\u CAP\u PROP\u POS\u FRAMES
    获取特定帧。设置
    CV\u CAP\u PROP\u POS\u MSEC
    :)

    是一个明智的选择,如果您愿意升级到OpenCV 3.0,以下两个用例可能会对您有所帮助。这可能适用于早期版本,但我还没有尝试过如果希望它捕获帧a和帧b之间的所有帧,请参考第二个用例,并将“所需帧”替换为:

    desired_frames = range(a,b)
    

    首先,导入一些包 每n秒捕获一次(此处,n=5) 或者,每n帧捕获一次(此处,n=10) 差不多就是这样


    一些不幸的警告…根据您的opencv版本(这是为opencv V3构建的),您可能需要以不同的方式设置fps变量。有关详细信息,请参阅。要了解您的版本,您可以执行以下操作:

    (major_ver, minor_ver, subminor_ver) = (cv2.__version__).split('.')
    major_ver
    

    奇怪的是,我面前有一个
    assert

    inputVideo.set(CV_CAP_PROP_POS_FRAMES, start); 
    

    删除
    assert
    解决了问题

    如何知道帧不正确?
    #################### 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
    
    inputVideo.set(CV_CAP_PROP_POS_FRAMES, start);