プロが教える店舗&オフィスのセキュリティ対策術

プログラミング初心者の者です。
今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;
intg_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;


}

A 回答 (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;のようなループカウンタによく使われる変数をグローバルで宣言するのは大変危険です。
    • good
    • 0
この回答へのお礼

詳細な回答ありがとうございます!
お礼、お返事が遅れたことを深くお詫びします。
申し訳ありません。

確かにCV _GET …の記述が抜けてました。
メモリの解放も訳もわからず色々なところに書いていたので、ご指摘の部分を消しました。
それでもやはり同じ文言のバグが消えないです。

輪郭抽出自体や画像表示、ガウスフィルタなどは問題なく動作するんですが。
どこかもっと違うところに問題があるのでしょうか…。

お礼日時:2012/07/12 10:45

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!