<< Prev Page Next Page >>

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。


サーモグラフィーのカラーマップをC#で生成する方法

半年以上も更新してないのに、急に記事を書くこのとってつけた感はいったい。

さておき、こういう仕事をしてると、赤外線カメラからUSB経由でとったシグナルデータをサーモグラフィー画像として表示するアプリを作る機会も多いですよね。そういうのはWindowsでやるのが多いので、まあ言語はC#になります(断言)。

そんなとき、画像の横にさらっと、
カラーマップ
こういう画像が置いてあると、説得力が増しますよね。

でも、色の対応とかは設定で変化したりするので、あらかじめ画像を用意しておくわけにいかないので、動的に作る必要がありますよね。たいていそうです。

なので計算で作ります。


まずはColorの配列を作るところから。RGBを徐々に変化させていくのがいいけど、線形に変化させるとどうもイマイチ綺麗じゃなかったので、最終的にはこんな感じで変化させることにしました。
グラフ
カーブのところはcos関数。関数グラフの平行移動とか反転とか懐かしみながら。
ちょっと赤が最大値になってる範囲が広いかな、という気もするけど、なに、i1〜i5の幅を調節できるようにすればいいのです。

ソースはこんな感じ。 全部はGitHubから見られます。
/// 256階調のカラーマップを1つ生成する
public static Color[] Create(FocusType focusType) {
	var ret = new Color[LENGTH];
	var pts = iPoints(focusType);
	int i1 = pts[1];
	int i2 = pts[2];
	int i3 = pts[3];
	int i4 = pts[4];
	int i5 = pts[5];
	for (int i = 0; i < LENGTH; i++) {
		// 6段階に分けて計算する
		int r = 0;
		int g = 0;
		int b = 0;
		if (i < i1) {
			b = increase(i, 0, i1);
		} else if (i < i2) {
			b = MAX;
			g = increase(i, i1, i2);
		} else if (i < i3) {
			r = increase(i, i2, i4);
			b = decrease(i, i2, i4);
			g = MAX;
		} else if (i < i4) {
			g = MAX;
			r = increase(i, i2, i4);
			b = decrease(i, i2, i4);
		} else if (i < i5) {
			r = MAX;
			g = decrease(i, i4, i5);
		} else {
			r = MAX;
			g = increase(i, i5, LENGTH);
			b = increase(i, i5, LENGTH);
		}
		// Debug.WriteLine("r=" + r + "/g=" + g + "/b=" + b);
		ret[i] = Color.FromArgb(r, g, b);
	}
	return ret;
}
/// 上り
private static int increase(int x, int x1, int x2) {
	double y = (Math.Cos(Math.PI / (x2 - x1) * (x - x2)) + 1) * MAX / 2;
	if (y > MAX) {
		return MAX;
	} else if (y < 0) {
		return 0;
	} else {
		return (int)Math.Round(y);
	}
}
/// 下り
private static int decrease(int x, int x1, int x2) {
	double y = (Math.Cos(Math.PI / (x2 - x1) * (x - x1)) + 1) * MAX / 2;
	if (y > MAX) {
		return MAX;
	} else if (y < 0) {
		return 0;
	} else {
		return (int)Math.Round(y);
	}
}
さらに、Color配列からBitmapにするくだり、Bitmap.setPixcel()がとてつもなく遅いっていう問題があるので、さくっとunsafeでポインタ直接触ると速いです。と思ったけどこれアニメーションじゃないから別に遅くても問題なかった。unsafe言いたいだけちゃうんか。
public static Bitmap CreateBitmap(Color[] map, int height) {
	Bitmap bmp = new Bitmap(map.Length, height);
	BitmapData data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
			ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);
	unsafe {
		byte* p = (byte*)data.Scan0;
		for (int y = 0; y < bmp.Height; y++) {
			for (int x = 0; x < map.Length; x++) {
				var c = map[x];
				p[0] = c.B;
				p[1] = c.G;
				p[2] = c.R;
				p += 3;
			}
		}
	}
	bmp.UnlockBits(data);
	return bmp;
}

GitHubにはUserControlにしたものも上げておきました。「FucusType」っていう変数を変えるとi1〜i5のバランスが変化します。
FocusType変化

この記事に対するコメント

この記事に対するコメントの投稿



管理者にだけ表示を許可する

この記事に対するトラックバック

トラックバックURL
http://tockri.blog78.fc2.com/tb.php/281-7b03323f
この記事にトラックバックする(FC2ブログユーザー)

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。