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

以前Raw画像を取り込んで処理するっていう投稿を書いた。

内部リンク: pythonでraw形式の画像を読み込んで処理する方法

この投稿はX線データなどの画像処理を書いたものだった。しかし後々考えるとRaw画像の取り込みっていうタイトルだと、写真画像が取り込みたくて訪れてくれてる人もいるのかなとちょっと気になっていた。

それが理由というわけでもないのだけど、この投稿では写真の画像を取り込んで処理するプログラムについて書いていきたい。
こんなプログラムを書いた理由は、容量がきつくなってきた古いパソコンのお掃除がしたかったこと。嫁が大量の写真データを保存していたので、Raw形式で保存しておく必要のないものを一括で読み込んで、jpegかなんかで小さめのファイルで書き出そうという試み。

使用した画像はNikonのデジタルカメラのRaw画像。拡張子はNEF。

rawpyを使ってRaw画像の読み込みと保存

というわけで画像の読み込みに使ったのはLibRawという様々なデジカメ画像を読み込んでくれるライブラリ。pythonの場合だとrawpyという素敵なwrapperがあるのでとても便利。installはpipで。

外部リンク1: LibRawのウェブページ

外部リンク2: rawpyのウェブページ

pip install rawpy

必要なライブラリなどのインポート

まずは必要なパッケージをインポートする。この投稿で使っているのはtkinter, rawpy, imageio, PILのImage,それとos。

from PIL import Image
from tkinter import Tk, ttk
import tkinter.filedialog as tkfd
import tkinter.messagebox as tkms
import rawpy
import imageio
import os

tkinterを使ってファイルの一括読み込み

まずはいつも通りtkinterを使ってファイルを一括読み込みする。

def main():
  tk = Tk()
  tk.withdraw()
  print ('select data files')
  filenames = tkfd.askopenfilenames(filetypes= [('raw','*.NEF')], initialdir='./')
  tkms.showinfo('file paths are',filenames)
  tk.destroy()

これでファイル名の読み込みは完了。読み込みの詳細は別投稿で。

内部リンク: pythonでファイルを読み込む時にファイル名を取得する方法のまとめ

rawpyを使っての読み込みとフォーマットを変えて保存

ファイル名の取得ができたらメインパート。

#forを使って読み込んだファイルを1個1個処理。
for i in range(len(filenames)):
  rawData = rawpy.imread(filenames[i])
  basename = os.path.basename(filenames[i])
#postprocessを使うとnumpyのarrayにデータを詰め込める。最初のオプションはホワイトバランスをカメラの設定で。2個目は明るさを勝手に調整しないっていう設定をオフにしている。
  rgb = rawData.postprocess(use_camera_wb=True,no_auto_bright=False)
#imageioを使ってjpegに書き出すパターン。
  imageio.imsave('test.jpeg',rgb)
#同じくPILを使って。
  img = Image.fromarray(rgb)
  img.save(basename+".jpeg",quality=85,optimize=True)
#保存フォーマットは適当に目的に合わせて。
  img.save(basename+".tiff")

  rawData.close()

というわけでこんな感じでrawpyを使うと、とてもあっさりと写真画像の読み込みができるということがわかった。
上のrgbはnumpyのarrayに詰まっているので、色々と処理をしたかったらここですることができる。
書き出しはまあ何を使ってもすぐ簡単にできるので問題はないでしょう。

rawpyの難点としては少し読み込みが遅いこと。
初期設定を使うと1ファイルの読み込みで4秒ほど、2ファイルをforで回して7秒ほどだった。特にforで遅くなるわけでもなさそう。
demosaic_algorithmを変えたらスピードが結構変わった。どこかウェブの片隅で早いらしいと読んだLINEARを使ったら約2倍の速度になった。何か速さの代償があるのかは知らない。

それでも1ファイル2秒ほどかかるので結構遅い。しかし一回動かしたら放っておけば良いタイプのプログラムなので、別に多少遅くても問題はないでしょう。

左:macのプレビューで書き出し 右:rawpy経由で書き出し

もう一つ問題点としては、ホワイトバランスなど画像読み込みの調整。
これは別にrawpyの問題というわけではなく、Rawデータを開くとどんなソフトだろうと起こる問題だそうな。
Rawデータから元々のデジカメがjpegなどに変換している詳細は企業秘密。カメラのホワイトバランスの値は使うことができるけど、同じ画像にしたかったら詳細をかなり頑張って調整しないといけないのだとか。
以下はそんな感じで色々と設定をいじりながら試していた時の一つ。一番よく映ったオプションというわけではない。
読み込みのオプションの詳細についてはrawpyのホームページに乗っている。

外部リンク: rawpyのオプション

rgb = rawData.postprocess(output_color=rawpy.ColorSpace.sRGB, demosaic_algorithm=rawpy.DemosaicAlgorithm.LINEAR,output_bps=8, use_camera_wb=True,no_auto_bright=True,bright = 1.8,gamma=(1.8,4.0), no_auto_scale=False)

カメラのホワイトバランスを使うuse_camera_wbか、rawpyにホワイトバランスを調整してもらうuse_auto_wbが一番劇的に結果が変わる。
基本的にはこの二つのどちらか好きな方を使ってあとは微調整をする感じだろうか。
それっぽく画像が変換できるオプションを知っている方がいたら教えていただきたいところ。

というわけでこの投稿はひとまずここでおしまい。時間ができたらもう少し他の読み込み方法など試してみたいところ。

関連記事

1. pythonのまとめ

2. pythonを使ってjpeg画像をまとめて圧縮する方法

D