• 締切済み

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

みんなの回答

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

X/Y両方同じことをやっているので、Yの方だけを書きます。 > int levels = 115; //トラックバーの値(2値化の際の閾値) >if((unsigned char)img->imageData > levels){ imageDataは画像データが保存されているメモリ空間へのポインタです。 それと、二値化閾値levelsを比較する理由がまったくわかりません。というより、無意味だと思います。 この比較がどうなるかはまったくの不定なので、それ以降の >for(j = 0;j < Y/*img->height*/; j++) > ... は実行されるかどうかは不確定です。 また、imgは > img = cvCloneImage (binaryImage); //画像をコピー ですから、 > cvThreshold( grayImage, binaryImage, levels, 255, CV_THRESH_BINARY ); で二値化され0か255しか入っていない状態です。 Hy[j]の値は「(y座礁=jにあるlevelsを越える画素数) × 255」になりますが、求めているものはそれであっていますか? >//Hy[j]の最大値の座標を調べる 求めているのは最大値ですね?極大値ではないですね? > if(Hy[j]<Hy[j+1]){ は「隣より大きい」、ですから、例えば →0 5 6 7 1 2 1 だったら「7」ではなく「2」になりますよ 最大値なら、比較するのは、「それまでの最大値」と「新たに比較したい数値」です。 int MY = Hy[0]; int my = 0; for(j=1; j< Y; j++){ if(MY < Hy[j]){ MY = Hy[j]; my = j; } } また、余談になりますが >int bytes_per_pixel = ((img->depth & 255) / 8) * img->nChannels; IPL_DEPTH_???の定義を見たら、一応 img->depth & 255 でビット数を取り出せるのを確認しました。 けど、あんまりいい書き方ではないですね。 > cvReleaseImage ... この例ではこれで終了なのでいいですが、 cvReleaseImage( &img ); を忘れています。

yoppi06
質問者

お礼

丁寧なご指導をありがとうございました。プログラミングならびに、opencvは周りに、詳しい方がおらず、本を頼りにプログラミングを書いておりました。まだ初心者で分からないことだらけで、恥ずかしいばかりですが、また機会があれば、ご指導宜しくお願い致します。 本当にありがとうございました。

関連するQ&A

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

  • OpenCV2-画素を配列に格納したい

    こんにちは。 私のパソコンにはOpenCV2.3をインストールしています。 たとえば、 IplImage* img; で読み込んだ画像を pixel[x][y] といった2次元配列に格納したいです。 といいますのも、 for(int i = 0; i < img->width; i++){ for(int j = 0; j < img->heifht; i++){ pixel[i][j] = ~~~~~~; } } といった処理をしたいからです。 ちなみに、この2次元配列にはRGBと輝度値が入っていればOKです。 ...説明が不十分ですが、どうか教えていただけるとすごく助かります>< お願いします!

  • ヒストグラム均等化処理プログラム

    どなたか以下のヒストグラム均等化処理プログラムを解説して頂けないでしょうか。特にgetMinMax関数とgetHistEqu関数で、何がしたいのか訳がわかりません。 以下のプログラムは、ヒストグラム均等化処理部分のみですが、分かる範囲でいいので、解説お願いします。 ------------------------------------------------------- // ヒストグラム均等化による画素値の割り当てを決定する // hist :入力画像のヒストグラム // min :割り当てられる画素値の最小 // max :割り当てられる画素値の最大 // たとえば,min[5]=4 max[5]=6の場合,画素値5には4-6の範囲に割り当てられる // pixs_min :最小値が割り当てられる画素数 // pixs_max :最大値が割り当てられる画素数 // ave :各画素値に割り当てられる画素数 //★★特にmin,max,pixs_min,pixs_maxの説明の意味が分からないのです。 int getMinMax(int *hist,int *min,int *max,int *pixs_min,int *pixs_max,int ave) { int i; int rest; int now; int pixels; int a,b; rest=0; now=0; for(i=0;i<256;i++) { pixels=rest+hist[i]; min[i]=now; if(rest>0) pixs_min[i]=ave-rest; else pixs_min[i]=ave+100; a=pixels/ave; rest=pixels%ave; max[i]=now+a; if(rest>0) pixs_max[i]=rest; else pixs_max[i]=ave+100; now+=a; } for(i=0;i<255;i++) { if(min[i]>255) min[i]=255; if(max[i]>255) max[i]=255; } max[255]=255; pixs_max[255]=ave*10; } // ヒストグラム均等化による画素値の決定 // 割り当てられる画素値の最小,最大の間で順番に割り当てていく // ただし,最小,最大については割り当てる画素数に制限がある int getHistEqu(int x,int *now,int *min,int *max,int *pix_min,int *pix_max) { int res; if(now[x]==max[x]) { if(pix_max[x]<=0) now[x]=min[x]; else pix_max[x]--; } if(now[x]==min[x]) { if(pix_min[x]<=0) now[x]=min[x]+1; else pix_min[x]--; } if(now[x]>max[x]) now[x]=min[x]; res=now[x]; now[x]++; return res; } int effect(ImageData *img,ImageData *outimg) { int x,y; int rr,gg,bb; int ro,go,bo; int i; int val; int ave; int histR[256],histG[256],histB[256]; // ヒストグラム int omaxR[256],omaxG[256],omaxB[256]; // 変換後,割り当てられる画素値の最小 int ominR[256],ominG[256],ominB[256]; // 変換後,割り当てられる画素値の最大 int pix_maxR[256],pix_maxG[256],pix_maxB[256]; // 最小値が割り当てられる画素数 int pix_minR[256],pix_minG[256],pix_minB[256]; // 最大値が割り当てられる画素数 int onowR[256],onowG[256],onowB[256]; // 次に割り当てる画素値 Pixel pix; for(i=0;i<256;i++) { histR[i]=histG[i]=histB[i]=0; } ave= img->height * img->width /256; // 画像の全画素数/画素値の範囲 // ヒストグラム作成 for(y=0;y<img->height;y++) { for(x=0;x<img->width;x++) { getPixel(img,x,y,&pix); //画像上の画素情報を取得 rr=pix.r; gg=pix.g; bb=pix.b; histR[rr]++; histG[gg]++; histB[bb]++; } } // 画素値の割り当て決定 getMinMax(histR,ominR,omaxR,pix_minR,pix_maxR,ave); getMinMax(histG,ominG,omaxG,pix_minG,pix_maxG,ave); getMinMax(histB,ominB,omaxB,pix_minB,pix_maxB,ave); for(i=0;i<256;i++) { onowR[i]=ominR[i]; onowG[i]=ominG[i]; onowB[i]=ominB[i]; } // ヒストグラム均等化処理 for(y=0;y<img->height;y++) { for(x=0;x<img->width;x++) { getPixel(img,x,y,&pix); //画像上の画素情報を取得 ro=pix.r; go=pix.g; bo=pix.b; rr=getHistEqu(ro,onowR,ominR,omaxR,pix_minR,pix_maxR); gg=getHistEqu(go,onowG,ominG,omaxG,pix_minG,pix_maxG); bb=getHistEqu(bo,onowB,ominB,omaxB,pix_minB,pix_maxB); pix.r=rr; pix.g=gg; pix.b=bb; setPixel(outimg,x,y,&pix); // 画像に値をセットする } } return 0; }

  • IplImageをPictureBoxへ表示がうまくいきません。

    VC++にてOpenCVを使い画像処理を行っている者です。 処理後の画像をMFCで作成した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++ ) { ColorBuf[ y * img->width * 4 + x * 4 + 0 ] = img->imageData[ y * img->widthStep + x * 3 + 0 ]; ColorBuf[ y * img->width * 4 + x * 4 + 2 ] = ColorBuf[ y * img->width * 4 + x * 4 + 1 ]= ColorBuf[ y * img->width * 4 + x * 4 + 0 ]; } } mbmp.CreateBitmap( img->width, img->height, 1, 32, ColorBuf ); free( ColorBuf ); ((CStatic*)GetDlgItem( IDC_IMGSRC ))->SetBitmap ( mbmp ); cvReleaseImage( &img ); } //--------------------------------------------------------------- 今はPictureBoxに3つ縦に画像が表示されてしまってます。 何か改善点などがありましたらよろしくお願いいたします。

  • このコードは省いてもよいのでしょうか?

    下記のプログラムは2行3列の行列と3行2列の行列の積を求めるものです。 int main(void) { int i, j, k; int mx[2][3] = {{1, 2, 3}, {4, 5, 6}}; int my[3][2] = {{1, 5}, {5, 3}, {8, 1}}; int mz[2][2] = {0}; for(i=0; i<2; i++) { for(j=0; j<2; j++) { mz[i][j] = 0; for(k=0; k<3; k++) mz[i][j] += mx[i][k] * my[k][j]; } } for(i=0; i<2; i++) { for(j=0; j<2; j++) printf("%3d", mz[i][j]); putchar('\n'); } return (0); } 【質問】 main関数冒頭で int mz[2][2] = {0}; と初期化されていますが、後に出てくるforループ中の mz[i][j] = 0; は結局同じことをして無駄なコードではないのでしょうか? このコードを省いたプログラムをコンパイルして実行しても結果には影響ありませんでした。 とはいえ、考えが合っているか不安なので回答よろしくお願いします。

  • なぜか,答えが出ません.

    まず,下記のプログラムをみてもらいたんですが,(OpenCVを使ってます.) int main(void){ double hyouka=0; IplImage *correct=cvLoadImage("19.bmp",0); fujita_t("19.jpg",27,27,1.414,1.414,4,0.25,50,0,24,24); IplImage *dst=cvLoadImage("i_plus.bmp",0); int count_all=0; int count_correct=0; for(int i=0; i<dst->height; i++){ for(int j=0; j<dst->width; j++){ if(dst->imageData[i*dst->widthStep+j]==correct->imageData[i*correct->widthStep+j]){ count_correct++; } count_all++; } } hyouka = (double)count_correct / (double)count_all; printf("評価値:%6.3d%\n",hyouka); return 0; } これは,原画像に画像処理をかけた結果画像(dst)と,原画像から必要なものだけを抽出した正解画像(correct)を比較して,全画像における画素の整合率を評価値としたものです. しかし,答えをみると 「評価値:1541606928%」 とでます. 中身を調べると, count_correctは88320 count_allは90000 と出て,端末には「評価値:98.133%」とでてもいいはずなんですが… 原因が判る方,よろしくお願いします. ちなみにfujita_tというのは,画像処理手法のパラメータです.

  • 画素を数えるプログラム

    現在、画像処理のプログラミングをやっているのですが、 2値化画像で黒の画素部分の数を求めて面積を出すプログラムを作っているのですが上手く出来ません。 誤ってる所ばかりだと思いますが、一応作ったソースを載せておきます。 int i, j; int histgram[color]; for(i=0; i<color; i++) { histgram[i]=0; } for(i=0;i<512;i++){ for(j=0;j<384;i++){ histgram[header[Isize][Jsize]]++; } } printf("%d\n",histgram[i]); 画像の読込みは自分で出来るので、255(黒)の画素がいくつあるのかを求める部分だけでも教えていただけるとありがたいです。 どうかよろしくお願いします。

  • OpenCVでRAW画像(カラー)を開くには

    OpenCVを使って、テキスト形式のヘッダーありのRAW画像(カラー)を、Cで書いたプログラムで開きたいのですが、 うまくいかず困っています。 “LoadRawImage”というWindowが起動しますが、真黒で何も表示されません。 RAW画像を開く関数myRawImageは以下のurlの「RAWデータの読み込みと表示」を参照させていただきました。(すみません、どうもありがとうございます。) http://wiki.livedoor.jp/mikk_ni3_92/d/raw%a5%c7%a1%bc%a5%bf%a4%ce%c6%c9%a4%df%b9%fe%a4%df%a4%c8%c9%bd%bc%a8 画像サイズはわかっているので、bmpなどに変換せず、RAWのまま開きたいのですが、どこを直せばいいのでしょうか。 どなたかヒントでも教えていただけると大変助かります、どうぞよろしくお願い致します。 //test.cpp #include <cv.h> #include <highgui.h> #include <iostream> #include <fstream> #include "raw_data_show.h" int main (int argc, char ** argv)================= { int x, y,i; uchar p1[3], p2[3]; IplImage *img1, *img2, *cp_img; img1 = myRawImage("D:\\My Pictures\\...\rawimage",500,500,3); cvShowImage("Load RawImage",img1); cvWaitKey(0); ============================================== #include <cv.h> #include <cxcore.h> #include <highgui.h> #include <iostream> #include <fstream> IplImage *myRawImage(char *filename, int w,int h,int channels) { if((channels != 3) && (channels != 1)) { std::cerr << " channel is not 3 or 1\n"; return NULL; } std::fstream ifs(filename,std::ios::in|std::ios::binary); if(!ifs.is_open()) { return NULL; } CvMat *Mat = cvCreateMat(h,w,CV_8UC3); ifs.read(reinterpret_cast<char*>(Mat->data.ptr),w*h*3); ifs.close(); IplImage img_hdr; IplImage *dst_img = cvGetImage (Mat, &img_hdr); IplImage *clone = cvCloneImage(dst_img);//クローン作成 cvReleaseImage(&dst_img); cvReleaseMat(&Mat); if(channels == 3){ for (i = 0; i < size; i++) { for (j = 0; j < size; j++) { CvMat m; float ret = 0.0; float a[] = { float (j) / size, float (i) / size }; cvInitMatHeader (&m, 1, 2, CV_32FC1, a); ret = svm.predict (&m); switch ((int) ret) { case 1: rcolor = CV_RGB (100, 0, 0); break; case 2: rcolor = CV_RGB (0, 100, 0); break; case 3: rcolor = CV_RGB (0, 0, 100); break; } cvSet2D (img, i, j, rcolor); } } cvCvtColor(clone,clone,CV_RGBA2BGR); return clone; } ========================================================

  • 画素数の計算について

    現在BMPで640×480の画像の左右両端の80画素ずつ切り取り480×480の画像を作って さらに、8×8のブロックに分けて各ブロックごとの光の強度をだすプログラミングをつくっているのですが、 (各ブロックはそれぞれ[1][1]~[8][8]となづけています) [1][8]、[2][8]、[3][8]…と8がつくブロックの強度がすべて0になってしまいます。 いろいろと考えてみたのですが、どうにもうまくいかずに悩んでおります。 助けていただけませんでしょうか? よろしくおねがいします。 おそらく、ここらへんがおかしいと思う部分をのせておきます。 /* 640側の左右80ずつ切り取り、480×480の正方形の画像にする */ int bunkatsu(BMP *rp,RESULT *res){ int x,y; int a=0; for(y = 0;y < rp->Bmpi.biHeight; y++){ for(x = 80;x < rp->Bmpi.biWidth - 80; x++){ res->data[a] = rp->blue[y * rp->Bmpi.biWidth + x] + rp->green[y * rp->Bmpi.biWidth + x] + rp->red[y * rp->Bmpi.biWidth + x]; a++; } } return 0; } /* 480×480を8×8のブロックに分け(60×60が64ブロック) 、各ブロックの明るさを計算する */ int keisan(BMP *rp,RESULT *res){ int b,c; int i=0,j=0; int x,y; for(y = 0;(y+60) < rp->Bmpi.biHeight;y+=60){ for(x = 0;(x + 60) < (rp->Bmpi.biWidth - 160);x+=60){ for(b = 0;b < 60;b++){ for(c = 0; c < 60;c++){ res->akarusa[i][j]+=res->data[(y + b) * rp->Bmpi.biWidth +(x + c)]; } } j++; } j=0; i++; } max(res); return 0; } /* 一番明るいブロックの特定 */ RESULT *max(RESULT *res){ int MAX1=0; int MAX2=0; int i=0; int j=0; for(i = 0;i < 8;i++){ for(j = 0;j < 8;j++){ printf("[%d][%d]=%d ",i+1,j+1,res->akarusa[i][j]); if(MAX1 < res->akarusa[i][j]){ MAX1 = res->akarusa[i][j]; res->maxi=i; res->maxj=j; } } printf("\n"); } printf("一番明るいブロックは[%d][%d]です\n",res->maxi + 1,res->maxj + 1); return 0; } です。よろしくおねがいします。

  • 動作しない

    下のプログラムのことなのですが、このプログラムをコンパイルし、実行すると動作するのですが画像を他のものに変更して同様に実行すると動作しなくなりました。どうすればいいのでしょうか?教えてくださいお願いします。 import java.applet.*; import java.awt.*; import java.awt.image.*; public class moji extends Applet { Image img; // 元のイメージ int img_width = 0; // 元のイメージの幅 int img_height = 0; // 元のイメージの高さ int pix[]; // 元のイメージを格納する配列 int wcnt_pix[]; // 行ごとの黒画素数を格納する配列 int hcnt_pix[]; // 列ごとの黒画素数を格納する配列 int cnt = 0; // 黒画素のカウント用 int cnt_sum = 0; // 黒画素のカウント総数 int chu = 0; // 中心値 int sum1 = 0; int sum2 = 0; int x = 0; int y = 0; int xmax = 0; // 黒画素の右端 int xmin = 0; // 黒画素の左端 int ymax = 0; // 黒画素の上端 int ymin = 0; // 黒画素の下端 public void init(){ img = getImage(getDocumentBase(), "test.jpg"); // イメージのロード MediaTracker mt = new MediaTracker(this); mt.addImage(img, 0); try{ mt.waitForID(0); }catch(InterruptedException e){} // イメージのロード完了まで待機 img_width = img.getWidth(this); // 元のイメージの幅を取得 img_height = img.getHeight(this); // 元のイメージの高さを取得 cntpix(); box_top(); box_bot(); box_rig(); box_lef(); } // 黒画素数のカウント public void cntpix(){ pix = new int[img_width * img_height]; wcnt_pix = new int[img_width]; hcnt_pix = new int[img_height]; try{ PixelGrabber pg = new PixelGrabber(img, 0, 0, img_width, img_height, pix, 0, img_width); pg.grabPixels(); }catch(InterruptedException e){} // 行ごとのカウント for(int wj = 0; wj < img_height; wj++){ cnt = 0; for(int wi = 0; wi < img_width; wi++){ if((pix[wj * img_width + wi] & 255) < 128){ cnt++; } } wcnt_pix[wj] = cnt; cnt_sum = cnt_sum + cnt; } // 列ごとのカウント for(int hi = 0; hi < img_width; hi++){ cnt = 0; for(int hj = 0; hj < img_height; hj++){ if((pix[hj * img_width + hi] & 255) < 128){ cnt++; } } hcnt_pix[hi] = cnt; } chu = cnt_sum / 2; // 中心値 // 中心値より重心が何行目かを求める int i = 0; while(sum1 < chu){ sum1 = sum1 + wcnt_pix[i]; i++; } x = i - 1; // 中心値より重心が何列目かを求める int j = 0; while(sum2 < chu){ sum2 = sum2 + hcnt_pix[j]; j++; } y = j - 1; } // 黒画素の上端を求める public void box_top(){ int ti = 0; while(wcnt_pix[ti] == 0){ ymax = ti; ti++; } } // 黒画素の下端を求める public void box_bot(){ int bi = img_height - 1; while(wcnt_pix[bi] == 0){ ymin = bi; bi--; } } // 黒画素の右端を求める public void box_rig(){ int ri = 0; while(hcnt_pix[ri] == 0){ xmin = ri; ri++; } } // 黒画素の左端を求める public void box_lef(){ int li = img_width - 1; while(hcnt_pix[li] == 0){ xmax = li; li--; } } // 画像等の描画 public void paint(Graphics g){ int box_w = xmax - xmin; int box_h = ymin - ymax; int dx = x - xmin; // 重心のX座標 int saku = dx / 20 * 3; // 錯視による誤差 int dy = ymin - y + saku; // 重心のY座標 g.drawImage(img, 0, 0, this); g.drawString("このイメージの幅は"+img_width+"で高さは"+img_height+"です。", 0, 20); // 画像の描画 g.drawRect(xmin, ymax, box_w, box_h); // バウンディングボックスの描画 g.setColor(Color.red); g.fillOval(xmin-3, ymin-3, 6, 6); g.drawString("原点( 0, 0 )", xmin-20, ymin+20); // 原点の描画 g.drawString("文字の重心は、( "+dx+", "+dy+" )です。", 0, 40); // 重心の描画 g.drawLine(x-10, y-saku, x+10, y-saku); // 重心の位置の描画 g.drawLine(x, y-saku+10, x, y-saku-10); // 重心の位置の描画 } }

    • ベストアンサー
    • Java

専門家に質問してみよう