• 締切済み

OpenCVでのcvCreateVideoWriterがうまくいきません

今回複数枚のbmp画像群を、その画像につけられた4桁の連番の順に順次AVIファイルのフレームとして格納して行き、最終的にひとつのAVIファイルを出力するというプログラムを書いていますが、OpenCVの関数である「cvCreateVideoWriter」で躓いています。 CvVideoWriter* cvCreateVideoWriter( const char* filename, int fourcc, double fps, CvSize frame_size, int is_color=1 ); という仕様で、第二引数に「-1」と入れることで、プログラム実行時ffmpegが自動的にどの動画像コーデックを使用するかを聞いてくるということだったのですが、そうしているにも関わらずコーデック選択画面は出ないどころか、出力された動画(avi)も再生できない破損したファイルとして出力されてしまいます。 何かコーデックをインストールする必要があるのか(動画のコーデックとして、Combined Community Codec Packをインストール済みです)、それともプログラム内にまずい箇所があるのか、わからなくてあせっています。どなたかわかる方いらっしゃいましたらご教授よろしくお願いいたします。 ソース↓↓ //--------------------------------------------------------- // bmp→aviコンバート //--------------------------------------------------------- #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 #include <stdio.h> #include <cv.h> #include <cxcore.h> #include <highgui.h> #include <iostream> using namespace std; #include <fstream> int main(int argc, char** argv) { //変数定義----------------------------------------------- int key=NULL; IplImage* img = NULL; //読み込んだ画像ファイル用 char* outputWindow = "Output"; //進行状況確認用ウィンドウ CvVideoWriter* VideoWriter = NULL; //ビデオライタ char* filename = "test.avi"; //出力ファイル名 double fps = 30; //ビデオのフレームレート int i=0; //画像の連番カウント用 char ImageName[104]; //読み込む画像ファイル名 char NameTmp[100]; //上の連番なし //-------------------------------------------------------- //元画像の読み込み&フレームへの埋込み---------------------------------------------- cout << "画像名を入力してください(4桁連番号省略)" << endl; cin >> NameTmp; sprintf(ImageName,"%s0000.bmp",NameTmp); img = cvLoadImage(ImageName, CV_LOAD_IMAGE_GRAYSCALE); //画像一枚目の読み込みの if(img==NULL){ cout << ImageName << "の読み込み失敗" <<endl; return 1; } //進行状況確認用ウィンドウ展開 cvNamedWindow(outputWindow, CV_WINDOW_AUTOSIZE); //ログファイル展開 std::ofstream ofs; ofs.open( "test.txt" ); ofs << "1枚目の画像展開成功" << std::endl; //ビデオライタ展開 VideoWriter = cvCreateVideoWriter(filename, -1, fps, cvGetSize(img), 0); ofs << "ビデオライタ展開" << std::endl; while(img!=NULL){ //画像ファイルの連番に合わせて読み込むファイル名を変更 if(i<10){ sprintf(ImageName,"%s000%d.bmp",NameTmp,i); } else if(i<100){ sprintf(ImageName,"%s00%d.bmp",NameTmp,i); } else if(i<1000){ sprintf(ImageName,"%s0%d.bmp",NameTmp,i); } else{ sprintf(ImageName,"%s%d.bmp",NameTmp,i); } //進境状況をウィンドウに出力 cvShowImage(outputWindow, img); //進行状況確認用。10ms待つ key = cvWaitKey(10); //ビデオ書き込み cvWriteFrame(VideoWriter,img); cout << ImageName << endl; i+=1; img = cvLoadImage(ImageName, CV_LOAD_IMAGE_GRAYSCALE); //次のフレーム画像の読み込み ofs << i << "枚目の画像書き込み成功" << std::endl; } //ビデオ書き込み用メモリを開放 cvReleaseVideoWriter(&VideoWriter); //ログファイルを閉じる ofs.close(); //進行状況確認ウィンドウを閉じる cvDestroyWindow(outputWindow); return 0; }

noname#123915
noname#123915

みんなの回答

  • chie65535
  • ベストアンサー率43% (8525/19378)
回答No.1

>第二引数に「-1」と入れることで、プログラム実行時ffmpegが自動的にどの動画像コーデックを使用するかを聞いてくるということだったのですが、 第二引数で、「-1」の代わりに、無圧縮コーデックの「CV_FOURCC('D','I','B',' ')」を指定して試してみて下さい。 第二引数に「-1」が使えるのは「一部の限られた実行環境のみ」で、質問者さんの実行環境で使える保障はどこにもありません。 (質問者さんの実行環境が明記されてないので「使える」とも「使えない」とも言えず、断言する事が出来ません)

noname#123915
質問者

補足

回答ありがとうございます。 第二引数に「CV_FOURCC('D','I','B',' ')」を指定しましたが、以下のようなエラーが出てプログラムがストップしてしまいます。 Unsupported format or combination of formats (FFMPEG could not find a codec matching the given FOURCC code. Use fourcc=CV_FOURCC_DEFAULT for auto selection.) in function CvVideoWriter_FFMPEG::open, d:\ArchivosDR\PruebasIMGS\PruebaV\OpenCV\otherlibs\highgui\cvcap_ffmpeg.cpp(1195) 一応一番下に記述してあるcvcap_ffmpeg.cppを見てみましたがさっぱりでした。;; ちなみに実行環境は OS:WindowsXP Professional Ver2002 ServicePack3 CPU:AMD Athron 64X2 Dual Core Processor 4000+ 2.10GHz メモリ:2GB コンパイラ:Visual C++ 2008 Express Edition あと、ffopencv110.dllはYahoo Groupsの「OpenCV &middot; Open Source Computer Vision Library Community」内にアップしてある、リビルド済みの物に変えてあります。(Feb 2, 2009付の物)

関連するQ&A

  • [C++]ファイル出力について

    教えてください。 コマンドプロンプトから何行か書いた文章をファイルにしたいのですが、 うまくいきません。 作ったものの結果は1行1文字で出力されて、eofでうまく 終わってくれません。 コマンドプロンプトで入力(改行)された通りにファイルに出力 できるようにしたいので、どこがおかしいのか指摘お願いします。 #include <iostream> #include <fstream> #include <stdlib.h> #include <string.h> #include <string> using namespace std; int main(int argc, char *argv[]) { char str[100]; int i; i = 0; if (argc <= 1) { cerr << "Need filename" << endl; exit (1); } ifstream ifs(argv[1], ios::in); if (ifs) { cerr << "Caution" << argv[1] << " already exists " << endl; cerr << " Specify a different filename " << endl; exit (2); } ofstream ofs(argv[1], ios::out); if (!ofs) { cerr << " Unable to write to " << argv[1] << endl; exit (3); } while(str[i] !=EOF) { cin >> str[i]; ofs << str[i] << endl; i++; } return 0; }

  • OpenCVでRAW画像(カラー)を開くには

    OpenCVを使って、テキスト形式のヘッダーありのRAW画像(カラー)を、Cで書いたプログラムで開きたいのですが、 うまくいかず困っています。 “LoadRawImage”というWindowが起動しますが、真黒で何も表示されません。 RAW画像を開く関数myRawImageは以下のurlの「RAWデータの読み込みと表示」を参照させていただきました。(すみません、どうもありがとうございます。) http://wiki.livedoor.jp/mikk_ni3_92/d/raw%a5%c7%a1%bc%a5%bf%a4%ce%c6%c9%a4%df%b9%fe%a4%df%a4%c8%c9%bd%bc%a8 画像サイズはわかっているので、bmpなどに変換せず、RAWのまま開きたいのですが、どこを直せばいいのでしょうか。 どなたかヒントでも教えていただけると大変助かります、どうぞよろしくお願い致します。 //test.cpp #include <cv.h> #include <highgui.h> #include <iostream> #include <fstream> #include "raw_data_show.h" int main (int argc, char ** argv)================= { int x, y,i; uchar p1[3], p2[3]; IplImage *img1, *img2, *cp_img; img1 = myRawImage("D:\\My Pictures\\...\rawimage",500,500,3); cvShowImage("Load RawImage",img1); cvWaitKey(0); ============================================== #include <cv.h> #include <cxcore.h> #include <highgui.h> #include <iostream> #include <fstream> IplImage *myRawImage(char *filename, int w,int h,int channels) { if((channels != 3) && (channels != 1)) { std::cerr << " channel is not 3 or 1\n"; return NULL; } std::fstream ifs(filename,std::ios::in|std::ios::binary); if(!ifs.is_open()) { return NULL; } CvMat *Mat = cvCreateMat(h,w,CV_8UC3); ifs.read(reinterpret_cast<char*>(Mat->data.ptr),w*h*3); ifs.close(); IplImage img_hdr; IplImage *dst_img = cvGetImage (Mat, &img_hdr); IplImage *clone = cvCloneImage(dst_img);//クローン作成 cvReleaseImage(&dst_img); cvReleaseMat(&Mat); if(channels == 3){ for (i = 0; i < size; i++) { for (j = 0; j < size; j++) { CvMat m; float ret = 0.0; float a[] = { float (j) / size, float (i) / size }; cvInitMatHeader (&m, 1, 2, CV_32FC1, a); ret = svm.predict (&m); switch ((int) ret) { case 1: rcolor = CV_RGB (100, 0, 0); break; case 2: rcolor = CV_RGB (0, 100, 0); break; case 3: rcolor = CV_RGB (0, 0, 100); break; } cvSet2D (img, i, j, rcolor); } } cvCvtColor(clone,clone,CV_RGBA2BGR); return clone; } ========================================================

  • OpenCVで画像を読み込みたい

    OpenCVを勉強しようと思い先日始めました。 http://chihara.naist.jp/opencv/?FrontPage 上記のサイトに掲載されている通りにVC++ 2008 EEで ・環境変数PATH ・インクルードファイル ・ライブラリファイル ・リンカ の設定をしました。 これでいざプログラムをコンパイルして実行すると何故か画像が読み込んでくれません。 これらの設定以外の他にするべきことがあるのでしょうか? いきなり出鼻を挫かれたので困っています。よろしくお願いします。 OS:XP SP2 開発環境:VC++ 2008 EE 実行したプログラム ---------------------------------------------------------------- #include "cv.h" #include "highgui.h" int main( int argc, char** argv ) { IplImage* img; char* filename = "abc.bmp"; if( argc == 2 && (img = cvLoadImage( filename, 1)) != 0 ) { cvNamedWindow( "Image view", 1 ); cvShowImage( "Image view", img ); cvWaitKey(0); // イベント処理を含む場合には,これが重要. cvDestroyWindow( "Image view" ); cvReleaseImage( &img ); return 0; } return -1; } ----------------------------------------------------------------

  • vectorの中にmap

    vectorの中にmapを入れて 添字:ノードID [どのノードから来たのか|それまでのコスト] を表現しようと考えています. #include<iostream> #include<vector> #include<map> #include<list> // MACROS #define UNDEF -1 // PROTOTYPE DCLARE void init_path(std::vector<std::map<char, int> >, int size); int main(void) { //source -> source node // //size -> the number of node // //path -> store path infomation // ex: // path[1]: 1 is node id // char : from node id // cost : how cost from source to here // //adj -> show adjacency list eace node int source; int size; std::vector<std::map<char, int> > path; std::vector<std::list<char> > adj; size = 5; std::cout << "before" << std::endl; init_path(path, size); std::cout << "after" << std::endl; std::map<char, int>::iterator it; for(int i = 0; i < size; i++) { it = path[i].begin(); // std::cout << it->first << ":" << it->second << std::endl; } return 0; } void init_path(std::vector<std::map<char, int> > path, int size) { std::map<char, int> init; init.insert( std::map<char, int>::value_type('-', UNDEF) ); for(int i = 0; i < size ; i++) { path.push_back(init); } return; } *結果 before after Segmentation fault となり初期化をする所までは正常に動いたっぽいのですが どこが悪いのかわかりません(おそらくイテレータあたりかと思うのですが・・・・ 具体的にどうしたらいいのか分からないのでご指導ねがいます.

  • プログラムの説明

    C++の初心者です。 ↓のプログラムの動作はさっぱりわかりませんが、それについての説明は具体的に教えていただきたいです。(できれば、詳しく) #include <iostream> #include <string> int getNinzu(int ARGC, char *ARGV[]) throw (char const *){ if(ARGC!=2){ throw "Needs only one argument."; } int ninzu=std::atoi(ARGV[1]); if(ninzu<=0){ throw "Value is too small."; } return ninzu; } #include <cstdlib> #include <ctime> int randfive(){ static bool firsttime=true; if(firsttime){ firsttime=false; std::srand(std::time(NULL)); } return static_cast<int>(static_cast<double>(std::rand())/RAND_MAX*(5+1)); } #include <iomanip> int main(int ARGC, char* ARGV[]){ std::string cmdname=ARGV[0]; int ninzu; try{ ninzu=getNinzu(ARGC,ARGV); std::cout << std::setfill('0'); for (int i = 1; i <= ninzu; ++i) { int score = 0; for (int k = 0; k < 20; ++k) score += randfive(); std::cout << "C" << std::setw(5) << i << " " << score << '\n'; } }catch(char const *str){ std::cerr << str << std::endl << "Usage: " << cmdname << " ninzu" << std::endl; return 1; } }

  • C++でofstreamに空白を含む文字列を<<するとそれ以降の文字が書き込まれない

    以下のようなテストプログラムを書いたのですが、 期待した動作になりません。 #include <fstream> int main() { std::ofstream ofs("C:/test.txt"); char moji[] = "aaa bbb"; ofs << moji << std::flush; ofs.close(); } テキストファイルにはaaaしか書き込まれず、bbbが無視されています。 ifstreamが空白文字までで処理をとめるのは知っていましたが、 ofstreamが書き込む際も同じなのでしょうか。 空白を含む文字列を書き込むにはどうすればよいでしょうか? よろしくお願いいたします。

  • バックグラウンドでの処理

    C言語のカテゴリで質問しようか迷いましたが動きはシェル関連なので質問させてください. 例えば,以下のようなCソースがあったとします. 1 #include<iostream> 2 3 int main(int argc, char *argv[]) 4 { 5 6 for (int i = 0;; i++) { 7 8 std::cout << "0" << std::endl; 9 } 10 11 return 0; 12 } 実行ファイル名を0として ./0 & としましたが,0が連続的に出力されるだけでした. バックグラウンドで処理させているはずなのになぜ0が出力されるのでしょうか?

  • ofstream::getがおかしい!

    ofstream::getの動作がおかしいのです #include <string> #include <iostream> #include <fstream> using namespace std; void main(void) { ifstream ifs; ofstream ofs; string str; char c; str="abc"; cout<<"before str: "<<str<<endl<<endl; ofs.open("gomi");ofs<<str;ofs.close(); ifs.open("gomi");for(str="";ifs.eof()==0;str+=c)ifs.get(c);ifs.close(); cout<<"after str: "<<str<<endl<<endl; } の結果が before str: abc after str: abcc になります 最後のcは何でつくのでしょうか? 回避する方法を教えてください

  • openCVの画像処理について

    画像の中にある粒子の位置を検出し、座標の値の取得をどうしてもOpenCVをつかって、出したいと考えております。 プログラミングが実行したら、すべて0と表示されたり、エラーが出たりします。 現在、画像を読み込み、2値化し、2値化した画像の画素数を列ごとに足して、垂直方向の画素数の最大値の検出、2値化した画像の画素数を行ごとに足して、水平方向の画素数の最大値の検出を行っています。 使用した画像を添付させていただきますので、もしアドバイスなどいただけたらよろしくお願い致します。 #include <stdio.h> #include <math.h> #include <cv.h> #include <cxcore.h> #include <highgui.h> #define X 640 #define Y 480 IplImage *grayImage; //グレースケール画像用IplImage IplImage *binaryImage; //2値画像用IplImage char windowNameBinarization[] = "Binarization";//2値化した画像を表示するウィンドウの名前 int levels = 115; //トラックバーの値(2値化の際の閾値) static int h[X][Y]; int main( /*int argc, char **argv*/ ){ // 画像を読み込む IplImage *sourceImage = cvLoadImage( "C:/Documents and Settings/Owner/My Documents/My Pictures/Logicool Webcam/Picture 10.jpg",CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR); if ( sourceImage == NULL ) { // 画像が見つからなかった場合 printf( "画像が見つかりません\n" ); return -1; } // 画像を生成する IplImage *grayImage = cvCreateImage( cvGetSize(sourceImage), IPL_DEPTH_8U, 1 );//グレースケール画像用IplImage IplImage *binaryImage = cvCreateImage( cvGetSize(sourceImage), IPL_DEPTH_8U, 1 ); //2値画像用IplImage // BGRからグレースケールに変換する cvCvtColor( sourceImage, grayImage, CV_BGR2GRAY ); // グレースケールから2値に変換する cvThreshold( grayImage, binaryImage, levels, 255, CV_THRESH_BINARY ); /*グラフ値の取得*/ IplImage *img; img = cvCloneImage (binaryImage); //画像をコピー int bytes_per_pixel = ((img->depth & 255) / 8) * img->nChannels; // (1)画素値を順次取得 int i,j,k,t; int Hy[Y],Hx[X]; //宣言 //垂直方向の画素値 for(k = 0; k <Y /*img->height*/; k++) { Hy[k] = 0;//初期化 } if((unsigned char)img->imageData>levels){ for(j = 0;j < Y/*img->height*/; j++) { for(i = 0; i < X; i++) {Hy[j] += *(img->imageData + (img->widthStep*j) + (i*bytes_per_pixel)); } }} //水平方向の画素値 for(t = 0; t < X/*img->width*/; t++) { Hx[t]=0; //初期化 } if((unsigned char)img->imageData>levels){ for(i = 0;i < X/*img->width*/; i++) { for(j = 0;j < Y; j++) { Hx[i] = Hx[i]+h[i][j]; } }} //Hy[j]の最大値の座標を調べる int MY = Hy[0]; int my = 0; for(int j=0; j< Y-1; j++){ if(Hy[j]<Hy[j+1]){ MY = Hy[j+1]; my = j+1; } } //Hx[i]の最大値の座標を調べる int MX = Hx[0]; int mx = 0; for(int i=0; i< X-1; i++){ if(Hx[i]<Hx[i+1]){ MX = Hx[i+1]; mx = i+1; } } printf("垂直方向の最大値 %d , 垂直方向の最大値になるときのy軸の値 %d \n", MY,my); printf("水平方向の最大値 %d , 水平方向の最大値になるときのx軸の値 %d \n", MX,mx); int cvWaitKey(int delay=10); //どこでとめるかをあらわす cvReleaseImage( &sourceImage ); cvReleaseImage( &grayImage ); cvReleaseImage( &binaryImage ); cvDestroyWindow( windowNameBinarization); return 0 ; }

  • OpenCVで32bit ヘッダ無しRaw画像表示

    OpenCVのIPLimage構造体にヘッダ無しRaw画像を読み込んで表示させたいのですが、OpenCVではヘッダ無しRaw画像を直接読み込む関数がないため(cvLoadImageは対応せず)自作しなければいけません。まだCプログラムを勉強し始めたばかりなのでなかなか上手くいかなくて困っております。どなたか教えていただけませんか?ここまで作っみました。コンパイルはできますが、原画像どおり表示してくれません。扱う画像はレントゲン画像で512*512 32bit実数データです。 #include <cv.h> #include <highgui.h> #include <stdio.h> #include <string.h> #include <math.h> #include <stdlib.h> int main(int argc, char *argv[]) { char infile[512]; /* (1) */ float *inputimg; /* (3) */ int i, j; int mszx, mszy; FILE *fp; IplImage* img; strcpy(infile,argv[1]); mszx = atoi(argv[2]); mszy = atoi(argv[3]); static const char* title="display"; inputimg = (float*)malloc(mszx*mszy*sizeof(float)); if((fp=fopen(infile,"rb")) == NULL) { printf("OPEN FAILED %s\n",infile); exit(0); } fread(inputimg, sizeof(float), mszx*mszy, fp); fclose(fp); img = cvCreateImage(cvSize(512,512),IPL_DEPTH_32F,1); cvSetZero(img); for (j = 0; j < mszy; j++) { for (i = 0; i < mszx; i++){ img->imageData[mszx * j + i] = inputimg[mszx * j + i]; } } cvNamedWindow(title,CV_WINDOW_AUTOSIZE); cvShowImage(title,img); cvWaitKey(0); cvDestroyWindow(title); cvReleaseImage(&img); return 0; } ここまでしかできませんでした。