2017年5月3日水曜日

輝点検出


 先程の画像から、輝点の重心を検出したりしてみました。2枚目は1枚目をトリミングした画像です。およそ1000x700pxの範囲ですが、この大きさを計算するのに30msecほどかかっています。VGAの30fpsくらいなら、輝点検出だけならリアルタイムで処理できますが、この後にマッチングとかいろいろやるので、ちょっと問題かも。

 アルゴリズム、というほどでもないですが、計算方法としては、まず画像を読み込んで輝度情報の2次元配列に変換します。
 次に、ある程度の輝度以下は0に置き換えます。これは闇電流によるノイズ対策です。
 その後、左上からスキャンしていって、輝度が0より大きいピクセルがあれば、その周り3方向に対して輝度の判定を行い、というのを再帰的に行います。
 輝度が0より大きければ、そのピクセルの輝度と位置の積を加算し、最終的にすべての輝度を加算した値で割って重心を計算しています。
 その際、輝点として処理したピクセル数と、最大の輝度の情報も返します。
 ということで、サブピクセルの重心位置と、面積、輝度の情報が得られます。輝度情報は後の処理で必用になります。面積は、一定の面積未満であれば無視するといった、フィルタリングに使います。
 国際宇宙ステーションで撮影された映像を見てみるとわかりますが、画面内に常に光っているピクセルが有ると思います。これは放射線により画素が破壊された影響によるものですが、基本的に連続した複数ピクセルに対して発生するものではないので、1ピクセル以下なら無視といった簡単な処理でキャンセルできると予想しています。
 ま、このプログラムが宇宙に行く予定はないんですが。出力画像を作る際に、面積があれば円を書いたりできるので、単純にインクリメントするだけですから、実装してみました。
 あともっともらしい理由としては、スタートラッカのカメラは、サブピクセルの重心を計算するために、わざとピントを外した画像を撮影します。これにより1つの恒星がピンぼけで複数のピクセルに対して照射されますから、それらのピクセルの輝度差からサブピクセルまで計算できるというわけです。このため、原理的に1つの星は一定以上の面積を持ちます。そうなっていない輝点は、充分な光量が無いか何らかのノイズが原因と考えられるので、除外します。

 今のところ、すべてのピクセルに対して輝度判定を行っていますが、例えば間の1ピクセルを飛ばしてチェックするといった処理を行えば、シングルピクセルのノイズを無視しやすくなり、計算に要する時間が数分の1になります。
 といったあたりの最適化は、ちゃんとこのアルゴリズムで問題ないとわかってからでも問題ないので、とりあえず今は全量を計算しています。


 上画像では、中心に木星がありますが、この明るいヤツの周りに、円周状にあるマーカーは木星由来のノイズによるものです。
 おそらくマッチングを行う際に、こういうのでマッチングを試しても、明らかに姿勢がおかしくなるはずで、よほど許容誤差を大きくしない限りは、問題とならないはずです。
 問題になるようであれば、一定以上の面積の輝点があれば、その中心からn倍の範囲のデータは使わない、とかをやるべきかもしれません。

 そういえば、今のアルゴリズムでは左右下への再帰呼び出しに制限がありませんから、目の前に太陽とか月とか地球みたいなデカイ奴がいるとスタックが足りなくなったり、加算レジスタでキャリーするかもしれません。あぁ、スタートラッカのエラー対策の(以下略。


 あとは、画像から計算した恒星候補と、恒星カタログからマッチングを行えば、スタートラッカができちゃうかも?いや、できてくれなきゃ困るんですけどね。

0 件のコメント:

コメントを投稿