• 締切済み

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

みんなの回答

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.1

とりあえず、気付いた点 > printf ("B=%d G=%d R=%d %d %d %d\n ", B,G,R,p[0],p[1],p[3] ); p[2]ですよね。 >((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]; これって、 画像のBRGにp[0],p[1],p[2]を代入してることになると思うんですが。

関連するQ&A

  • opencvで特定の座標を指定しその座標の色変換

    #include <cv.h> #include <highgui.h> #include <stdio.h> /* グローバル変数 */ CvFont font; IplImage *img; int num1=0; int num2=0; int num3=0; int num4=0; /* プロトタイプ宣言 */ void on_trackbar1 (int val1); void on_trackbar2 (int val2); void on_trackbar3 (int val3); void on_trackbar4 (int val4); int main (int argc, char *argv[]) { img = cvLoadImage ( "bgr.jpg", CV_LOAD_IMAGE_COLOR); cvInitFont (&font, CV_FONT_HERSHEY_DUPLEX, 1.0, 1.0); cvNamedWindow ("Image", CV_WINDOW_AUTOSIZE); cvCreateTrackbar ("X", "Image", 0, 255, on_trackbar1); cvCreateTrackbar ("Y", "Image", 0, 255, on_trackbar2); cvCreateTrackbar ("COLOR", "Image", 0, 255, on_trackbar3); cvCreateTrackbar ("-", "Image", 0, 100, on_trackbar4); cvShowImage ("Image", img); int x,y; uchar p[3]; for (y = 0; y < img->height; y++) { for (x = 0; x < img->width; x++) { p[0] =((uchar*)(img->imageData + img->widthStep*num2))[num1*3]; // B p[1] =((uchar*)(img->imageData + img->widthStep*num2))[num1*3+1]; // G p[2] =((uchar*)(img->imageData + img->widthStep*num2))[num1*3+2]; // R p[0] = num3; p[1] = num3; p[2] = num3; } } cvWaitKey (0); cvDestroyWindow ("Image"); cvReleaseImage (&img); return 0; } /* コールバック関数 */ void on_trackbar1 (int val1) { num1 = val1; char str[64]; printf ( "X=%d Y=%d C=%d -=%d\n", val1, num2, num3, num4); } void on_trackbar2 (int val2) { num2 = val2; char str [64]; printf ( "X=%d Y=%d C=%d -=%d\n", num1, val2, num3, num4); } void on_trackbar3 (int val3) { num3 = val3; char str [64]; printf ( "X=%d Y=%d C=%d -=%d\n", num1, num2, val3, num4); } void on_trackbar4 (int val4) { num4 = val4; char str [64]; printf ( "X=%d Y=%d C=%d -=%d\n", num1, num2, num3, val4); } このプログラムで特定の座標の色変換をしたいのですがうまくいきません。 トラックバー1でX座標 トラックバー2でY座標 トラックバー3で変更後の色 を指定します。 実行すると画像は表示されますがトラックバーを動かしても変化がありません。トラックバーを動かした時にmain関数に戻れば良いと思い、思いつく限り試しましたが上手くいきません。 どなたかアドバイスお願いします。

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

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

  • for文の変数エラー

    いつも大変お世話になっております。 連日すみません。 以下のfor文で 変数mが初回から「7」になってしまい、困っています。 if(m=0...)を通過した後、次の行でmが「7」に変わっています。 なぜなのか理由がわかりません。 この変数を他の文字に変えても事象は同じです。 renzokuは「6」が代入されています。 初回から「7」になってしまうため、1回で処理が終了してしまい、困っています。 作り直すべきでしょうか? かなり関数を書いたので、移植するときにミスをしないか心配で このままこの文を修正して済むようであればそうしたいのですが。。 int m = 0; if (renzoku > 4) { for (m = 0; m < renzoku + 1; m++); { printf("m = %d\n", m); out_img->imageData[out_img->widthStep * (point_y[m]) + (point_x[m]) * 3] = 0; printf("m = %d\n", m); out_img->imageData[out_img->widthStep * (point_y[m]) + (point_x[m]) * 3 + 1] = 0; printf("m = %d\n", m); out_img->imageData[out_img->widthStep * (point_y[m]) + (point_x[m]) * 3 + 2] = 0; printf("m = %d\n", m); } } どうぞよろしくお願い致します。

  • ピクセルの座標を取得するには

    OpenCVを使っています。 輪郭抽出のプログラムでうまくいかないところがあり困っています。 もし原因や修正方法をおわかりの方がいらしたらぜひアドバイスいただけると助かります。 11×11ピクセルの画像(CV_8UC3)に、一本 上から下に伸びた輪郭線があります。 この輪郭線を境に白黒に塗りつぶしています。 左上から右へ走査し 「もしピクセルが白なら黒にする」 として 処理された画像は輪郭線で白黒に塗り分けることはできました。 このとき、輪郭線の「頂点」を保存したいのですが、うまくいきません。 頂点を表示させると以下のようになってしまいます。 0,0 0,1 0,2 0,3 : 0,10 どこを直すとうまくいくでしょうか。 ========= while (k < 11){ // k = y軸 tate[k] = k; // y方向 cb = lap_img->imageData[lap_img->widthStep * k + j * 3]; while(j < 11 && cb == -1){ // j = x軸 lap_img->imageData[lap_img->widthStep * k + j * 3] = 0; lap_img->imageData[lap_img->widthStep * k + j * 3 + 1] = 0; lap_img->imageData[lap_img->widthStep * k + j * 3 + 2] = 0; lap_img->imageData[lap_img->widthStep * k + j * 3 + 3] = 0; lap_img->imageData[lap_img->widthStep * k + j * 3 + 4] = 0; yoko[k] = j; // x方向 if (top == j || top < j){ top =j; } j = j + 1; cb = lap_img->imageData[lap_img->widthStep * k + j * 3]; printf("%d, %d\n", tate[k],top); j = 0; k = k + 1; } }

  • OpenCvのCvMatについて教えて下さい。

    いつもお世話になっております。 質問ですが、配列で画像のピクセル値(R,G,B)を行列に代入する場合は CvMat *points = cvCreateMat (size, 1, CV_32FC3); ピクセルの値を行列へ代入 for (i = 0; i < size; i++) { points->data.fl[i * 3 + 0] = (uchar) src_img->imageData[i * 3 + 0]; points->data.fl[i * 3 + 1] = (uchar) src_img->imageData[i * 3 + 1]; points->data.fl[i * 3 + 2] = (uchar) src_img->imageData[i * 3 + 2]; } のような流れでできますが、 これをピクセル値ではなく座標(x,y)を代入するにはどのように変更したらよいでしょうか。教えて下さい。

  • IplImageのBmp変換。

    いつもこちらでお世話になっております。 現在OpenCVをつかって画像処理を行なっています。言語はVC++です。 OpenCVで処理した画像をPictureBoxに表示させたいのですが、 うまく表示できません。 IplImageをBmpに変換させる部分がおかしいとは思うのですが… //-------------------------------------------------------- IplImage *img; img = cvLoadImage(filename, 0); // 0: グレイスケールで読み込む cvThreshold(img,img, 70, 255, CV_THRESH_BINARY_INV);//二値化 // ビットマップ用のカラーバッファ char* ColorBuf = (char*)calloc( sizeof(char), img->width * img->height * 4 ); for( int y = 0; y < img->height; y++ ) { for( int x = 0; x < img->width; x++ ) { // Blue ColorBuf[ y * img->width + x * 4 + 0 ] = img->imageData[ y * img->widthStep + x * 3 + 0 ]; // Green ColorBuf[ y * img->width + x * 4 + 1 ] = img->imageData[ y * img->widthStep + x * 3 + 1 ]; // Red ColorBuf[ y * img->width + x * 4 + 2 ] = img->imageData[ y * img->widthStep + x * 3 + 2 ]; } } mbmp.CreateBitmap( img->width, img->height, 1, 32, ColorBuf ); free( ColorBuf ); ((CStatic*)GetDlgItem( IDC_IMGSRC ))->SetBitmap ( mbmp ); myDC.CreateCompatibleDC(pDC); CBitmap *oldBMP = myDC.SelectObject(&mbmp); pDC->BitBlt(0,0,300,300,&myDC,0,0,SRCCOPY); myDC.SelectObject(oldBMP); cvReleaseImage( &img ); //----------------------------------------------- PictureBoxのリソースIDをIDC_IMGSRCに設定しています。 今はPictureBoxの上部に画像が4つ並んでしまっている状態です。 なにか改善すべきところがありましたらよろしくお願いいたします。

  • C言語の問題です

    二つの仮分数の加算を行うプログラミングである。 x/w+z/y=(xy+wz)/(wy) 1. w,x,y,zは正の整数である。 2.上式のように計算した後、約分して結果を求める。約分には最大公約数を使う。最大公約数の計算は関数gcd(a,b)で以下のアルゴリズム(ユークリッド互除法)で行う。 (1) a,bの大きいほうをp,小さいほうをqとする。 (2) pをqで割った余りをrとする。r=0ならqが解。 r≠0なら、q=r、r=qとして(2)に戻る。 3.計算結果が仮分数ならば、帯分数にして出力する。 次のプログラムの空欄((1)から(3):を埋め、完成させて下さい。 #include <stdio.h> int gcd(int a, int b) { int p,q,r; if(a<b) { q=a; p=b; }else{ q=b; p=a; } while(q>0){ (1); p=q; q=r; } (2); } main(){ int g,k,m,n,p,q,w,x,y,z; printf("x/w + z/yの数値を入力して下さい(x w z y)"); scanf("%d %d %d %d, &x,&w,&z,&y"); m= w*y; n=x*y+w*z; p=m; q=n; g=gcd(p,q); m=m/g; n=n/g; if((3)) { k = n/m; n = n - k*m; if(n==0) printf("%d\n",k); else printf("%d %d/%d\n",k,n,m); } else printf("%d/%d\n",n,m); } 全く見当がつきません。どなたかお助け下さい。回答を教えてください。

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

  • 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をすることで 回避できているのではと考えたのですが・・・ なぜエラーが発生するのかご教授よろしくお願いします。

専門家に質問してみよう