【问题标题】:Writing video with openCV - no key frame set for track 0使用 openCV 编写视频 - 没有为轨道 0 设置关键帧
【发布时间】:2013-09-03 17:27:34
【问题描述】:

我正在尝试使用以下代码使用 openCV 2.4.6.1 修改和编写一些视频:

cv::VideoCapture capture( video_filename );

    // Check if the capture object successfully initialized
    if ( !capture.isOpened() ) 
    {
        printf( "Failed to load video, exiting.\n" );
        return -1;
    }

    cv::Mat frame, cropped_img;

    cv::Rect ROI( OFFSET_X, OFFSET_Y, WIDTH, HEIGHT );


    int fourcc = static_cast<int>(capture.get(CV_CAP_PROP_FOURCC));
    double fps = 30;
    cv::Size frame_size( RADIUS, (int) 2*PI*RADIUS );
    video_filename = "test.avi";
    cv::VideoWriter writer( video_filename, fourcc, fps, frame_size );

    if ( !writer.isOpened() && save )
    {
        printf("Failed to initialize video writer, unable to save video!\n");
    }

    while(true)
    {   
        if ( !capture.read(frame) )
        {
            printf("Failed to read next frame, exiting.\n");
            break;
        }

        // select the region of interest in the frame
        cropped_img = frame( ROI );                 

        // display the image and wait
        imshow("cropped", cropped_img);

        // if we are saving video, write the unwrapped image
        if (save)
        {
            writer.write( cropped_img );
        }

        char key = cv::waitKey(30);

当我尝试使用 VLC 运行输出视频“test.avi”时,我收到以下错误:avidemux 错误:没有为轨道 0 设置关键帧。我使用的是 Ubuntu 13.04,我尝试使用编码的视频使用 MPEG-4 和 libx264。我认为修复应该很简单,但找不到任何指导。实际代码可在https://github.com/benselby/robot_nav/tree/master/video_unwrap 获得。提前致谢!

【问题讨论】:

  • 你有没有弄清楚问题是什么?我遇到了同样的问题。
  • 我现在也在尝试追查这个问题。如果我找到答案,我会回来报告。
  • 在我的情况下,问题是:1)大小不匹配:Mat 有height 行和width 列,但作者采用了(width,height) 的大小,即按其他顺序和2 ) 灰度图像:我传递的 Mat 是 width x height x 1,显然它想要 width x height x 3(在 python 下)。这是 OpenCV 2.4.8。

标签: c++ opencv video


【解决方案1】:

[PYTHON] 除了分辨率不匹配,也可能存在每秒帧数不匹配。就我而言,分辨率设置正确,但问题在于 fps。检查 VideoCapture 对象正在读取的每秒帧数,它显示为 30.0,但如果我将 VideoWriter 对象的 fps 设置为 30.0,则在 VLC 中会引发相同的错误。您可以通过将其设置为 30 来解决错误,而不是将其设置为 30.0。

附:您可以在捕获 while/for 循环中使用 cap.get(3) 表示宽度,cap.get(4) 表示高度,cap.get(5) 表示 fps,以检查您正在录制的分辨率和 fps。

完整代码如下:

import numpy as np
import cv2 as cv2
cap = cv2.VideoCapture(0)

#Define Codec and create a VideoWriter Object
fourcc = cv2.VideoWriter_fourcc('X','V','I','D')
#30.0 in the below line doesn't work while 30 does work.
out = cv2.VideoWriter('output.mp4', fourcc, 30, (640, 480))

while(True):
    ret, frame = cap.read()
    colored_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2BGRA)
    print('Width = ', cap.get(3),' Height = ', cap.get(4),' fps = ', cap.get(5))
    out.write(colored_frame)
    cv2.imshow('frame', colored_frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
out.release()
cv2.destroyAllWindows()

可在此处查看所有属性的完整文档 (C++):propId OpenCV Documentation

【讨论】:

    【解决方案2】:

    这似乎是写入的帧与打开的 VideoWriter 对象之间大小不匹配的问题。当我尝试将一系列调整大小的图像从我的网络摄像头写入视频输出时,我遇到了这个问题。当我删除调整大小步骤并从初始测试帧中获取大小时,一切正常。

    为了修复我的调整大小代码,我基本上在处理过程中运行了一个测试帧,然后在创建 VideoWriter 对象时拉出它的大小:

    #include <cassert>
    #include <iostream>
    #include <time.h>
    
    #include "opencv2/opencv.hpp"
    
    using namespace cv;
    
    int main()
    {
        VideoCapture cap(0);
        assert(cap.isOpened());
    
        Mat testFrame;
        cap >> testFrame;
        Mat testDown;
        resize(testFrame, testDown, Size(), 0.5, 0.5, INTER_NEAREST);
        bool ret = imwrite("test.png", testDown);
        assert(ret);
    
        Size outSize = Size(testDown.cols, testDown.rows);
        VideoWriter outVid("test.avi", CV_FOURCC('M','P','4','2'),1,outSize,true);
        assert(outVid.isOpened());
    
        for (int i = 0; i < 10; ++i) {
            Mat frame;
            cap >> frame;
    
            std::cout << "Grabbed frame" << std::endl;
    
            Mat down;
            resize(frame, down, Size(), 0.5, 0.5, INTER_NEAREST);
    
            //bool ret = imwrite("test.png", down);
            //assert(ret);
            outVid << down;
    
    
            std::cout << "Wrote frame" << std::endl;
            struct timespec tim, tim2;
            tim.tv_sec = 1;
            tim.tv_nsec = 0;
            nanosleep(&tim, &tim2);
        }
    }
    

    我的猜测是你的问题在于尺寸计算:

    cv::Size frame_size( RADIUS, (int) 2*PI*RADIUS );
    

    我不确定您的帧来自哪里(即如何设置捕获),但可能在四舍五入或其他地方您的尺寸被弄乱了。我建议做一些类似于我上面的解决方案的事情。

    【讨论】:

      猜你喜欢
      • 2017-11-21
      • 2023-01-25
      • 1970-01-01
      • 2018-08-13
      • 1970-01-01
      • 2017-07-04
      • 1970-01-01
      • 1970-01-01
      • 2015-08-11
      相关资源
      最近更新 更多