ピクセルの座標を取得する方法

このQ&Aのポイント
  • OpenCVを使ってピクセルの座標を取得する方法について教えてください。
  • 輪郭抽出のプログラムでうまくいかないところがあります。頂点を保存する方法を教えてください。
  • ピクセルの座標を取得するための修正方法について教えてください。
回答を見る
  • ベストアンサー

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

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

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

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

画像は小さくて、全然わかりません。 lap_img->imageData[lap_img->widthStep * k + (j + 1) * 3 ] = 0; を直したようですが、そもそもこれは何のために入れているのですか? 範囲外になる、という他にも、ループの最後にある cb = lap_img->imageData[lap_img->widthStep * k + j * 3]; は、 その前でj++された状態なので、 lap_img->imageData[lap_img->widthStep * k + (j + 1) * 3 ] = 0; で0にした場所です。ということは、cbは必ず0になります。 つまり  j=0、cb=-1でループに入る  x座標0 を0にする  x座標1 も0にする  j++  x座標j(つまりx座標1) の値をcbに代入する。(つまり、cb=0)  ループ終了 となります j = j++; これ、意味わかってますか? たまたま期待通りに動いているかもしれませんが、それはたまたまであって、常にそうなるわけではありません。 j ++ のように、++を後に付けると j の値を使う → j=j+1 にする と動作します。  j0 = j ++ なら  oldJ = j ;  j0 = oldJ ;  j = j + 1 ; と等価です。 では、 j= j++ がどうなるか、というと、決まっていません。  j= oldJ と  j=j+1 が、どちらが先に実行されるか、C言語としては決まっていないのです。  oldJ = j ;  j = oldJ ;  j = j + 1 ; で実行されれば、 j は一つ増えますが  oldJ = j ;  j = j + 1 ;  j = oldJ ; だったら、jは前のままです。 単に一つ増やしたいだけなら、 j++ だけ書きましょう。 で、前回も書きましたが、 jを0にしてから始めるのですから、素直に  for( j=0; j < 11 && cb == -1; j ++ ) にして、ループ後のj++を抜いた方がいいのではないでしょうか? さらに  while(j < 11 && cb == -1){ // j = x軸 となっているのを  for( j=0; j < 11; j ++ ) {   cb = lap_img->imageData[lap_img->widthStep * k + j * 3];   if ( cb != -1 ) { break ; } とすれば、ループ終わりのcb=~が不要になります。

rosafilipes
質問者

お礼

kmeeさま 2度も長い丁寧なコメントをくださいまして、本当にありがとうございました! 間違いがわかり、ようやく、ようやくまともに動きました。 もちろん、ピクセルの座標もまともに取得できるようになりました。 ひとつひとつどこがどうおかしいか、自分で自覚して確認できるアドバイスを くださいまして、本当にありがとうございました。 もう、毎回ですけれども、本当に感謝しています! ありがとうございました!!!

その他の回答 (3)

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

追記します。 まず、やろうとしていることを、日本語(またはあなたが普段使う母国語)で書いてみましょう。 最初はおおざっぱでいいです。 次に「おおざっぱ」の各項目で何をするのか、より細かく書きます。 さらに細かく... と続けて、機械的にC言語の命令に置き換えられる、というくらいまでになったら、C言語に「翻訳」してください。 この設計がちゃんとできていないから、プログラムをどう直していいかもわからないのでは? うまく動作しないときも、設計図通りに動作していてるなら直すべきは設計図、設計図通りに動作していないなら直すべきはプログラム、と修正箇所の切り分けができます。 この設計図が無ければ、「明らかにおかしい」という箇所しか指摘できません。 指摘できても、修正方法まで指摘できないこともあります。 ・j=j++ は「明らかにおかしい」し、意図を推測できたので、修正方法も指摘できました ・+ j * 3 + 3 は範囲外になるという点では「明らかにおかしい」ですが、これが何を意図したものかが理解できないので、修正方法は指摘できません。 ・top変数の扱いは、top変数が何を意図したものかがわからないので、指摘も修正もできません。 画像全体で境界線の最も右の座標、なら、このプログラムの通りになりますが 注目y座標での境界線の座標、なら、jのループの前に初期化する必要があります。 コメントが少ないのも、わかりずらい理由の一つです。 先のtopについても、コメントで説明があれば解決します 例えば、設計図からプログラムへは次のような流れになります 輪郭の座標を抽出する ↓ 左上から走査して、白→黒になった座標を抽出する ↓ 「左上から走査」とは 「左から右へ走査」を上から下まで順番に行う  ↓  「上から下まで」とは y座標を0から最大y座標(今回は10)まで繰り返すこと  ↓  for( k=0 ; k < 11 ; k ++ ) {   「左から右へ走査して変化点を探す」  }

rosafilipes
質問者

お礼

はい、わかりました。 次回からもっとコメントを多く書いておおまかな流れを誰が見てもわかるように残すようにします。 足りないところを補足して考えてくださいまして、ありがとうございました。 毎回 貴重なアドバイスをありがとうございます。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

いちおうねんのため: j=j++; でどうなるかは確かに #2 でいわれているように「決まっていない」のですが, 正確にいうと 未定義動作である と決まっています. 「未定義動作」ですから, 何が起きても規格上は全く問題ありません. たとえプログラムを実行している途中で突然鼻歌を歌い出したとしても文句を言ってはいけないのです.

rosafilipes
質問者

お礼

そうなのですね、知りませんでした。 鼻歌を歌いださないように気を付けます(笑) いろいろとわかっていなくて、アドバイスいただけるととても助かります。 ありがとうございました!

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

そもそも、何をどうしたいのかが、プログラムから読み取るのが困難です。 ・ while(j < 11 && cb == -1){ // j = x軸 のループの中で j = 0; k = k + 1; を実行しています。つまり、 lap_img->imageData[lap_img->widthStep * k + j * 3] = 0; のjは常に0であり、「左上から右へ走査し」ているつもりが、一番左を縦に走査しています。 ただ、それだと printf("%d, %d\n", tate[k],top); でtopの値が変化する理由がわかりません。 本当にこのプログラムの結果なのでしょうか? 質問する際に、実際のプログラムをコピーして貼り付けていますか? 結果、またはプログラムをここに書き込む際に間違えていませんか? あとは、今回とは関係無いかもしれませんが。 ○ 変数cbの型は? IPLImageのimageDataはchar * 型であり、char が符号付き整数になっていることがよくあります。 そのため cb = lap_img->imageData[lap_img->widthStep * k + j * 3]; だと、画素の値が255 だと cb = -1 になったりします。 0か255かの判定くらいならまだいいのですが、 画素Aと画素Bのどちらが明るいか、とかの場合には、判定が難しくなります。 ( 0と64では64の方が明るいですが、 64 と -1では-1の方が明るい、ということになります) cbをunsignd charとか、int等の整数にして、255までの正の整数が扱えるようにして cb =(uchar)( lap_img->imageData[lap_img->widthStep * k + j * 3] ); 等と、符号無しcharに型変換するとかしましょう。 ○次の処理 lap_img->imageData[lap_img->widthStep * k + j * 3 + 3] = 0; lap_img->imageData[lap_img->widthStep * k + j * 3 + 4] = 0; は lap_img->imageData[lap_img->widthStep * k + (j + 1) * 3 ] = 0; lap_img->imageData[lap_img->widthStep * k + (j + 1) * 3 + 1] = 0; と同じであり、x座標 j+1の画素のうち、2つのチャンネルを0にしています。 これは意図した操作なのでしょうか? このままだと、 j=10 のときに X座標11という範囲外にアクセスします。 C言語の仕様で、範囲外にアクセスすること自体は可能ですが、その結果どうなるかは保証されていません。 ○同じく j = j + 1; の後で cb = lap_img->imageData[lap_img->widthStep * k + j * 3]; をしていますが、 j=10のループのときは j=j+1でj=11になり、そのj=11を使って座標を求めようとします。 これも範囲外です。 ○このプログラムだと、y座標kの一番左が白でないとその横一列はなにもしないことになります。 それでいいのでしょうか? ○変数topが初期化されていないようですが、それでいいのですか? 例えば k=0のとき top=6 だと k=1の境界線が4でもtop=6のままです。 ○この例ならwhileではなくforの方がいいのでは? ○ (top == j || top < j) は (top<=j)とも書けます。というより、普通はそうします。

rosafilipes
質問者

お礼

kmeeさま いつもとても迅速に丁寧なアドバイスをくださいまして、ありがとうございます。 プログラムの処理経過のスクリーンショットを添付致しますので ご参照いただけますでしょうか。 なお、コードは以下のように修正致しました。 ==== tate[11] = { 0}; yoko[11] = { 0}; if (ue == 1 && shita == 1) { top = 0; 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; if (j < 11){ lap_img->imageData[lap_img->widthStep * k + (j + 1) * 3] = 0; lap_img->imageData[lap_img->widthStep * k + (j + 1) * 3 + 1] = 0; } yoko[j] = j; // x方向 if (top <= j){ top =j; } j = j++; cb = lap_img->imageData[lap_img->widthStep * k + j * 3]; printf("%d, %d\n", k, j); //printf("%d\n", k); //printf("%d\n", j); } cvShowImage("Shirokuro", lap_img); cvWaitKey(0); k =k ++; j = 0; } } =====

関連する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] ); } } } }

  • opencvの画像データを格納する構造体IplImageについて質問で

    opencvの画像データを格納する構造体IplImageについて質問です。 今opencvを用いて画像処理をしていて、test1とtest2という画像データを宣言して test1からは横:縦が640:512の画像を読み込みます。 そして、IplImageの中のImageDataにアクセスし、test2のImageDataにtest1のImageDataを 各ピクセルに代入して、test2という画像データをウィンドウに表示させたいと思ってます。 私的にはtest1とtest2には同じ画像データが表示されると考えているのですが、実際に実行してみると 少し違う画像が表示され、次のようなエラーが表示されます。 「"0x7c951909"の命令が"0xfffffff8"のメモリを参照しました。メモリが"read"になることはできませんでした。」 実際にCの中では以下のようにプログラムを組んでいます。 for(i=0;i<test->height;i++){ for(j=0;j<test->widthStep;j++){ *(test2->imageData+test2->widthStep*i+j)=*(unsigned char *)(test->imageData+i*test->widthStep+j); } } 何が原因なのか教えていただけないでしょうか。

  • 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ピクセルずつ進める 初歩的な質問で申し訳ありません。 ぜひアドバイスをいただけると助かります。 どうぞよろしくお願い致します。

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

    3次元配列を用いて、ルックアップテーブルを作成しているのですが、下のようなエラーが出て困っています。 『○○○の 0x000000013f336f85 でハンドルされていない例外が発生しました: 0xC0000005: 場所 0xffffffffffffffff を読み込み中にアクセス違反が発生しました。』 いろいろ調べてみたのですが、私自身の力だけでは解読できません。 どうぞよろしくお願いします。 //LUTの作成 int ***LUT = new int**[180]; for(int i=0;i<180;i++){ LUT[i] = new int*[255]; } for(int i=0;i<180;i++){ for(int j=0;j<255;j++){ LUT[i][j] = new int[255]; } } for(int i = 0; i < 180; i++){ for(int j = 0; j < 255; j++){ for( int k = 0; k < 255; k++){ LUT[i][j][k]= 0; if(6 < i && i< 38){ if( 79 < j && j < 256){ if( 0 <= k){ LUT[i][j][k] = 1; } } } } } } //LUT作成終了 cvCvtColor(image3, image5, CV_BGR2HSV); IplImage* image5 = cvCreateImage(cvSize(640, 480), IPL_DEPTH_8U, 3); //if(hand == 0){ for(int i = 0; i < 480; i++){ for(int j = 0; j <680 ; j++){ //判定(LUT[ Hの値 ][ Sの値 ][ Vの値 ] ) if((LUT[(unsigned char)image5->imageData[( i * image5->widthStep + j) * 3 + 0]] [(unsigned char)image5->imageData[( i * image5->widthStep + j) * 3 + 1]] [(unsigned char)image5->imageData[( i * image5->widthStep + j) * 3 + 2]]) == 1){ printf("1\n"); } else{ printf("0\n"); } } } //LUT no atosyori for(int i=0;i<180;i++){ for(int j=0;j<255;j++){ delete[] LUT[i][j]; } } for(int i=0;i<180;i++){ delete[] LUT[i]; } delete[] LUT; よろしくお願いします。

  • opencvを用いた二値画像のアクセスと座標の取得

    いつもお世話になっています。 opencvを用いたプログラムを作成しています。 真ん中に大きな塗りつぶされた●が1つあるカラー画像を二値画像に変換して、●の部分のすべての座標をとりたいと考えています。(●は大きいので1ピクセルではありません。●を構成しているピクセルの座標すべてをとるといった感じです。) 今、途中まで作成したのですが間違っているところがあると考えられるので、エラーは出ないのですがプログラムが正常に動きません。このプログラム内での間違いであるとは考えられるので、間違っている部分を教えてもらえないでしょうか? よろしくお願いします。 //元のカラー画像 IplImage* image = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3); IplImage* gray_image = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1); //二値画像 IplImage* niti_image = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1); //座標を入れるための配列 int test_width[500]; int test_height[500]; //カラー画像ここでimage画像に大きな●を書きました。これ以降は●がimageに存在するものとして考えてくださいお願いします cvDrawContours( image, hand_contour[0], CV_RGB (0, 0, 0), CV_RGB (0, 0, 0), -1, CV_FILLED, 8 ,cvPoint(0,0)); //グレースケールの作成 cvCvtColor(image,gray_image,CV_BGR2GRAY); // 画像の二値化【判別分析法(大津の二値化)】 cvThreshold (gray_image, niti_image, 90, 255, CV_THRESH_BINARY); int k = 0;      // 左上から順番に画像を見ていく for( int y = 0; y < niti_image->height; y++){ for(int x = 0; x < niti_image->width; x++){ //もし黒色の値が入っていたら配列に座標を代入する if(niti_image->imageData[y * niti_image->widthStep + x * niti_image->nChannels] == 0){ test_width[k] = x; test_height[k] = y;   k++;             }//if } }

  • openCVの画像処理について

    画像の中にある粒子の位置を検出し、座標の値の取得をどうしてもOpenCVをつかって、出したいと考えております。 プログラミングが実行したら、すべて0と表示されたり、エラーが出たりします。 現在、画像を読み込み、2値化し、2値化した画像の画素数を列ごとに足して、垂直方向の画素数の最大値の検出、2値化した画像の画素数を行ごとに足して、水平方向の画素数の最大値の検出を行っています。 使用した画像を添付させていただきますので、もしアドバイスなどいただけたらよろしくお願い致します。 #include <stdio.h> #include <math.h> #include <cv.h> #include <cxcore.h> #include <highgui.h> #define X 640 #define Y 480 IplImage *grayImage; //グレースケール画像用IplImage IplImage *binaryImage; //2値画像用IplImage char windowNameBinarization[] = "Binarization";//2値化した画像を表示するウィンドウの名前 int levels = 115; //トラックバーの値(2値化の際の閾値) static int h[X][Y]; int main( /*int argc, char **argv*/ ){ // 画像を読み込む IplImage *sourceImage = cvLoadImage( "C:/Documents and Settings/Owner/My Documents/My Pictures/Logicool Webcam/Picture 10.jpg",CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR); if ( sourceImage == NULL ) { // 画像が見つからなかった場合 printf( "画像が見つかりません\n" ); return -1; } // 画像を生成する IplImage *grayImage = cvCreateImage( cvGetSize(sourceImage), IPL_DEPTH_8U, 1 );//グレースケール画像用IplImage IplImage *binaryImage = cvCreateImage( cvGetSize(sourceImage), IPL_DEPTH_8U, 1 ); //2値画像用IplImage // BGRからグレースケールに変換する cvCvtColor( sourceImage, grayImage, CV_BGR2GRAY ); // グレースケールから2値に変換する cvThreshold( grayImage, binaryImage, levels, 255, CV_THRESH_BINARY ); /*グラフ値の取得*/ IplImage *img; img = cvCloneImage (binaryImage); //画像をコピー int bytes_per_pixel = ((img->depth & 255) / 8) * img->nChannels; // (1)画素値を順次取得 int i,j,k,t; int Hy[Y],Hx[X]; //宣言 //垂直方向の画素値 for(k = 0; k <Y /*img->height*/; k++) { Hy[k] = 0;//初期化 } if((unsigned char)img->imageData>levels){ for(j = 0;j < Y/*img->height*/; j++) { for(i = 0; i < X; i++) {Hy[j] += *(img->imageData + (img->widthStep*j) + (i*bytes_per_pixel)); } }} //水平方向の画素値 for(t = 0; t < X/*img->width*/; t++) { Hx[t]=0; //初期化 } if((unsigned char)img->imageData>levels){ for(i = 0;i < X/*img->width*/; i++) { for(j = 0;j < Y; j++) { Hx[i] = Hx[i]+h[i][j]; } }} //Hy[j]の最大値の座標を調べる int MY = Hy[0]; int my = 0; for(int j=0; j< Y-1; j++){ if(Hy[j]<Hy[j+1]){ MY = Hy[j+1]; my = j+1; } } //Hx[i]の最大値の座標を調べる int MX = Hx[0]; int mx = 0; for(int i=0; i< X-1; i++){ if(Hx[i]<Hx[i+1]){ MX = Hx[i+1]; mx = i+1; } } printf("垂直方向の最大値 %d , 垂直方向の最大値になるときのy軸の値 %d \n", MY,my); printf("水平方向の最大値 %d , 水平方向の最大値になるときのx軸の値 %d \n", MX,mx); int cvWaitKey(int delay=10); //どこでとめるかをあらわす cvReleaseImage( &sourceImage ); cvReleaseImage( &grayImage ); cvReleaseImage( &binaryImage ); cvDestroyWindow( windowNameBinarization); return 0 ; }

  • OPEN

    画像の中にある粒子の位置を検出し、座標の値の取得をどうしてもOpenCVをつかって、出したいと考えております。 プログラミングが実行したら、すべて0と表示されたり、エラーが出たりします。 現在、画像を読み込み、2値化し、2値化した画像の画素数を列ごとに足して、垂直方向の画素数の最大値の検出、2値化した画像の画素数を行ごとに足して、水平方向の画素数の最大値の検出を行っています。 使用した画像を添付させていただきますので、もしアドバイスなどいただけたらよろしくお願い致します。 #include <stdio.h> #include <math.h> #include <cv.h> #include <cxcore.h> #include <highgui.h> #define X 640 #define Y 480 IplImage *grayImage; //グレースケール画像用IplImage IplImage *binaryImage; //2値画像用IplImage char windowNameBinarization[] = "Binarization";//2値化した画像を表示するウィンドウの名前 int levels = 115; //トラックバーの値(2値化の際の閾値) static int h[X][Y]; int main( /*int argc, char **argv*/ ){ // 画像を読み込む IplImage *sourceImage = cvLoadImage( "C:/Documents and Settings/Owner/My Documents/My Pictures/Logicool Webcam/Picture 10.jpg",CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR); if ( sourceImage == NULL ) { // 画像が見つからなかった場合 printf( "画像が見つかりません\n" ); return -1; } // 画像を生成する IplImage *grayImage = cvCreateImage( cvGetSize(sourceImage), IPL_DEPTH_8U, 1 );//グレースケール画像用IplImage IplImage *binaryImage = cvCreateImage( cvGetSize(sourceImage), IPL_DEPTH_8U, 1 ); //2値画像用IplImage // BGRからグレースケールに変換する cvCvtColor( sourceImage, grayImage, CV_BGR2GRAY ); // グレースケールから2値に変換する cvThreshold( grayImage, binaryImage, levels, 255, CV_THRESH_BINARY ); /*グラフ値の取得*/ IplImage *img; img = cvCloneImage (binaryImage); //画像をコピー int bytes_per_pixel = ((img->depth & 255) / 8) * img->nChannels; // (1)画素値を順次取得 int i,j,k,t; int Hy[Y],Hx[X]; //宣言 //垂直方向の画素値 for(k = 0; k <Y /*img->height*/; k++) { Hy[k] = 0;//初期化 } if((unsigned char)img->imageData>levels){ for(j = 0;j < Y/*img->height*/; j++) { for(i = 0; i < X; i++) {Hy[j] += *(img->imageData + (img->widthStep*j) + (i*bytes_per_pixel)); } }} //水平方向の画素値 for(t = 0; t < X/*img->width*/; t++) { Hx[t]=0; //初期化 } if((unsigned char)img->imageData>levels){ for(i = 0;i < X/*img->width*/; i++) { for(j = 0;j < Y; j++) { Hx[i] = Hx[i]+h[i][j]; } }} //Hy[j]の最大値の座標を調べる int MY = Hy[0]; int my = 0; for(int j=0; j< Y-1; j++){ if(Hy[j]<Hy[j+1]){ MY = Hy[j+1]; my = j+1; } } //Hx[i]の最大値の座標を調べる int MX = Hx[0]; int mx = 0; for(int i=0; i< X-1; i++){ if(Hx[i]<Hx[i+1]){ MX = Hx[i+1]; mx = i+1; } } printf("垂直方向の最大値 %d , 垂直方向の最大値になるときのy軸の値 %d \n", MY,my); printf("水平方向の最大値 %d , 水平方向の最大値になるときのx軸の値 %d \n", MX,mx); int cvWaitKey(int delay=10); //どこでとめるかをあらわす cvReleaseImage( &sourceImage ); cvReleaseImage( &grayImage ); cvReleaseImage( &binaryImage ); cvDestroyWindow( windowNameBinarization); return 0 ; }

  • 教えてください。

    画像を読み込んでRだけの値のピクセル値をだしたいのですがうまくいきません。 ピクセルデータの読み込みは for(i=0;i<HSIZE;i++) { fread(buf,sizeof(unsigned char),WSIZE*3),fp); for(j=0;j<WSIZE;j++) { for(k=0;k<3;k++) { img[HSIZE-1-i][j][k]=buf[j*3+k]; } } } これにprintfを加えてピクセル値の値を出したいのです。 i・縦のカウンタj・横のカウンタ・k・RGBのカウンタ