豪鬼メモ

一瞬千撃

画像アラインメントのコントロールポイント

手持ちSTFモードのための画像自動合成コマンドではHuginを使っているが、その重要なパラメータにコントロールポイントの数がある。その設定によって結果と処理時間がどの程度変わるのかを調べた。
f:id:fridaynight:20220324130457j:plain


手ブレでずれているかもしれない複数の画像を合成するにあたって、アラインメント(位置合わせ)にはHuginというソフトウェアパッケージのalign_image_stackコマンドを使っている。Huginは何気に他の有名なアプリケーション(Luminance HDRとか)でも使われていて、OSS界隈では定番になっていると言えよう。そのalign_image_stackは-cオプションで「コントロールポイント」の数を指定できる。画像AとBの位置合わせをするとして、A内の任意の座標をコントロールポイントとして選んだら、その周辺の特徴が似た領域を画像Bの中から探すことで、整列は行われるらしい。平面の整列には少なくとも2つのコントロールポイントが必要だが、一致判定の誤差を考えると、コントロールポイントの数は多ければ多いほど最終的な精度は良くなる。当然トレードオフもあり、コントロールポイントの数に比例して処理は遅くなる。そのバランス点を探るのが本稿の目的だ。

デフォルトでは、コントロールポイントの数は8である。画像を5x5=25個のグリッドに分割して、各グリッドで8個のコントロールポイントを使うとのこと。多くのケースでは、それで十分にうまくいく。しかし、ピントが合った領域の割合が比較的少ない、言い換えればボケた領域の割合が多い画像では、十分な精度が出ないことがある。ピントが合った部分のコントラストが低い場合にもそうなる。たった8個では、ピントが合った領域の特徴的な部分にうまいことコントロールポイントが来ないということだろう。以下の画像がその失敗例である。狐の目の部分を見ると、ぶれていることがわかる。
f:id:fridaynight:20220319154144j:plain

こんな場合、コントロールポイントの数を増やしてやると、うまくいくことがある(それでもうまくいかないこともある)。この例では、256に増やすとこのようにうまくいった。目がぶれていない。
f:id:fridaynight:20220319154145j:plain

コントロールポイントの数を8、16、32、64、256、512、1024と変えながら結果を見ていこう。狐の目の周辺だけを抜き出す。

f:id:fridaynight:20220326132132j:plain:w250f:id:fridaynight:20220326132141j:plain:w250
f:id:fridaynight:20220326132231j:plain:w250f:id:fridaynight:20220326132236j:plain:w250
f:id:fridaynight:20220326132245j:plain:w250f:id:fridaynight:20220326132252j:plain:w250
f:id:fridaynight:20220326132259j:plain:w250f:id:fridaynight:20220326132832j:plain:w250

当然ながら入力画像によって精度は大きく変わるので、あくまでこの例ではこういう結果になったという認識をすべきだ。その上で、256くらいまでは順調に精度が上がっていく場合があるということは判断できる。任意の画像に対する設定として統計的に考えれば、コントロールポイントを増やすことによる精度への悪影響はない。個々の例で考えると確率的な要素が絡んでくるが、基本的には多ければ多いほど良い。とはいえ、256くらいで精度は頭打ちになり、それ以上増やしても変わらないと推定する。他の画像で試してみても、だいたい同じ傾向だ。256でうまくいかない例は1024でもうまくいかない。

コントロールポイントの数によるalign_image_stack単体の処理時間の変化を図ってみた。使用機種はMacbook Air 2020 M1。結果の単位は秒だ。

  • 8 = 19.8
  • 16 = 21.0
  • 32 = 22.8
  • 64 = 27.7
  • 128 = 34.8
  • 256 = 49.0
  • 512 = 61.7
  • 1024 = 72.5

f:id:fridaynight:20220326134031p:plain

コントロールポイントの数を増やすほど処理に時間がかかることは間違いないのだが、どうも線形ではないっぽい。むしろ対数スケールのX軸に対して線形に見えるので、対数的なのかもしれないとすら思う。並列化しているとか、キャッシュが効いているとか、なんか理由があるのだろう。とりあえず今のところ言えるのは、32くらいまではあまり処理時間が伸びないということだ。その割には精度が良くなる。つまり多くの場合で32を指定しておけば良さそうだ。それでだめだったら、256やそれ以上を試すべきだ。それでもダメなら、-sオプションでスケールダウン処理を行うとか、-gオプションでグリッド数を変えるとか、--corrオプションで一致判定の閾値を変えるとか、その他のワークアラウンドを試すことになる。とはいえ、実際のところ、私の経験則では、それらをいじって結果がよくなることは稀だ。前後ブレした場合には-mをつけると多少マシになることがあるが、多少だ。基本的にはコントロールポイントを256にしてダメなら諦めた方がいい。jkzr_combineコマンドでは、--align_cpオプションでコントロールポイントの数を指定できるようにした。

おまけ。当ブログではご無沙汰な上の子だが、この3月で小学校を卒業した。おめでとー。
f:id:fridaynight:20220324123722j:plain