Last modified: Mon Aug 18 17:05:54 JST 2008

伊達 >> gnuplot で画像を表示

gnuplot で画像を表示

目的

Matlab は購入価格も維持費も高い. C言語で画像を処理する場合,結果の表示に手間取ることが多い. gdk などを使えば綺麗に表示できるが, 比較的長いコードを書く必要があり,慣れていないと戸惑う. このページでは普段 gnuplot を使っている人が, とりあえずの結果を比較的簡単に表示する方法を紹介する. C言語と gnuplot の環境はあるけれど, Matlab や FreeMat, R, octave がインストールされていない環境で 仕事をする場合に役に立つはずである. 具体的には3次元プロットを駆使し, gnuplot 本来の目的とは違う使い方をする.

サンプルコード

どういうことができるのか,早く知りたい人は以下の Cのコードをコンパイルして走らせてください. 最も応用の効くコードは gp-image003.c です. 各ピクセルは int で表現していますが 必要な時は char や double 型に 適宜変更して使ってください.

基本的な考え方と利点

  1. 座標軸など深く考える必要はない.
  2. とりあえずの結果の表示には便利.

3x3 ピクセルの例

100
011
101
という画像!を表現したい場合.
% gnuplot

gnuplot> set pm3d
gnuplot> splot '-' 

0 0 1
0 1 1
0 1 0
0 2 0
0 2 1
0 3 1

1 0 1
1 1 1
1 1 0
1 2 0
1 2 1
1 3 1

1 0 0
1 1 0
1 1 1
1 2 1
1 2 0
1 3 0

2 0 0
2 1 0
2 1 1
2 2 1
2 2 0
2 3 0

2 0 1
2 1 1
2 1 1
2 2 1
2 2 0
2 3 0

3 0 1
3 1 1
3 1 1
3 2 1
3 2 0
3 3 0

e
と入力すれば,画像が表示される. この結果だけ見るととても大変. 1ピクセルごとの描画ではうまくいかないので, 幅1の帯を6本描いている.

横 nx ピクセル, 縦 ny ピクセルからなる画像データを表示したい場合, 1次元の配列 img[i] に画像データを入れ 関数 write_data を 呼び出せば,画像を描画してくれる関数を以下に示します. 表示するだけなら,あとは何も考えなくてよい(はず). 多数の小さい画像を並べて表示させたい場合は, 自分で大きい画像データ img[i] を作る必要があります. やさしい問題なので write_multi_images という名前で関数を作ってみてください.

/* Write data for gnuplot */
void write_data( int *img, int nx, int ny){ 

	int i,x,y;

	for (x=0; x < nx; x++){
		for (y=0; y < ny; y++){
			i = x + (ny -y -1)*nx;
			fprintf(gp, "%d  %d %d\n", x, y,    img[i]);
			fprintf(gp, "%d  %d %d\n", x, y+1,  img[i]);
		}
		fprintf(gp, "\n"); 
		
		for (y=0; y < ny; y++){
			i = x + (ny -y -1)*nx;
			fprintf(gp, "%d  %d %d\n", x+1,   y, img[i]);
			fprintf(gp, "%d  %d %d\n", x+1, y+1, img[i]);
		}
		fprintf(gp, "\n");
	}

}

例えば 8 x 8 ピクセルの画像(パッチ)25 枚を 5 x 5 段 で 表示したい場合,あらかじめ img[] という1つの配列に 自分でレイアウトした結果を書き込んでおけばよい. あらかじ画像パッチと画像パッチの上下と左右の 間隔を設定しておく必要がある.