私のいつもの画像処理の流れとしては、
- PixInsightでキャリブレーション・リニア処理・ストレッチ
- ステライメージでストレッチ後の強調処理など
- Photoshopで仕上げ処理
の順で行うことがほとんど。細かく言えばStarNetをするためにノンリニアでPixInsightに戻ったりすることもあるが、おおむね上の1~3の順になる。ここで異なるソフト間の受け渡しだが
- PixInsight -> ステライメージ:FITS(32bit, Integer)
- ステライメージ -> Photoshop:TIFF(16bit)
にしている。PixInsight内ではxisfを使って中間ファイルを保存しているが、それはステライメージで読めないので、最大限に階調を保持するために32bit整数のFITSで渡す。ステライメージ内ではそのまま32bit FITSで中間ファイルを保存するが、PhotoshopではFITSを読めないので16bit TIFFで書き出している。その書き出しは手作業だが、1コマ~数コマならばたいした手間ではないので問題ない。
ところが数百コマをバッチ処理する場合、ステライメージのワークフローのバッチ処理は入力と同じファイル形式でしか出力できない(私が知らないだけかもしれないが)。そのため、流星や彗星、タイムラプスなどの画像をバッチで一括処理するとTIFFに変換できない。FITSからTIFFへの変換はPixInsightでもBatchFormatConversionで出来るが、ステライメージで書き出したFITSをPixInsightに読ませると、ステライメージで実施したレベル調整が引き継げないためか、破綻した状態になってしまう。

またそこから再度レベル調整して、というのは大変面倒くさい。
Sirilを使えば32bitFITS->TIFF変換をレベル調整した上で可能かと思ったが、Sirilは使ったことがないし、新しいソフトのバッチスクリプトの使い方を一から覚えるのも大変。
そこで、コマンドラインで使う極めて単純な変換ソフトを作ってみることにした。言語は使い勝手を考えてコンパイル不要のPython。だが私はこれまで実用的なPythonソフトなど作ったことがないし、FITSやTIFFの書式なども全く知らない。これまでならばそんな状況で変換ソフトを作るのは絶対無理だが、最近ではAIコーディングツールという強い味方がある。今回はVIsual Studio Code(VS CODE)に拡張機能「GitHub Copilot」を入れ、無課金のFree版で生成させてみた。モードはAgentで、LLMモデルはコーディングに定評ある「Claude sonnet 3.5」。Pro版なら今はsonnet 4.5やGPT-5-codexが使えるのだが、Free版は2世代ほど遅れている。とりあえず下記のようなプロンプトを入れてみた。
## 概要
– 天体を撮影した画像の書式変換を行うPythonソフトウェア。
– コンソールで動作するバッチ形式。
– WIndows11で動作すること。
##入力
– FITSの形式は16bit integerと32bit intejerに対応し、両者を自動判別する。
– コンソールで実行時、必須オプションとして入力画像データが格納されたフォルダを指定する。
– 指定されたフォルダに格納されているFITSファイルをすべて変換対象とする。
– FITSファイルの拡張子はfits, fit, fisに対応し、大文字と小文字を区別しない。
– 入力FITSファイルの形式は16bit integerと32bit integer, 32bit real に対応し、それらは自動判別する。
– カラー画像とモノクロ画像の両方に対応する。
## 出力
– 入力ファイルと同じフォルダに書き出す。
– 出力形式は16bit integer, IBM PC形式, 無圧縮のTIFFとする。
– ファイル名は、入力ファイル名の拡張子をtifに変えたものとする。
そもそも、FITSとTIFFの仕様をちゃんと理解していないと適切なプロンプトは書けないのだが、そこは何とかなるだろう、とのいい加減な気持ちで臨んだ。その結果、当然ながら最初はまともに変換できない状態だったが、GitHub Copilotと何度も問答を繰り返しているうちに、なんとか形になってきた。

プログラムを生成するだけならChatGPTでも出来るが、このGitHub Copilotの良いところは、コードエディタに組み込まれているので、ディレクトリ構造を丸ごと理解してくれるし、インラインでのコード補完もできる。なんといっても、自動で実行して結果を分析し、修正をしてくれる。こちらは修正結果を見ながら、必要な指示を追加していくだけ。
例えば下記のような感じ。
テスト用データの入ったフォルダは、D:\astro\convert\testdata\fits2 です。これで自動テストを行い、不具合は修正してください。
ハイライトが飽和しています。99%点を高くするのではなく、低くする必要があります。
最初はまったく理解していなかったのだが、TIFF変換するにあたっては、レベルを適切に調整してやらなければいけない。その調整も、各ファイルでそのファイルだけのヒストグラムを見てやっていると、各コマの状態は異なるので背景レベルがバラバラになってしまう。それはタイムラプスなどの連続画像ではあまりよろしくない。そこで変換対象のファイルをいったん全て読み込んでヒストグラムの状態を分析し、背景レベルが同程度になるように調整する機能を入れた。
出力された各画像の輝度レベルにバラツキがあり、画像の大部分を占める背景の明るさがバラバラです。そこで、いったん全ての画像を読み取って基準のヒストグラム分布を定め、その基準の分布になるように各画像を調整して出力するようにしてください。
また、彗星の移動など位置合わせの結果、画像の端の部分に真っ白・真っ黒の部分ができる場合、そこがヒストグラム分析に悪影響を起こすので、画面中央の90%の部分で分析・調整するようにした。
次に、画像の周辺部が真っ黒だったり、真っ白だったりする場合があります。それらがヒストグラム分析に与える影響を避けるため、最初の分析処理およびヒストグラム調整処理においては、画像の縦横サイズの90%の中央部分だけで行ってください。
こんなやり取りを続け、ちゃんと変換できるPythonプログラムが完成。
変換プログラムの動作の様子
変換後の16bit TIFFファイルはPhotoshopで問題なく開くことができた。

変換した複数のコマで背景のレベルが揃っているので、タイムラプスにしたときに背景のちらつきが無い。ただし彗星のレベルが揃っていないので、彗星のほうにちらつきが発生している。これは撮影時に周囲の照明状況が刻々変化して、背景のレベルと彗星のレベルの差がコマごとに異なっているので、今のところ仕方がない。

また、元のFITSファイルが16bit 整数の場合でも正常に動作した(32bit 実数は時間がなく未検証。あまり使わないので)。
もしかすると、テスト事例とは異なるヒストグラム分布の画像では上手くいかないかもしれない。しかしその場合はソースコードが手元にあるので、その都度GitHub Copilotに頼んで修正・調整してもらえば良い。それから今回はひとまず動作させるために逐次処理だったが、次の段階では並列化したい。I/Oのことを考えるとスレッド並列よりもプロセス並列の方が良いのか? そのあたりも素人なのでよくわからないが、それもAIに相談すれば適切な実装をしてくれるはず。
それら今後の改良や発展を考え、とりあえずローカルにGitリポジトリを作って、GUIで操作できるtortoiseGitで管理することにした。それも今後はVS CODEの拡張機能で管理すればコミットなどもVS CODE上からできるようなので、そちらに移行した方が良いのかも(でもtortoiseGitの使いやすさは手放せない)。
そういうわけで、Pythonや画像ファイルの書式をほとんど知らなくても、AIで変換ツールが作れるという体験ができた。これに味をしめて、画像処理の簡単なツールなら作れそうな気がしてきた。


コメント