【问题标题】:extract frame from a video for detection with opencv从视频中提取帧以使用 opencv 进行检测
【发布时间】:2016-09-14 15:01:28
【问题描述】:

我正在开发一个程序来检测视频或图像中的对象。 它适用于图像,但现在我想将它与视频一起使用。我使用特定文件夹来选择图像,因此我想在检测之前将视频中的帧保存在该文件夹中。 变量 video 和 salvataggio 已经设置好了。 在以下代码中,我导航抛出文件夹以分析视频:

DIR *dir;
dir = opendir(video.c_str());
string vidName;
struct dirent *ent;
if (dir != NULL) {
        while ((ent = readdir (dir)) != NULL) {
            vidName= ent->d_name;
            if(vidName.compare(".")!= 0 && vidName.compare("..")!= 0)
            {
            //string vidPath(neg + vidName);
                estraiframe(video, vidName, salvataggio);
            }
        }
        closedir (dir);

}
else {
    cout<<"directory "<< video << " not present"<<endl;
}
}

函数 estraiframe 将帧保存在输出文件夹中。

void estraiframe(string path, string vidName, string output){

string vidPath(path + vidName);
VideoCapture cap(vidPath);
if( !cap.isOpened()){
        cout << "Cannot open the video file" << endl;
        return;
}

double count = cap.get(CV_CAP_PROP_FRAME_COUNT);
double rate = cap.get(CV_CAP_PROP_FPS);
int counter = 0;
for (int i=1; i< count; i+=rate*5)
{


cap.set(CV_CAP_PROP_POS_FRAMES,i);

Mat frame;
cap.read(frame);

counter++;
string nomeframe = to_string(counter) + "-frame_from"+vidName+".jpg";
string percorso (output+nomeframe);
cout << percorso;
imwrite(percorso,frame);
}
}

显然它可以工作,但在最后一帧之后它给了我以下错误:

断言 stream_index nstreams 在 libavformat/oggdec.c:898 失败 我锁定它,但我没有找到错误在哪里

【问题讨论】:

  • 那是因为你没有给出任何退出循环的条件。读取图像后,在 for 循环中使用此条件。 "if(frame.empty()) 中断";

标签: c++ opencv video frame


【解决方案1】:

您的视频包含各种流索引,例如3 个音频和 1 个视频流将产生 4 个流索引。我建议您检查视频包含的流数量并打印 ogg->nstreams 以检查这是否对应。在第 898 行查看 oggdec.c 中的源代码

static int ogg_read_seek(AVFormatContext *s, int stream_index,
                         int64_t timestamp, int flags)
{
    struct ogg *ogg       = s->priv_data;
    struct ogg_stream *os = ogg->streams + stream_index;
    int ret;

    av_assert0(stream_index < ogg->nstreams); /* Line 898 */

你显然在这里越界了。

【讨论】:

  • 我使用了ubuntu的默认视频,文件夹示例中的那个。感谢指出问题出在哪里。
【解决方案2】:

显然我设法解决了,我修改了提取帧的函数。

void estraiframe(string path, string vidName, string output){
string vidPath(path + vidName);
VideoCapture cap(vidPath);
if( !cap.isOpened()){
        cout << "Cannot open the video file" << endl;
        return;
}

double rate = cap.get(CV_CAP_PROP_FPS);
int counter = 0;
Mat frame;
int i=1;

while(1)
{
     cap.read ( frame);
     if( frame.empty()) break;
     counter++;

     if (counter == rate*5*i){
     i++;
     string nomeframe = to_string(counter) + "-frame_from"+vidName+".jpg";
     string percorso (output+nomeframe);
     imwrite(percorso, frame);
     }

     char key = waitKey(10);
     if ( key == 27) break;
}
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-04
    • 2013-07-29
    • 2022-12-29
    • 2018-03-09
    • 2011-03-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多