ページ 11

ヒストグラム

Posted: 2008年12月25日(木) 16:30
by hyoma
現在256×256画像から要素を抽出し、ヒストグラムを作成しようと思っています。
ただ2次元画像から1次元画像の配列に格納する方法はわかったのですが、それを
ヒストグラムとして画像に抽出するプログラムの書き方がわかりません。
ぜひアドバイスをお願いします。

Re:ヒストグラム

Posted: 2008年12月25日(木) 16:44
by Dixq (管理人)
ビットマップですか?
画像からデータをとってくる方法がわかったのですから、
画像データがどのようになっているかも解ったと思いますが、その辺大丈夫でしょうか?
例えば、「白い背景に赤の長方形を描いた画像を出力せよ」みたいに言われたら出来ますか?

それが出来たら出来そうです。

あと、ヒストグラムって何のヒストグラムですか?
http://retouch-weblab.com/kennkyuu/histogram.html

こんな感じで画像として出力するのでしょうか?

まずは、テキストファイルにヒストグラムとして使うデータを出力してみてはどうでしょう?

Re:ヒストグラム

Posted: 2008年12月25日(木) 17:24
by Dixq (管理人)
ビットマップデータから赤のヒストグラムを表示するサンプルを作ってみました。
#include <stdio.h> 
#include <stdlib.h> 

/* ビットマップの横 */
#define YOKO 256
/* ビットマップの縦 */
#define TATE 256
/* ビットマップのヘッダサイズ */
#define HEAD 54
/* トータルサイズ */
#define TOTAL (YOKO*TATE*3+HEAD)

typedef struct{
    //[0]青 [1]緑 [2]赤
    unsigned char Col[3];
}Color_t;//色の構造体

/* ビットマップデータを読み込む */
int ReadBmp(char *name, unsigned char data[/url]){
    FILE *fp;
    fp = fopen( name , "rb" );
    if( fp == NULL ){
        printf( "%sが見つかりません。",name);
        exit (1);
    }
    fread( data, TOTAL, 1, fp );
    fclose(fp);
    return 0;
}

/* ビットマップデータを扱いやすいようPixelDataに変換する */
void ConvPixelData( Color_t PixelData[ YOKO ][ TATE ], unsigned char BmpData[/url] ){
    int t=HEAD;
    int x,y,c;
    for(y=TATE-1; y>=0; y--){
        for(x=0; x<YOKO; x++){
            for(c=0; c<3; c++){
                PixelData[y][x].Col[c]=BmpData[t];
                t++;
            }
        }
    }
}

/* 赤の出現頻度をカウントする */
void CalcRed( Color_t PixelData[ YOKO ][ TATE ], int iRed[/url] ){
    int x,y;
    for(y=TATE-1; y>=0; y--){
        for(x=0; x<YOKO; x++){
            iRed[ PixelData[y][x].Col[2] ]++;
        }
    }
}

/* 赤の出現頻度を表示する */
void ShowRed( int iRed[/url] ){
    int i,n;
    printf("赤の分布\n");
    for(i=0; i<256; i+=10){
        printf("%3d:",i);
        for(n=0; n<iRed[ i ]/10; n++){
            printf("*");
        }
        printf("%d\n", iRed[ i ]);
    }
}

int main(){
    int iRed[ 256 ]={0,};
    Color_t PixelData[ YOKO ][ TATE ];
    unsigned char BmpData[TOTA[/url];

    ReadBmp( "pict.bmp", BmpData );//読み込んで
    ConvPixelData( PixelData, BmpData );//変換して
    CalcRed( PixelData, iRed );//計算して
    ShowRed( iRed );//表示
}

実行結果

赤の分布
  0:*15
 10:*18
 20:******65
 30:**********************227
 40:********************************325
 50:*************************************375
 60:********************************************443
 70:**************************************************500
 80:********************************************442
 90:**********************************************462
100:**********************************************463
110:******************************************427
120:****************************************400
130:**************************************385
140:*************************************379
150:***********************************354
160:****************************283
170:***************************274
180:**********************220
190:**************141
200:******65
210:*****52
220:****43
230:**26
240:**22
250:**************148
 

Re:ヒストグラム

Posted: 2008年12月25日(木) 17:27
by hyoma
形式はpgmです。

画像データがどのようになっているかの理解はできていると思います。
しかし、画像を出力せよと言われたら出来ないです。

ヒストグラムはそのURL先にあるようなものを作成したいと思っています。

アドバイスをもらいやってみましたがやはりうまく出力はできませんでした。

Re:ヒストグラム

Posted: 2008年12月25日(木) 22:42
by Dixq (管理人)
では、まずは真っ白な画像を作ってみて下さい。
pgmファイルがどんなファイルか知りませんが、
わからなければヘッダの中身はそのまま移せばいいと思います。

Re:ヒストグラム

Posted: 2008年12月25日(木) 23:01
by Dixq (管理人)
とりあえず適当な四角形を書き出すサンプル書いてみました。
サンプルのプログラムは上のサンプルを利用して作りました。
関数を呼ぶ順番と中身が少し変わっているだけです。

ファイルはbmpですがpgmも無圧縮だと思うので、恐らく同じ要領で出来ると思います。
以下のプログラムで作った画像が添付画像です。

bmpのヘッダはあえて、既存のファイルからコピーする方法を取りました。
まずはコピーでやってみて、出来たらヘッダファイルの構造体を用意し、
ちゃんと画像サイズなども指定出来るようにしてみて下さい。
#include <stdio.h> 
#include <stdlib.h> 

/* ビットマップの横 */
#define YOKO 256
/* ビットマップの縦 */
#define TATE 256
/* ビットマップのヘッダサイズ */
#define HEAD 54
/* トータルサイズ */
#define TOTAL (YOKO*TATE*3)

typedef struct{
    //[0]青 [1]緑 [2]赤
    unsigned char Col[3];
}Color_t;//色の構造体


/* ビットマップデータのヘッダ部分を読み込む */
int ReadBmpHead(char *name, unsigned char BmpHead[/url]){
    FILE *fp;
    fp = fopen( name , "rb" );
    if( fp == NULL ){
        printf( "%sが開けません。",name);
        exit (1);
    }
    fread( BmpHead, HEAD, 1, fp );
    fclose(fp);
    return 0;
}

/* ビットマップデータを書き出す */
int WriteBmp(char *name, unsigned char BmpHead[/url], unsigned char BmpData[/url]){
    FILE *fp;
    fp = fopen( name , "wb" );
    if( fp == NULL ){
        printf( "%sがエラーっす。",name);
        exit (1);
    }
    fwrite( BmpHead, HEAD, 1, fp );
    fwrite( BmpData, TOTAL, 1, fp );
    fclose(fp);
    return 0;
}

/* ビットマップデータをPixelDataからBmpDataに変換する */
void ConvToBmpData( Color_t PixelData[ YOKO ][ TATE ], unsigned char BmpData[/url] ){
    int t=0;
    int x,y,c;
    for(y=TATE-1; y>=0; y--){
        for(x=0; x<YOKO; x++){
            for(c=0; c<3; c++){
                BmpData[t]=PixelData[y][x].Col[c];
                t++;
            }
        }
    }
}

/* 画像に赤と青の四角形を書き込む */
void WriteColor( Color_t PixelData[ YOKO ][ TATE ] ){
    int x,y;
    for(y=100; y<180; y++){
        for(x=100; x<180; x++){
            PixelData[y][x].Col[2] = 255;
        }
    }
    for(y=120; y<200; y++){
        for(x=120; x<200; x++){
            PixelData[y][x].Col[0] = 255;
        }
    }
}

int main(){
    Color_t PixelData[ YOKO ][ TATE ]={0,};
    unsigned char BmpData[TOTA[/url];
    unsigned char BmpHead[HEAD];

    ReadBmpHead( "pict.bmp", BmpHead );//ヘッダを読みんで
    WriteColor( PixelData );//ピクセルデータを書き込んで
    ConvToBmpData( PixelData, BmpData );//変換して
    WriteBmp( "pict2.bmp", BmpHead, BmpData);//書き込む
}
  

Re:ヒストグラム

Posted: 2008年12月26日(金) 00:41
by hyoma
なんとか完成できました。
アドバイスありがとうございました。

また何か疑問に思いわからないことがあれば利用させてもらいます。

Re:ヒストグラム

Posted: 2008年12月26日(金) 00:43
by hyoma
解決マークを入れ忘れたので連投です。