• 締切済み

OpenCV輪郭抽出→座標取得でのバグ(C++)

プログラミング初心者の者です。 今OpenCVを色々勉強してるのですが、全く行き詰ってしまいました。 サンプルを打ち込んだりして、輪郭抽出、表示まではできましたが、それに加えて座標の取得、表示の部分を書いてみたんですが、バグが一向に取れません。 OpenCV2.4.1 Visual Studio2010ExpressC++でやっています。 0x00411845 でハンドルされていない例外が発生しました: 0xC0000005: 場所 0x00000004 を読み込み中にアクセス違反が発生しました。 という内容が表示されます。 以下のようなコードを書きました。 おかしいところもたくさんあると思いますが、何卒ご教示頂ければと思います。 using namespace cv; using namespace std; int i; IplImage *g_image = NULL; IplImage *g_gray = NULL; IplImage *src_img = NULL; IplImage *tmp_img = NULL; int g_thresh = 100;//閾値 CvMemStorage *g_storage = NULL;//データ格納用低レベル構造体 CvFileStorage *fs;//ファイルストレッジ CvTreeNodeIterator it;//イテレータ CvPoint *point,*tmp; void on_trackbar(int){ if( g_storage == NULL ){ g_gray = cvCreateImage( cvGetSize( g_image ), 8, 1 ); g_storage = cvCreateMemStorage(0); } else { cvClearMemStorage( g_storage ); } CvSeq* contours = 0; cvCvtColor( g_image, g_gray, CV_BGR2GRAY ); cvThreshold( g_gray, g_gray, g_thresh, 255, CV_THRESH_BINARY ); cvFindContours( g_gray, g_storage, &contours,sizeof(CvContour ),CV_RETR_TREE,CV_CHAIN_APPROX_NONE); //輪郭抽出 (入力画像、保存先、一番外の輪郭、サイズ、  ) 抽出モード cvZero( g_gray ); if( contours ){ cvDrawContours( g_gray, contours, cvScalarAll(255), cvScalarAll(255), 100 ); } cvInitTreeNodeIterator (&it, contours,1); fs=cvOpenFileStorage("Contours.xml",NULL,CV_STORAGE_WRITE); //輪郭線上を走査 while((contours=(CvSeq*)cvNextTreeNode(&it))!=NULL){ cvClearMemStorage( g_storage ); cvStartWriteStruct(fs,"Contours",CV_NODE_SEQ); for (i=0;i<contours->total;i++){ point=CV_GET_SEQ_ELEM(CvPoint,contours,i); cvLine(g_gray,*tmp,*point,CV_RGB(0,0,255),2); cvStartWriteStruct(fs,NULL,CV_NODE_MAP); cvWriteInt(fs,"x",point->x); cvWriteInt(fs,"y",point->y); //座標取得 cvEndWriteStruct(fs); tmp=point; } cvEndWriteStruct(fs); cvReleaseFileStorage(&fs); } cvShowImage( "Contours", g_gray ); } int _tmain(int argc, _TCHAR* argv[]){ g_image = cvLoadImage( "C:\\OpenCV2.4.1\\opencv\\samples\\c\\lena.jpg" ); //入力画像       cvNamedWindow( "Contours", 1 ); cvCreateTrackbar( "Threshold", "Contours", &g_thresh, 255, on_trackbar ); on_trackbar(0); cvWaitKey(); return 0; }

みんなの回答

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.1

中身は、ほぼ http://opencv.jp/sample/tree.html#contour_treenode の通りですよね? 差分を見ていくと > while((contours=(CvSeq*)cvNextTreeNode(&it))!=NULL){ > cvClearMemStorage( g_storage ); > cvStartWriteStruct(fs,"Contours",CV_NODE_SEQ); ここcvClearMemStroge があるのは変じゃないですか? g_storageは抽出した輪郭を記憶するために用意したはずです。その内容を消してしまってから、輪郭情報を取り出すことになりませんか? また、サンプルコードにある > tmp = CV_GET_SEQ_ELEM (CvPoint, contour, -1); がありません。このため、一番最初のtmpは初期値(グローバル変数として定義されているのでNULL)ですから、cvLineがうまく動作しないはずです。 cvDrawContoursがあるので、cvLine(そしてtmp)自体を使わない、という方法もあります あと、今回は直接の影響はありませんが、グローバル変数を使いすぎ。 少なくとも nt i; CvFileStorage *fs;//ファイルストレッジ CvTreeNodeIterator it;//イテレータ CvPoint *point,*tmp; これらは、 on_trackbar関数の中だけで完結している変数です。 特に、int i;のようなループカウンタによく使われる変数をグローバルで宣言するのは大変危険です。

mayone-zunameo
質問者

お礼

詳細な回答ありがとうございます! お礼、お返事が遅れたことを深くお詫びします。 申し訳ありません。 確かにCV _GET …の記述が抜けてました。 メモリの解放も訳もわからず色々なところに書いていたので、ご指摘の部分を消しました。 それでもやはり同じ文言のバグが消えないです。 輪郭抽出自体や画像表示、ガウスフィルタなどは問題なく動作するんですが。 どこかもっと違うところに問題があるのでしょうか…。

すると、全ての回答が全文表示されます。

関連するQ&A