これ何て呼びますか

画像の中にある粒子の位置を検出し、座標の値の取得をどうしても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 ;
}

A 回答 (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 ); を忘れています。
    • good
    • 0
この回答へのお礼

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

お礼日時:2010/01/26 15:08

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!