C言語で画像を平滑化、エッジ抽出を行うプログラムを作成

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

C言語で画像を平滑化、エッジ抽出を行うプログラムを作成

#1

投稿記事 by jsanym » 6年前

初めまして、jsanymと申します。
大学の授業で 「カメラで撮影した画像を用いて、平滑化ならびにエッジ抽出を作成せよ」といった課題が出されました。
以下のソースコードで私が書いた部分は平滑化とエッジ抽出です。他の部分はあらかじめ用意されていたソースコードです。

一応、コンパイルはできるのですが、処理命令を平滑化にすると「動作は停止しました」となります。エッジ抽出にすると動作は停止しないのですが、
何も起きません。元画像もエッジ抽出されていません。

どこが間違っているかご指摘お願いします。

コンパイラはEasyIDEC Ver0.0.6.0
言語はCです。

C言語は得意ではありません。

コード:

//24bitビットマップ画像を処理するプログラム

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

#define H 320		//画像の縦幅 Height
#define W 240		//画像の横幅 Width

//-----入力関数-------------------------------------------------------
int readImageFile(char filename[], unsigned char bufhead[], unsigned char image[W][H][3])
{
	unsigned char buf[W*3];
	int i,j,k;
	FILE *fp;

    if((fp=fopen(filename, "rb")) == NULL){
		return 0;								//読み込みに失敗した場合0を返す
	}

	fread(bufhead,54,1,fp);						//54Byte分のヘッダ情報を確保しておく

	for(j=0;j<H;j++){
		fread(buf,W*3,1,fp);					//一行分のB,G,R値をbufに格納
		for(i=0;i<W;i++){
			for(k=0;k<3;k++){
				image[i][j][k] = buf[i*3+k];	//一次元配列を三次元配列に分解 (k = 0:B, 1:G, 2:R) 
			}
		}
	}
    fclose(fp);

	return 1;									//正常終了した場合1を返す
}

//-----出力関数------------------------------------------------------
int writeImageFile(char filename[], unsigned char bufhead[], unsigned char image[W][H][3])
{
	unsigned char buf[W*3];
    int i,j,k;
    FILE *fp;

    if((fp=fopen(filename, "wb")) == NULL){
		return 0;
	}

	fwrite(bufhead,54,1,fp);					//入力関数で確保したヘッダ情報をそのまま書き込む

	for(j=0;j<H;j++){
		for(i=0;i<W;i++){
			for(k=0;k<3;k++){
				buf[i*3+k] = image[i][j][k];	//三次元配列を一次元配列に格納
			}
		}
		fwrite(buf,W*3,1,fp);					//一行分のB,G,R値を書き込む
	}
    fclose(fp);

	return 1;
}

//-----複写---------------------------------------------------------
void copyImage(unsigned char input[W][H][3], unsigned char output[W][H][3])
{
	int i,j,k;

	for(j=0;j<H;j++){
		for(i=0;i<W;i++){
			for(k=0;k<3;k++){
				output[i][j][k] = input[i][j][k];	//outputにinputをそのまま格納する
			}
		}
	}
}

//----グレースケール化------------------------------------------------
void transformGrayImage(unsigned char input[W][H][3], unsigned char output[W][H][3])
{
	int i,j,k;
	int temp;

	for(j=0;j<H;j++){
		for(i=0;i<W;i++){
			temp = (input[i][j][0] + input[i][j][1] + input[i][j][2]) / 3;	//RGB各値の平均
			for(k=0;k<3;k++){
				output[i][j][k] = temp;
			}
		}
	}
}
//----単純平滑化------------------------------------------------------
void smoothImage(unsigned char input[W][H][3], unsigned char output[W][H][3]) 
{
	int i,j,k;
	int buf;
	unsigned char c[9];
	
	for(i=1;i<H-1;i++){
		for(j=1;j<W-1;j++){
		     for(k=0;k<3;k++){
		     	     buf = (int)input[i-1][j-1][k]
				+  (int)input[i-1][j][k]
				+  (int)input[i-1][j+1][k]
				+  (int)input[i][j-1][k]
				+  (int)input[i][j][k]
				+  (int)input[i][j+1][k]
				+  (int)input[i+1][j-1][k]
				+  (int)input[i+1][j][k]
				+  (int)input[i+1][j+1][k];
				output[i][j][k] = buf/9;
			}
		}
	}
}
//----エッジ抽出------------------------------------------------------
void edgeImage(unsigned char input[W][H][3], unsigned char output[W][H][3], float amp)
{
    static int cx[9] = { 0, 0, 0,    /* オペレータの係数x(Roberts) */
                         0, 1, 0,    /* 他のオペレータの時は        */
                         0, 0,-1};    /* 書き換えて下さい            */
    static int cy[9] = { 0, 0, 0,    /* オペレータの係数y(Roberts) */
                         0, 0, 1,    /* 他のオペレータの時は        */
                         0,-1, 0};    /* 書き換えて下さい            */
    int        d[9];
    int        i, j,k, dat;
    float    xx, yy, zz;

    for (i = 1; i < W-1; i++) {
        for (j = 1; j < H-1; j++) {
        	for(k=0;k<3;k++){
            d[0] = input[i-1][j-1][k];
            d[1] = input[i-1][j][k];
            d[2] = input[i-1][j+1][k];
            d[3] = input[i][j-1][k];
            d[4] = input[i][j][k];
            d[5] = input[i][j+1][k];
            d[6] = input[i+1][j-1][k];
            d[7] = input[i+1][j][k];
            d[8] = input[i+1][j+1][k];
            xx = (float)(cx[0]*d[0] + cx[1]*d[1] + cx[2]*d[2]
                       + cx[3]*d[3] + cx[4]*d[4] + cx[5]*d[5]
                       + cx[6]*d[6] + cx[7]*d[7] + cx[8]*d[8]);
            yy = (float)(cy[0]*d[0] + cy[1]*d[1] + cy[2]*d[2]
                       + 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));
            dat = (int)zz;
            if(dat > 255) dat = 255;
            output[i][j][k] = (char)dat;
        }
    }
}
}
//-----メイン文-----------------------------------------------------
int main(void)
{
	unsigned char bufhead[54], inputImage[W][H][3], processImage[W][H][3], outputImage[W][H][3];
	char inputFileName[100];
	char outputFileName[100];
	float amp;

	int command;
	int theta;	//しきい値

	printf("入力画像 (24bit BMP):");	scanf("%s",&inputFileName);

	if((readImageFile(inputFileName, bufhead, inputImage)) == 0){
		printf("File load error\n");
		return 0;

	}
	
	printf("\n  1:複写\n  2:Gray化\n  3:保存\n  4:平滑化\n  5:エッジ抽出  0:終了\n");

	do{
		printf("\n処理命令:");	scanf("%d",&command);

		if(command == 1){
			copyImage(inputImage, processImage);
			printf("複写しました\n");
		}
		if(command == 2){
			transformGrayImage(inputImage, processImage);
			printf("Gray化しました\n");
		}
		if(command == 4){
			smoothImage(inputImage, processImage);
			printf("平滑化しました\n");
		}
		if(command == 5){
			edgeImage(inputImage,processImage, amp);
			printf("エッジ抽出しました\n");
		}
		if(command == 3){
			copyImage(processImage,outputImage);
			printf("\n出力画像 (24bit BMP):");	scanf("%s",&outputFileName);
			if((writeImageFile(outputFileName, bufhead, outputImage)) == 0){
				printf("File save error\n");
				return 0;
			}
		}
		
		copyImage(processImage, inputImage);		//次の処理のため、処理した画像をinputImageに複写

	}while(command != 0);

return 0;
}


アバター
usao
記事: 1552
登録日時: 6年前

Re: C言語で画像を平滑化、エッジ抽出を行うプログラムを作成

#2

投稿記事 by usao » 6年前

とりあえず平滑化の箇所を見ましたが
ひょっとして,配列の添え字が,幅方向と高さ方向とで逆になっていませんか?

アバター
へにっくす
記事: 628
登録日時: 7年前
住所: 東京都

Re: C言語で画像を平滑化、エッジ抽出を行うプログラムを作成

#3

投稿記事 by へにっくす » 6年前

エッジ抽出で渡している変数ampが初期化されていませんね。
C言語では、変数を宣言しただけですと、どんな値が入っているか分かりません。
ちゃんと初期化することをお勧めします。
written by へにっくす

jsanym

Re: C言語で画像を平滑化、エッジ抽出を行うプログラムを作成

#4

投稿記事 by jsanym » 6年前

お二人方、ありがとうございました。

閉鎖

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