• 締切済み

c++のif文についてです。

webカメラを使って肌色の面積を求めて、現在より1フレーム前の値と比較したいのですが、そのif文の部分がどのように書けば良いのかわかりません。 printf関数を使ってwebカメラで取得した肌色部分のピクセル数の前後を比較する場合(例えば、前のあたいより10倍以上大きかったら等)のif文の書き方をどなたかご教授お願いします。 以下ソースコードです。 #include "stdafx.h" #include <cv.h> #include <highgui.h> #include <time.h> #include <math.h> #include <string> int hsv=0; IplImage*mask = 0; CvSeq* contour = 0; void GetMaskHSV(IplImage* src, IplImage* mask,int erosions, int dilations) { int x = 0, y = 0; uchar H, S, V; uchar minH, minS, minV, maxH, maxS, maxV; CvPixelPosition8u pos_src, pos_dst; uchar* p_src; uchar* p_dst; IplImage* tmp; tmp = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 3); cvCvtColor(src, tmp, CV_RGB2HSV); CV_INIT_PIXEL_POS(pos_src, (unsigned char*) tmp->imageData, tmp->widthStep,cvGetSize(tmp), x, y, tmp->origin); CV_INIT_PIXEL_POS(pos_dst, (unsigned char*) mask->imageData, mask->widthStep, cvGetSize(mask), x, y, mask->origin); minH = 100; maxH = 120; minS = 70; maxS = 255; minV = 70; maxV = 255; for(y = 0; y < tmp->height; y++) { for(x = 0; x < tmp->width; x++) { p_src = CV_MOVE_TO(pos_src, x, y, 3); p_dst = CV_MOVE_TO(pos_dst, x, y, 3); H = p_src[0]; S = p_src[1]; V = p_src[2]; if( minH <= H && H <= maxH && minS <= S && S <= maxS && minV <= V && V <= maxV ) { p_dst[0] = 255; p_dst[1] = 255; p_dst[2] = 255; hsv++; } else { p_dst[0] = 0; p_dst[1] = 0; p_dst[2] = 0; } } } if(erosions > 0) cvErode(mask, mask, 0, erosions); if(dilations > 0) cvDilate(mask, mask, 0, dilations); printf("%d\n",hsv); if(){}←ここのif文がわかりません cvReleaseImage(&tmp); } int _tmain(int argc, _TCHAR* argv[]) { int key; CvCapture* src; IplImage* frame; cvNamedWindow("カメラ映像表示"); src = cvCaptureFromCAM(0); if(src == NULL){ printf("映像が取得できません。\n"); cvWaitKey(0); return -1; } frame = cvQueryFrame(src); mask = cvCreateImage(cvSize(frame->width,frame->height), IPL_DEPTH_8U, 3); while(1){ frame = cvQueryFrame(src); cvShowImage("カメラ映像表示", frame); GetMaskHSV(frame,mask,1,1); cvDrawContours(frame, contour, CV_RGB (255, 255, 0), CV_RGB (0, 0, 0), 1, 1, CV_AA, cvPoint (0, 0)); key = cvWaitKey(33); if(key == 27) break; } cvDestroyWindow("カメラ映像表示"); cvReleaseCapture(&src); return 0; } 1フレーム前の値を変数に記憶して、その前の状態を記憶しておいた変数と hsv とを比較すればよいというアルゴリズムは想像できるのですが、その“1フレーム前の値”というのを、どのように表現していいかわからないのです・・

みんなの回答

  • a_kwn
  • ベストアンサー率34% (8/23)
回答No.1

> 1フレーム前の値を変数に記憶して hsv 自体がグローバル変数なので、まぁ、グローバル変数にしときます。 (あまり、グローバル変数の多用はお勧めできないんですが) int hsv=0; // フレームの肌色ピクセル数。 int prev_hsv=-1; // ひとつ前のフレームの肌色ピクセル数。 > その前の状態を記憶しておいた変数と hsv とを比較すればよいというアルゴリズムは想像できるのですが、 printf("%d\n",hsv); // まず、prev_hsv と hsv の値で判定(例えば、前回値の10倍より大きい場合の判定 if(prev_hsv >= 0 && hsv > prev_hsv * 10){ } prev_hsv = hsv; // 判定が終わったら、前の値を覚えておく こんな感じで、どうでしょう?

関連するQ&A

  • OpenCV2.4.6で色抽出を行いたい。

    Webカメラから取得した映像を用いて色抽出を行いたいです。 システム開発はVisual Studio 2012で言語はC++です。 OpenCV2.4.6を利用しているのですが、サンプルプログラムが古いバージョンで、OpenCV2.4.6では動かないので以下のプログラムを改良したいです。 参考にしたサイトはこちらです。 http://d.hatena.ne.jp/wah-wah-hawah/20090325/1237996168 以下プログラム #include <cv.h> #include <highgui.h> void GetMaskHSV(IplImage* src, IplImage* mask,int erosions, int dilations) { int x = 0, y = 0; uchar H, S, V; uchar minH, minS, minV, maxH, maxS, maxV; CvPixelPosition8u pos_src, pos_dst; uchar* p_src; uchar* p_dst; IplImage* tmp; tmp = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 3); //HSVに変換 cvCvtColor(src, tmp, CV_RGB2HSV); CV_INIT_PIXEL_POS(pos_src, (unsigned char*) tmp->imageData, tmp->widthStep,cvGetSize(tmp), x, y, tmp->origin); CV_INIT_PIXEL_POS(pos_dst, (unsigned char*) mask->imageData, mask->widthStep, cvGetSize(mask), x, y, mask->origin); minH = 100; maxH = 115; minS = 80; maxS = 255; minV = 120; maxV = 255; for(y = 0; y < tmp->height; y++) { for(x = 0; x < tmp->width; x++) { p_src = CV_MOVE_TO(pos_src, x, y, 3); p_dst = CV_MOVE_TO(pos_dst, x, y, 3); H = p_src[0]; //0から180 S = p_src[1]; V = p_src[2]; if( minH <= H && H <= maxH && minS <= S && S <= maxS && minV <= V && V <= maxV ) { p_dst[0] = 255; p_dst[1] = 255; p_dst[2] = 255; } else { p_dst[0] = 0; p_dst[1] = 0; p_dst[2] = 0; } } } if(erosions > 0) cvErode(mask, mask, 0, erosions); if(dilations > 0) cvDilate(mask, mask, 0, dilations); cvReleaseImage(&tmp); } int main(int argc, char **argv) { int c; CvCapture* capture = 0; IplImage* frame = 0; IplImage* mask = 0; IplImage* dst = 0; if(argc == 1 || (argc == 2 && strlen (argv[1]) == 1 && isdigit(argv[1][0]))) capture = cvCreateCameraCapture(argc == 2 ? argv[1][0] - '0' : 0); frame = cvQueryFrame(capture); mask = cvCreateImage(cvSize(frame->width, frame->height), IPL_DEPTH_8U, 3); dst = cvCreateImage(cvSize(frame->width, frame->height), IPL_DEPTH_8U, 3); cvNamedWindow("src", CV_WINDOW_AUTOSIZE); cvNamedWindow("dst", CV_WINDOW_AUTOSIZE); while(1) { frame = cvQueryFrame(capture); GetMaskHSV(frame, mask, 1, 1); cvAnd(frame, mask, dst); cvShowImage("src", frame); cvShowImage("dst", dst); c = cvWaitKey(10); if(c == 'q') break; } cvDestroyWindow("src"); cvDestroyWindow("dst"); cvReleaseImage(&frame); cvReleaseImage(&dst); cvReleaseImage(&mask); cvReleaseCapture(&capture); return(0); }

  • C++の関数等を使った書き方

    C++OpenCVで関数等を使ってプログラムをみやすくまとめたいのですが、教えていただけないでしょうか。 プログラムの内容はHSV変換をしています。 これをmain文より外に出したい場合どのような書き方をすればいいでしょうか。 返り値はHSVの3つがほしいです。 struct _HSV { int H; int S; int V; }HSV[2000][2000]; main(void){ 宣言 src_img = cvLoadImage (filename, CV_LOAD_IMAGE_COLOR); for(y = 0; y < src_img->height; y++) { for(x = 0; x < src_img->width; x++) { p[0] = src_img->imageData[src_img->widthStep * y + x * 3]; // B p[1] = src_img->imageData[src_img->widthStep * y + x * 3 + 1]; // G p[2] = src_img->imageData[src_img->widthStep * y + x * 3 + 2]; // R if (p[0] >= p[1] && p[0] >= p[2]) {max = p[0];} //Bがmax else if (p[1] >= p[0] && p[1] >= p[2]) {max = p[1];} //Gがmax else {max = p[2];} //Rがmax if (p[0] <= p[1] && p[0] <= p[2]) {min = p[0];} //Bがmin else if (p[1] <= p[0] && p[1] <= p[2]) {min = p[1];} //Gがmin else {min = p[2];} //Rがmin if(max==min){ HSV[y][x].H = 0; HSV[y][x].S = 0; HSV[y][x].V = p[0]; //R } else { if(max==p[2]){ //Rがmax HSV[y][x].H = 60 * (p[1]-p[0])/(max-min); } else if(max==p[1]) //Gがmax { HSV[y][x].H = 60 * (p[0]-p[2])/(max-min); HSV[y][x].H += 120; } else //Bがmax { HSV[y][x].H = 60 * (p[2]-p[1])/(max-min); HSV[y][x].H += 240; } if(HSV[y][x].H < 0) { HSV[y][x].H += 360; } } if(x % 60== 0){ fprintf(fp, "%d ,%d\n", HSV[y][x].H, HSV[y][x].S); } } } } 初歩的な質問ですみません。 できれば、関数以外でもこうすれば見やすい等ご指摘頂けると助かります。 よろしくお願いします。

  • カメラを用いて動画から画像を取り込みトリミングしようとするプログラムを

    カメラを用いて動画から画像を取り込みトリミングしようとするプログラムを作っています. 最下部のプログラムを貼り付けているところまででデバックしつつ実行すると "OpenCVwithDShow.exe の 0x00462614 でハンドルされていない例外が発生しました: 0xC0000094: Integer division by zero" とエラー文がでてきます. 色々考えたのですが、原因が分からないのでどなたかご教授お願いします. よろしくお願いします. //トリミング CvRect cvClipRect(IplImage *frame, CvRect r) { r.x = 240; r.y = 0; r.width = 1080; r.height = 1680; if (r.x < 0) {r.width += r.x; r.x = 0;} if (r.y < 0) {r.height += r.y; r.y = 0;} if (r.x >= frame->width ) {r.width -= r.x - frame->width ; r.x = frame->width - 1;} if (r.y >= frame->height) {r.height -= r.y - frame->height; r.y = frame->height - 1;} if (r.width > frame->width - r.x) {r.width = frame->width - r.x;} if (r.height > frame->height - r.y) {r.height = frame->height - r.y;} return r; } IplImage *cvCreateSubRectImage(IplImage *frame, CvRect r) { IplImage tmp; CvMat submat; cvGetSubRect(frame, &submat, cvClipRect(frame, r)); cvGetImage(&submat, &tmp); return cvCloneImage(&tmp); } //トリミング終了 int main (int argc, char **argv){ CvCapture *capture = 0; IplImage *frame = NULL; IplImage *frame1 = NULL; IplImage *reduce = NULL; int c; int x,y; int max,min; int h,s; uchar p[3]; LabelingSS labeling; short *src_buf; float centerX,centerY; HANDLE hCom; //トリミング関数 // (1)コマンド引数によって指定された番号のカメラに対するキャプチャ構造体を作成する if (argc == 1 || (argc == 2 && strlen (argv[1]) == 1 && isdigit (argv[1][0]))) capture = cvCreateCameraCapture (argc == 2 ? argv[1][0] - '0' : 0); /* この設定は,利用するカメラに依存する */ // (2)キャプチャサイズを設定する. cvNamedWindow ("Capture", CV_WINDOW_AUTOSIZE); frame1 = cvQueryFrame (capture); src_buf = new short[ frame1->width * frame1->height ]; // (3)カメラから画像をキャプチャする while (1) { frame1 = cvQueryFrame (capture); frame = cvCloneImage(frame1); //トリミング呼び出し CvRect cvClipRect(IplImage *frame, CvRect r); IplImage *cvCreateSubRectImage(IplImage *frame, CvRect r);

  • OpenCV 2値化について

    いつもお世話になっております。 画像の2値化(黒は全てゼロ、白は全て255)をした画像bw_imgを用意して 左上端から11×11サイズのROIに切り取って決まった処理をかけていこうとしていますが、 2値化した画像をROIで保持させることができず、困っています。 int main() { //画像の2値化処理用変数 IplImage *src_img = 0, *dst_img = 0, *bw_img = 0; IplImage *src_img_gray = 0; IplImage *tmp_img, *out_img, *lap_img; CvMemStorage *storage = cvCreateMemStorage(0); CvSeq *contours = 0; // (1)画像を読み込み、グレースケール化(src_img_gray)、二値化(tmp_img) src_img = cvLoadImage("C:\\Users...\\サンプル画像\\sample.jpg", CV_LOAD_IMAGE_COLOR); tmp_img = cvCreateImage(cvGetSize(src_img), IPL_DEPTH_8U, 1); src_img_gray = cvCreateImage(cvGetSize(src_img), IPL_DEPTH_8U, 1);//もとはIPL_DEPTH_8U cvCvtColor(src_img, src_img_gray, CV_BGR2GRAY); cvAdaptiveThreshold(src_img_gray, tmp_img, 255, CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, 7, 8); //11×11 走査用変数 dst_img = cvCreateImage(cvGetSize(tmp_img), IPL_DEPTH_8U, 1); bw_img = cvCreateImage(cvGetSize(tmp_img), IPL_DEPTH_8U, 1); out_img = cvCreateImage(cvGetSize(tmp_img), IPL_DEPTH_8U, 1); cvThreshold(tmp_img, bw_img, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU); for (x = 0; x < bw_img->width; x++){ // x 座標を 1ピクセルずつ進める for (y = 0; y < bw_img->height; y++){ // y 座標を 1ピクセルずつ進める //(1) 11×11ピクセルに切り取って2値化する。 cvCopy(bw_img, dst_img); lap_img = cvCreateImage(cvSize(11, 11), IPL_DEPTH_8U, 1); CvMat *sub = cvCreateMatHeader(11, 11, CV_8UC1); cvGetSubRect(bw_img, sub, cvRect(y, x, 11, 11)); //コピー画像から11×11切り取り。 cvThreshold(sub, lap_img, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU); //2値化、結果はlap_img. uchar iro = lap_img->imageData[lap_img->widthStep * (y + 6) + (x + 6)]; if (iro ==0){ →ここでどうみても黒なのにiroに「238」「71」などの値が入っています。 roiで切り取ったlap_imgが2値になっていません。 何が問題で2値化できていないのでしょうか。 どうすると2値化した画像(lap_img)を決まったサイズのウィンドウで扱えるでしょうか。 もしおわかりでしたらヒントでも結構ですのでぜひ教えてください。 よろしくお願いします。

  • OpenCVでサンプルコードを使うとエラーが出ます

    環境はVidualStudio2008、OpenCVは2.1のバージョンを利用しています。 OpenCVのテンプレートマッチングのサンプルを利用したところエラーが発生しました。 ソースは以下のものを使っています。 ところどころに入っているprintfは私が自分で入れたものですがこれが原因であるとは考えにくいのです。 エラーは添付したような画像で現れます。 またデバッグしたところ [下のフレームは間違っているか、または見つかりません。KernelBase.dll に対して読み込まれたシンボルはありません。] KernelBase.dll!76b7b9bc() このような文章も表示されました。 どうすれば解決できるでしょうか。 #include <cv.h> #include <highgui.h> int main (int argc, char **argv) { double min_val, max_val; CvPoint min_loc, max_loc; CvSize dst_size; IplImage *src_img, *tmp_img, *dst_img; argv[1]="○○"; argv[2]="○○"; argc=3; printf("1complete\n"); cvNamedWindow ("Image", 1); src_img = cvLoadImage (argv[1], CV_LOAD_IMAGE_COLOR); tmp_img = cvLoadImage (argv[2], CV_LOAD_IMAGE_COLOR); if(argc != 3 || (src_img = cvLoadImage (argv[1], CV_LOAD_IMAGE_COLOR))==0||(tmp_img = cvLoadImage (argv[2], CV_LOAD_IMAGE_COLOR))==0) return -1; printf("2complete\n"); // (1)探索画像全体に対して,テンプレートのマッチング値(指定した手法に依存)を計算 dst_size = cvSize (src_img->width - tmp_img->width + 1, src_img->height - tmp_img->height + 1); printf("2-1complete\n"); dst_img = cvCreateImage (dst_size, IPL_DEPTH_32F, 1);    //ここで動作停止 printf("2-2complete\n"); cvMatchTemplate (src_img, tmp_img, dst_img, CV_TM_CCOEFF_NORMED); printf("2-3complete\n"); cvMinMaxLoc (dst_img, &min_val, &max_val, &min_loc, &max_loc, NULL); printf("3complete\n"); // (2)テンプレートに対応する位置に矩形を描画 cvRectangle (src_img, max_loc, cvPoint (max_loc.x + tmp_img->width, max_loc.y + tmp_img->height), CV_RGB (255, 0, 0), 3); printf("4complete\n"); cvShowImage ("Image", src_img); printf("ALL COMPLETE!\n"); cvWaitKey (0); cvDestroyWindow ("Image"); cvReleaseImage (&src_img); cvReleaseImage (&tmp_img); cvReleaseImage (&dst_img); return 0; }

  • 【OpenCV】BGRからHSVへの画像変換

    OpenCVを使って任意の画像データをBGR表色系からHSV表色系に変換するプログラムです。 コンパイルして実行してみたところ、添付画像のように元画像とは色味が異なった画像が出力されてしまいます。 他の画像ファイルを使ってみましたが結果は同じでした。 HSVへの変換がうまくいってないのでしょうが、調べても原因は分かりませんでした。 どなたか分かる方がいらっしゃいましたらご指摘お願いします。 以下にコードを載せます。 #include <cv.h> #include <highgui.h> int main (int argc, char **argv){ IplImage *src_img=0; // 入力画像 IplImage *hsv_img=0; // hsvに変換された画像 // (1)画像を読み込む src_img = cvLoadImage (argv[1], CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR); // (2)読み込んだ画像をhsvに変換する hsv_img = cvCreateImage (cvGetSize (src_img), IPL_DEPTH_8U, 3); cvCvtColor (src_img, hsv_img, CV_BGR2HSV); // (3)画像を表示,キーが押されたときに終了 cvNamedWindow ("Source_Image", CV_WINDOW_AUTOSIZE); cvNamedWindow ("HSV_Image", CV_WINDOW_AUTOSIZE); cvShowImage ("Source_Image", src_img); cvShowImage ("HSV_Image", hsv_img); cvWaitKey (0); // (4)メモリ解放 cvDestroyWindow ("Source_Image"); cvDestroyWindow ("HSV_Image"); cvReleaseImage (&src_img); cvReleaseImage (&hsv_img); return 0; } OS:Windows7 OpenCVのバージョン:2.1 添付画像で用いた画像の形式:png

  • opencv c++についての質問です

    int main (int argc, char **argv){ int i, c, counter; int INIT_TIME = 100; int w = 0, h = 0; char *FileName = "動画名"; if((capture = cvCaptureFromFile(FileName)) == NULL){ printf("指定された動画がみつかりません\n"); return -1; } CvCapture *capture = 0; IplImage *frame; IplImage *av_img, *sgm_img; IplImage *lower_img, *upper_img, *tmp_img; IplImage *dst_img, *msk_img; CvFont font; capture = cvCreateFileCapture (FileName); // (2)1フレームキャプチャし,キャプチャサイズを取得する. frame = cvQueryFrame (capture); w = frame->width; h = frame->height; // (3)作業用の領域を生成する av_img = cvCreateImage (cvSize (w, h), IPL_DEPTH_32F, 3); sgm_img = cvCreateImage (cvSize (w, h), IPL_DEPTH_32F, 3); tmp_img = cvCreateImage (cvSize (w, h), IPL_DEPTH_32F, 3); lower_img = cvCreateImage (cvSize (w, h), IPL_DEPTH_32F, 3); upper_img = cvCreateImage (cvSize (w, h), IPL_DEPTH_32F, 3); dst_img = cvCreateImage (cvSize (w, h), IPL_DEPTH_8U, 3); msk_img = cvCreateImage (cvSize (w, h), IPL_DEPTH_8U, 1); // (4)背景の輝度平均の初期値を計算する printf ("Background statistics initialization start\n"); cvSetZero (av_img); for (i = 0; i < INIT_TIME; i++) { frame = cvQueryFrame (capture); cvAcc (frame, av_img); } cvConvertScale (av_img, av_img, 1.0 / INIT_TIME); // (5)背景の輝度振幅の初期値を計算する cvSetZero (sgm_img); for (i = 0; i < INIT_TIME; i++) { frame = cvQueryFrame (capture); cvConvert (frame, tmp_img); cvSub (tmp_img, av_img, tmp_img); cvPow (tmp_img, tmp_img, 2.0); cvConvertScale (tmp_img, tmp_img, 2.0); cvPow (tmp_img, tmp_img, 0.5); cvAcc (tmp_img, sgm_img); } cvConvertScale (sgm_img, sgm_img, 1.0 / INIT_TIME); printf ("Background statistics initialization finish\n"); // (6)表示用ウィンドウを生成する cvInitFont (&font, CV_FONT_HERSHEY_COMPLEX, 0.7, 0.7); cvNamedWindow ("Input", CV_WINDOW_AUTOSIZE); cvNamedWindow ("Substraction", CV_WINDOW_AUTOSIZE); // (7)取得画像から背景を分離するループ counter = 0; while (1) { frame = cvQueryFrame (capture); cvConvert (frame, tmp_img); // (8)背景となりうる画素の輝度値の範囲をチェックする cvSub (av_img, sgm_img, lower_img); cvSubS (lower_img, cvScalarAll (Zeta), lower_img); cvAdd (av_img, sgm_img, upper_img); cvAddS (upper_img, cvScalarAll (Zeta), upper_img); cvInRange (tmp_img, lower_img, upper_img, msk_img); // (9)輝度振幅を再計算する cvSub (tmp_img, av_img, tmp_img); cvPow (tmp_img, tmp_img, 2.0); cvConvertScale (tmp_img, tmp_img, 2.0); cvPow (tmp_img, tmp_img, 0.5); // (10)背景と判断された領域の背景の輝度平均と輝度振幅を更新する cvRunningAvg (frame, av_img, B_PARAM, msk_img); cvRunningAvg (tmp_img, sgm_img, B_PARAM, msk_img); // (11)物体領域と判断された領域では輝度振幅のみを(背景領域よりも遅い速度で)更新する cvNot (msk_img, msk_img); cvRunningAvg (tmp_img, sgm_img, T_PARAM, msk_img); // (12)物体領域のみを出力画像にコピーする(背景領域は黒) cvSetZero (dst_img); cvCopy (frame, dst_img, msk_img); // メディアンフィルタでノイズを除去する cvSmooth( dst_img, dst_img, CV_MEDIAN ); cvMoments( frame, &moment, 0 ); m_00 = cvGetSpatialMoment( &moment, 0, 0 ); m_10 = cvGetSpatialMoment( &moment, 1, 0 ); m_01 = cvGetSpatialMoment( &moment, 0, 1 ); gravityX = m_10 / m_00; gravityY = m_01 / m_00; if (frame->nChannels == 3 && cvGetImageCOI (frame) == 0) cvSetImageCOI (frame, 1); cvSetImageCOI (frame, 0); cvCircle( dst_img, cvPoint( gravityX, gravityY ), CIRCLE_RADIUS,CV_RGB( 255, 0, 0 ), LINE_THICKNESS, LINE_TYPE, 0 ); // (13)処理結果を表示する cvShowImage ("Input", frame); cvShowImage ("Substraction", dst_img); counter++; c = cvWaitKey (10); if (c == '\x1b') break; } cvDestroyWindow ("Input"); cvDestroyWindow ("Substraction"); cvReleaseImage (&frame); cvReleaseImage (&dst_img); cvReleaseImage (&av_img); cvReleaseImage (&sgm_img); cvReleaseImage (&lower_img); cvReleaseImage (&upper_img); cvReleaseImage (&tmp_img); cvReleaseImage (&msk_img); return 0; } 動画を指定して背景差分を行い、動画内の物体の重心を求めて円を描きたいのですがcvMoments()とcvCircle()関数を入れてコンパイルしたところウィンドウが出て動画が始まる前に終了してしまいます。 どのようにすれば正常に動くようになるのでしょうか?

  • K-meansについて教えてください。

    OpenCVを利用し、肌色部分をHSV値の範囲により緑色に変えています。(while文)ここから顔、右手、左手の3つにK-meansを使って三色に分けたいのですが、どのように変えればいいですか?クラスタの中心の座標を使うので座標でクラスタリングしたいです。 #include "stdafx.h" #include <cv.h> #include <highgui.h> #pragma comment(lib,"cv.lib") #pragma comment(lib,"cxcore.lib") #pragma comment(lib,"highgui.lib") #include <math.h> #define LINE_THICKNESS -1 #define LINE_TYPE 8 #define SHIFT 0 #define MAX_CLUSTERS (3) int _tmain(int argc, _TCHAR* argv[]) { CvSeq *objects; CvRect *r; char *cascade_name; int key; int i = 1; ////////////////////////////////////////////////////////////////// int x, y, W, H; int ofs, idx; unsigned char *pix; int pixCnt; int pixCnt2; int h, s, v; double n, m; double aveH, aveS, aveV; double divh, divs, divv; double divH, divS, divV; double aveH2, aveS2, aveV2; double sigmaH, sigmaS, sigmaV; /////////////////////////////////////////////////////////////////////////// CvCapture* src; IplImage *frame1; IplImage *frame2; IplImage *frame3; CvHaarClassifierCascade *cascade; CvMemStorage *storage; cvNamedWindow ("原画像"); cvNamedWindow ("HSV画像"); cvNamedWindow ("処理結果"); // カスケード・ファイルの読み込み cascade_name = "haarcascade_frontalface_default.xml"; cascade = (CvHaarClassifierCascade *) cvLoad(cascade_name, 0, 0, 0); storage = cvCreateMemStorage (0); cvClearMemStorage(storage); src = cvCaptureFromCAM(0); if(src == NULL){printf("映像が取得できません。\n"); cvWaitKey(0); return -1; } frame1 = cvQueryFrame(src); frame2 = cvCreateImage(cvGetSize(frame1), IPL_DEPTH_8U, 3); frame3 = cvCreateImage(cvGetSize(frame1), IPL_DEPTH_8U, 3); //顔領域の検出 objects = cvHaarDetectObjects(frame1, cascade, storage, 1.1, 3, 0, cvSize(0, 0)); r = (CvRect *) cvGetSeqElem(objects, i); cvRectangle(frame1, cvPoint(r->x, r->y) , cvPoint(r->x + r->width, r->y + r->height), CV_RGB(0, 255, 0), 4); cvCvtColor(frame1, frame2, CV_BGR2HSV); ///////////////////////////////////////////////////////////////////////// pix = (unsigned char*)frame2->imageData; pixCnt = frame2->width*frame2->height; pixCnt2 = r->width/6*r->height/6; printf( "%d\n", pixCnt ); printf("pixCnt2: %d\n", pixCnt2); aveV = aveS = aveH = 0; for( y=r->y+r->height/2; y<r->y+r->height/2+r->height/6; y++ ) { ofs = y*frame2->widthStep; for( x=r->x+r->width*2/3; x<r->x+r->width*2/3+r->width/6; x++ ) { idx = ofs + x*3; aveS += pix[idx+1]; if (pix[idx+1] >= 0) { aveH += pix[idx]; } else { pixCnt2--; } } } aveS /= pixCnt2; aveH /= pixCnt2; printf("H%f,S%f,V%f\n", aveH, aveS, aveV); aveH2 = 0; divh = 0; for( y=r->y; y<r->y+r->height; y++ ) { ofs = y*frame2->widthStep; for( x=r->x; x<r->x+r->width; x++ ) { idx = ofs + x*3; aveH2 += (pix[idx]-aveH)*(pix[idx]-aveH); } } aveH2 /= pixCnt2; divH = aveH2; sigmaH = sqrt(aveH2); while(1){ frame1 = cvQueryFrame(src); if(frame1 == NULL) break; // 1フレーム取得 cvRectangle(frame1, cvPoint(r->x, r->y) // 検出部に四角枠描画 , cvPoint(r->x + r->width, r->y + r->height), CV_RGB(0, 255, 0), 4); cvCvtColor(frame1, frame2, CV_BGR2HSV); cvShowImage ("原画像", frame1); // 検出結果表示 cvShowImage ("HSV画像", frame2); // 検出結果表示 for( y=0; y<frame2->height; y++ ) { ofs = y*frame2->widthStep; for( x=0; x<frame2->width; x++ ) { idx = ofs + x*3; v = pix[idx+2]; s = pix[idx+1]; h = pix[idx]; if ((h > aveH-sigmaH && h < aveH+sigmaH)&& (s > aveS-10 && s < aveS+10)) { pix[idx+2] = 230; pix[idx+1] = 230; pix[idx] = 60; } else { pix[idx+2] = 0; pix[idx+1] = 0; pix[idx] = 0; } } } cvCvtColor(frame2, frame3, CV_HSV2BGR); cvShowImage ("処理結果", frame3); // 検出結果表示 if(cvWaitKey(33) == 27) break; // ESCキーを押した時終了 } // ウィンドウ・キャプチャ・メモリの解放 cvReleaseImage(&frame1); cvReleaseImage(&frame2); cvReleaseImage(&frame3); cvDestroyWindow("原画像"); cvDestroyWindow("HSV画像"); cvDestroyWindow("処理結果"); cvReleaseCapture(&src); cvReleaseMemStorage(&storage); return 0; }

  • C メモリの解放について

    Cで書いたコードを動かすと、ヒープが壊れてたというエラーが出るようになりました。 freeなどで、自分なりに調べてメモリを解放したつもりですが、 その後また再発するようになったので、すみません、どの変数をどう解放するべきか、アドバイスをいただけると助かります。OpenCVの関数を使っています。 内容は、Aというファイルに20枚のテンプレートBを当てて近似値をとり、それを1行の文字列にしてCSVに保存する、というものです。 ====== #include <cv.h> #include <highgui.h> #include <stdio.h> #include <string.h> #define snprintf _snprintf #include <errno.h> #include <math.h> int main (void) { FILE *fp; char str[60], str2[200], str3[200]; int i,ii; double result[20]; CvFont font; IplImage *src_img1, *src_img2, *src_img3; IplImage *dst_img[1]; IplImage *fresh_img,*mask_img; char *fname = "C:\\Documents and Settings\\...\\result.csv"; char kugiri[]=","; result[ii]=NULL; free(str2); fp = fopen( fname, "w" ); if( fp == NULL ){ printf( "%sファイルが開けません\n", fname ); return -1; } //ファイルA=src_img1 src_img1 = cvLoadImage ("C:\\Documents and Settings\\...\\2.jpg", CV_LOAD_IMAGE_GRAYSCALE); for (ii=0; ii<20; ii++) {    sprintf(str,"%s%d%s","C:\\Documents and Settings\\...\\",ii, ".png"); //ファイルB=src_img2 src_img2 = cvLoadImage (str, CV_LOAD_IMAGE_GRAYSCALE); //テンプレートのファイルBを、比較用にコピーしています dst_img[0] = (IplImage *) cvClone (src_img2); //result[ii]には近似値が格納されます result[ii] = cvMatchShapes (src_img1, src_img2, CV_CONTOURS_MATCH_I1, 0); //ここで ↓ エラーが出るので、型がおかしいのかと直していたのですがヒープが壊れて直せなくなりました。str2に、近似値の結果+区切り文字(カンマ)をテンプレート枚数(20)回ループで回して文字連結して格納したいのです。近似値は小数点6ケタまであればいいので、floatでいいと思ったのですが違うでしょうか。    sprintf(str2,"%f%s",result[ii],kugiri); if (ii==0){ sprintf(str3,"%s",str2); return -1; } sprintf(str3,"%s%s",str3,str2); //メモリの解放 cvReleaseImage(&src_img2); cvReleaseImage(&dst_img[0]); free(str2); result[ii]=NULL; printf("%f",str3); } fprintf(fp, "%s", str3); fclose( fp ); free(str3); return 0; } == すみません、とても基本的なことなのだろうと思うのですが、ぜひ教えてください。

  • OpenCVを用いたヒストグラムの比較について

     現在画像の類似度を求めるために、OpenCV1.0を使って色のヒストグラムの距離を求めるということを行っております。OpenCVで公開されているヒストグラム間の距離のサンプルプログラムを使って行っているのですが、結果があまり芳しくないためいろいろ調べなおしたところ、減色処理、量子化というワードにたどり着きました。  しかし調べてみてもいまいち分からず、行き詰っているのが現状です。どなたか減色処理や量子化について詳しい人がおりましたら、是非回答のほうよろしくお願いします。以下がOpenCVのコードなのですが、どこの部分をどのように変えたらそれが実現できるのかも是非回答お願いいたします。 #include <cv.h> #include <highgui.h> #include <math.h> #include <stdio.h> int main (int argc, char **argv) { char text[16]; int i, hist_size = 256, sch = 0; float range_0[] = { 0, 256 }; float *ranges[] = { range_0 }; double tmp, dist = 0; IplImage *src_img1 = 0, *src_img2 = 0, *dst_img1[4] = { 0, 0, 0, 0 }, *dst_img2[4] = { 0, 0, 0, 0}; CvHistogram *hist1, *hist2; CvFont font; CvSize text_size; // (1)二枚の画像を読み込む.チャンネル数が等しくない場合は,終了 if (argc >= 3) { src_img1 = cvLoadImage (argv[1], CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR); src_img2 = cvLoadImage (argv[2], CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR); } if (src_img1 == 0 || src_img2 == 0) return -1; if (src_img1->nChannels != src_img2->nChannels) return -1; // (2)入力画像のチャンネル数分の画像領域を確保 sch = src_img1->nChannels; for (i = 0; i < sch; i++) { dst_img1[i] = cvCreateImage (cvSize (src_img1->width, src_img1->height), src_img1->depth, 1); dst_img2[i] = cvCreateImage (cvSize (src_img2->width, src_img2->height), src_img2->depth, 1); } // (3)ヒストグラム構造体を確保 hist1 = cvCreateHist (1, &hist_size, CV_HIST_ARRAY, ranges, 1); hist2 = cvCreateHist (1, &hist_size, CV_HIST_ARRAY, ranges, 1); // (4)入力画像がマルチチャンネルの場合,画像をチャンネル毎に分割 if (sch == 1) { cvCopy (src_img1, dst_img1[0], NULL); cvCopy (src_img2, dst_img2[0], NULL); } else { cvSplit (src_img1, dst_img1[0], dst_img1[1], dst_img1[2], dst_img1[3]); cvSplit (src_img2, dst_img2[0], dst_img2[1], dst_img2[2], dst_img2[3]); } // (5)ヒストグラムを計算,正規化して,距離を求める for (i = 0; i < sch; i++) { cvCalcHist (&dst_img1[i], hist1, 0, NULL); cvCalcHist (&dst_img2[i], hist2, 0, NULL); cvNormalizeHis

専門家に質問してみよう