はじめに
こんにちは.あけましておめでとうございます.今年は自作プログラムの天体画像処理機能を充実させたいという思いがあったので,年末から三が日にかけて,少しだけ進めていました.
やっていくぞ
まだ特に「天体写真の画像処理用途」の機能を実装していなかった私の研究用プログラムということで,初回である今回の目標は
- (複数の)Raw 画像を読込み
- 位置合わせなしコンポジット(平均値,中央値,分散,標準偏差などの統計値計算)
- (主にダークデータの)ノイズ解析用 scatterplots 生成
となります.特にノイズ解析ではあぷらなーとさんがよくダークデータのノイズ解析をしてらっしゃいますので,あんな感じのことができればいいかなということになります.
プログラムの全般的な詳しい機能の紹介は,以前書いたコンセプトの記事をご覧ください.
その1. Rawを開く(ファイルパス群→三次元データ)
まず,Raw を開くだけなら簡単です.以前紹介した rawloader crate を使用すれば開けます.
が,今回はコンポジットやノイズ解析をしたいので,複数枚の Raw 画像を読む必要があります.
これまでは一つの Path というノードで単一のデータファイルパスを表現していましたが,これを一つのノードで複数枚のリストが表現できるように改造する必要がありました.
これからコードをドバドバ貼っていきますが,自分のメモ代わりなので読み飛ばしてください.
1 | pub enum PATHS { |
するとこんな感じに↓
なんかカレントディレクトリの表示がおかしいですが,ちゃんと動作するので今はキニシナイ.
次に,この Path 改め Paths を受け取り,画像を展開して**三次元データ(0番目の軸で何枚目かというインデックス,1番目と2番目の軸で画像の輝度にアクセスできる)**を生成するノードを作ります.
1 | cake_transform!( |
cake_transform!マクロは,ノードを作るためのマクロです.引数で入力の型を指定し,->以降に出力の型を指定します.複数のデータを出力することも可能です.実際のデータは,Vec<Result<IOValue, IOErr>>
という型のベクタで返しています.
i番目の画像をスライスして取り出して表示できています.
これで統計値計算への準備が整いましたので,このタイミングであぷらなーとさんに連絡をし,Nikon D3 と D810A のダークデータをいただきました(妥当性の検証ができるのはとても助かります,ありがたいです).とりあえず D3 のダーク Raw データが開けそうなので,こちらを使っていきます.
その2. 統計値計算(三次元データ→二次元データ)
三次元データを生成したら,各種統計値を計算するノードを作っていきます.平均はすでに実装済みでしたし,分散と標準偏差も使っている ndarray ライブラリに計算するための関数があります.中央値だけは,こちらで実装する必要がありそうだったので用意.
1 | cake_transform!( |
これは平均を計算するノード(average ノード)を使った例です.3枚のデタラメなライトフレームを単純に加算平均してます.
これで位置合わせなしコンポジット機構もできましたので,位置合わせのいらない master dark や master flat をコンポジットするのはこのプログラムだけで完結できるということになります.やったー.
その3. リストへ変換
統計値計算をして得られるデータは二次元のデータです.各画素に,その位置の画素の統計値が入っています.ノイズ解析用 scatterplots ではこれらの統計値を横軸,縦軸の値として使用するため,一次元リストへ変換しておくと便利です.
ついでに常用対数を通した値にしておきます.
1 | cake_transform!( |
その4. scatterplots の描画
これらの2つのリストから,scatterplots データを作っていきます.このプログラムでは様々な次元のデータを様々な形式で見られるようにしたいので,最終データには「タグ文字列」を付加するようにしています.今回の場合,形状が (2, データ数) の “scatter” タグがついた二次元データをscatterplots と解釈して描画することになります.
1 | cake_transform!( |
うーん.コードが汚い.ここはなんとかしたいですね….
データポイントをとりあえずソートしています.これは描画を軽くするために必要なのですが,あとあとアルゴリズムを変えるかもしれません.
最後に scatterplots を描画してみます.ライブラリは implot を利用.
1 | Some(tag) => match tag.as_ref() { |
ソートされているので,dedup関数で近い位置のデータを削除して描画点を減らしているわけですが,dedup関数の仕様上思惑通りにはいきません.この関数は連続する要素しか見ないので,y軸の値が近いのデータペアを見つけられないためです.ここは要改善です.
最終的には,こんな感じのデータが見られます.↑今回得られた散布図.↓あぷらなーとさんの結果
ある程度インタラクティブに拡大したり,移動したりといった操作ができるビューアができましたので今はこれで良しとしておきます.やったぜ.
全体のビジュアルプログラムはこんな感じ.少し複雑(?)ですが,上に書いた流れをそのまま表現しているだけです.
例えばこのプログラムで「中央値画像を生成」の部分を「平均値画像を生成」するようなノードに変更すれば,横軸が平均値になったようなプロットを得たりといったことが誰でもコーディングなしでできるようになるわけです.どちらかの対数に変換するノードを消せば,片対数のプロットも作れたりします.以上!
おまけ. Fitsデータのカラー画像解釈
研究では輝度単一の値をカラーテーブルで変換することでしかデータを見てこなかったので,普通の天体画像のように3チャンネルあるような Fits データをカラー画像解釈できるようにしていきます.つまり,形状が (3, 画像横幅,画像縦幅) の “color_image” タグがついた三次元データをカラー画像と解釈して描画することになります.
チャンネル取り出しだけですが,ぐらすのすちさんも似たようなことをやっています.
1 | Some(tag) => match tag.as_ref() { |
カラー画像がでました!めでたしめでたし.
おわりに
とりあえず三が日を使って Raw データ処理のスタートアップができました.今後は位置合わせコンポジットやコンポジット後の単一画像の画像処理など,PixInsight も導入したのでアルゴリズムを勉強しながら実装していく予定です.モジュールを分割して具体例と一緒に提供することで,僕以外の方にも使っていただけるようなものが作れたらいいなあと思っています.また何か成果が出たら記事にしたいと思います.
それでは.