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;
}