画像処理のプログラムについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
たかP

画像処理のプログラムについて

#1

投稿記事 by たかP » 10年前

初めまして、こんにちは
いま、C言語を使って画像処理のプログラミングを行っているのですが、少し行き詰ってしまっているので皆様のお力をお借りしたいです。
処理内容としては、画像を二値化(仮に黒を0、白を1とします)したあとに、その二値化した画像をY軸方向(画像を上から)からスキャンし、
その列で一番初めの0の部分の座標(X.Y)を求めて、その座標をもとに横からスキャンし、先ほど求めた座標のひとつ前にある座標の値を変える(0の場合1に、1の場合0にする)

という処理なのですが画像の二値化まではできたのですが、その後の部分の作成の仕方がわからないので、アドバイスをよろしくお願いいたします。

以下、ソースコードです。(二値化まで)

コード:



#include <stdio.h>
#include <process.h>



#define Y_SIZE 512	// 処理できる最大画像
#define X_SIZE 512

#define HIGH   255	// 画像の最大強度値
#define LOW      0	// 画像の最小強度値
#define LEVEL  256	// 画像の強度レベル値

// BMPファイルのフォーマットに従って用意した変数
typedef unsigned short WORD;
typedef unsigned long DWORD;

WORD  bfType;
DWORD bfSize;
WORD  bfReserved1,
      bfReserved2;
DWORD bfOffBits;
DWORD biSize, 
      biWidth, biHeight;
WORD  biPlanes,
      biBitCount;
DWORD biCompression,       
      biSizeImage,
      biXPelsPerMeter,
      biYPelsPerMeter,
      biClrUsed, 
      biClrImportant;

unsigned char image_in[Y_SIZE][X_SIZE][3];	// 入力カラー画像配列
unsigned char image_out[Y_SIZE][X_SIZE][3];	//出力カラー画像配列
unsigned char image_bw[Y_SIZE][X_SIZE];		//濃淡画像配列

unsigned char data_rgb[Y_SIZE][X_SIZE][3];	// RGB画像配列



void readBMP(
		char *filename,							// BMPファイル名
		unsigned char image[Y_SIZE][X_SIZE][3]	// 24ビットRGB画像配列 
		    )
{
	FILE *fp;
	int i, j, k;
	
	// ファイルオープン 
	if ((fp = fopen(filename, "rb"))==NULL) {
		printf("readBmp: Open error!\n");
		exit(1);
	}
	printf("input file : %s\n", filename);

	// ヘッダー情報読み込む
	fread(&bfType, sizeof(bfType), 1, fp);
	fread(&bfSize, sizeof(bfSize), 1, fp);
	fread(&bfReserved1, sizeof(bfReserved1), 1, fp);
	fread(&bfReserved2, sizeof(bfReserved2), 1, fp);
	fread(&bfOffBits, sizeof(bfOffBits), 1, fp);

	fread(&biSize, sizeof(biSize), 1, fp);
	fread(&biWidth, sizeof(biWidth), 1, fp);
	fread(&biHeight, sizeof(biHeight), 1, fp);
	fread(&biPlanes, sizeof(biPlanes), 1, fp);
	fread(&biBitCount, sizeof(biBitCount), 1, fp);
	fread(&biCompression, sizeof(biCompression), 1, fp);
	fread(&biSizeImage, sizeof(biSizeImage), 1, fp);
	fread(&biXPelsPerMeter, sizeof(biXPelsPerMeter), 1, fp);
	fread(&biYPelsPerMeter, sizeof(biYPelsPerMeter), 1, fp);
	fread(&biClrUsed, sizeof(biClrUsed), 1, fp);
	fread(&biClrImportant, sizeof(biClrImportant), 1, fp);

	// RGB画像データ読み込む
	for (i=0; i<(int)biHeight; i++)
	for (j=0; j<(int)biWidth; j++) {
		for (k=0; k<3; k++) {
			//fread(&image[i][j][2-k], 1, 1, fp);
			fread(&image[biHeight-i][j][2-k], 1, 1, fp);
		}
	}
	
	fclose(fp);
}



void writeBMP(
		unsigned char image[Y_SIZE][X_SIZE][3],
		char *filename                         )
{
	FILE *fp;
	int i, j, k;
	
	// ファイルオープン 
	if ((fp = fopen(filename, "wb"))==NULL) {
		printf("writeBmp: Open error!\n");
		exit(1);
	}
	printf("output file : %s\n", filename);

	// ヘッダー情報 
	fwrite(&bfType, sizeof(bfType), 1, fp);
	fwrite(&bfSize, sizeof(bfSize), 1, fp);
	fwrite(&bfReserved1, sizeof(bfReserved1), 1, fp);
	fwrite(&bfReserved2, sizeof(bfReserved2), 1, fp);
	fwrite(&bfOffBits, sizeof(bfOffBits), 1, fp);

	fwrite(&biSize, sizeof(biSize), 1, fp);
	fwrite(&biWidth, sizeof(biWidth), 1, fp);
	fwrite(&biHeight, sizeof(biHeight), 1, fp);
	fwrite(&biPlanes, sizeof(biPlanes), 1, fp);
	fwrite(&biBitCount, sizeof(biBitCount), 1, fp);
	fwrite(&biCompression, sizeof(biCompression), 1, fp);
	fwrite(&biSizeImage, sizeof(biSizeImage), 1, fp);
	fwrite(&biXPelsPerMeter, sizeof(biXPelsPerMeter), 1, fp);
	fwrite(&biYPelsPerMeter, sizeof(biYPelsPerMeter), 1, fp);
	fwrite(&biClrUsed, sizeof(biClrUsed), 1, fp);
	fwrite(&biClrImportant, sizeof(biClrImportant), 1, fp);

	// ビットマップデータ 
	for (i=0; i<(int)biHeight; i++)
	for (j=0; j<(int)biWidth; j++) {
		for (k=0; k<3; k++) {
			fwrite(&image[biHeight-i][j][2-k], 1, 1, fp);
		}
	}
	
	fclose(fp);
}


void BMPto256BW(
		unsigned char image[Y_SIZE][X_SIZE][3],
		unsigned char image_bw[Y_SIZE][X_SIZE]  )
{
	int y, x, a;
	for (y=0; y<(int)biHeight; y++)
	for (x=0; x<(int)biWidth; x++) {
		a = (int)(0.3*image[y][x][0] + 0.59*image[y][x][1] + 0.11*image[y][x][2]);
		if (a<LOW) a = LOW;
		if (a>HIGH) a = HIGH;
		image_bw[y][x] = a;
	}
}





void BWto24BMP(
		unsigned char image_bw[Y_SIZE][X_SIZE],
		unsigned char image[Y_SIZE][X_SIZE][3] )
{
	int y, x, a;
	for (y=0; y<(int)biHeight; y++)
	for (x=0; x<(int)biWidth; x++) {
		a = image_bw[y][x];
		image[y][x][0] = a;
		image[y][x][1] = a;
		image[y][x][2] = a;
	}
}



void toBinary(
		int atai,
		unsigned char image_bw[Y_SIZE][X_SIZE] )
{
	int y, x;
	for (y=0; y<(int)biHeight; y++)
	for (x=0; x<(int)biWidth; x++) {
		if(image_bw[y][x] >= atai)	image_bw[y][x]=HIGH;
		else image_bw[y][x] = LOW;
	}
}



void imageCopyBW(
		unsigned char image1[Y_SIZE][X_SIZE],
		unsigned char image2[Y_SIZE][X_SIZE] )
{
	int x, y;
	for (y=0; y<(int)biHeight; y++)
	for (x=0; x<(int)biWidth; x++)
		image2[y][x] = image1[y][x];
}


void main(void)
{
	char input[100], output[100];
	int intensity;

	printf("入力画像ファイル名(*.bmp):"); scanf("%s", input);

	readBMP(input, image_in);	  // 画像の入力,RGB24ビットカラーBMP画像を配列に格納

	//画像処理2:白黒変換
	BMPto256BW(image_in, image_bw); // RGBカラー画像を白黒画像に変換
	BWto24BMP(image_bw, image_out); // 単チャンネル白黒画像を3チャンネルBMP標準フォーマットへ変換
	printf("白黒出力画像ファイル名(output.bmp):"); scanf("%s", output);
	writeBMP(image_out, output);		// 白黒画像出力

	//画像処理3:2値化
	printf("2値化画像の閾値(0~255):"); scanf("%d", &intensity);
	toBinary(intensity,image_bw);
	BWto24BMP(image_bw, image_out);
	printf("2値化出力画像ファイル名(*.bmp):"); scanf("%s", output);
	writeBMP(image_out, output);		// 白黒画像出力

}






アバター
usao
記事: 1887
登録日時: 11年前

Re: 画像処理のプログラムについて

#2

投稿記事 by usao » 10年前

>処理内容としては、画像を二値化(仮に黒を0、白を1とします)したあとに、その二値化した画像をY軸方向(画像を上から)からスキャンし、
>その列で一番初めの0の部分の座標(X.Y)を求めて、その座標をもとに横からスキャンし、先ほど求めた座標のひとつ前にある座標の値を変える(0の場合1に、1の場合0にする)

意味がよくわかりません.

>画像をY軸方向(画像を上から)からスキャンし、
というのは,
(x,0) → (x,1) → (x,2) → ... → (x,ymax)
という順で見ていく,ということだろうと思いますが,x座標はどうやって決定するのでしょうか?

>その列で一番初めの0の部分の座標(X.Y)を求めて、
例えば,この結果が(x=10,y=20)だったとして,
座標(x=9,y=20)の画素値を反転したい,ということなのでしょうか?

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 画像処理のプログラムについて

#3

投稿記事 by みけCAT » 10年前

とりあえず、この5パターンの5×5の入力に対する期待する出力を教えていただけますか?

コード:

11111
11111
11111
11111
11111

00000
00000
00000
00000
00000

01111
11111
11111
11111
11111

10101
01010
10101
01010
10101

11111
10001
10101
10001
11111
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

たかP

Re: 画像処理のプログラムについて

#4

投稿記事 by たかP » 10年前

コード:

>というのは,
(x,0) → (x,1) → (x,2) → ... → (x,ymax)
という順で見ていく,ということだろうと思いますが,x座標はどうやって決定するのでしょうか?

あ、X座標の指定をすっかり忘れていました
(x,y)→(0,0)→(0,1)→(0,2)→・・・
yが画像の一番下までいったら、(1.0)→(1.1)→(1.2)・・・
という感じにしたいです

>その列で一番初めの0の部分の座標(X.Y)を求めて、
>例えば,この結果が(x=10,y=20)だったとして,
>座標(x=9,y=20)の画素値を反転したい,ということなのでしょうか?

説明がへたくそで申し訳ないです。要はそうしたいのです。

たかP

Re: 画像処理のプログラムについて

#5

投稿記事 by たかP » 10年前

みけCAT さんが書きました:とりあえず、この5パターンの5×5の入力に対する期待する出力を教えていただけますか?

コード:

11111
11111
11111
11111
11111

00000
00000
00000
00000
00000

01111
11111
11111
11111
11111

10101
01010
10101
01010
10101

11111
10001
10101
10001
11111

出力はこのようにしたいと考えています

コード:

11111
01111
01111
01111
01111

00000
00000
00000
00000
00000

01111
01111
01111
01111
01111

00101
01010
00101
01010
00101

01111
00001
00101
00001
01111

アバター
usao
記事: 1887
登録日時: 11年前

Re: 画像処理のプログラムについて

#6

投稿記事 by usao » 10年前

うーん,処理内容説明と出力例との対応がわからない…
例えば一番上の例で言えば,入力に0な箇所が無いのにどうして一番左の列の要素が反転されたのかが?

たかP

Re: 画像処理のプログラムについて

#7

投稿記事 by たかP » 10年前

説明不足なうえ説明が下手くそで申し訳ないです・・・。
二値化した画像を
0=白 1=黒 で表します。

入力画像

コード:

11111
01110  01110
01110  01110
01110  01110
01110  01110

01110  01110
01110  01110
01110  01110
01110  01110
01110  01110


11111
出力

コード:

11111
11110  11110
11110  11110
11110  11110
11110  11110

11110  11110
11110  11110
11110  11110
11110  11110
11110  11110


11111
という風に変えたいのです。

たかP

Re: 画像処理のプログラムについて

#8

投稿記事 by たかP » 10年前

たかP さんが書きました: ごめんなさい、上記のものは間違ってました。
二値化した画像を
0=白 1=黒 で表します。

入力画像

コード:

01110  01110
01110  01110
01110  01110
01110  01110

01110  01110
01110  01110
01110  01110
01110  01110
01110  01110


出力

コード:

11110  11110
11110  11110
11110  11110
11110  11110

11110  11110
11110  11110
11110  11110
11110  11110
11110  11110


という風に変えたいのです。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 画像処理のプログラムについて

#9

投稿記事 by softya(ソフト屋) » 10年前

途中参加ですいません。

> その列で一番初めの0の部分の座標(X.Y)を求めて、その座標をもとに横からスキャンし、先ほど求めた座標のひとつ前にある座標の値を変える(0の場合1に、1の場合0にする)
と書かれた最初のものと矛盾して見えます。

元 → 変換後
01110 → 11110

なぜ先頭だ1/0け反転したの説明してもらえますか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
usao
記事: 1887
登録日時: 11年前

Re: 画像処理のプログラムについて

#10

投稿記事 by usao » 10年前

いつのまにか 白と黒を表す{0,1}の関係が逆転しているのかな?
だとしても,本当にやりたい処理内容が何なのかがやっぱりわからないです.

{0,1}だとどっちが何なのか混乱するので白と黒を { W,B } で表記することにすれば,
説明された文面からの私の理解は以下のようなことになります.

 ・各列の中で,最も上にあるBを見つける
 ・そのBの位置の左隣の要素を反転する

例で言うとこう.(0と1で示された例と同じ形のデータです)

コード:

W B B B W
W B B B W
W B B B W
W B B B W
W B B B W
 ↓
B W W B W
W B B B W
W B B B W
W B B B W
W B B B W
で,示されている結果例がこれとは違うようなので,
説明文 と 本当にやりたいこと とが合致していないのではないか?と思います.

たかP

Re: 画像処理のプログラムについて

#11

投稿記事 by たかP » 10年前

Usaoさんが仰るようなプログラムを作成したいのです。

説明のしかたがへたくそで本当に申し訳ないです・・・

アバター
usao
記事: 1887
登録日時: 11年前

Re: 画像処理のプログラムについて

#12

投稿記事 by usao » 10年前

いや,でも処理結果例が違ってますし……

仮に私が示した結果例が求めるものなのだとしても,何に困っているのかも良くわからないのです.
(2値化が書けてこの処理コードを書けないということも無いような気がしますので.)
本当にそれだけの話であれば,
とりあえず一番左の列(x==0)では,反転対象が存在しないので「上から見ていく」処理の対象となる列は x>1 でしょうから,

コード:

for( int x=0; x<画像幅; x++ )
{
  ・上(y=0)から順に見ていき,最初の黒の場所を見つける
  ・その左の場所を反転する
}
というだけのことになりますよ?

たかP

Re: 画像処理のプログラムについて

#13

投稿記事 by たかP » 10年前

どこにプログラムを挿入したらいいのかというのと、どのようなプログラムを書いていけばいいのかがよくわからくて・・・

このプログラムも私が友人に教えてもらいながらようやっと書き上げたものですので、あまり深くは理解できておりません。
友人も「二値化後の作業については自分の力でやってみて」と、言われたのでここで質問させていただいたのです。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 画像処理のプログラムについて

#14

投稿記事 by softya(ソフト屋) » 10年前

プログラム以前にアルゴリズムをよく理解されていないのが最大の問題だと思います。
このままだと机上で確認データを作ってテストもできませんので、正しいかどうかがご本人にも理解できない状態です。
プログラムの前に机上で、入力と出力をちゃんと書ける事が最優先かと。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
usao
記事: 1887
登録日時: 11年前

Re: 画像処理のプログラムについて

#15

投稿記事 by usao » 10年前

「本当にやりたいこと」をご自身が完全に説明できない限り,内情を知らないこちらとしてはどうしようもないので,
一度そこらへんを整理してみたほうがよいかと思います.

たとえば,現在既に実装されている「2値化」とか「グレースケール化」とかって”何やってるのかがはっきりわかる”処理ですよね.
仮に「2値化」という言葉を全く用いずにその処理内容を
(画素ごとに輝度値と閾値とを比較して,輝度値>=閾値 であれば結果255に,そうでなければ0にするような処理がしたいです,みたく)
説明されたとしても,「ああ,こういうことがしたいんだろうなぁ」って想像がつく,というか.
もしそうであれば,こちらも想像を働かせて答えることも不可能ではないのですが,
今やろうとしている処理って,説明からはどうにも
何が目的なのか(説明に一部不足や誤りがあったとしても,本当はこういうことなんだろうなぁみたいな)想像がつかないのですよね…

オフトピック
ところで,画像処理のプログラムをやっているのはなぜなんでしょう?(別に無理に答えていただく必要はありませんが)

(1)C言語の練習とか : 単に練習問題として選んだ
(2)趣味 : 何かのツールを作るとか
(3)学校の課題
(4)例えば大学の卒業研究課題だとかそういった重い雰囲気の事柄
(5)その他

例えば,(1)とか(2)だと「最初はもうちょっと簡単な問題から始めませんか?」とか言える雰囲気ですが,
(3)であれば後回しにする選択肢は取れないのでしょうし,最悪(4)だったりした場合には……
まぁいずれにしろ,どうしても自前でやらなくてはならなくて
>どこにプログラムを挿入したらいいのかというのと、どのようなプログラムを書いていけばいいのかがよくわからくて・・・
という状態にあるのであれば,Cの基礎をしっかりやられた方が良いと思います.

たかP

Re: 画像処理のプログラムについて

#16

投稿記事 by たかP » 10年前

そうですね・・・、ひとまずはC言語の本とにらめっこしてもう少し自分なりに考えてみようと思います
usaoさんが仰るようにこれは(3)の学校の課題なのですが、プログラミング自体が得意ではないのでどうしようもなくて・・・

内容としては、二値化した画像に電子透かしを埋め込むというものです。
授業では、画像が何枚もの層になって重なっていることなどは理解できましたが、実際にプログラミングでやれといわれても正直よくわかりません。
先生にも、聞いたところ理論がわかるのに何故できないのか?と言われお手上げ状態なのです。
これはその中でも初歩的な事だといわれました。
画像は、何でも良いそうなのですが最初から白黒で表されているバーコードを使うのが良いと言われ、
一応そちらのほうで作成しようと思っていました。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 13年前
住所: 東海地方
連絡を取る:

Re: 画像処理のプログラムについて

#17

投稿記事 by softya(ソフト屋) » 10年前

たかP さんが書きました:そうですね・・・、ひとまずはC言語の本とにらめっこしてもう少し自分なりに考えてみようと思います
usaoさんが仰るようにこれは(3)の学校の課題なのですが、プログラミング自体が得意ではないのでどうしようもなくて・・・

内容としては、二値化した画像に電子透かしを埋め込むというものです。
授業では、画像が何枚もの層になって重なっていることなどは理解できましたが、実際にプログラミングでやれといわれても正直よくわかりません。
先生にも、聞いたところ理論がわかるのに何故できないのか?と言われお手上げ状態なのです。
これはその中でも初歩的な事だといわれました。
画像は、何でも良いそうなのですが最初から白黒で表されているバーコードを使うのが良いと言われ、
一応そちらのほうで作成しようと思っていました。
申し訳ありませんが、今問題となっているのは理論の方の理解です。
つまり、コードを組む以前の理解が出来ていないと言う状況なのです。
なので、そこからと書いたつもりなのですが。
【補足】 C言語の話は、その後の話です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

たかP

Re: 画像処理のプログラムについて

#18

投稿記事 by たかP » 10年前

あぁ、そういうことなのですね・・・
申し訳ないです。

画像処理自体あまりやったことがないので理論も知識もなくって・・・

閉鎖

“C言語何でも質問掲示板” へ戻る