C言語 画像処理 エッジ抽出

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
rampom
記事: 5
登録日時: 10年前
住所: 東京都

C言語 画像処理 エッジ抽出

#1

投稿記事 by rampom » 10年前

こんにちは.
C言語で,エッジ抽出のプログラムを組んで,cygwinでコンパイルし,実行したのですが,グレイスケール画像までは上手くいくのですが,エッジ検出画像ののエッジが2重になってしまいます.
原因が分からず困っているので.よろしくお願いします.

コード:

 
#include<stdio.h>
#define X_SIZE 2000	/*画像の横サイズを定義*/
#define Y_SIZE 2000	/*画像の縦サイズを定義*/
#define amp 1		/*エッジ強度の倍率を定義*/

unsigned char header[54];			/*unsigned:符号無しの整数型、char:文字データ、header[54]:0~53の1次配列*/
	unsigned char 	screen[Y_SIZE][X_SIZE][3],	/*unsigned:符号無しの整数型、char:文字データ、screen[480][640][3]:3次配列*/
			img_work[Y_SIZE][X_SIZE][3],	/*screen[y][x][color(b=0,g=1,r=2と割り当てられる)]	0~255を値として取る*/
			ttv_work[Y_SIZE][X_SIZE][3],
			edge_work[Y_SIZE][X_SIZE][3];

int main() 
{

	FILE *fp;	/*ファイルポインタの宣言*/

	int thresh;	/*閾値(0~255)*/
	char input_file[128],gray_file[128],edge_file[128],ttv_file[128];	/*ファイル名の配列を定義*/
	unsigned char Light[256]={0};	/*ヒストグラム白黒濃淡配列を定義*/


	/*------------画像ファイルを読み込む------------*/


	printf("処理を行う画像ファイル名を入力してください.(拡張子:bmp)\n---");
	scanf("%s",input_file);					/*入力ファイル名を指定*/
	printf("処理を行う画像ファイルは「 %s 」です.\n\n",input_file);
	fp=fopen(input_file,"rb"); 	/* 処理する画像をオープンする	
					Windowsビットマップ形式 X_SIZE*Y_SIZEピクセル,24ビットカラー、rb:バイナリデータの読み込みに使用 */
	if((fp=fopen(input_file,"rb"))==NULL){		/*ファイルが開けない場合のエラー表示*/
		printf("画像ファイルが正常に開けませんでした.\n");
		exit(1);
	}
	fread(header,1,54,fp); /* ヘッダ(54バイト)を飛ばす */
	fread(screen,1,X_SIZE*Y_SIZE*3,fp); /* 残りはデータ(最下行から順に入る) */
	fclose(fp);


	/*------------カラー画像をグレースケールに変換する------------*/


	int X,Y,k,col;
	for(X=0;X<X_SIZE;X++){
		for(Y=0;Y<Y_SIZE;Y++){
			for(col=0;col<=2;col++){
				img_work[Y][X][col]=0.1145*screen[Y][X][0]
					+0.5866*screen[Y][X][1]+0.2989*screen[Y][X][2];	
			}
		}
	}


	/*------------グレースケール画像を保存する------------*/


	printf("グレースケールにする画像ファイル名を入力してください.(拡張子:bmp)\n---");
	scanf("%s",gray_file);		/*グレースケールとするファイル名を指定*/
	fp=fopen(gray_file,"wb");	/*処理した画像を書き込むファイルをオープンする*/
	if((fp=fopen(gray_file,"wb"))==NULL){		/*ファイルが開けない場合のエラー表示*/
		printf("画像ファイルが正常に開けませんでした.\n");
		exit(1);
	}
	fwrite(header,1,54,fp); /* ヘッダ */
	fwrite(img_work,1,X_SIZE*Y_SIZE*3,fp); /* データ */
	fclose(fp);
	printf("グレースケールの画像ファイル「 %s 」を保存しました.\n\n",gray_file);


	/*------------エッジ検出処理をする------------*/


	static int cx[9]={-1,0,0,			/*static:関数が終了しても消滅せず、値を残すことができる*/
			 				-1,0,0,			/*cx:Sobelオペレータ(微分オペレータの一種)*/
			  				-1,0,-1};
	static int cy[9]={-1,-1,-1,
			  				0,0,1,			/*cy:Sobelオペレータ(微分オペレータの一種)*/
			  				1,1,1};
	int d[9];
	int I,J,edge_int;
	int color;
	float xx,yy,zz;

	for(I=1;I<Y_SIZE-1;I++){
		for(J=1;J<X_SIZE-1;J++){
			d[0]=img_work[I-1][J-1][0];		/*d[9]:3×3の画素データ*/
			d[1]=img_work[I-1][J][0];			/*d[]にgrayscaleの青色濃度データを代入*/
			d[2]=img_work[I-1][J+1][0];
			d[3]=img_work[I][J-1][0];
			d[4]=img_work[I][J][0];
			d[5]=img_work[I][J+1][0];
			d[6]=img_work[I+1][J-1][0];
			d[7]=img_work[I+1][J][0];
			d[8]=img_work[I+1][J+1][0];
			x_edge=(float)(	 cx[0]*d[0]+cx[1]*d[1]+cx[2]*d[2]	/*x方向エッジ強度データ*/
					+cx[3]*d[3]+cx[4]*d[4]+cx[5]*d[5]
					+cx[6]*d[6]+cx[7]*d[7]+cx[8]*d[8]);
			y_edge=(float)(	 cy[0]*d[0]+cy[1]*d[1]+cy[2]*d[2]	/*y方向エッジ強度データ*/
					+cy[3]*d[3]+cy[4]*d[4]+cy[5]*d[5]
					+cy[6]*d[6]+cy[7]*d[7]+cy[8]*d[8]);
			zz=(float)(amp*sqrt(xx*xx+yy*yy));/*エッジ強度の値(sqrt:平方根)、※amp値によって強度を調節*/
			edge_int=(int)zz;					/*エッジ強度を整数型に変換*/
			if(edge_int>255){					/*エッジ強度の最大値を255に調整*/
				edge_int=255;
			}
			for(color=0;color<=2;color++){
				edge_work[I][J][color]=(unsigned char)edge_int;	/*エッジ強度を符号なし文字型に変換し出力画像配列に代入*/
			}
		}
	}


	/*------------エッジ強調処理した画像を保存する------------*/


	printf("エッジ検出処理をする画像ファイル名を入力してください.(拡張子:bmp)\n---");
	scanf("%s",edge_file);		/*エッジ検出処理をするファイル名を指定*/
	fp=fopen(edge_file,"wb");	/*処理した画像を書き込むファイルをオープンする*/
	if((fp=fopen(edge_file,"wb"))==NULL){		/*ファイルが開けない場合のエラー表示*/
		printf("画像ファイルが正常に開けませんでした.\n");
		exit(1);
	}
	fwrite(header,1,54,fp); /* ヘッダ */
	fwrite(edge_work,1,X_SIZE*Y_SIZE*3,fp); /* データ */
	fclose(fp);
	printf("エッジ検出処理をした画像ファイル「 %s 」を保存しました.\n\n",edge_file);


	/*------------白黒濃淡情報を抽出する------------*/


	for(Y=0;Y<Y_SIZE;Y++){
		for(X=0;X<X_SIZE;X++){
			for(k=0;k<256;k++){
				if(k==img_work[Y][X][0]){/*画像配列のデータを明度配列に代入*/
					Light[k]++;
				}
			}
		}
	}

	/*------------判別分析法により閾値を決定する------------*/


	int s,i;
	double n1,n2,m1,m2;
	double v[256],vmax;

	for(s=1;s<256;s++){
		n1=0;
		m1=0;
		for(i=0;i<s;i++){
			n1+=Light[i];
			m1+=i*Light[i];
		}
		if(n1==0.0){
			m1=0.0;
		}else{
			m1/=n1;
		}
		n2=0;
		m2=0;
		for(i=s;i<256;i++){
			n2+=Light[i];
			m2+=i*Light[i];
		}
		if(n2==0.0){
			m2=0.0;
		}else{
			m2/=n2;
		}
		v[s]=n1*n2*(m1-m2)*(m1-m2);
	}

	vmax=0;
	s=0;
	for(i=1;i<256;i++){
		if(v[i]>vmax){
			vmax=v[i];
			s=i;
			thresh=s;							/*求められた値をthreshに代入*/
		}
	}


	/*------------エッジ抽出画像に対して2値化処理を行う------------*/


	for(X=0;X<X_SIZE;X++){
		for(Y=0;Y<Y_SIZE;Y++){
			if(edge_work[Y][X][0]<=thresh){
				for(col=0;col<3;col++){
					edge_work[Y][X][col]=0;	/*閾値以下の場合、画素の値を0とする*/
				}
			}else{
				for(col=0;col<3;col++){
					edge_work[Y][X][col]=255;/*閾値以上の場合、画素の値を255とする*/
				}
			}
		}
	}



	/*------------2値化画像を保存する------------*/


	printf("二値化する画像ファイル名を入力してください.(拡張子:bmp)\n---");
	scanf("%s",ttv_file);					/*二値化するファイル名を指定*/

	fp=fopen(ttv_file,"wb");	/*2値化した画像を書き込むファイルをオープンする*/
	if((fp=fopen(ttv_file,"wb"))==NULL){		/*ファイルが開けない場合のエラー表示*/
		printf("画像ファイルが正常に開けませんでした.\n");
		exit(1);
	}
	fwrite(header,1,54,fp); /* ヘッダ */
	fwrite(edge_work,1,X_SIZE*Y_SIZE*3,fp); /* データ */
	fclose(fp);
	printf("閾値を%dとして処理を行いました.\n",thresh);
	printf("二値化処理の画像ファイル「 %s 」を保存しました.\n",ttv_file);

	printf("全ての作業が終了しました.\n");

	return 0;
}

non
記事: 1097
登録日時: 13年前

Re: C言語 画像処理 エッジ抽出

#2

投稿記事 by non » 10年前

言葉では症状がわからないので、実行してみようと思ったのですが、コンパイルエラーは出るし、サンプルの画像ファイルもないので
見る気がしません。

まして、最近別のスレッドが2つあったと思いますが、そちらも中途半端ですね。指摘があったところをなおしてもいないし。。。。応答もない。
もっと真摯に対応してはいかがでしょうか。
non

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

Re: C言語 画像処理 エッジ抽出

#3

投稿記事 by usao » 10年前

エッジが2重って言われても…
・単にそういう画像をつかってるんじゃないの?
・そもそもSobelフィルタならエッジの幅は1画素にならないけど?
・というかそれ以前にcx[],cy[]がSobelフィルタのカーネルに見えない

まず,前のスレッドを放置しないように.

閉鎖

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