#ifdef _DEBUG //Debugモードの場合 #pragma comment(lib,"C:\\OpenCV2.0\\build\\lib\\debug\\cv200d.lib") #pragma comment(lib,"C:\\OpenCV2.0\\build\\lib\\debug\\cxcore200d.lib") #pragma comment(lib,"C:\\OpenCV2.0\\build\\lib\\debug\\cvaux200d.lib") #pragma comment(lib,"C:\\OpenCV2.0\\build\\lib\\debug\\highgui200d.lib") #else //Releaseモードの場合 #pragma comment(lib,"C:\\OpenCV2.0\\build\\lib\\release\\cv200.lib") #pragma comment(lib,"C:\\OpenCV2.0\\build\\lib\\release\\cxcore200.lib") #pragma comment(lib,"C:\\OpenCV2.0\\build\\lib\\release\\cvaux200.lib") #pragma comment(lib,"C:\\OpenCV2.0\\build\\lib\\release\\highgui200.lib") #endif #include "cv.h" #include "highgui.h" #include "cxcore.h" #include "cvaux.h" #include #include #include //#include //#include //#include //#include using namespace std; using namespace cv; #define CAPTURE_WIDTH 640 // カメラの横幅の設定 #define CAPTURE_HEIGHT 480 // カメラの高さの設定 #define CAPTURE_FRAMERATE 30 // カメラのフレームレートの設定 #define Mark_Size 800 //マークのサイズを設定することで微小なものを検出しないようにする(この大きさ以上のピクセル数のものを検出対象とする) // Binary_Displayが1なら2値化画像の表示を行う,0なら表示しない #define Binary_Display 0 // VSが2005か2008か選択する(選択は2005と2008のみ) #define VS 2008 #if (VS==2005) #pragma comment(lib,".\\Header&Library\\VS2005\\videoInput.lib") //ライブラリ読み込み(videoInput Library関連) #include ".\\Header&Library\\VS2005\\videoInput.h" //ヘッダインクルード(videoInput Library関連) #endif #if (VS==2008) #pragma comment(lib,".\\Header&Library\\VS2008\\videoInput.lib") //ライブラリ読み込み(videoInput Library関連) #include ".\\Header&Library\\VS2008\\videoInput.h" //ヘッダインクルード(videoInput Library関連) #endif //--------------------------------------------------------------// // マーク認識用閾値 // // 黄色のマーク閾値設定 #define Yellow_Ymin 55//89 #define Yellow_Ymax 248//207 #define Yellow_Umin 128//130 #define Yellow_Umax 145//170 #define Yellow_Vmin 59//25 #define Yellow_Vmax 98//87 // 赤色のマークの閾値設定 #define Red_Ymin 66//81 #define Red_Ymax 141//168 #define Red_Umin 155//161 #define Red_Umax 182//204 #define Red_Vmin 104//86 #define Red_Vmax 133//127 // 青色のマーク閾値設定 #define Blue_Ymin 38//62 #define Blue_Ymax 133//146 #define Blue_Umin 91//91 #define Blue_Umax 129//123 #define Blue_Vmin 131//145 #define Blue_Vmax 200//200 // 緑色のマーク閾値設定 #define Green_Ymin 47//68 #define Green_Ymax 76//128 #define Green_Umin 103//96 #define Green_Umax 122//127 #define Green_Vmin 108//97 #define Green_Vmax 127//133 // マーク認識用閾値 // //--------------------------------------------------------------// //--------------------------------------------------------------// // マウスコントロール用設定 // #define kp 1 //動きの大きさ #define noise_fileter 1 //カメラによる重心位置のばらつきの範囲を指定する #define mouse_click_on 120 //この距離離れたらクリックとみなす #define mouse_click_off 90 //この距離戻ったら再びクリック判定を可能にする // マウスコントロール用設定 // //--------------------------------------------------------------// int main(int argc, char** argv) { // webカメラを使うための初期設定 int device1=0; videoInput VI; //videoInputオブジェクト int numDevices = VI.listDevices(); //利用可能なキャプチャデバイス数を取得 if(numDevices == 0) { //キャプチャデバイスが見つからなかったら終了 cerr << "[Error] Capture device not found!!" << endl; exit(-1); } VI.setIdealFramerate(device1, CAPTURE_FRAMERATE); //フレームレート設定 VI.setupDevice(device1, CAPTURE_WIDTH, CAPTURE_HEIGHT); //デバイス初期化(ここではデバイスID = 0,CAPTURE_WIDTH x CAPTURE_HEIGHTでキャプチャ) //// webカメラを使うための初期設定 // 画像容量の確保 IplImage *frame = cvCreateImage( cvSize(CAPTURE_WIDTH,CAPTURE_HEIGHT), IPL_DEPTH_8U, 3 ); // カメラキャプチャ用 IplImage *result = cvCreateImage( cvSize(CAPTURE_WIDTH,CAPTURE_HEIGHT), IPL_DEPTH_8U, 3 ); // 結果出力用 IplImage *ycrcb = cvCreateImage( cvSize(CAPTURE_WIDTH,CAPTURE_HEIGHT), IPL_DEPTH_8U, 3 ); // YUV画像用 IplImage *binary[4]; // 二値化画像用 IplImage *tmp_img[4]; // 輪郭検出用 CvMemStorage *storage[4]; // 輪郭情報を保存するためのメモリ CvContourScanner scanner[4]; // 輪郭走査の状態を保持するためのメモリ CvSeq *contours[4]; // 輪郭の一つの情報を格納しておくためのメモリ CvMoments moments[4]; // 画像特徴量を記録するためのメモリ for(int i=0;i<4;i++) { binary[i] = cvCreateImage( cvSize(CAPTURE_WIDTH,CAPTURE_HEIGHT), IPL_DEPTH_8U, 1 ); tmp_img[i] = cvCreateImage( cvSize(CAPTURE_WIDTH,CAPTURE_HEIGHT), IPL_DEPTH_8U, 1 ); storage[i] = cvCreateMemStorage(0); } //// 画像容量の確保 double object_x[4], object_y[4], object_pix[4]; // オブジェクトを走査するときに使用する double answer_x[4], answer_y[4], answer_pix[4]; // 一番大きいオブジェクトのデータを入れるために使用するる bool mark_flag = false; // マークが検出されていればtrue , 検出されなければfalse int key; // キー入力用の変数 // キャプチャした画像を表示するウィンドウの名前の設定 char windowNameCapture[] = "Capture"; char windowNameResult[] = "Result"; #if Binary_Display char windowNameYellow[] = "Yellow"; char windowNameRed[] = "Red"; char windowNameBlue[] = "Blue"; char windowNameGreen[] = "Green"; #endif //// キャプチャした画像を表示するウィンドウの名前の設定 // キャプチャした画像を表示するウィンドウを生成する cvNamedWindow( windowNameCapture, CV_WINDOW_AUTOSIZE ); cvNamedWindow( windowNameResult , CV_WINDOW_AUTOSIZE ); #if Binary_Display cvNamedWindow( windowNameYellow, CV_WINDOW_AUTOSIZE ); cvNamedWindow( windowNameRed , CV_WINDOW_AUTOSIZE ); cvNamedWindow( windowNameBlue , CV_WINDOW_AUTOSIZE ); cvNamedWindow( windowNameGreen , CV_WINDOW_AUTOSIZE ); #endif //// キャプチャした画像を表示するウィンドウを生成する // 画像座標系を左下原点に設定(OpenCV for Windowsのバグ回避用) frame->origin = 1; result->origin = frame->origin; ycrcb->origin = frame->origin; binary[0]->origin = frame->origin; binary[1]->origin = frame->origin; binary[2]->origin = frame->origin; binary[3]->origin = frame->origin; // ラインのカラーリング設定 CvScalar Line_Color[4]; Line_Color[0] = CV_RGB(255,255, 0); //黄色 Line_Color[1] = CV_RGB(255, 0, 0); //赤色 Line_Color[2] = CV_RGB( 0, 0,255); //青色 Line_Color[3] = CV_RGB( 0,255, 0); //緑色 //マウス・キーボード制御に必要な設定 // INPUT mouse_input[] = {{INPUT_MOUSE,0,0,0,MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE,0,0}}; INPUT mouse_input[] = {{INPUT_MOUSE,0,0,0,MOUSEEVENTF_MOVE,0,0}}; double answer_old_x[4]={0,0,0,0},answer_old_y[4]={0,0,0,0}; bool mouse_click_flag=false; bool mouse_right_click_flag=false; // メインループ while(1) { // カメラからの入力画像をframeに格納する memcpy(frame->imageData, VI.getPixels(device1, false), CAPTURE_WIDTH*CAPTURE_HEIGHT*3); // 処理結果用に画像のコピーを行う cvCopy(frame,result,0); // YUV画像に変換 cvCvtColor( frame, ycrcb, CV_BGR2YCrCb ); // 各色の閾値で二値化を行う cvInRangeS( ycrcb, cvScalar( Yellow_Ymin, Yellow_Umin, Yellow_Vmin ), cvScalar( Yellow_Ymax, Yellow_Umax, Yellow_Vmax ), binary[0] ); cvInRangeS( ycrcb, cvScalar( Red_Ymin, Red_Umin, Red_Vmin ), cvScalar( Red_Ymax, Red_Umax, Red_Vmax ), binary[1] ); cvInRangeS( ycrcb, cvScalar( Blue_Ymin, Blue_Umin, Blue_Vmin ), cvScalar( Blue_Ymax, Blue_Umax, Blue_Vmax ), binary[2] ); cvInRangeS( ycrcb, cvScalar( Green_Ymin, Green_Umin, Green_Vmin ), cvScalar( Green_Ymax, Green_Umax, Green_Vmax ), binary[3] ); for(int i=0;i<4;i++) { // 膨張・収縮(ノイズ除去のため???) cvDilate( binary[i], binary[i], NULL, 2 ); // 膨張 cvErode( binary[i], binary[i], NULL, 3 ); // 収縮 //輪郭の走査処理のための画像をコピーする cvCopy(binary[i],tmp_img[i],0); //輪郭の走査処理の初期化 scanner[i] = cvStartFindContours(tmp_img[i], storage[i], sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_NONE, cvPoint(0,0)); //初期化 answer_x[i] = 0.f; answer_y[i] = 0.f; answer_pix[i] = 0.f; // 輪郭が残っている間ループ while((contours[i] = cvFindNextContour(scanner[i]))!=0) { // 1つの輪郭に対して重心を求める cvMoments(contours[i], &moments[i]); // 重心座標を算出する object_x[i] = (cvGetSpatialMoment(&moments[i], 1, 0) / cvGetSpatialMoment(&moments[i], 0, 0)); object_y[i] = (cvGetSpatialMoment(&moments[i], 0, 1) / cvGetSpatialMoment(&moments[i], 0, 0)); // 計算エラーの場合はデータ破棄 if(_finite(object_x[i])==0 || _finite(object_y[i])==0) continue; // 検出物のpix数を計算 object_pix[i] = cvGetSpatialMoment(&moments[i], 0, 0); // 一番大きいものをボールとする if( object_pix[i] > answer_pix[i] ) { // 検出物の方が大きい場合 answer_x[i] = object_x[i]; answer_y[i] = object_y[i]; answer_pix[i] = object_pix[i]; } } // 輪郭の走査処理を終了 cvEndFindContours(&scanner[i]); } // マークのあるところに十字線と円を引く for(int i=0;i<4;i++) { if(answer_pix[i] > Mark_Size) { cvLine(result, cvPoint( 0, (int)(answer_y[i]+0.5f) ), cvPoint( cvGetSize(frame).width, (int)(answer_y[i]+0.5f) ), Line_Color[i], 1, 8 ); cvLine(result, cvPoint( (int)(answer_x[i]+0.5f), 0 ), cvPoint( (int)(answer_x[i]+0.5f), cvGetSize(frame).height ), Line_Color[i], 1, 8 ); // cvCircle(result,cvPoint( (int)(answer_x[i]+0.5f), (int)(answer_y[i]+0.5f) ), 10, Line_Color[i],CV_AA,0); } } //マウスコントロール関係 if(answer_pix[0] > Mark_Size){ if(answer_pix[1] > Mark_Size) { //色1はクリックポインタとする(ベースポインタからの距離でクリックを検知する) if(sqrt((answer_x[1] - answer_x[0]) * (answer_x[1] - answer_x[0]) + (answer_y[1] - answer_y[0]) * (answer_y[1] - answer_y[0])) >= mouse_click_on) { if(mouse_click_flag == false) { mouse_click_flag = true; mouse_input[0].mi.dwFlags = MOUSEEVENTF_LEFTDOWN; ::SendInput(1, mouse_input, sizeof(INPUT)); Sleep(10); mouse_input[0].mi.dwFlags = MOUSEEVENTF_LEFTUP; ::SendInput(1, mouse_input, sizeof(INPUT)); mouse_input[0].mi.dwFlags = MOUSEEVENTF_MOVE; } } if(sqrt((answer_x[1] - answer_x[0]) * (answer_x[1] - answer_x[0]) + (answer_y[1] - answer_y[0]) * (answer_y[1] - answer_y[0])) <= mouse_click_off) { mouse_click_flag = false; } } if(answer_pix[2] > Mark_Size) { //色2は右クリックポインタとする(ベースポインタからの距離で右クリックを検知する) if(sqrt((answer_x[2] - answer_x[0]) * (answer_x[2] - answer_x[0]) + (answer_y[2] - answer_y[0]) * (answer_y[2] - answer_y[0])) >= mouse_click_on) { if(mouse_right_click_flag == false) { mouse_right_click_flag = true; mouse_input[0].mi.dwFlags = MOUSEEVENTF_RIGHTDOWN; ::SendInput(1, mouse_input, sizeof(INPUT)); Sleep(10); mouse_input[0].mi.dwFlags = MOUSEEVENTF_RIGHTUP; ::SendInput(1, mouse_input, sizeof(INPUT)); mouse_input[0].mi.dwFlags = MOUSEEVENTF_MOVE; } } if(sqrt((answer_x[2] - answer_x[0]) * (answer_x[2] - answer_x[0]) + (answer_y[2] - answer_y[0]) * (answer_y[2] - answer_y[0])) <= mouse_click_off) { mouse_right_click_flag = false; } } //色3が表示されている時はポインタの移動を停止する if(answer_pix[3] > Mark_Size) { }else{ //色0をベースポインタとする(移動を検知する) if(abs(answer_x[0] - answer_old_x[0]) >= noise_fileter || abs(answer_y[0] - answer_old_y[0]) >= noise_fileter) { // mouse_input[0].mi.dx = (answer_x[0]-answer_old_x[0])*kp / CAPTURE_WIDTH * 65535; // mouse_input[0].mi.dy = (CAPTURE_HEIGHT - (answer_old_y[0] -answer_y[0])*kp) / CAPTURE_HEIGHT * 65535; mouse_input[0].mi.dx = (answer_old_x[0] - answer_x[0])*kp / CAPTURE_WIDTH * ::GetSystemMetrics(SM_CXSCREEN); mouse_input[0].mi.dy = ((CAPTURE_HEIGHT - answer_old_y[0]) - (CAPTURE_HEIGHT - answer_y[0]))*kp / CAPTURE_HEIGHT * ::GetSystemMetrics(SM_CXSCREEN); ::SendInput(1, mouse_input, sizeof(INPUT)); }else { mouse_input[0].mi.dx = 0; mouse_input[0].mi.dy = 0; } } answer_old_x[0] = answer_x[0]; answer_old_y[0] = answer_y[0]; } ////マウスコントロール関係 // 画像を表示する cvShowImage( windowNameCapture, frame ); cvShowImage( windowNameResult , result ); #if Binary_Display cvShowImage( windowNameYellow, binary[0]); cvShowImage( windowNameRed , binary[1]); cvShowImage( windowNameBlue , binary[2]); cvShowImage( windowNameGreen , binary[3]); #endif // 'Esc'キー(Code:27)が入力されたらループを抜ける key = cvWaitKey( 1 ); if ( key == 27 ) break; } // キャプチャを解放する VI.stopDevice(device1); // 画像格納用のメモリを解放する cvReleaseImage( &frame ); cvReleaseImage( &ycrcb ); for(int i=0;i<4;i++) { cvReleaseImage( &binary[i] ); cvReleaseImage( &tmp_img[i] ); cvReleaseMemStorage( &storage[i] ); } // ウィンドウを破棄する cvDestroyWindow( windowNameCapture ); cvDestroyWindow( windowNameResult ); #if Binary_Display cvDestroyWindow( windowNameYellow ); cvDestroyWindow( windowNameRed ); cvDestroyWindow( windowNameBlue ); cvDestroyWindow( windowNameGreen ); #endif return 0; }