ShihTzu
@ShihTzu

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

C言語でグレースケールの入力画像の濃度ヒストグラムを計算し、gnuplotに出力したい。

解決したいこと

C言語で、グレースケールの入力画像の濃度ヒストグラムを計算し、gnuplotに出力するプログラムを作りたいです。実行するとコアダンプとなり、gnuplotの画面までは出るのですが、ヒストグラムが描画されません。解決方法を教えてください。

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

Segmentation fault: 11 (core dumped)

実行した時のgnuplotの画面のスクショ↓
スクリーンショット 2022-09-12 15.46.56.PNG

該当するソースコード

/****************
* ヒストグラム作成 *
*****************/

#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 Expansion(unsigned char **input, unsigned char **output, int size_f, int size_x, int size_y);
long int hist[256];

void histogram(){	//画像からヒストグラムを作る

		int i, ix, iy;// ループ用変数
		int	size_x, size_y;	// 入力画像の大きさ
		unsigned char	**input;	// 入力画像
	//ヒストグラムの初期化
        	for(i=0;i<256;i++) hist[i]=0;
	
	//ヒストグラムを作る      
	        for(iy=0;iy<size_y;iy++){
        	     for(ix=0;ix<size_x;ix++){	
         	         hist[input[iy][ix]]++;//累積を1追加
		    		}
      			}
}

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!=2 && argc!=4) {
		printf("Usage: EXPANSION [in_file] [out_file] [size_filter] {size_x} {size_y}\n");
		exit(1);
	}

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

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

	/*********************
	* 画像格納領域の確保 *
	*********************/
	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);		// 画像ファイルの読込
	histogram();				//ヒストグラムを作成
	file_out(argv[2], output, size_x, size_y);		// 画像ファイルの出力
	
	hoge=popen("gnuplot -persist","w");	//gnuplot起動。-persistでずっと開いた状態にする
	//fprintf(hoge, "set xrange [0:256]\n");	//x軸の設定
	//fprintf(hoge, "set yrange [0:256]\n");	//y軸の設定
	fprintf(hoge, "plot '-' with lines\n");
	int i;
	for(i=0;i<256;i++){
		fprintf(hoge,"%d\t%ld\t",i,hist[i]);
	}
	fprintf(hoge, "e\n");
	pclose(hoge);
	fprintf(hoge, "pause -1\n");
	//return 0;
}

自分で試したこと

ヒストグラムの配列hist[256]の値を300や512など大きくしてみましたが、解決しませんでした。

0

3Answer

main関数内でallocateされているinputをhistogram関数に渡してあげる必要がある気がします。
現状だとhistogram関数内で未初期化状態のinputにアクセスを試みていると思います。

0Like

Comments

  1. @ShihTzu

    Questioner

    inputをhistogram関数に渡すということは、main関数内のhistogram()の部分を、histogram(unsigned char **input)と書き直すということでしょうか?
    書き直して実行してみてもヒストグラムが描画されませんでした。

上の解答で言われていることの改善が必要なことを前提に,まだ存在する問題として,ヒストグラムを作る関数histogram()における変数size_xおよびsize_yの値が未定義のため23-27行目の二重for内のループで,配列の範囲外アクセスが起きる可能性が挙げられます.

上の解答と同様に,histogram()関数に画像サイズの値size_xsize_yを渡してあげてください.

0Like

Comments

  1. @ShihTzu

    Questioner

    コメントありがとうございます。
    修正後実行してみてもヒストグラムはまだ描かれませんが、見たことの無い警告が出てしまいました。↓

    Warning: slow font initializationqt.qpa.fonts: Populating font family aliases took 946 ms. Replace uses of missing font family "Sans" with one that exists to avoid this cost.

    行った修正は以下です。
    14行目(histogram関数内) void histogram(unsigned char **input,int size_x,int size_y){ //画像からヒストグラムを作る
    17,18行目 size_x, size_y, inputの定義文をコメントアウト
    91行目(main関数内) histogram(input, size_x, size_y);
  2. Warningは今回無視して進めたいと思います.
    GnuPlotを使ったことはないのですが,感覚的に最後の2行の
    pclose(hoge);
    fprintf(hoge, "pause -1\n");
    の順番が逆だと思いました.
    fprintf(hoge, "pause -1\n");
    pclose(hoge);
    に直してみたらどうなりますか?
  3. @ShihTzu

    Questioner

    逆にしても結果は変わりませんでした。
  4. GnuPlotのウィンドウは開くのですよね?
    fprintf(hoge,"%d\t%ld\t",i,hist[i]);
    において,改行がなされていないのも問題かと思われます.
    fprintf(hoge,"%d\t%ld\t\n",i,hist[i]);
    にしてみたらどうでしょうか?
  5. @ShihTzu

    Questioner

    ヒストグラムらしきものが描かれました!
    ですが、グラフの範囲をx軸もy軸も0から256で設定しているのに、x軸は問題なさそうですが、y軸は100から256くらい、上半分にしか描画されていません。
    ヒストグラムですので、グラフは画面の下辺と接していないとおかしいかなと思いました。
  6. 今回使った画像のヒストグラムにおけるy軸の値域がそれだからなのでは?
    y軸設定が1つコメントアウトされているようですが,外すとおそらく0-256の範囲で描画されると思います.
    fprintf(hoge, "set yrange [0:256]\n");
    のところです.コメントアウトを外された上で値域がおかしいのなら原因はわかりません.
  7. @ShihTzu

    Questioner

    うまく表示されました!ご丁寧に教えていただき、ありがとうございます!
  8. よかったです.本質問は「クローズ」にして終了になります.

Your answer might help someone💌