pythonでraw形式の画像を読み込んで処理する方法

pythonは画像処理のパッケージが結構あるので、ちょっと画像処理をしてみようなんて始めるにも良い言語だったりする。
とはいえ研究者が2次元データの処理を自分でする機会というのはそんなにはないだろう。 手元に来る頃には1Dプロファイルなどの扱いやすい形に変換されていることが多いからだ。
しかし時たまそんな変換が納得できるものではなかったり、もしくはニッチすぎる分野にいるせいで十分なソフトウエアに恵まれない場合もある。
今回はRAW形式のデータを読み込んで、処理して書き出す方法についてまとめておきたい。

私が今使っているのはanacondaのpython3(anaconda4.4.0 python3.6.1)であるが、前のバージョンでも問題ないはずだ。 python2の場合はちょろちょろと変える必要があるかもしれないが。
さて画像処理するのには、まずは画像を読み込む必要がある。RAW形式の画像を読み込めるパッケージは色々ある。
私が最初二次元X線データの画像処理を試みたときも、色々とソフトを試した記憶がある。
ちなみにデジカメの写真なんかを読み込みたい場合は、専用のライブラリやwrapperがpythonには用意されている。

内部リンク: pythonでデジカメのraw画像を一括読み込みして別形式で保存する

しかしここで私が使うことにしたのはpillowという画像処理ライブラリ。これを選んだ理由は、様々な形式のrawデータを読み込んでくれたからであった。
私が具体的に使いたかったのは16ビットのunsignedのpixcelデータだったのだが、これを読み込んでくれたのがこのpillowであった。pillowはpipでインストールすることができる。

pip install pillow

プログラムではまずこのpillowでの画像読み込みをするのにImageを呼び出しておく。

from PIL import Image

まずはピクセルデータをバイナリモードでファイルに読み込んでrawdataに格納。ヘッダーがある場合はseekを使ってピクセルデータの場所までスキップしておく(file.seek(number))。

2022年6月23日追記:

私の使ってた画像データでは確かヘッダーサイズは画像のピクセルサイズに依存してたはずで、3000x3000ピクセルの画像ファイルではnumber=6000、4000x4000の画像ファイルではnumber=8000てな感じでうまく読み込めていたかと思います。ファイル次第な気はしますが……間違っていると画像がとてもおかしくなるので、意味のある画像が出てきたらnumberがあってるはずです。

追記終わり。

file = open(filename, 'rb')
rawdata = file.seek(number)
rawdata = file.read()
file.close()

読み込んだバイナリをpillowのImage.frombytesを使ってイメージ形式に変換する。
オプションは左から、mode、size、filename、data、decoder_name、args。 modeは公式を読むと32ビット?と思いつつもFで良い。
sizeは私の場合ピクセルサイズで(2000,2000)など。 dataはこの例だとrawdata。

最後の二つが実質重要で、decoderでrawを指定して、argsで実際のファイルフォーマットを指定する。 私の場合は16ビットのbig endianだったので16B。
ここの指定がおかしくて、変なデータになることがよくある。 正しくプロセスするには、自分の使っている画像データをよく知っておく必要がある。 ちなみにどのデータタイプにどのargsを使えば良いかは公式ページに詳しい

img = Image.frombytes('F', Imagesize, rawdata,"raw", 'F;16B')

ここまできたらimgはイメージデータになっているので、適当な画像形式で出力してあげれば正しく処理されているかが確認できる。

img.save("test.tif")

私はnumpyを使ってデータ処理することが多いのでさらにnumpyのarrayに突っ込んでおく。

npimg = np.array(img)

ここまできたらnumpyの(ピクセル、ピクセル)のデータになっているはずなので、あとは好きな様に補正を加えるなり図表を作ることができる。

関連記事

pythonのまとめ

D