C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[1]: マルチスレッドが上手く働かない


(過去ログ 70 を表示中)

[トピック内 2 記事 (1 - 2 表示)]  << 0 >>

■40673 / inTopicNo.1)  マルチスレッドが上手く働かない
  
□投稿者/ だだだ (1回)-(2009/09/01(Tue) 00:15:46)

分類:[C/C++] 

プログラミングを始めて1年程の初心者の質問です。
VisualC++2008でC++言語で開発しています。
現在、ARToolKitとOpenCVとを組み合わせたプログラムを作っています。
それは動くようになり(問題点も多々あるでしょうが)良かったのですが、
それと同時に加速度センサーのプログラムも動かして、その情報を使いたいと
考えております。
その方法として、マルチスレッドを採用することにしました。
そして、作ってみたのはいいのですが、何故かargMainLoopの関数に到達した
時点でプログラムが止まって(こちらの方のスレッドだけが止まり、もう一つのwii関数の中は動く)
しまいます。単純なマルチスレッドのプログラム等を書いたりインターネットで調べたりして、
自分なりには考えてみたのですが、完全につまづいてしまいましたので、質問が悪いかとは思いますが、
どなたかご回答、もしくはヒントを頂けないでしょうか?


#include<windows.h> //windowsプログラムの際付けることがある
#include<stdio.h>
#include<process.h>

#include<GL/gl.h>  //OpenGLのヘッダファイルを読み込む
#include<Gl/glu.h>
#include<GL/glut.h>

#include<AR/ar.h> //ARToolKitのヘッダファイルを読み込む
#include<AR/param.h>
#include<AR/video.h>
#include<AR/gsub.h>

#include<cv.h>
#include<highgui.h>

//グローバル変数
char *vconf_name="Data/WDM_camera_flipV.xml";  //ビデオデバイスの設定
char *cparam_name="Data/camera_para.dat";  //カメラパラメータファイル
char *patt_name="Data/patt.elenew";  //パターンファイル


int patt_id; //パターンID
double patt_trans[3][4];  //座標変換行列
double patt_center[2]={0.0, 0.0};  //パターン中心座標
double patt_width=80.0;  //パターンのサイズ
int thresh=100;  //二値化の閾値

//プロトタイプ宣言
void MainLoop(void);
void KeyEvent(unsigned char key, int x, int y);
void MouseEvent(int button, int state, int x, int y);
void Cleanup(void);
void DrawObject(void);

void wii(LPVOID	pParam); //つけた!!!!
void func(LPVOID	pParam); //つけた!!!

//マクロ・大域変数等の設定
#define Page 5  //最大ページ数
IplImage *sourceImage;  //現在の画像を格納する
IplImage *sourceImages[Page+1];  //全ての画像を個々に格納する配列
int page;  //現在のページ数
IplImage *TransImage;  //平行移動後の画像を格納する
IplImage *ScaleImage;  //拡大後の画像を格納する


	int opencv(double x, double y, double z){
	//中身は省略
	return 0;
}



int main(int argc, char **argv){  //引数はコマンドライン
	ARParam cparam;  //カメラパラメータ
	ARParam wparam;  //カメラパラメータ(作業用変数)
	int xsize,ysize;  //画像サイズ

	//HANDLE hThread[2];


	glutInit(&argc, argv);  //GLUTの初期化

	if(arVideoOpen(vconf_name)<0){  //ビデオデバイスの設定
		printf("video devise error!");
		return -1;  //プログラムの終了
	}


	//計算に用いるパラメータをグローバル変数で内部管理している。ファイルから値を読み込んで
	//内部の変数にセットする必要があるが、ファイルを読み込んだ後、カメラ画像の解像度に合わせて
	//変更してからセットをしなければならない。よって次の4ステップを踏む。

	if(arVideoInqSize(&xsize, &ysize)<0) return -1;  //画像サイズの習得

	if(arParamLoad(cparam_name, 1, &wparam)<0){  //カメラパラメータファイルのロード
		printf("miss reading camera parameta");
		return -1;
	}

	arParamChangeSize(&wparam, xsize, ysize, &cparam);  //画像サイズに合わせてカメラパラメータを変更
	arInitCparam(&cparam);  //カメラパラメータをセット

	if( (patt_id=arLoadPatt(patt_name))<0 ){  //パターンファイルのロード(パターンごとにIDを割り当てる)
		printf("miss reading patten file");
		return -1;
	}

	//画像の読み込み(ページごとに)
	sourceImages[0] = cvLoadImage("img0.jpg", CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);
	sourceImages[1] = cvLoadImage("img1.jpg", CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);
	sourceImages[2] = cvLoadImage("img2.jpg", CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);
	sourceImages[3] = cvLoadImage("img3.jpg", CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);
	sourceImages[4] = cvLoadImage("img4.jpg", CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);
	sourceImages[5] = cvLoadImage("img5.jpg", CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);
	sourceImages[6] = cvLoadImage("img6.jpg", CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR);
	int jj;
	for(jj=0; jj<=Page+1; jj++){
		if(sourceImages[jj]==NULL){
			puts("画像が読み込めませんでした");
			return -1;
		}
	}

	sourceImage = sourceImages[page];  //初期画像の選択 


	argInit(&cparam, 1.0, 0, 0, 0, 0);  //ウインドウの設定(3つ目の引数はフルスクリーンモード1(On)0(Off))
	                                    //フルスクリーンモードにする場合は、二つ目の引数の拡大率も変更しないといけない

	arVideoCapStart();  //ビデオキャプチャーの開始


	cvNamedWindow("ScaleChange", CV_WINDOW_AUTOSIZE);

	//!!!!!!!!!!!!!!!!!!!!マルチスレッドの開始!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

	HANDLE hThread[2];
	hThread[0] = (HANDLE)_beginthread(func,0,NULL);	//スレッド1作成
	hThread[1] = (HANDLE)_beginthread(wii,0,NULL);	//スレッド2作成


	//スレッド1、2終了待ち
	WaitForMultipleObjects(2,hThread,TRUE,INFINITE);  //どういう意味??

	//ハンドルクローズ
	CloseHandle(hThread[0]);
	CloseHandle(hThread[1]);
	
	
	//argMainLoop(MouseEvent, KeyEvent, MainLoop);  //メインループの開始(マウス入力・キーボード入力・メインループ関数)



	return 0;
}


void wii(LPVOID	pParam){
	while(1){
		Sleep(100);
		puts("aaa");
	}
}

void func(LPVOID	pParam){
	argMainLoop(MouseEvent, KeyEvent, MainLoop);  //メインループの開始(マウス入力・キーボード入力・メインループ関数)
}

void MainLoop(void){
	ARUint8 *image;
	ARMarkerInfo *marker_info;
	int marker_num;
	int j,k;

	if( (image=(ARUint8 *)arVideoGetImage()) ==NULL){  //カメラ画像の習得
		arUtilSleep(2);  //失敗したら(画像の準備ができていなければ)少し待って
		return;  //mainループ最初から(一度抜ける)
	}

	//カメラ画像の描写(レンズの歪みの補正も行うため、次の2ステップが必要)
	argDrawMode2D();  //2次元画像を描写するための準備
	argDispImage(image, 0, 0);  //画像を描写


	//marker_infoについて
	//area(マーカ領域の画素数=面積) id(パターンID) dir(方向1〜3のいずれか)
	//cf(信頼度) pos[2](マーカーの中心座標) line[4][3](直線の式(ax+by+c=0)*4辺)
	//vertex[4][2](頂点座標(x,y)*4辺)

	if(arDetectMarker(image, thresh, &marker_info, &marker_num)<0){  //マーカーの検出と認識
		Cleanup();
		exit(0);  //変ならプログラム終了
	}

	arVideoCapNext();  //次の画像のキャプチャー指示(画像の描写とマーカ検出が終われば指令を出さないといけない)

	//マーカーの一致度の比較(自分で書く!!)
	k=-1;
	for(j=0;j<marker_num;j++){
		if(patt_id==marker_info[j].id){
			if(k==-1) k=j;
			else if(marker_info[k].cf<marker_info[j].cf) k=j;
		}
	}


	//マーカーを近づけすぎると急に値が飛ぶ!!
	if(k!=-1){   // マーカー情報ポインタ、マーカーの原点位置、マーカーサイズ(mm)、マーカー・カメラ間の座標変換行列
		arGetTransMat(&marker_info[k], patt_center, patt_width, patt_trans);

		printf("距離:%f\n", patt_trans[2][3]);  //マーカーとの距離を表示
		printf("x:%f   y:%f\n", patt_trans[0][3], patt_trans[1][3]);  //縦・横を表示


		//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
		if(100<patt_trans[2][3] && patt_trans[2][3]<1000 && -300<patt_trans[0][3] && patt_trans[0][3]<300 && -200<patt_trans[1][3] && patt_trans[1][3]<200)
			opencv(patt_trans[0][3], patt_trans[1][3], patt_trans[2][3]);
		

	

		DrawObject();  //3Dオブジェクトの描写

	}

		argSwapBuffers();  //バッファの内容を画面に表示(ダブルバッファの考え方で、表と裏画像を交換する)
}


void DrawObject(void){  //3Dオブジェクトの描写を行う関数
	double gl_para[16];

	argDrawMode3D();
	argDraw3dCamera(0,0);

	argConvGlpara(patt_trans, gl_para);
	glMatrixMode(GL_MODELVIEW);
	glLoadMatrixd(gl_para);

	glTranslatef(0.0, 0.0, 20.0);
	glColor3f(0.0, 1.0, 0.0);
	glLineWidth(3.0);
	glutWireCube(40.0);
}


void KeyEvent(unsigned char key, int x, int y){  //キーボード入力処理関数
	if(key==0x1b){
		Cleanup();
		exit(0);
	}

	else if(key==0x09){
		if(--page<0)
			exit(0);

		puts("前の画像を表示します");
		sourceImage = sourceImages[page];  //注目画像の変更 
		argMainLoop(MouseEvent, KeyEvent, MainLoop); 
	}

	else if(key==0x20){
		if(++page>Page)
			exit(0);

		puts("次の画像を表示します");
		sourceImage = sourceImages[page];  //注目画像の変更
		argMainLoop(MouseEvent, KeyEvent, MainLoop); 
	}

}


void MouseEvent(int button, int state, int x, int y){  //マウス入力処理関数
	printf("button:%d, statement:%d, zahyou:(x,y)=(%d, %d)\n", button, state, x, y);
}


void Cleanup(void){  //終了処理関数
	arVideoCapStop();
	arVideoClose();
	argCleanup();
	cvReleaseImage(&sourceImage);
	cvReleaseImage(sourceImages);  //配列の先頭ポインタを渡して開放すればよい!
	cvReleaseImage(&TransImage);
	cvReleaseImage(&ScaleImage);
	cvDestroyWindow("ScaleChange");
}

引用返信 編集キー/
■40676 / inTopicNo.2)  Re[1]: マルチスレッドが上手く働かない
□投稿者/ れい (854回)-(2009/09/01(Tue) 03:04:47)
No40673 (だだだ さん) に返信
> そして、作ってみたのはいいのですが、何故かargMainLoopの関数に到達した
> 時点でプログラムが止まって(こちらの方のスレッドだけが止まり、もう一つのwii関数の中は動く)
> しまいます。

とりあえず、argMainLoopの使い方を間違っているように見えます。
argMainLoopは内部でglutMainLoopを呼んでいて、これは戻りません。

なので、KeyEventの中で呼んだらおかしなことになります。
最良でもスタックオーバーフローです。

「到達した時点」というのはあいまいですが、
おそらくargMainLoopから戻ってこないということを言っているのかと思います。

上記のように、それは「仕様」です。
スレッドの前に、ARToolKitの中身を少し眺めたほうがよいかと。

引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -