无法在C ++中使用OpenCV播放Y800单色AVI文件

时间:2014-01-08 15:46:57

标签: c++ opencv codec avi

我面临以下问题。由于我想从相机录制和播放RAW图像数据,我目前正在使用

录制图像
VideoWriter outputVideo1("camera1.avi", CV_FOURCC('Y','8','0','0'), frameRate, frameSize, false);

这很好用,我可以使用VLC播放器播放视频文件,例如 MediaInfo还确认,格式为GrayScale,编解码器ID为Y800。

不幸的是,当我尝试使用

在OpenCV中打开此文件时
VideoCapture cap1("camera1.avi");
Mat frame1;
for(;;)
{
cap1 >> frame1;
}

程序在for循环内崩溃,异常

  

cam_interface.exe中0x715f39c2处的未处理异常:0xC0000005:访问冲突读取位置0x010a0040。

当我使用霍夫曼无损编解码器('H','F','Y','U')时,我可以打开AVI文件。但由于我的数据只包含一个频道,我只想保存一个频道。使用霍夫曼编解码器作为单色图像,存储了所有三个通道的相同值,这不是我想要做的。

如果您对如何解决此问题有任何帮助或想法。

非常感谢!

1 个答案:

答案 0 :(得分:0)

我在http://answers.opencv.org找到了一个解决方法,其中用户皮埃尔遇到了同样的问题,并自己创建了解决方法。我将重新发布此处找到的原始答案: http://answers.opencv.org/question/2133/videocapture-not-working-with-uncompressed-files/

皮尔回答:

  

问题没有解决但我找到了一个程序来分别阅读图像来解决这个问题。首先,有必要打开序列以获取有关视频文件的FOURCC代码和信息,图像大小,图像数量......然后,如果FOURCC对应于非压缩AVI,则关闭序列并通过经典重新打开C函数fopen并跳转标题,然后使用fread函数获取每个图像。请参阅以下代码:

void CMFC_OpencvDlg::OnBnClickedLitSeqAvi()
{
 static CString Filter=_T("Video files (*.avi; *.mpg) |*.avi;*.mpg|All Files (*.*)|*.*||");
 CFileDialog Load(TRUE, _T("*.bitmap"), NULL, OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST|OFN_HIDEREADONLY,Filter,NULL); 
 Load.m_ofn.lpstrTitle= _T("Lecture video");
 int value = 0 ;
 double Height, Width, Nb_images, Code  ;
 FILE *Seq_Avi ;
 Mat Img ;
 if (Load.DoModal() == IDOK) 
 {
     img_path = Load.GetPathName() ;
     Nom_de_Sequence = Load.GetPathName() ; 
     Nom_de_Sequence.Truncate(Nom_de_Sequence.GetLength()-4) ;
     VideoCapture Sequence(img_path);
     Nb_images = Sequence.get(CV_CAP_PROP_FRAME_COUNT ) ;
     Width = Sequence.get(CV_CAP_PROP_FRAME_WIDTH ) ;
     Height = Sequence.get(CV_CAP_PROP_FRAME_HEIGHT ) ;
     Code = Sequence.get(CV_CAP_PROP_FOURCC ) ;
     Nb_Images_Seq = 0 ;
     if (Code == CV_FOURCC('Y','8','0','0')|| (Code == 0 ))
     {
         Sequence.release() ;  // Fermeture du fichier 
         char *tmp, c ;
         string Tag = "movi00d" ;
         int i =0 ;
         fpos_t pos;
         BOOLEAN Fin = TRUE ;
         tmp = (char *)malloc(Width*Height) ;
         fopen_s(&Seq_Avi,img_path.c_str(),"rb") ;
         do  // Gestion de la taille d'entête variable
         {
             fread(&c,1,1,Seq_Avi) ;
             if (c==Tag[i]) 
             {
                 i++ ;
                 if (i==7) Fin = FALSE ;
                 if (i==4)  fgetpos(Seq_Avi,&pos) ;
             }
             else i = 0 ;
         }
         while (Fin) ;
         fsetpos( Seq_Avi, &pos ) ;
         for (i= 0 ; i < Nb_images ;i++)
         {
             fread(tmp,1,8,Seq_Avi) ;  // Saut du séparateur, "00dc"+taille image
             fread(tmp,1,Width*Height,Seq_Avi) ;
             Img = Mat(Height, Width, CV_8U, tmp) ;
             Seq_image[Nb_Images_Seq] = Img.clone() ;
             if (Code == 0 ) flip(Seq_image[Nb_Images_Seq],Seq_image[Nb_Images_Seq],0 ) ;  // Lorsque le code est 0 les images sont stokées bas en haut 
             imshow("image", Seq_image[Nb_Images_Seq++]);
     //      AfxMessageBox(_T("Image suivante"),0,0) ;
         }
         fclose(Seq_Avi) ;
         free(tmp) ;
     }
     else
     {
     // Cette partie ne marche pas avec les AVI non compressés !!!!!
         while( Sequence.read(src)) //Relecture de out le fichier et traitement associé
         {
             Seq_image[Nb_Images_Seq++] = src ;
             imshow("image", src);
     //      AfxMessageBox(_T("Image suivante"),0,0) ;
         }
     }
 }
}