デジタルカメラのRAWファイル(.ARW, .CR2, .NEF など)は、Pillow や OpenCV といった標準的な画像処理ライブラリでは直接読み込むことができません。
RAWファイルの現像処理には専門のライブラリが必要となります。
この記事では、LibRawのPythonラッパーである rawpy を使用してRAWファイルを現像し、Pillow を使ってJPGとして一括保存する手順をまとめます。
環境
- Python 3.x
- rawpy
- Pillow
ライブラリはpipでインストールします。
pip install rawpy pillow
単一のRAWファイルを現像する
まず、rawpy を使ってRAWファイルを読み込み、現像処理を行う基本的な流れを確認します。
rawpy はRAWファイルを読み込むとNumPy配列として画像データを出力するため、Pillow の Image.fromarray() を使ってPillowオブジェクトに変換し、保存します。
import rawpy
from PIL import Image
in_path = "input.arw"
out_path = "output.jpg"
try:
# 1. RAWファイルを開く
with rawpy.imread(in_path) as raw:
# 2. postprocess()で現像処理を実行
# use_camera_wb=True でカメラ設定のホワイトバランスを使用する
rgb = raw.postprocess(use_camera_wb=True)
# 3. NumPy配列からPillowイメージオブジェクトに変換
img = Image.fromarray(rgb)
# 4. JPGとして保存
img.save(out_path, quality=95)
print(f"処理完了: {in_path} -> {out_path}")
except Exception as e:
print(f"処理失敗: {in_path} (エラー: {e})")
raw.postprocess() がデモザイク、ホワイトバランス、ガンマ補正などの主要な現像処理を実行します。use_camera_wb=True を指定しない場合、撮影時の生データ(緑がかった状態)のまま出力されるため、通常は指定を推奨します。
バッチ処理の実装
上記の基本処理を応用し、指定したフォルダ内のRAWファイルを一括で処理するスクリプトを作成します。
ファイルの検索には glob を、フォルダやパスの操作には os を使用します。
-
INPUT_DIR: RAWファイルが格納された入力フォルダ -
OUTPUT_DIR: 現像後のJPGを保存する出力フォルダ -
RAW_EXTENSIONS: 処理対象とするRAWファイルの拡張子リスト
コード全体
以下に、バッチ処理スクリプトの全体像を示します。
出力フォルダが存在しない場合は自動的に作成する処理も加えています。
import rawpy
from PIL import Image
import glob
import os
# --- 設定 ---
INPUT_DIR = "raw_folder" # 入力フォルダ
OUTPUT_DIR = "jpg_folder" # 出力フォルダ
JPG_QUALITY = 95 # 保存するJPGの品質
# 処理対象の拡張子(小文字)
RAW_EXTENSIONS = ['.arw', '.cr2', '.nef', '.dng', '.raf', '.crw', '.cr3']
# --- ---
def batch_convert_raw_to_jpg(input_dir, output_dir):
"""
指定フォルダ内のRAWファイルを検索し、JPGに一括変換する
"""
print(f"処理を開始します。")
print(f"入力: {input_dir}")
print(f"出力: {output_dir}")
# 1. 出力フォルダを作成 (存在しない場合)
os.makedirs(output_dir, exist_ok=True)
# 2. 対象ファイルを検索
raw_files = []
for ext in RAW_EXTENSIONS:
# os.path.join を使ってパスを結合
search_path = os.path.join(input_dir, f"*{ext}")
# 大文字の拡張子も考慮 (glob.escape は Python 3.10以降)
search_path_upper = os.path.join(input_dir, f"*{ext.upper()}")
raw_files.extend(glob.glob(search_path))
raw_files.extend(glob.glob(search_path_upper))
if not raw_files:
print("対象のRAWファイルが見つかりませんでした。")
return
print(f"{len(raw_files)} 件のファイルを処理します。")
# 3. ファイルを順次処理
processed_count = 0
failed_count = 0
for in_path in raw_files:
# 出力ファイルパスを生成
# (例: raw_folder/image1.arw -> jpg_folder/image1.jpg)
filename = os.path.splitext(os.path.basename(in_path))[0]
out_path = os.path.join(output_dir, f"{filename}.jpg")
try:
# 4. RAW現像
with rawpy.imread(in_path) as raw:
# オプション: half_size=True で高速化 (解像度半分)
# no_auto_bright=True で自動輝度補正をオフ
rgb = raw.postprocess(use_camera_wb=True, half_size=False, no_auto_bright=False)
# 5. Pillowで保存
img = Image.fromarray(rgb)
img.save(out_path, quality=JPG_QUALITY)
print(f"[OK] {in_path}")
processed_count += 1
except Exception as e:
# エラーが発生しても処理を中断せず、ログを残す
print(f"[NG] {in_path} (エラー: {e})")
failed_count += 1
print(f"--- 処理完了 ---")
print(f"成功: {processed_count} 件, 失敗: {failed_count} 件")
if __name__ == "__main__":
batch_convert_raw_to_jpg(INPUT_DIR, OUTPUT_DIR)
実行結果
上記スクリプトを実行すると、INPUT_DIR(例: raw_folder)内のRAWファイルが検索され、現像処理が行われた後、OUTPUT_DIR(例: jpg_folder)に同名のJPGファイルが保存されます。
処理の進捗はコンソールに出力されます。
処理を開始します。
入力: raw_folder
出力: jpg_folder
3 件のファイルを処理します。
[OK] raw_folder/DSC0001.ARW
[OK] raw_folder/_MG_0002.CR2
[OK] raw_folder/image_test.NEF
--- 処理完了 ---
成功: 3 件, 失敗: 0 件
最後に
rawpyを利用することで、これまで専用ソフトウェアが必要だったRAW現像処理をPythonで制御可能になります。
postprocess() のオプションを変更することで、プレビュー用の高速生成(half_size=True)なども行えます。
大量のRAWファイルを扱う際のワークフロー自動化に活用できると考えられます。