C++OpenCVでHSV変換をみやすくまとめる方法

このQ&Aのポイント
  • C++OpenCVでHSV変換を行うプログラムを、関数を使ってみやすくまとめたいです。具体的な書き方や返り値について教えてください。
  • プログラムの内容は、HSV変換を行っています。main文の外に変換処理を記述したい場合、どのような書き方をすれば良いでしょうか。また、返り値はHSVの3つの値が欲しいです。
  • 初歩的な質問で申し訳ありません。関数以外でもプログラムを見やすくする方法があれば、教えていただけると助かります。
回答を見る
  • ベストアンサー

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); } } } } 初歩的な質問ですみません。 できれば、関数以外でもこうすれば見やすい等ご指摘頂けると助かります。 よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

こんな感じですかね。 あと、この場合のように、使う必要のないところで配列を使うのは、たとえば、 HSV[y][x].V = p[0]; //R else{min = p[2];} //Rがmin で、どっちが red ? というように混乱のもとかと思います。 一応そのあたり振り直したつもりですが、間違っているかもしれません。 あと、処理自体がどうも不自然な感じがしますが、そのまま書き直しました(と思います) また、ここでは使ってないですが、本当に、HSV[y][x].H = 0; のような添え字付きで同じものを書く必要があるときは、 struct _HSV *ptr = &HSV[y][x]; とするだけで、 ptr->H のように(あと、ptr->V, ptr->S も同じ)アクセスできるので見かけは変わりますね。 struct colorSetType {  int red;  int green;  int blue; }; struct _HSV { int H; int S; int V; }; int minColor(struct colorSetType color) {  int result = color.red;  if (reuslt > color.green) result = color.green;  if (result > color.blue ) result = color.blue;  return result; } int maxColor(struct colorSetType color) {  int result = color.red;  if (reuslt < color.green) result = color.green;  if (result < color.blue ) result = color.blue;  return result; } strcut _HSV getHSV(struct colorSetType color) {  struct _HSV resut;  int max = maxColor(color);  int min = minColor(color);  int diff = max - min;  if (min == max)  {   result.H = 0;   result.S = 0;   result.V = color.blue;  }  else if (color.red == max)  {   result.H = 60 * (color.green - color.blue) / diff;  }  else if (color.green == max)  {   result.H = 60 * (color.blue - color.red) / diff;   result.V += 120;  }  else  {   result.H = 60 * (color.red - color.green) / diff;   result.V += 240;  }  if (result.H < 0) result.H += 360;  return result; } int main() {  struct _HSV HSV[2000][2000];  struct colorSetType p;  int x;  int y;  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.blue = src_img->imageData[src_img->widthStep * y + x * 3]; // B   p.green = src_img->imageData[src_img->widthStep * y + x * 3 + 1]; // G   p.red = src_img->imageData[src_img->widthStep * y + x * 3 + 2]; // R   HSV[y][x] = getHSV(p);   if(x % 60== 0)   {   fprintf(fp, "%d ,%d\n", HSV[y][x].H, HSV[y][x].S);   }   } } return 0; }

mitti0157
質問者

お礼

迅速かつ、わかりやすい説明ありがとうございます。 大変勉強になります! これをもとにプログラムを組んでみようと思います。 ありがとうございました。

関連するQ&A

  • OpenCV での画素値の比較について

    サイズが同じ2枚のbmp画像(img1とimg2)の色をピクセルごとに比較し、同じ色ならそのピクセルを白、違う色なら黒にして、3枚目(img3)の画像を生成するコードを書いています。 imgとimg2は同じ画像ですが、img2にのみ「あ」という文字が書いてあります。うまくいけばimg3には、白い背景に「あ」と黒く表示されるはずです。 ところが、結果に「あ」と表示されません。ピクセル単位で比較していますが、白い背景に、まだらなな黒色と、2~3ミリ四方の同じ大きさの黒い四角形もたくさん(規則的にではなく、ランダムに)表示されます。 img1と2と3が、それぞれ違うピクセルを参照しているのだろうかと、自分なりに調べていますが、どこがまずいのかわからず困っています。どなたかおわかりになれば、ぜひアドバイスをいただけると助かります。 どうぞ宜しくお願い致します。 === int main (int argc, char :: argv) { int x, y, i; uchar p1[3], p2[3]; IplImage *img1, img2, img3; img1 = cvLoadImage ("D:\\...\\ichimaime.bmp", CV_LOAD_IMAGE_COLOR); img2 = cvLoadImage ("D:\\...\\nimaime.bmp", CV_LOAD_IMAGE_COLOR); img3 = cvCreateImage(cvSize (100, 100), IPL_DEPTH_8U, 3); cvZero (img3); for (y = 0 ; y < img1->height; y++) { for (x = 0 ; x < img1->width, x++) { //一枚目の画素値 p1[0] = img1->imageData[img->widthStep * y + x * 3]; // B p1[1] = img1->imageData[img->widthStep * y + x * 3 + 1]; // G p1[2] = img1->imageData[img->widthStep * y + x * 3 + 2]; // R //二枚目の画素値 p2[0] = img2->imageData[img->widthStep * y + x * 3]; // B p2[1] = img2->imageData[img->widthStep * y + x * 3 + 1]; // G p2[2] = img2->imageData[img->widthStep * y + x * 3 + 2]; // R if ( p1[0]!=p2[0] || p1[1]!=p2[1] || p1[2]!=p2[2] ) { /*もし違う色なら黒にする*/ img3-> imageData[img3->widthStep * y + x * 3] = 0; img3-> imageData[img3->widthStep * y + x * 3 +1] = 0; img3-> imageData[img3->widthStep * y + x * 3 +2] = 0; }else{ /*もし同じ色なら白にする*/ img3-> imageData[img3->widthStep * y + x * 3] = 255; img3-> imageData[img3->widthStep * y + x * 3 +1] = 255; img3-> imageData[img3->widthStep * y + x * 3 +2] = 255; } } } cvNmaedWindow(“Image”, CV_WINDOW_AUTOSIZE); CVsHOWiMAGE (“Image”, img3); cvWaitKey(0); cvDestroyWindow(“Image”); cvReleaseImage (&img1); cvReleaseImage (&img2); cvReleaseImage (&img3); return 0; } ===

  • opencv BGR成分を指定し、該当するピクセルの位置を表示させる

    トラックバー1,2,3を使用します。 トラックバー1,2,3がそれぞれB,G,Rの値を指定します。 トラックバー1、2、3で指定したBGR成分を持つピクセルの色情報の座標をforループと、if文で探しprintfで表示させます。 私が作成したプログラムだとコンパイルは通りますが、BGR=(0,0,0)の時にのみ、x=0~254y=0~254が羅列されますが、上記の動作をしてくれません。 どなたかアドバイスお願いします。 #include <cv.h> #include <highgui.h> #include <stdio.h> /* グローバル変数 */ CvFont font; IplImage *img; int B = 0; int G = 0; int R = 0; uchar p[3]; void on_trackbar1 (int val1); void on_trackbar2 (int val2); void on_trackbar3 (int val3); int main (int argc, char *argv[]) { img = cvLoadImage ( "bgr2.jpg", CV_LOAD_IMAGE_COLOR); cvInitFont (&font, CV_FONT_HERSHEY_DUPLEX, 1.0, 1.0); cvNamedWindow ("Image", CV_WINDOW_AUTOSIZE); cvCreateTrackbar ("B", "Image", 0, 255, on_trackbar1); cvCreateTrackbar ("G", "Image", 0, 255, on_trackbar2); cvCreateTrackbar ("R", "Image", 0, 255, on_trackbar3); cvShowImage( "Image", img); cvWaitKey (0); cvDestroyWindow ("Image"); cvReleaseImage (&img); return 0; } void on_trackbar1 (int val1) { printf ("B=%d G=%d R=%d %d %d %d\n ", B,G,R,p[0],p[1],p[3] ); B = val1; char str [64]; int x, y; for (y = 0; y < img->height; y++) { for (x = 0; x < img->width; x++) { ((uchar*)(img->imageData + img->widthStep*y))[x*3]=p[0]; ((uchar*)(img->imageData + img->widthStep*y))[x*3+1]=p[1]; ((uchar*)(img->imageData + img->widthStep*y))[x*3+2]=p[2]; if ((p[0] == B) && (p[1] == G) && (p[2] == R)) { printf ("X=%d Y=%d %d %d %d\n ", y, x, p[0],p[1],p[3] ); } } } } void on_trackbar2 (int val2) { printf ("B=%d G=%d R=%d %d %d %d\n ", B,G,R,p[0],p[1],p[3] ); G = val2; char str [64]; int x, y; for (y = 0; y < img->height; y++) { for (x = 0; x < img->width; x++) { ((uchar*)(img->imageData + img->widthStep*y))[x*3]=p[0]; ((uchar*)(img->imageData + img->widthStep*y))[x*3+1]= p[1]; ((uchar*)(img->imageData + img->widthStep*y))[x*3+2]=p[2]; if ((p[0] == B) && (p[1] == G) && (p[2] == R)) { printf ("X=%d Y=%d %d %d %d\n", y, x, p[0],p[1],p[2] ); } } } } void on_trackbar3 (int val3) { printf ("B=%d G=%d R=%d %d %d %d\n ", B,G,R,p[0],p[1],p[2] ); R = val3; char str [64]; int x, y; for (y = 0; y < img->height; y++) { for (x = 0; x < img->width; x++) { ((uchar*)(img->imageData + img->widthStep*y))[x*3]=p[0]; ((uchar*)(img->imageData + img->widthStep*y))[x*3+1]=p[1]; ((uchar*)(img->imageData + img->widthStep*y))[x*3+2]=p[2]; if ((p[0] == B) && (p[1] == G) && (p[2] == R)) { printf ("X=%d Y=%d %d %d %d\n", y, x, p[0],p[1],p[2] ); } } } }

  • 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フレーム前の値”というのを、どのように表現していいかわからないのです・・

  • IplImageをHSの閾値から2値化をしようとしています.

    IplImageをHSの閾値から2値化をしようとしています. 表示させたい画像は1920x1080で取り込んだ1枚の画像の2値化です. しかし以下のプログラムを実行し実際画像を見てみると, 1枚の画像の中にx=1080以降から 同じ画像がもう一枚でてきます. どうすれば一枚の画像をそのまま2値化して表示することができますか? よろしくおねがいします. xx=1920; yy=1080; for(yy = 0; yy < frame->height; yy++) {   for(xx = 0; xx < frame->width; xx++)   { if(HSV[yy][xx].H > HMin && HSV[yy][xx].H < HMax && HSV[yy][xx].S > SMin && HSV[yy][xx].S < SMax) {   src_buf[frame->width * yy + xx] = 1;   frame->imageData[frame->widthStep * yy + xx * 3] = 0x00;   frame->imageData[frame->widthStep * yy + xx * 3 + 1] = 0x00;   frame->imageData[frame->widthStep * yy + xx * 3 + 2] = 0x00; } else{   src_buf[frame->width * yy + xx] = 0;   frame->imageData[frame->widthStep * yy + xx * 3] = 0xff;   frame->imageData[frame->widthStep * yy + xx * 3 + 1] = 0xff;   frame->imageData[frame->widthStep * yy + xx * 3 + 2] = 0xff; }   } }

  • Yesならこっちへ、NOならあっちへ(c++)

    取り組んでる課題で、Yとタイプしたら1のステップにいけて、Nとタイプしたら2のステップに行くというところでわからなくなってしまいました。Userにそういう選択させるのには何をどう書いたらいいのですか? --------------------------------------------------------------------- 問題:1から100までの整数をUserに選ばせ、Userに、「選んだ数字はXX以上ですか?」と質問を繰り返し、最後にUserの選んだ数字を当てるという課題です。(Userはそれに対してYes/Noでしか答えられません。) --------------------------------------------------------------------- int max=100; int min=0; int mid, x; int systemtype=y, sytemtype=n; main(){ while(1){ cout<<"1から100までで好きな数字を選んでね。"; cin>> x; if (n<=0 || n>=100){ break; } if (mid == (max + min)/2){ cout<<"選んだ数字は :" << mid << " より大きい? "<< endl; cout<<" y は YES, n は NO :" << endl; } else if(min == max){ cout<<"その数字は" << x <<endl; break; } else if(min == mid){ mid += ( max - mid)/2; cout<<"あなたの選んだ数は :" << mid <<" より大きい? "<<endl; } else if(max == mid){ mid -= (mid - min)/2; cout<<"あなたの選んだ数は:" << mid << " より大きい? "<< endl; } else cout<<"その数字は :"<< n <<endl; } return 0; }

  • Iplimageについて

    Iplimageについて プログラムを組み立てた際, 以下のエラー文がでてきます。 Null pointer(NULL array pointer is passed) in function cvGetMat, C:\user\VP\opencv\cxcore\src\cxarray.cpp(2780) Press "Abort" to terminate application. Press "Retry" to debug (if the app is running under debugger). Press "Ignore" to continue(this is not safe). これが、 空のポインタを渡したとき 出るエラー文だとわかったのですが、以下のように組むと cvSaveImageのときにエラー文が発生します。 また、cvShowImageではエラー文は出ません。 (ただ、cvShowImageの場合、画像の大きさがディスプレイよりも 大きいために調整して出力されるので全体が見えません・・・) IplImage *src_img = 0, *dst_img = 0; src_img = cvLoadImage ("a.jpg", CV_LOAD_IMAGE_COLOR); //画像読み込み dst_img = cvCloneImage(src_img); //dst_imgを黒画像に for(int y = 0; y < dst_img->height ; y++) { for(int x = 0; x < dst_img->width ; x++) { dst_img->imageData[dst_img->widthStep * y + x * 3] = 0x00; dst_img->imageData[dst_img->widthStep * y + x * 3 + 1] = 0x00; dst_img->imageData[dst_img->widthStep * y + x * 3 + 2] = 0x00; } } cvSaveImage("test.jpg",dst_img); 空のポインタはcvCloneImageをすることで 回避できているのではと考えたのですが・・・ なぜエラーが発生するのかご教授よろしくお願いします。

  • OpenCv 透明度について

    OpenCv 透明度について 透明度を表すRGBAのA(アルファチャネル)をいじって画像の透明にしたいのですが、いじってみてもなにも変化がありません。 なにが悪いのかわかりません ↓こんな感じでやってます。 // 画像を読み込む src_img = cvLoadImage(src_imgfile,CV_LOAD_IMAGE_COLOR); //RGBA変換 dst_img = cvCreateImage(cvGetSize(bg_img),IPL_DEPTH_8U,4); cvCvtColor(bg_img,dst_img,CV_RGB2RGBA); //透明度をいじる for ( int y = 0 ; y < dst_img->height ; y++ ) { for ( int x = 0 ; x < dst_img->width ; x++ ) { dst_img->imageData[dst_img->widthStep * y + x * 4 + 3] = -255; } }

  • 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); }

  • openCVでの白黒画像読み込み

    いつも大変お世話になっております。 ピクセルの値を「ゼロ(黒)」にしたピクセルを読み込んでも「255(白)」となってしまい困っています。cvShowImageでこの画像を表示すると、どうみてもその場所は黒です。 なぜ「255(白)」になるのかわからず困っています。 原因を教えていただけませんでしょうか。 詳細は以下のとおりです。 out_imgという変数名のCV_LOAD_IMAGE_COLORの真っ白の画像 out_img = cvLoadImage("C:...\shiro.jpg", CV_LOAD_IMAGE_COLOR); の6×6ピクセルの値を、以下の文で「黒」にして    out_img->imageData[out_img->widthStep * 6 + 6 * 3] = 0;    out_img->imageData[out_img->widthStep * 6 + 6 * 3 + 1] = 0;    out_img->imageData[out_img->widthStep * 6 + 6 * 3 + 2] = 0; 保存し、再び(別のソリューションで)src_img変数としてこの画像を読み込み    src_img = cvLoadImage("C:...¥shiro.jpg", CV_LOAD_IMAGE_COLOR); グレースケール化し、       src_img_gray = cvCreateImage(cvGetSize(src_img), IPL_DEPTH_8U, 1); tmp_img = cvCreateImage(cvGetSize(src_img), IPL_DEPTH_8U, 1 ゼロイチの2値化(バイナリ画像)に変換し、 cvCvtColor(src_img, src_img_gray, CV_BGR2GRAY); 閾値でゼロイチに変換した後(なぜか上のsrc_img_grayでは黒がゼロにはならないため) cvAdaptiveThreshold(src_img_gray, tmp_img, 255, CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, 7, 8); 6×6の位置の値(変数iro)を確認すると「255」となります。 for (x = 0; x < tmp_img->width; x = x + 1){ // x 座標を 1ピクセルずつ進める for (y = 0; y < tmp_img->height; y = y + 1){ // y 座標を 1ピクセルずつ進める if (x == 6 && y == 6){ x = 6; (ここでデバックを掛けて、下の変数iroの値がいくつかを確認しています。ゼロであってほしいのですが、255です。 } uchar iro = tmp_img->imageData[tmp_img->widthStep * y + x * 3]; if (iro == 0){ 画像読み込みの引数がおかしいのだろうと思い、 CV_LOAD_IMAGE_ANYCOLOR や「0」にしたところ 今度はfor文のところでエラーになり、走査が始まりません。 for (x = 0; x < tmp_img->width; x = x + 1){ // x 座標を 1ピクセルずつ進める for (y = 0; y < tmp_img->height; y = y + 1){ // y 座標を 1ピクセルずつ進める 初歩的な質問で申し訳ありません。 ぜひアドバイスをいただけると助かります。 どうぞよろしくお願い致します。

  • 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; }

専門家に質問してみよう