掲示板利用宣言

 次のフォームをすべてチェックしてからご利用ください。

 私は

 題名と投稿者名は具体的に書きます。
 課題の丸投げはしません。
 ソースの添付は「HTML変換ツール」で字下げします。
 返信の引用は最小限にします。
 環境(OSとコンパイラ)や症状は具体的に詳しく書きます。
 返信の付いた投稿は削除しません。
 マルチポスト(多重投稿)はしません。

掲示板2

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.29538

BMPを2値化処理して保存したい
投稿者---若旦那(2007/01/22 17:52:43)


BMPを2値化処理して、2値化されたものをBMPとして保存したいのですが、保存方法がわかりません。そもそも2値化の閾値は濃度平均を境に白と黒に分ける方法であっていますでしょうか?
以下が作りかけのプログラムです。

#include <stdio.h>


int main(void)
{
FILE *fp;
int wide,hite,cm;
int v[256][256];
int h[54],palette[1024];
int i,j,a,b,x,n;
int heikin,sum=0;


/*1枚目の画像data*/

fp=fopen("c.bmp","rb"); // mono画像ファイルを開く
if(fp==NULL){
printf("エラー\n");
return 1; }

for(j=0; j<54; j++) h[j]=fgetc(fp); // ヘッダの読み込み
wide=h[18]+h[19]*256; // 画像の幅の計算
hite=h[22]+h[23]*256; // 画像の高さの計算
cm=h[28];
if(cm=8)for(j=0; j<1024; j++) palette[j]=fgetc(fp);

//mono画像データ読み込み
for(a=0; a<hite; a++)for(b=0; b<wide; b++){
v[a][b]=fgetc(fp); //濃度値を取得
n=v[a][b];

sum+=n; //濃度値合計sum
heikin=sum/(wide*hite); //閾値を決めるためのheikin


if(n>heikin) n=0; //濃度値がheikin以上なら黒
else n=255; //以下なら白にする

printf("v=%d\n",n);
}



return 0;
}


この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:BMPを2値化処理して保存したい 29539 breakwind4u 2007/01/22 18:30:32
<子記事> Re:BMPを2値化処理して保存したい 29540 あかま 2007/01/22 18:33:50
<子記事> Re:BMPを2値化処理して保存したい 29544 yoh2 2007/01/22 22:34:51
<子記事> Re:BMPを2値化処理して保存したい 29558 ルナレルナ 2007/01/23 14:04:57


No.29539

Re:BMPを2値化処理して保存したい
投稿者---breakwind4u(2007/01/22 18:30:32)


>BMPを2値化処理して、2値化されたものをBMPとして
>保存したいのですが、保存方法がわかりません。

こちらへどうぞ。
http://www.wotsit.org/

>そもそも2値化の閾値は濃度平均を境に白と黒に分ける方法で
>あっていますでしょうか?

そもそも日本語の意味がわかりません。

「課題の意図が『濃度平均を境に白と黒に分ける方法』でしょうか?」
という意味であれば、そんなことは知ったこっちゃありません
(他にも、白と黒の生起確率が等しくなるように閾値を決める方法など
があります)。

「濃度平均を境に白と黒に分ける方法として下記プログラムは正しいですか?」
という意図であれば、間違えています。"heikin" の値がどうなっているか、
printf すなりして調べて下さい。





この投稿にコメントする

削除パスワード

No.29541

Re:BMPを2値化処理して保存したい
投稿者---若旦那(2007/01/22 19:39:35)


お礼がおそくなりました。
返答ありがとうございます。
質問の仕方がへたくそですみません。
2値化するプログラムとして正しいか?という意味でした。
heikinのご指摘ありがとうございました。
解決することができました。
breakwind4uさんありがとうございました!


この投稿にコメントする

削除パスワード

No.29540

Re:BMPを2値化処理して保存したい
投稿者---あかま(2007/01/22 18:33:50)


前スレは解決しました?
したなら、まとめやお礼や出来上がったプログラムの投稿などなさってください。
投げっぱなしは最悪です。

プログラムの投稿はHTML変換ツールを使ってインデントしてください。
前スレでも言われていますね?

>BMPを2値化処理して、2値化されたものをBMPとして保存したいのですが、保存方法がわかりません。
fopenで読み込んだのと逆の方法で、書き込めばいいのでは?

>そもそも2値化の閾値は濃度平均を境に白と黒に分ける方法であっていますでしょうか?
2値化は「なんらかのルール」にしたがって黒と白に分ければ2値化と呼べるわけで、
「濃度平均を境」とするルールを使うかどうかは作りたいプログラムによるでしょう。
それは自分で決めてください。
その決めたルールを元にプログラムがうまく書けませんというなら力になれると思います。


この投稿にコメントする

削除パスワード

No.29542

Re:BMPを2値化処理して保存したい
投稿者---若旦那(2007/01/22 20:00:35)


プログラムで悩んでてお礼が遅くなりました。
すみません。

返答ありがとうございます。

HTML変換ツールを説明どおり使用したんですが。。
もう一度読み直します。

fopenで読み込んだのと逆の方法というのは
fp=fopen("5.bmp","wb");
を使えばいいのでしょうか?

濃度平均を境に2値化プログラムを作ります!
わからないことだらけなので、お力を貸していただければと思います。







この投稿にコメントする

削除パスワード

No.29543

Re:BMPを2値化処理して保存したい
投稿者---ぽへぇ(2007/01/22 21:54:57)



>fopenで読み込んだのと逆の方法というのは
>fp=fopen("5.bmp","wb");
>を使えばいいのでしょうか?
そうだ、といえば、そうだし、違うといえば違う。
fopenだけでビットマップが作れたら苦労せんわ:-)

重要なのは「定まった書式(フォーマット)に従ってファイルを書く」ということ。
その書式は No.29539 で breakwind4u さんが紹介したリンクにもあります。

>wide=h[18]+h[19]*256; // 画像の幅の計算
>hite=h[22]+h[23]*256; // 画像の高さの計算
>cm=h[28];

この配列の添字(h[18], h[19]等)はどこから引っ張ってきたんですか?
書式が理解できていないと書けない数字のはずなんですが
(っつうか理解してください)。



この投稿にコメントする

削除パスワード

No.29549

Re:BMPを2値化処理して保存したい
投稿者---若旦那(2007/01/23 01:39:10)


ぽへぇさん返答ありがとうございます。

fopenだけではないのですね。

添字は参考にしている本にBMPの構造が載っており使ってます。
54バイトのヘッダと画像データからなることは理解しています。



この投稿にコメントする

削除パスワード

No.29552

Re:BMPを2値化処理して保存したい
投稿者---ぽへぇ(2007/01/23 04:41:03)



>fopenだけではないのですね。
若旦那さんのコードで fp = fopen("c.bmp","rb"); だけで
ファイルが読めていますか? fgetc(fp); ってやってますよね。
それと同じことです(個人的にはfread/fwriteの方が好みですが)。

>添字は参考にしている本にBMPの構造が載っており使ってます。
>54バイトのヘッダと画像データからなることは理解しています。

若旦那さんのプログラムを見た限りでは、構造体が出てきませんね。
そこまで(授業/講義が?)進んでいないのか、お使いの参考書で
扱われていないのか不明ですが。

更なる混乱を招かないことを祈りつつ。

Bitmap Storage
http://msdn2.microsoft.com/en-us/library/ms532311.aspx

BITMAPFILEHEADER
http://msdn2.microsoft.com/en-us/library/ms532321.aspx

Storing an Image
http://msdn2.microsoft.com/en-us/library/ms532340.aspx



この投稿にコメントする

削除パスワード

No.29560

Re:BMPを2値化処理して保存したい
投稿者---若旦那(2007/01/23 14:42:23)


構造体を習ってないんです。

リンクまで貼っていただいてほんとにありがとうございます。







この投稿にコメントする

削除パスワード

No.29698

Re:BMPを2値化処理して保存したい
投稿者---ぽへぇ(2007/02/03 06:27:38)


手抜き

#include    <stdio.h>
#include    <stdlib.h>

int main(int argc, char* argv[])
{
    FILE*         fp;
    FILE*         outfp;
    int    wide, hite, cm;
    long**      ppPixel;  // 画像用領域
    unsigned char   h[54];  // header
    int    j, x, y;
    double      heikin, sum = 0.;

    // 画像ファイルを開く
    fp = fopen("c.bmp","rb");
    if(fp == NULL) {
        printf("エラー\n");
        return 1;
    }

    // ヘッダの読み込み
    for(j = 0; j < 54; j++) {
        h[j] = fgetc(fp);
    }
    wide = h[18]+h[19]*256; // 画像の幅の計算
    hite = h[22]+h[23]*256; // 画像の高さの計算

    // biBitCount
    cm = h[28];
    if(cm != 24) {
        printf("24bitでない\n");
        return 1;
    }

    // 画像用領域確保
    ppPixel = (long**)malloc(sizeof(long*) * wide);
    if(!ppPixel) {
        printf("mallocでエラー\n");
        return 1;
    }
    for(x = 0; x < wide; x++) {
        long* p = (long*)malloc(sizeof(long) * hite);
        if(!p) {
            printf("mallocでエラー\n");
            return 1;
        }
        ppPixel[x] = p;
    }

    // 画像読み込み
    for(y = 0; y < hite; y++) {
        for(x = 0; x < wide; x++) {
            long    colorvalue = 0;
            int  r = 0, g = 0, b = 0;
            // bbggrr bbggrr ...
            for(j = 0; j < 3; j++) {
                colorvalue = colorvalue + ( fgetc(fp)<<((2-j)*8) );
            }
            ppPixel[x][y] = colorvalue; 
            r = (colorvalue & 0x0000ff);
            g = (colorvalue & 0x00ff00) >>  8;
            b = (colorvalue & 0xff0000) >> 16;
            // 輝度合計
            sum += (0.298912*r + 0.586611*g + 0.114478*b);
        }
    }
    fclose(fp);

    //閾値を決めるため平均
    heikin = sum/(wide*hite);
    // 2値変換
    for(y = 0; y < hite; y++) {
        for(x = 0; x < wide; x++) {
            int b = (ppPixel[x][y] & 0xff0000) >> 16;
            int g = (ppPixel[x][y] & 0x00ff00) >>  8;
            int r = (ppPixel[x][y] & 0x0000ff);
            // 
            int l = (int)(0.298912*r + 0.586611*g + 0.114478*b);
            if(l < heikin) {
                // 平均よりも暗ければ黒
                ppPixel[x][y] = 0;
            } else { // 白
                ppPixel[x][y] = 0xffffff;
            }
        }
    }

    //  サイズ, 色bit数 とも変更なしのはずなので、ヘッダも変更しない
    outfp = fopen("out.bmp","wb");
    if(outfp == NULL) {
        printf("エラー\n");
        return 1;
    }
    // ヘッダ書き出し
    fwrite(h, 54, 1, outfp);
    // 本体書き出し
    for(y = 0; y < hite; y++) {
        for(x = 0; x < wide; x++) {
            // 24bit -> 3byte
            for(j = 0; j < 3; j++) {
                // bbrrggまったく同じ値になっているので
                //  書く順番は関係ない。好みの問題かも。
                unsigned char wvalue = (unsigned char)(ppPixel[x][y] >> ((2-j)*8));
                fwrite(&wvalue, 1, 1, outfp);
            }
        }
    }
    fclose(outfp);

    // メモリ開放
    for(x = 0; x < wide; x++) {
        free(ppPixel[x]);
    }
    free(ppPixel);

    return 0;
}



この投稿にコメントする

削除パスワード

No.29544

Re:BMPを2値化処理して保存したい
投稿者---yoh2(2007/01/22 22:34:51)


前スレに引き続き、BMPフォーマットの扱いを間違えているように見えます。
# ところで、wideとhiteはwidthとheightかwideとhighでは?

というわけで問題がふたつ。

1. 多分若旦那さんの望んだ通りには2値化されません。
2. (仮に正しい2値化データを得られたとして)フォーマットを誤解したままでは、正しいBMPを書き出せません。

もう一度フォーマットを調べ直してみて下さい。

ちょいと純粋なCからはズレてきますが、とりあえずヒント。

1に関して:
前にもちょっと書きましたが、読み込み対象は無圧縮8ビットBMPですか?
もしそうなら、若旦那さんが濃度(輝度?)と思っているのはカラーパレットのインデックスです。
輝度を得るには、そこからカラーパレットを見てRGB値を得て、さらにRGB→輝度の変換を
行う必要があります。
それに、幅が4の倍数(32ビットの倍数)でないと、読み込みがズレていきます(パディングって奴が入りますので)。
もし、読み込み対象が無圧縮8ビットBMPではないなら、1ピクセル=8ビットとして読んでいる
ことが間違っています。

2に関してはBMPフォーマットを確認してから。
printf()やfwrite()といった道具の使い方を覚えても、目的となるもの(BMPファイル)の作り方を
知らなくては何もできませんから。


最後に。
もう指摘されていますが、次にコードを投稿する時は今度こそインデントをしっかりして下さいね。
投稿内容を確定する前に内容確認できるのですから。
# ま、私も誤字脱字が多いですけど。


この投稿にコメントする

削除パスワード

No.29550

Re:BMPを2値化処理して保存したい
投稿者---若旦那(2007/01/23 02:05:03)


yoh2さんご指摘ありがとうございます。

wideとhiteは参考書どおりにしているのですがまちがっていますか??

読み込み対象は無圧縮8ビットBMPではなく24ビットBMPです。
24ビットの場合は輝度値はそのまま利用できるということでしょうか?
それとも、輝度を得るにはRGB値→輝度の変換作業は必要ですか?

幅は256×256または1024×1024のBMPを使います。
このときはパディングを考慮しなくてもよいということでしょうか?

質問ばかりですみません。
フォーマットを勉強しなおします。



この投稿にコメントする

削除パスワード

No.29551

Re:BMPを2値化処理して保存したい
投稿者---kolona(2007/01/23 03:20:48)


>読み込み対象は無圧縮8ビットBMPではなく24ビットBMPです。
>24ビットの場合は輝度値はそのまま利用できるということでしょうか?
>それとも、輝度を得るにはRGB値→輝度の変換作業は必要ですか?

RGBと輝度の変換は検索すればすぐに出てきます。
輝度を扱う規格は複数あるようですから、まずどの規格にするか決める必要があります。


>幅は256×256または1024×1024のBMPを使います。
>このときはパディングを考慮しなくてもよいということでしょうか?

サイズ固定なら、該当のBMPを扱っている限りは正常に動作する、ということになります。
余力があれば直した方がいいですが。


それと、BMPの扱いが間違ってます。
24bitBMPなら、色はRGBで直接指定するため、カラーパレット(カラーマップ)は不要です。
256色とごっちゃにしてませんか?


この投稿にコメントする

削除パスワード

No.29554

Re:BMPを2値化処理して保存したい
投稿者---breakwind4u(2007/01/23 10:43:23)


若旦那さん:

まずは質問の内容をよく吟味する所から始めてはいかがでしょうか?
「何がわからないのかわからない」のは、初心者がよく陥る所です。
それから、「環境(OSとコンパイラ)や症状は具体的に詳しく書きます」
も忘れずに。

「BMPを2値化処理して保存したい」には、二つの意味があります。
・画像を2値化したい
・BMPに保存したい

研究や検討が目的であって、最終的にBMPになっていれば良いのなら、
BMPより簡単な中間フォーマットで出力して後で変換する、という手が
あります。その場合の中間フォーマットとしては、PPMが最もお手軽です。

ユーティリティなどを作っていて、BMPに保存するのが主目的とあれば、
もう少しBMPについて勉強する必要があると思います。

仮に、質問の内容が下記であった場合:
(1) 画像ファイルを2値化したい
(2) 用意されている入力ファイルはBMP形式
(3) 出力も最終的にはBMPにしたい
(4) OS は Linux/GNU System
(5) コンパイラは gcc 4

次のように回答できるっつーもんです。

(2) については、前処理でPPMに変換すると扱いが簡単です。
例えば、ImageMagic がインストールされていれば下記の通り。
$ for i in input/*.bmp; do convert $i ${i%.bmp}.ppm; done

(3) についても同様、PPMで出力して後処理でBMPにするのが良いでしょう。
$ for i in output/*.ppm; do convert $i ${i%.ppm}.bmp; done

(1) については、入出力がPPMであるとすれば、下記のように書けます。

#include <stdio.h>

int main(int argc, char *argv[])
{
    FILE *fpr, *fpw;

    char format;
    int  width, height, maxinum;
    
    // fopen と PPM ヘッダ読み込み

    if (argc < 3
        || ((fpr = fopen(argv[1], "rb")) == NULL)
        || ((fpw = fopen(argv[2], "wb")) == NULL)
        || fscanf(fpr, "P%c %d %d %d ", &format, &width, &height, &maxinum) != 4
        || format != '6' || maxinum != 255) {
        fprintf(stderr, "usage: %s [input.ppm] [output.ppm]\n", argv[0]);
    }

    // C99 可変長配列

    struct {
        unsigned char r, g, b;
    } pixels[height][width];

    // PPM 本体の読み込み

    if (fread(pixels, sizeof(pixels), 1, fpr) != 1) {
        fprintf(stderr, "%s: read error\n", argv[1]);
    }
    fclose(fpr);

    // 輝度平均算出

    int sum = 0;
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            // r, g, b は全て同じ値が入っているものと仮定

            sum += pixels[y][x].g;
        }
    }

    // 2値化

    int average = sum / (width * height);
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            if (pixels[y][x].g < average) {
                pixels[y][x].r = pixels[y][x].g = pixels[y][x].b = 0;
            } else {
                pixels[y][x].r = pixels[y][x].g = pixels[y][x].b = 255;
            }
        }
    }

    // PPM 書き出し

    fprintf(fpw, "P6\n%d %d\n255\n", width, height);
    fwrite(pixels, sizeof(pixels), 1, fpw);
    fclose(fpw);

    return 0;
}




この投稿にコメントする

削除パスワード

No.29555

Re:BMPを2値化処理して保存したい
投稿者---若旦那(2007/01/23 12:11:03)


breakwind4uさん何度もありがとうございます。

QSはwindowsでvisual studio 2005を使用しています。
コンパイラはVisual Studio 2005 コマンドプロンプトです。

BMP出力が最終目的ではなく、正しく2値化されているか確認したかっただけなんです。PPMについて調べてみます。




この投稿にコメントする

削除パスワード

No.29556

Re:BMPを2値化処理して保存したい
投稿者---若旦那(2007/01/23 13:18:31)


kolonaさんありがとございます。

もう一度調べなおしました。
もし他のソフトで24bitカラーBMPを濃淡画像に変換してから作業する場合はRGBと輝度の変換については考えずに私の考えたプログラムでも2値化は可能ですよね?
24bitカラーBMPを濃淡画像に変えた場合は24bitの濃淡画像になり0〜255の輝度で表せることであっていますか?
この場合はパレットが存在しないので不要でいいんですよね。



この投稿にコメントする

削除パスワード

No.29557

Re:BMPを2値化処理して保存したい
投稿者---kolona(2007/01/23 13:57:03)


>kolonaさんありがとございます。
>
>もう一度調べなおしました。
>もし他のソフトで24bitカラーBMPを濃淡画像に変換してから作業する場合はRGBと輝度の変換については考えずに私の考えたプログラムでも2値化は可能ですよね?

私の指摘は、24bit固定なら、1ピクセルのサイズを調べて8bitの時だけ256色のカラーパレットを読み飛ばす処理は不要なのでは?というそれだけの指摘です。
この処理↓
if(cm=8)for(j=0; j<1024; j++) palette[j]=fgetc(fp);

グレー画像に別ソフトで変換して良いのなら、それを24ビットに変換して保存すれば問題ないと思います。

>24bitカラーBMPを濃淡画像に変えた場合は24bitの濃淡画像になり0〜255の輝度で表せることであっていますか?
>この場合はパレットが存在しないので不要でいいんですよね。

輝度かどうかはわかりません。濃淡画像なら2値化は簡単だと思いますが。
パレットの処理は24bitなら不要です。



この投稿にコメントする

削除パスワード

No.29561

Re:BMPを2値化処理して保存したい
投稿者---若旦那(2007/01/23 14:46:25)


if(cm=8)for(j=0; j<1024; j++) palette[j]=fgetc(fp); はご指摘どおり必要ないです、ありがとうございます。

輝度というより濃度値は0〜255で表せるの方が正しいのかな??
とりあえず濃度値平均で2値化できたらいいと思っています。


この投稿にコメントする

削除パスワード

No.29578

Re:BMPを2値化処理して保存したい
投稿者---yoh2(2007/01/23 22:24:49)


>wideとhiteは参考書どおりにしているのですがまちがっていますか??

別に間違いではないのですが、ちょっと違和感を感じたもので。

タイプ数が増えるのを嫌って、heightを同じ発音に読めるhiteにするのはたまに見かけますが、
それなら、対になる言葉はwidthとかwidとかになりそうだと思いました。

また、wideという言葉を基準に考えるなら、対になる言葉はhighかtallじゃないかと。
どちらにせよ、hiteという名前は出てきそうにないな、と。
highを省略してhiというのはよく見かけますが。

尤も、私が不自然に思っているだけですので、wideとhiteの組合わせに統一感があると
感じるならば、あえてそれを否定するものではありません。


この投稿にコメントする

削除パスワード

No.29579

Re:BMPを2値化処理して保存したい
投稿者---若旦那(2007/01/23 22:29:39)


英語の問題ですねww
本で慣れてしまったのでこのままでいきます!
ご指摘ありがとうございます。


この投稿にコメントする

削除パスワード

No.29558

Re:BMPを2値化処理して保存したい
投稿者---ルナレルナ(2007/01/23 14:04:57)
http://park6.wakwak.com/~nougaki/mini_program/


> if(cm=8)for(j=0; j<1024; j++) palette[j]=fgetc(fp);

if(cm=8)でいいの?
cmに8を代入していいの?
cmとの比較じゃないの?

> //mono画像データ読み込み
> for(a=0; a<hite; a++)for(b=0; b<wide; b++){
> v[a][b]=fgetc(fp); //濃度値を取得
> n=v[a][b];
>
> sum+=n; //濃度値合計sum
> heikin=sum/(wide*hite); //閾値を決めるためのheikin

濃度値「合計」sumがまだ「合計」じゃないのに、heikinを出していいの?

> if(n>heikin) n=0; //濃度値がheikin以上なら黒
> else n=255; //以下なら白にする

そんなheikin使っていいの?


この投稿にコメントする

削除パスワード

No.29562

Re:BMPを2値化処理して保存したい
投稿者---若旦那(2007/01/23 14:49:59)


ルナレルナさんありがとうございます。

if(cm=8)for(j=0; j<1024; j++) palette[j]=fgetc(fp);
の行は24bitBMPのみ扱うなら不要というご指摘があり削除しました。

>濃度値「合計」sumがまだ「合計」じゃないのに、heikinを出していいの?
完全にぼけていました。。ありがとうございます。







この投稿にコメントする

削除パスワード

No.29564

Re:BMPを2値化処理して保存したい
投稿者---若旦那(2007/01/23 15:27:57)


そんなheikin使っていいの?という質問の意図をおしえていただけますでしょうか?
単に合計じゃないsumを使おうとしてたからですか?
私の考え方が間違っている可能性がありますので。。



この投稿にコメントする

削除パスワード

No.29566

Re:BMPを2値化処理して保存したい
投稿者---ルナレルナ(2007/01/23 18:22:16)
http://park6.wakwak.com/~nougaki/mini_program/


>単に合計じゃないsumを使おうとしてたからですか?

使おうとしてたんじゃなく、使っています。


この投稿にコメントする

削除パスワード

No.29567

Re:BMPを2値化処理して保存したい
投稿者---若旦那(2007/01/23 18:26:36)


使っていました。
ループの外にだしたらよいということですよね?


この投稿にコメントする

削除パスワード

No.29568

Re:BMPを2値化処理して保存したい
投稿者---ルナレルナ(2007/01/23 18:45:00)
http://park6.wakwak.com/~nougaki/mini_program/


>ループの外にだしたらよいということですよね?

何を?
ループの外といってもいろいろある・ありすぎる。

いま、若旦那のソースは、どんな風になっていますか?


この投稿にコメントする

削除パスワード

No.29571

Re:BMPを2値化処理して保存したい
投稿者---若旦那(2007/01/23 19:28:53)


今はこんな感じなんですが、2値化した輝度の値(変数sとt)が相関の式へどのようにいれたらいいのか悩んでます。

字下げしたんですがこれで大丈夫ですか??

#include <stdio.h>
#include <math.h>


 int main(void)
{
    FILE  *fp;
    int wide,hite,wd,ht,cm;
    int v[256][256],v2[256][256];
    int h[54],palette[1024];
    int i,j,a,b,x;
    int n,m,p,t,s; 
    double sum[4];
    double z;
    char  gazou[256];
    double heikin,heikin2;
   
    

      /*原画像data*/
  
    fp=fopen("5.bmp","rb");     // mono画像ファイルを開く
     if(fp==NULL){
      printf("エラー\n");
      return 1; }
       for(j=0; j<54; j++) h[j]=fgetc(fp);      // ヘッダの読み込み 
         wide=h[18]+h[19]*256;              // 画像の幅の計算
         hite=h[22]+h[23]*256;            // 画像の高さの計算
         cm=h[28];
        
    
       //mono画像データ読み込み
     sum[0]=0;
    for(a=0; a<hite; a++)for(b=0; b<wide; b++)
    {
       v[a][b]=fgetc(fp);
        
       sum[0]+=v[a][b];                     //濃度値合計sum      
    }
        
    heikin=sum[0]/(wide*hite);     //閾値を決めるためのheikin
        
    for(a=0; a<hite; a++)for(b=0; b<wide; b++)
    { 
       s=v[a][b];
       if(s>heikin) s=255;       //濃度値がheikin以上なら白
        else s=0;            //以下なら黒にする
       
     }

    
      /*入力画像data*/
   for (x=0; x<15; x++) 
   {
      sprintf(gazou,"%d.bmp",x);
      fp=fopen(gazou,"rb");      // mono画像ファイルを開く
                    
       if(fp==NULL){
        printf("エラー2\n");
        return 1; }
          
  
        for(j=0; j<54; j++)  h[j]=fgetc(fp);   // ヘッダの読み込み 
        wd=h[18]+h[19]*256;              // 画像の幅の計算
        ht=h[22]+h[23]*256;            // 画像の高さの計算
         cm=h[28];
          
    
        //mono画像データ読み込み
        sum[1]=0;
       for(a=0; a<ht; a++)for(b=0; b<wd; b++)
        {
           v2[a][b]=fgetc(fp);
   
           sum[1]+=v2[a][b];                 //濃度値合計sum
       } 
         
           heikin2=sum[1]/(wd*ht);     //閾値を決めるためのheikin2
       
           for(a=0; a<ht; a++)for(b=0; b<wd; b++)
           { 
              t=v2[a][b];
              if(t>heikin2) t=255;         //濃度値がheikin2以上なら白
              else t=0;            //以下なら黒にする

          }  
    
           /*相関の式に代入*/
  
    
            //左下の計算//
            sum[2]=0;
            for(a=0;a<hite;a++) for(b=0;b<wide;b++)
            {
               n=(v[a][b])*(v[a][b]);
               sum[2]+=n;
 
            }   
     
            //右下の計算//
            sum[3]=0;
            for(a=0;a<ht;a++) for(b=0;b<wd;b++)
            {
               m=(v2[a][b])*(v2[a][b]);
               sum[3]+=m;

            }   
    
     
             //分子の計算//
             sum[4]=0;
             for(a=0;a<hite;a++) for(b=0;b<wide;b++)
             {
                p=(v[a][b])*(v2[a][b]);
                sum[4]+=p;
             }  
     
             //sum4÷sum2*sum3のルート
              z=sum[4]/sqrt(sum[2]*sum[3]);
       
              printf("類似度%d=%f\n",x,z);
 
   }
    return 0;
}





この投稿にコメントする

削除パスワード

No.29572

Re:BMPを2値化処理して保存したい
投稿者---ルナレルナ(2007/01/23 20:32:43)
http://park6.wakwak.com/~nougaki/mini_program/


>今はこんな感じなんですが、2値化した輝度の値(変数sとt)が相関の式へどのようにいれたらいいのか悩んでます。

二値化は二値化、相関は相関、ここでの相関の話は筋違い。
二値化のみのプログラムを求む。


この投稿にコメントする

削除パスワード

No.29573

Re:BMPを2値化処理して保存したい
投稿者---若旦那(2007/01/23 20:56:32)


失礼しました。
これが2値化のコードです。


#include <stdio.h>
#include <math.h>


 int main(void)
{
    FILE  *fp;
    int wide,hite,wd,ht,cm;
    int v[256][256],v2[256][256];
    int h[54],palette[1024];
    int i,j,a,b,x;
    int n,m,p,t,s; 
    double sum[4];
    double z;
    char  gazou[256];
    double heikin,heikin2;
   
    

      /*原画像data*/
  
    fp=fopen("5.bmp","rb");     // mono画像ファイルを開く
    if(fp==NULL){
      printf("エラー\n");
      return 1; }
    for(j=0; j<54; j++) h[j]=fgetc(fp);      // ヘッダの読み込み 
       wide=h[18]+h[19]*256;              // 画像の幅の計算
       hite=h[22]+h[23]*256;            // 画像の高さの計算
       cm=h[28];
        
    
      //mono画像データ読み込み
      sum[0]=0;
      for(a=0; a<hite; a++)for(b=0; b<wide; b++)
      {
         v[a][b]=fgetc(fp);
        
         sum[0]+=v[a][b];                     //濃度値合計sum      
      }
        
      heikin=sum[0]/(wide*hite);     //閾値を決めるためのheikin
        
      for(a=0; a<hite; a++)for(b=0; b<wide; b++)
      { 
         s=v[a][b];
         if(s>heikin) s=255;         //濃度値がheikin以上なら白
         else s=0;            //以下なら黒にする
       
      }

    
      /*入力画像data*/
      for (x=0; x<15; x++) 
      {
         sprintf(gazou,"%d.bmp",x);
         fp=fopen(gazou,"rb");      // mono画像ファイルを開く
                    
         if(fp==NULL){
         printf("エラー2\n");
         return 1; }
          
  
         for(j=0; j<54; j++)  h[j]=fgetc(fp);  // ヘッダの読み込み 
         wd=h[18]+h[19]*256;              // 画像の幅の計算
         ht=h[22]+h[23]*256;            // 画像の高さの計算
         cm=h[28];
          
    
         //mono画像データ読み込み
         sum[1]=0;
         for(a=0; a<ht; a++)for(b=0; b<wd; b++)
         {
            v2[a][b]=fgetc(fp);
   
            sum[1]+=v2[a][b];                     //濃度値合計sum
         } 
         
         heikin2=sum[1]/(wd*ht);     //閾値を決めるためのheikin2
       
         for(a=0; a<ht; a++)for(b=0; b<wd; b++)
         { 
             t=v2[a][b];
             if(t>heikin2) t=255;       //濃度値がheikin2以上なら白
             else t=0;            //以下なら黒にする

         }  
      }
      return 0;
}






この投稿にコメントする

削除パスワード

No.29574

Re:BMPを2値化処理して保存したい
投稿者---ルナレルナ(2007/01/23 21:25:59)
http://park6.wakwak.com/~nougaki/mini_program/


> int wide,hite,wd,ht,cm;

cmってなんだろう?

> int h[54],palette[1024];

配列paletteは、必要無くなったんじゃなかったのか?

> fp=fopen("5.bmp","rb");     // mono画像ファイルを開く

mono画像を開くのか?
mono画像を開いて、二値化するのか?

> for(j=0; j<54; j++) h[j]=fgetc(fp);      // ヘッダの読み込み 
>       wide=h[18]+h[19]*256;              // 画像の幅の計算
>       hite=h[22]+h[23]*256;            // 画像の高さの計算

画像のサイズは、もうわかってるんじゃないのか?

>       cm=h[28];

???

>      //mono画像データ読み込み

mono画像データを読み込むのか?

>         v[a][b]=fgetc(fp);

fgetc()で画像データは、正しく読みこめるのか?
        
>         sum[0]+=v[a][b];                     //濃度値合計sum      

v[a][b]の値は正しいだろうか?
sumの値は正しいだろうか?
heikinの値は正しいだろうか?




この投稿にコメントする

削除パスワード

No.29575

Re:BMPを2値化処理して保存したい
投稿者---若旦那(2007/01/23 22:00:33)


何度もありがとうございます!

cm、paletteは不要でした

濃淡画像の間違いです。
濃淡画像を二値化するプログラムを考えています、

濃度値などfgetc()で正しく読みこめてると思っていましたがまさか違いますか!?

v[a][b]、sum、heikinの値をprintfで出力したらそれらしい値がでているので合っていると思います。
こっちも間違っているのですか!?

もう一度プログラムです。



#include <stdio.h>
#include <math.h>


 int main(void)
{
    FILE  *fp;
    int wide,hite,wd,ht;
    int v[256][256],v2[256][256];
    int h[54];
    int i,j,a,b,x;
    int t,s; 
    double sum[4];
    double z;
    char  gazou[256];
    double heikin,heikin2;
   
    

      /*原画像data*/
  
    fp=fopen("5.bmp","rb");     // 濃淡画像ファイルを開く
    if(fp==NULL){
      printf("エラー\n");
      return 1; }
    for(j=0; j<54; j++) h[j]=fgetc(fp);      // ヘッダの読み込み 
       wide=h[18]+h[19]*256;              // 画像の幅の計算
       hite=h[22]+h[23]*256;            // 画像の高さの計算
       cm=h[28];
        
    
      //濃淡画像データ読み込み
      sum[0]=0;
      for(a=0; a<hite; a++)for(b=0; b<wide; b++)
      {
         v[a][b]=fgetc(fp);
        
         sum[0]+=v[a][b];                     //濃度値合計sum      
      }
        
      heikin=sum[0]/(wide*hite);     //閾値を決めるためのheikin
        
      for(a=0; a<hite; a++)for(b=0; b<wide; b++)
      { 
         s=v[a][b];
         if(s>heikin) s=255;         //濃度値がheikin以上なら白
         else s=0;            //以下なら黒にする
       
      }

    
      /*入力画像data*/
      for (x=0; x<15; x++) 
      {
         sprintf(gazou,"%d.bmp",x);
         fp=fopen(gazou,"rb");      // 濃淡画像ファイルを開く
                    
         if(fp==NULL){
         printf("エラー2\n");
         return 1; }
          
  
         for(j=0; j<54; j++)  h[j]=fgetc(fp);  // ヘッダの読み込み 
         wd=h[18]+h[19]*256;              // 画像の幅の計算
         ht=h[22]+h[23]*256;            // 画像の高さの計算
         cm=h[28];
          
    
         //濃淡画像データ読み込み
         sum[1]=0;
         for(a=0; a<ht; a++)for(b=0; b<wd; b++)
         {
            v2[a][b]=fgetc(fp);
   
            sum[1]+=v2[a][b];                     //濃度値合計sum
         } 
         
         heikin2=sum[1]/(wd*ht);     //閾値を決めるためのheikin2
       
         for(a=0; a<ht; a++)for(b=0; b<wd; b++)
         { 
             t=v2[a][b];
             if(t>heikin2) t=255;       //濃度値がheikin2以上なら白
             else t=0;            //以下なら黒にする

         }  
      }
      return 0;
}


戻る



この投稿にコメントする

削除パスワード

No.29576

Re:BMPを2値化処理して保存したい
投稿者---yoh2(2007/01/23 22:01:27)


気になるところが3箇所。

まずひとつ目。
>    int v[256][256],v2[256][256];

別枝で、想定している画像サイズが256x256または1024x1024であるという発言が
ありましたが、これでは1024x1024の画像は扱えません。

かといって、単にv[1024][1024]等としても、スタックを食い潰して、正常に動作しない
可能性があります。

まあ、この問題に関しては、スタックの食い潰しとか、メモリの動的確保とか聞いてピンと
来ないなら、いくつか新しいことを覚えなければ解決できないので、まずは256x256で
完全に動作するものを作ってから取り組んだ方がよいと思います。


でもってふたつ目。
>      //mono画像データ読み込み
>      sum[0]=0;
>      for(a=0; a<hite; a++)for(b=0; b<wide; b++)
>      {
>         v[a][b]=fgetc(fp);
>        
>         sum[0]+=v[a][b];                     //濃度値合計sum      
>      }

読み込もうとしているBMPは24ビットカラーですよね? それなら、1ピクセル当たり3バイト
読まなければならないハズですが、ここでは1ピクセル当たり1バイトしか読んでいません。
……と思っていたのですが、これだけレスが付いて誰も突っ込まないところを見ると、幅の
フィールドがピクセル数でなく、バイト数で書かれているフォーマットもあるのでしょうか。

# 昔、16ビットBMPは存在しないと豪語した後に16ビットBMPの仕様を見付けて
# 恥ずかしい思いをしたことがあったし……

もし、3バイトずつ読むのが正解でしたら、別枝でbreakwind4uさんが書いたコードが
参考になりますが。


最後にみっつ目。
>         s=v[a][b];
>         if(s>heikin) s=255;         //濃度値がheikin以上なら白
>         else s=0;            //以下なら黒にする

前の相関計算込みのソースも合わせて見ると、この部分でv[a][b]の値を0か255に
書き換えようとしているように思えます。
しかし、これではv[a][b]は書き変わりません。

    int x = 1, y = 2;
    x = y;
    x = 3;

としたところで、yが3になるわけでないのと一緒。


この投稿にコメントする

削除パスワード

No.29580

Re:BMPを2値化処理して保存したい
投稿者---yoh2(2007/01/23 22:44:08)


>もし、3バイトずつ読むのが正解でしたら、別枝でbreakwind4uさんが書いたコードが
>参考になりますが。

おっと、すみません。breakwind4uさんが書いたコードはppmの読み書きですね。
まあ、3バイトずつ読む、というところだけ取り出せばBMPでも同じ要領ですが。
ただし、(グレースケールだと関係ないけど)ppmとbmpはRGBの並び順が違いますね。


この投稿にコメントする

削除パスワード

No.29581

Re:BMPを2値化処理して保存したい
投稿者---若旦那(2007/01/23 23:11:32)


1024x1024は必ず使いますのでまずいです。。

v[1024][1024]でやってみたが、おっしゃるとおりプログラムが正常に動作しませんでした。
malloc()とfree()を使えば解決できるようですね!


24ビットカラーBMPを濃淡画像に処理したものを読み込みます。
v[256][256][3]が正しいのでしょうか?
私も混乱しております。。

v[a][b]の値を書き換えようとしています。
やはり、おかしいですよね、考えてるんですがだめです。。







この投稿にコメントする

削除パスワード

No.29604

Re:BMPを2値化処理して保存したい
投稿者---yoh2(2007/01/25 22:37:02)


>24ビットカラーBMPを濃淡画像に処理したものを読み込みます。
>v[256][256][3]が正しいのでしょうか?

一応それでもできますが、濃淡画像、つまりグレースケールなら、どうせRGBすべて同じ値に
なっているはずですので、律儀にRGB全色持つ必要はありません。
例えば、色の読み込みループ中で、fgetc()を3つ一組で使い、保存するのはひとつだけ、
とする方法を取れば、256x256の配列(つまりいままでと同じ)で済みます。
    v[a][b] = fgetc(fp);
    fgetc(fp); /* 読み捨て */
    fgetc(fp); /* 読み捨て */

>v[a][b]の値を書き換えようとしています。
>やはり、おかしいですよね、考えてるんですがだめです。。

まあまあ、落ち付いて。
配列などが出てきて混乱しているのなら、まずは単純な例を考えてみましょう。
以下の動作をするコードは書けますか?

(a) 変数xの値が100以上なら、xに255を代入する。
(b) (a)が成立しなければ、xに0を代入する。

できたのなら、xをv[a][b]に、100をheikinに置き換えてみましょう。
置き換えたコードは、若旦那さんが望むコードになっているはずです。


この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧