じゃんけんのコード

以下の流れで判定している。
  1. 肌色検出 トラックバーによる調整
  2. モロフォロジー演算
  3. 2値化
  4. ラベリング
  5. 手の輪郭の凹状欠損
  6. 楕円のフィッティングによる指の検出
  7. COMポート出力
使っているライブラリ関数の説明。COMポート出力以外はOpenCVの関数
COMポートの入出力は、全てWin32API関数。CreateFile,GetCommState,SetCommState,ReadFile,WriteFile,CloseHandle
cvConvexHull2 手の輪郭の凹状欠損
cvGetReal2D 
cvFitEllipse2 楕円のフィッティング

ユーザ定義の関数

※詳しくはリンクを参照

作者の意図

  • 緑の枠
緑の枠drawConvexHullユーザ関数で大きすぎたり、小さすぎると判定しないようにしている。
  • 動作の順番
キャプチャー→肌色検出・2値化→欠陥領域の修正→ラベリング→最大領域の抽出(手の面積)→緑の枠を生成・描画・枠内の面積を求める
→指の本数を求める→ジャンケンの判定を行う→メモリを開放→終了
  • 判定の順番
枠内の面積→枠内の白い部分の面積→枠内の白と黒の割合→指の本数

名前:
コメント:
「今日の訪問数: -
「昨日の訪問数: -
「今までの訪問数: -
#include "rockpaperscissors.h"
#include <windows.h>
#include "submit.h"
 
void Ellipse(IplImage * sabunn_img);
char windowNameCapture[] = "Capture"; //      キャプチャした画像を表示するウィンドウの名前
char windowNameSkin[] = "Skin";	//      肌色抽出画像を表示するウィンドウの名前
char windowNameConvexHull[] = "ConvexHull";   //      ConnvexHull画像を表示するウィンドウの名前
char windowNameTrack[] = "Track";	//      トラックバーの表示
char windowNameFit[] = "Fit";
int hullarea;		//      ConvexHull内の面積
int handarea;		//      手領域の面積
 
IplImage *frameImage = 0;
//最低限、ウィンドウに表示するイメージ
//      モルフォロジー
IplImage *dst_img_subunn = 0;
 
//      ellipseの処理用
IplImage *dst_img = 0;
 
//      矩形の枠の個数を格納するもの
int kukei_count = 0;
//      指の個数をカウント
int yubi_count = 0;
 
//      画像を生成する
IplImage *hsvImage;		//      HSV画像用IplImage
IplImage *convexHullImage;	//      ConvexHull画像用IplImage
IplImage *skinImage;		//      肌色抽出画像用IplImage
IplImage *temp;			//      一時保存用IplImage
IplImage *label;		//      ラベル結果保存用IplImage
int count = 1;
int hmax, hmin, smax, smin, vmax, vmin;	//h:色相 s:色彩 v:明度
static int rockmax = 100, rockmin = 80, scissormax = 80, scissormin =
    70, papermax = 70, papermin = 50;
//グー最大、グー最小,チョキ最大、チョキ最小,パー最大、パー最小の並び
 
char filename[1000];
char *path =
    "C:\\Documents and Settings\\Administrator\\My Documents\\My Pictures\\frame";
double ireko[10][2];
 
 
//
// ウィンドウを作成する
//
void createWindows()
{
    cvNamedWindow(windowNameCapture);
    cvNamedWindow(windowNameSkin);
    cvNamedWindow(windowNameConvexHull);
    cvNamedWindow(windowNameTrack);
    cvNamedWindow(windowNameFit);
}
 
//
//      肌色を抽出する
//
//      引数:
//              frameImage : キャプチャした画像用IplImage
//              hsvImage   : HSV画像用IplImage
//              skinImage  : 肌色抽出画像用IplImage
//
void extractSkinColor(IplImage * frameImage, IplImage * hsvImage,
		      IplImage * skinImage)
{
    CvScalar color;		//      HSV表色系で表した色
    unsigned char h;		//      H成分
    unsigned char s;		//      S成分
    unsigned char v;		//      V成分
 
    //      BGRからHSVに変換する
    cvCvtColor(frameImage, hsvImage, CV_BGR2HSV);
 
    //肌色抽出
    for (int x = 0; x < skinImage->width; x++) {
	for (int y = 0; y < skinImage->height; y++) {
 
	    color = cvGet2D(hsvImage, y, x);
	    h = color.val[0];
	    s = color.val[1];
	    v = color.val[2];
 
	    if (h <= hmax && h >= hmin &&
		s <= smax && s >= smin && v <= vmax && v >= vmin) {
		//      肌色の場合
		cvSetReal2D(skinImage, y, x, 255);
	    } else {
		cvSetReal2D(skinImage, y, x, 0);
	    }
	}
    }
}
 
//
//      欠損領域を補間する
//
//      引数:
//              skinImage : 肌色抽出画像用IplImage
//              temp      : 一時保存用IplImage
//
void interpolate(IplImage * skinImage, IplImage * temp)
{
    //膨張をITERATIONS回行う
    cvDilate(skinImage, temp, NULL, ITERATIONS);
 
    //収縮をITERATIONS回行う
    cvErode(temp, skinImage, NULL, ITERATIONS);
}
 
//
//      最大領域(手領域)の抽出を行う
//
//      引数:
//              skinImage       : 肌色抽出画像用IplImage
//              label           : ラベリングした結果
//              convexHullImage : ConvexHull画像用IplImage
//
//      戻り値:
//              手領域の面積
//
int pickupMaxArea(IplImage * skinImage, IplImage * label,
		  IplImage * convexHullImage)
{
 
    int handarea = 0;		//      手領域の面積
 
    for (int x = 0; x < skinImage->width; x++) {
	for (int y = skinImage->height - 1; y >= 0; y--) {
	    if (cvGetReal2D(label, y, x) == 1) {
		//      最大領域だった場合
		handarea++;
		cvSet2D(convexHullImage, y, x, CV_RGB(255, 255, 255));
	    } else {
		cvSetReal2D(skinImage, y, x, 0);
		cvSet2D(convexHullImage, y, x, CV_RGB(0, 0, 0));
	    }
	}
    }
    return handarea;
}
 
//
//      ConvexHullを生成する
//
//      引数:
//              skinImage   : 肌色抽出画像用IplImage
//              handarea    : 手領域の面積(点の数)
//              handpoint   : 手領域内の点の座標配列へのポインタ
//              hull        : ConvexHullの頂点のhandpointにおけるindex番号へのポインタ
//              pointMatrix : 手領域用行列へのポインタ
//              hullMatrix  : ConvexHull用行列へのポインタ
//
void createConvexHull(IplImage * skinImage, int handarea,
		      CvPoint ** handpoint, int **hull,
		      CvMat * pointMatrix, CvMat * hullMatrix)
{
    int i = 0;
 
    //      ConvexHullを計算するために必要な行列を生成する
    *handpoint = (CvPoint *) malloc(sizeof(CvPoint) * handarea);
    *hull = (int *) malloc(sizeof(int) * handarea);
    *pointMatrix = cvMat(1, handarea, CV_32SC2, *handpoint);
    *hullMatrix = cvMat(1, handarea, CV_32SC1, *hull);
 
    for (int x = 0; x < skinImage->width; x++) {
	for (int y = 0; y < skinImage->height; y++) {
	    if (cvGetReal2D(skinImage, y, x) == 255) {
		(*handpoint)[i].x = x;
		(*handpoint)[i].y = y;
		i++;
	    }
	}
    }
 
    //      ConvexHullを生成する
    cvConvexHull2(pointMatrix, hullMatrix, CV_CLOCKWISE, 0);
}
 
//
//      ConvexHullを描画する
//
//      引数:
//              convexHullImage : ConvexHull画像用IplImage
//              handpoint       : 手領域内の点の座標配列
//              hull            : ConvexHullの頂点のhandpointにおけるindex番号
//              hullcount       : ConvexHullの頂点の数
//
void drawConvexHull(IplImage * convexHullImage, CvPoint * handpoint,
		    int *hull, int hullcount)
{
    CvPoint pt0 = handpoint[hull[hullcount - 1]];
    for (int i = 0; i < hullcount; i++) {
	CvPoint pt = handpoint[hull[i]];
	cvLine(convexHullImage, pt0, pt, CV_RGB(0, 255, 0));
	pt0 = pt;
    }
}
 
//
//      ConvexHull内の面積を求める
//
//      引数:
//              convexHullImage : ConvexHull画像用IplImage
//              handpoint       : 手領域内の点の座標配列
//              hull            : ConvexHullの頂点のhandpointにおけるindex番号
//              hullcount       : ConvexHullの頂点の数  
//
//      戻り値:
//              ConvexHull内の面積
//
int calcConvexHullArea(IplImage * convexHullImage, CvPoint * handpoint,
		       int *hull, int hullcount)
{
 
    //      ConvexHullの頂点からなる行列を生成
    CvPoint *hullpoint = (CvPoint *) malloc(sizeof(CvPoint) * hullcount);
    CvMat hMatrix = cvMat(1, hullcount, CV_32SC2, hullpoint);
    for (int i = 0; i < hullcount; i++) {
	hullpoint[i] = handpoint[hull[i]];
    }
 
    //      ConvexHull内の点の数を数える
    int hullarea = 0;
    for (int x = 0; x < convexHullImage->width; x++) {
	for (int y = 0; y < convexHullImage->height; y++) {
	    if (cvPointPolygonTest(&hMatrix, cvPoint2D32f(x, y), 0) > 0) {
		hullarea++;
		if (count == 1)
		    cvCircle(frameImage, cvPoint(x, y), 1,
			     cvScalar(0, 0, 0), -1);
	    }
	}
    }
    count = 0;
 
    free(hullpoint);
    return hullarea;
}
 
//
//      ジャンケンの判定を行う
//
//      引数:
//              handarea : 手領域の面積
//              hullarea : ConvexHull内の面積
//
void decide(int handarea, int hullarea)
{
    double ratio;		//      ConvexHull内の面積に対する手領域の面積の割合
    //	送信用変数
    char goo='g';		
    char tyoki='t';		
    char par='p';		
    char null='n';
    //	割合判定用変数
    float rockmax1, rockmin1, scissormax1, scissormin1, papermax1, papermin1;
    //	指の距離用変数
    int mater = 0;
 
    rockmax1 = rockmax / 100.0;
    rockmin1 = rockmin / 100.0;
    scissormax1 = scissormax / 100.0;
    scissormin1 = scissormin / 100.0;
    papermax1 = papermax / 100.0;
    papermin1 = papermin / 100.0;
 
    //printf("rockmax1 = %lf\n", rockmax1);
    //printf("rockmin1 = %lf\n", rockmin1);
    //printf("scissormax1 = %lf\n", scissormax1);
    //printf("scissormin1 = %lf\n", scissormin1);
    //printf("papermax1 = %lf\n", papermax1);
    //printf("papermin1 = %lf\n", papermin1);
 
    //	割合計算
    ratio = handarea / (double) hullarea;
    //	指距離計算
    if(yubi_count==2){
	mater=(int)((ireko[yubi_count-2][0] - ireko[yubi_count-1][0]) + (ireko[yubi_count-2][1] - ireko[yubi_count-1][1]));
	if(mater<0)   mater = mater * (-1);
    }
 
    //printf("Ratio = %lf", ratio);
    //printf("hullarea:%d→ ",hullarea);
    //printf("handarea:%d→ ",handarea);
    //printf("Ratio : %lf→", ratio);
    //printf("yubi_count:%d",yubi_count);
 
    printf("--------------------------------------------------------------------------------\n");
    printf("面積の判定\n");
    printf("if((%d <= 190000 && %d >= 19000) && (%d >= 18000 && %d <= 110000))\n",hullarea,hullarea,handarea,handarea);
    if((hullarea <= 190000 && hullarea >= 19000) && (handarea >= 18000 && handarea <= 110000)){
	//	グーの判定
	if ((ratio >= rockmin1 && ratio <= rockmax1) && yubi_count == 0 ){
		printf("グー\n");
        }
	//	チョキの判定
	}else if ( yubi_count == 2 ) {
	    printf("チョキの面積\n");
    	    printf("if((%d >= 21000 && %d <= 110000) && (%d >= 15000 && %d <= 75000))\n",hullarea,hullarea,handarea,handarea);
    	    if((hullarea >= 21000 && hullarea <= 110000) && (handarea >= 15000 && handarea <= 75000)){
		printf("チョキの白黒の割合\n");
		printf("if(%f >= %f && %f <= %f)\n",ratio,scissormin1,ratio,scissormax1);
		if(ratio >= scissormin1 && ratio <= scissormax1){
		    printf("指の距離判定\n");
		    printf("if(%d<100.0)\n",mater);
		    if(mater<130){
			printf("チョキ\n");
		    }
		}else 	printf("数値がおかしい\n");
	    }else   printf("数値がおかしい\n");
	//	パーの判定
        }else if ( yubi_count == 5 ) {
	    printf("パーの面積\n");
    	    printf("if((%d >= 43000 && %d <= 180000) && (%d >= 28000 && %d <= 100000))\n",hullarea,hullarea,handarea,handarea);
    	    if((hullarea >= 43000 && hullarea <= 180000) && (handarea >= 28000 && handarea <= 100000)){
		printf("パーの白黒の割合\n");
		printf("if(%f >= %f && %f <= %f)\n",ratio,papermin1,ratio,papermax1);
		if(ratio >= papermin1 && ratio <= papermax1){
		    printf("パー\n");
	        }else 	printf("数値がおかしい\n");
	    }else   printf("数値がおかしい\n");
	} else {
		printf("数値がおかしい\n");
    	}
    }
    if(hullarea >= 190000){
	printf("もう少し離してください\n");
    }else if(hullarea <= 19000){
	printf("もう少し近づけてください\n");
    }
}
 
void sabun(IplImage * src_img)
{
    //      モロフォロジー演算用
    IplImage *dst_img_dilate;
    IplImage *dst_img_erode, *dst_img_erode1;
    IplImage *dst_img_opening;
    IplImage *tmp_img;
    IplConvKernel *element;
 
    dst_img_dilate = cvCloneImage(src_img);	//拡大
    dst_img_erode = cvCloneImage(src_img);	//縮小
    //dst_img_erode1 = cvCloneImage(src_img);
    dst_img_opening = cvCloneImage(src_img);	//差分
    dst_img_subunn = cvCloneImage(src_img);
    tmp_img = cvCloneImage(src_img);
 
    //構造要素を生成する
    element =
	cvCreateStructuringElementEx(9, 9, 4, 4, CV_SHAPE_RECT, NULL);
 
    //各種のモルフォロジー演算を実行する
    cvMorphologyEx(src_img, dst_img_opening, tmp_img, element, CV_MOP_OPEN, 1);
    //cvMorphologyEx(src_img, dst_img_subunn , tmp_img, element, CV_MOP_OPEN, 1);
 
    cvErode(dst_img_opening, dst_img_erode, element, 5);	//縮小を5回繰り返す
    cvDilate(dst_img_erode, dst_img_dilate, element, 8);	//拡大を8回繰り返す
    cvSub(dst_img_opening, dst_img_dilate, dst_img_subunn);	//差分を求める
 
    //      メモリを解放する
    cvReleaseImage(&dst_img_dilate);
    cvReleaseImage(&dst_img_erode);
    cvReleaseImage(&dst_img_opening);
    Ellipse(dst_img_subunn);
    cvReleaseImage(&dst_img_subunn);
    cvReleaseImage(&tmp_img);
}
 
void Ellipse(IplImage * sabunn_img)
{
    //      ellipseの処理用
    IplImage *dst_img;
    IplImage *src_img_gray = 0;
    IplImage *tmp_img;
    CvMemStorage *storage = cvCreateMemStorage(0);
    CvSeq *contours = 0;
    CvBox2D ellipse;
    CvTreeNodeIterator it;
    CvPoint2D32f pt[4];
 
    src_img_gray = cvCloneImage(sabunn_img);
    tmp_img = cvCreateImage(cvGetSize(sabunn_img), IPL_DEPTH_8U, 1);
    dst_img = cvCloneImage(sabunn_img);
 
    // (2)二値化と輪郭の検出
    cvThreshold(src_img_gray, tmp_img, 95, 255, CV_THRESH_BINARY);
    cvReleaseImage(&src_img_gray);
    cvFindContours(tmp_img, storage, &contours, sizeof(CvContour),
		   CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0));
 
    if (contours == NULL)
	printf("\n");
else{
 
	// (3)ツリーノードイテレータの初期化
	cvInitTreeNodeIterator(&it, contours, 3);
	while ((contours = (CvSeq *) cvNextTreeNode(&it)) != NULL) {
	    if (contours->total > 6) {
		// (4)楕円のフィッティング
		ellipse = cvFitEllipse2(contours);
		ellipse.angle = 90.0 - ellipse.angle;
		// (5)輪郭,楕円,包含矩形の描画
		if (ellipse.size.width > ellipse.size.height
		    && ellipse.size.height * 2 <= ellipse.size.width
		    || ellipse.size.width < ellipse.size.height
		    && ellipse.size.height >= ellipse.size.width * 2) {
		    if (ellipse.size.width * ellipse.size.height > 2000) {
 
			ireko[yubi_count][0] = ellipse.center.x;
			ireko[yubi_count][1] = ellipse.center.y;
 
			yubi_count++;
			printf("中心:%f %f\n",ellipse.center.x, ellipse.center.y);
 
			cvDrawContours(dst_img, contours,
				       CV_RGB(255, 0, 0), CV_RGB(255, 0,
								 0), 0, 1,
				       CV_AA, cvPoint(0, 0));
			cvEllipseBox(dst_img, ellipse, CV_RGB(0, 0, 255),
				     2);
			cvBoxPoints(ellipse, pt);
			cvLine(dst_img, cvPointFrom32f(pt[0]),
			       cvPointFrom32f(pt[1]), CV_RGB(0, 255, 0));
			cvLine(dst_img, cvPointFrom32f(pt[1]),
			       cvPointFrom32f(pt[2]), CV_RGB(0, 255, 0));
			cvLine(dst_img, cvPointFrom32f(pt[2]),
			       cvPointFrom32f(pt[3]), CV_RGB(0, 255, 0));
			cvLine(dst_img, cvPointFrom32f(pt[3]),
			       cvPointFrom32f(pt[0]), CV_RGB(0, 255, 0));
		    }
		}
	    }
	}
    }
    if (dst_img->origin == 0) {
	// 左上が原点の場合
	cvFlip(dst_img, dst_img, 0);
    }
    //      画像を表示させる
    cvShowImage(windowNameFit, dst_img);
    //      メモリを解放する
    cvReleaseImage(&dst_img);
    cvReleaseMemStorage(&storage);
    cvReleaseImage(&tmp_img);
 
}
 
void Track(void)
{
    //      肌色を抽出する
    extractSkinColor(frameImage, hsvImage, skinImage);
 
    //      欠損領域を補間する
    interpolate(skinImage, temp);
 
    //      ラベリングを行う
    Label *labeling = createLabeling();
    exec(labeling, skinImage, label, true, IGNORE_SIZE);
 
    if (getNumOfResultRegions(labeling) > 0) {
	//      IGNORE_SIZEよりも大きな領域があった場合
 
	int hullcount;		//      ConvexHullの頂点の数
	CvPoint *handpoint;	//      手領域内の点の座標配列
	int *hull;		//      ConvexHullの頂点のhandpointにおけるindex番号
	CvMat pointMatrix;	//      手領域用行列
	CvMat hullMatrix;	//      ConvexHull用行列
 
	//      最大領域(手領域)の抽出を行う
	handarea = pickupMaxArea(skinImage, label, convexHullImage);
 
	//      ConvexHullを生成する
	createConvexHull(skinImage, handarea, &handpoint, &hull,
			 &pointMatrix, &hullMatrix);
 
	hullcount = hullMatrix.cols;
 
	//      ConvexHullを描画する
	drawConvexHull(convexHullImage, handpoint, hull, hullcount);
 
	//      ConvexHull内の面積を求める
	hullarea =
	    calcConvexHullArea(convexHullImage, handpoint, hull,
			       hullcount);
 
	//	差分を求める
	sabun(skinImage);
 
	//      ジャンケンの判定を行う
	decide(handarea, hullarea);
 
	//      メモリを解放する
	free(handpoint);
	free(hull);
    } else {
	//      画像を初期化する
	cvSetZero(convexHullImage);
    }
 
    releaseLabeling(labeling);
 
    if (skinImage->origin == 0) {
	// 左上が原点の場合
	cvFlip(skinImage, skinImage, 0);
    }
    if (convexHullImage->origin == 0) {
	// 左上が原点の場合
	cvFlip(convexHullImage, convexHullImage, 0);
    }
}
 
void on_change(int pos)
{
    Track();
}
 
int main(int argc, char **argv)
{
    int key;			//      キー入力用の変数
    CvCapture *capture = NULL;	//      カメラキャプチャ用の構造体
 
    //      カメラを初期化する
    if ((capture = cvCreateCameraCapture(-1)) == NULL) {
	//      カメラが見つからなかった場合
	printf("カメラが見つかりません\n");
	return -1;
    }
 
    frameImage = cvQueryFrame(capture);	//      キャプチャ画像用IplImage
 
    hsvImage = cvCreateImage(cvGetSize(frameImage), IPL_DEPTH_8U, 3);
    convexHullImage =
	cvCreateImage(cvGetSize(frameImage), IPL_DEPTH_8U, 3);
    skinImage = cvCreateImage(cvGetSize(frameImage), IPL_DEPTH_8U, 1);
    temp = cvCreateImage(cvGetSize(frameImage), IPL_DEPTH_8U, 1);
    label = cvCreateImage(cvGetSize(frameImage), IPL_DEPTH_16S, 1);
 
    //      ウィンドウを生成する
    createWindows();
 
    //      トラックバーを生成
    cvCreateTrackbar("色相最大値", "Track", &hmax, 255, on_change);
    cvSetTrackbarPos("色相最大値", "Track", 26);
    cvCreateTrackbar("色相最小値", "Track", &hmin, 255, on_change);
    cvSetTrackbarPos("色相最小値", "Track", 1);
    cvCreateTrackbar("色彩最大値", "Track", &smax, 255, on_change);
    cvSetTrackbarPos("色彩最大値", "Track", 255);
    cvCreateTrackbar("色彩最小値", "Track", &smin, 255, on_change);
    cvSetTrackbarPos("色彩最小値", "Track", 51);
    cvCreateTrackbar("明度最大値", "Track", &vmax, 255, on_change);
    cvSetTrackbarPos("明度最大値", "Track", 255);
    cvCreateTrackbar("明度最小値", "Track", &vmin, 255, on_change);
    cvSetTrackbarPos("明度最小値", "Track", 0);
 
    //      ジャンケン判定感度を生成
    cvCreateTrackbar("グー最大値", "Track", &rockmax, 100, on_change);
    cvSetTrackbarPos("グー最大値", "Track", 100);
    cvCreateTrackbar("グー最小値", "Track", &rockmin, 100, on_change);
    cvSetTrackbarPos("グー最小値", "Track", 85);
    cvCreateTrackbar("チョキ最大値", "Track", &scissormax, 100, on_change);
    cvSetTrackbarPos("チョキ最大値", "Track", 85);
    cvCreateTrackbar("チョキ最小値", "Track", &scissormin, 100, on_change);
    cvSetTrackbarPos("チョキ最小値", "Track", 60);
    cvCreateTrackbar("パー最大値", "Track", &papermax, 100, on_change);
    cvSetTrackbarPos("パー最大値", "Track", 75);
    cvCreateTrackbar("パー最小値", "Track", &papermin, 100, on_change);
    cvSetTrackbarPos("パー最小値", "Track", 50);
 
    while (1) {
 
	frameImage = cvQueryFrame(capture);
 
	on_change(hmax);
	//on_change1(rockmax);
 
	//      画像を表示する
	cvShowImage(windowNameCapture, frameImage);
	cvShowImage(windowNameSkin, skinImage);
	cvShowImage(windowNameConvexHull, convexHullImage);
	yubi_count = 0;
 
 
	//      キー入力判定
	key = cvWaitKey(1);
	if (key == 'q') {
	    //      'q'キーが押されたらループを抜ける
	    break;
	} else if (key == 'c') {
	    printf("撮影します\n");
	    sprintf(filename, "%s%d.bmp", path, count);
	    cvSaveImage(filename, skinImage);
	    printf("撮影しました\n");
	    count++;
	}
    }
 
    //      キャプチャを解放する
    cvReleaseCapture(&capture);
    //      メモリを解放する
    cvReleaseImage(&hsvImage);
    cvReleaseImage(&skinImage);
    cvReleaseImage(&temp);
    cvReleaseImage(&label);
    cvReleaseImage(&convexHullImage);
    cvReleaseImage(&dst_img_subunn);
    cvReleaseImage(&dst_img);
 
    //      ウィンドウを破棄する
    cvDestroyWindow(windowNameCapture);
    cvDestroyWindow(windowNameSkin);
    cvDestroyWindow(windowNameConvexHull);
    cvDestroyWindow(windowNameFit);
 
    return 0;
}
最終更新:2010年02月08日 16:45
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。