ShihTzu
@ShihTzu

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

入力画像にメディアンフィルタを適用して平滑化画像を出力するプログラムを作りたい

解決したいこと

グレースケールの入力画像にメディアンフィルタを適用して平滑化画像を出力するプログラムを作りたいです。エラーが発生して困っています。解決方法を教えてください。

発生している問題・エラー

clang: error: linker command failed with exit code 1 (use -v to see invocation)

該当するソースコード

/****************
* メディアンフィルタを用いた平滑化 *
*****************/

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

void file_in(char *file_name, unsigned char **input, int size_x, int size_y);
void file_out(char *file_name, unsigned char **output, int size_x, int size_y);
void median(unsigned char **input, unsigned char **output, int size_f, int size_x, int size_y)
{
	int ix, iy;//ループ用変数
	int fix, fiy;//フィルタの変数
	int M=size_f*size_f;
	unsigned char data[M];//並べ替えでM番目を使う
	int count;
	int i,j;//並べ替えループ用変数

	if(!(size_f>0)&&(size_f%2)==1){//フィルタサイズは正の奇数
		printf("error");
		exit(1);
	}

	for(ix=size_f/2;ix<size_x-size_f/2;ix++){
		for(iy=size_f/2;iy<size_y-size_f/2;iy++){
			count=0;
			for(fix=-size_f/2;fix<=size_f/2;fix++)
				for(fiy=-size_f/2;fiy<=size_f/2;fiy++){
					data[count]=input[iy+fiy][ix+fix];
						count++;
				}
			for(i=0;i<(M-1);i++);//昇順ソート
			for(j=i;j<(M-1);j++)
				if(data[i]<data[j+1]){
					data[M]=data[i];
					data[i]=data[j+1];
					data[j+1]=data[M];
				}
			output[iy][ix]=data[(M-1)/2];//中央値の代入
		}
	}
}

int main(int argc, char *argv[])
{
	int		ix, iy;		// ループ用変数
	int		size_x, size_y;	// 入力画像の大きさ
	int		size_f;		// フィルタの大きさ
	unsigned char	**input;	// 入力画像
	unsigned char	**output;	// 出力画像
	FILE		*fp;		// ファイルポインタ
	FILE		*hoge;		//パイプを開く
	/*************
	* 引数の確認 *
	*************/
	if (argc!=4 && argc!=6) {
		printf("Usage: EXPANSION [in_file] [out_file] [size_filter] {size_x} {size_y}\n");
		exit(1);
	}

	if (argc == 4) {
		size_f = atoi(argv[3]);
		size_x = SIZE_X;
		size_y = SIZE_Y;
	}

	if (argc == 6) {
		size_f = atoi(argv[3]);
		size_x = atoi(argv[4]);
		size_y = atoi(argv[5]);
	}

	/*********************
	* 画像格納領域の確保 *
	*********************/
	input = (unsigned char **)malloc(size_y*sizeof(unsigned char *));
	if (input == NULL) {
		printf("MEMORY ERROR!\n");
		exit(1);
	}
	for (iy=0; iy<size_y; iy++) {
		input[iy] = (unsigned char *)malloc(size_x*sizeof(unsigned char));
		if (input[iy] == NULL) {
			printf("MEMORY ERROR!\n");
			exit(1);
		}
	}
	output = (unsigned char **)malloc(size_y*sizeof(unsigned char *));
	if (output == NULL) {
		printf("MEMORY ERROR!\n");
		exit(1);
	}
	for (iy=0; iy<size_y; iy++) {
		output[iy] = (unsigned char *)malloc(size_x*sizeof(unsigned char));
		if (output[iy] == NULL) {
			printf("MEMORY ERROR!\n");
			exit(1);
		}
	}

	/*******************************
	* ファイル入出力・フィルタ処理 *
	*******************************/
	file_in(argv[1], input, size_x, size_y);		// 画像ファイルの読込
	median(input, output, size_f, size_x, size_y);//メディアンフィルタ
	file_out(argv[2], output, size_x, size_y);		// 画像ファイルの出力
	return 0;
}
0

1Answer

コードの問題というよりはコンパイル時の問題です.エラー文

clang: error: linker command failed with exit code 1 (use -v to see invocation)

翻訳結果

clang: リンカーのコマンドは終了コード1で失敗しました。(-v で呼び出しを表示1)

です.リンカの動作に異常があったようです.

質問の内容から確実にわかるのは「リンカの動作に異常があった」までです.
エラーの詳細が不明なため,ここから先は推察になります.

こちらの環境で同様のエラーが出るように仕組むとエラー全文2は以下になりました.

Undefined symbols for architecture x86_64:
  "_file_in", referenced from:
     _main in main-ab3fbc.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

同じエラー文であるのなら,「シンボル解決」というリンカ3の仕事のうちの1つがうまく動作しなかったということになります.

原因として

  • file_in(),file_out()が実装されていない.
  • コンパイラ/リンカがimage.hやその中間ファイルを読み込めてない.

の2つが挙げられます.

コンパイルするときのコマンドを間違えていませんか?特にimage.hに入ってそうなfile_in()file_out()が見つからない場合,このようなエラーが出ます.コンパイラにimage.hの存在を教えてあげれていますか?

コンパイルのコマンドや手順を忘れがちなのであれば,Makefileを書くことをお勧めします.

余談

20行目の条件分岐!(size_f>0)&&(size_f%2)==1はコメントアウトの文面に反して「フィルタサイズによらずいつでもFalse」になります4

左式!(size_f>0)size_fが0以下の場合に真になり,右式(size_f%2)==1の評価をするものの,0以下の整数の2で割った余りは0-1なので右辺1と一致しません.

括弧を1つ増やして!(size_f > 0 && size_f % 2 == 1)にするか,ド・モルガンの法則を利用して短くsize_f < 0 || !(size_f % 2)と書くなどにしましょう.

また,median()関数内の整数配列data[]の長さはMなのにも関わらず,36.38行目でdata[M]として範囲外アクセスを行なっています.したがってセグフォ/コアダンプになります.

  1. -vオプションでclangが実際に動作させたコマンドが確認できます.おそらくリンカのコマンド動作後にエラーが起きていることでしょう.

  2. なるべくエラーは全文載せるようにしてください.長くなりそうなのであれば,折り畳み<details></details>が使えるので活用してください.今回記述していただいたエラー文では情報が不足していて,あまり正確な回答ができていません.

  3. エラー文中のldはGNUリンカです.そちらの環境で何のリンカが使われるかはわかりませんが,同様にリンカからのエラーメッセージが出ると思います.エラー解決のための本質的な情報はldが吐き出しています.このldコマンドが返したexit code 1を受け取ったclangは上で示した最後の行を吐き出すだけです.clang観点では「linkerが異常終了した」としかわからないのです.

  4. 否定の単項演算子!の優先順位は論理AND&&よりも高いです.よってこのような結果になります.

1Like

Comments

  1. @ShihTzu

    Questioner

    コメントありがとうございます。
    おかげさまで、エラーは仰るものと同じものでした。
    修正後、エラーは出なくなりました。
    ですが、出力結果を見てみると、
    上から2/3くらいに白黒のぼやけたような画像があり、それより下が真っ白という結果になりました。
  2. じゃあまた入力画像がうまく読み取れてなくておかしいんじゃないですかね...
    今気づいたんですけど,昇順ソートも上手く動いていないです.
  3. @ShihTzu

    Questioner

    入力画像を変えたらうまく動きました!ありがとうございました!
  4. file_in()が扱えない画像フォーマットで記述されている画像を指定すると,変な画像になると思います.使えない画像は避けるようにして動作確認をしてください.当たり前ですが拡張子の書き換えでは中身のフォーマットまで変わりません.

Your answer might help someone💌