Moiz's journal

プログラミングやFPGAなどの技術系の趣味に関するブログです

【技術書典6】キヤノンD70のRAW画像のPythonによる現像

キヤノンD70のRAW画像のPythonによる現像

このページについて

このページでは「技術書典6」にて配布する「PythonとColabでできる - ゼロからできるRAW現像」のデモとして、書籍ではあつわかないキヤノンのRAWファイルの現像を行ってみます。

あくまでデモという目的なのでパラメータは最適化していませんし、一部機能はオフにしています。

このデモの内容をColabで実際に実行するには次のリンクからアクセスしてみて下さい。

colab.research.google.com

準備

まずライブラリーのインストールと、モジュールのインポート、画像の読み込みを行います。内容については書籍を参照ください。

# rawpyとimageioのインストール
!pip install rawpy;
!pip install imageio;

# rawpy, imageio, numpuy, pyplot, imshowのインポート
import rawpy, imageio
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.pyplot import imshow

# 前節までに作成したモジュールのダウンロードとインポート
!if [ ! -f raw_process.py ]; then wget https://github.com/moizumi99/camera_raw_processing/raw/master/raw_process.py; fi
from raw_process import simple_demosaic, white_balance, black_level_correction, gamma_correction
from raw_process import demosaic, defect_correction, color_correction_matrix, lens_shading_correction
from raw_process import noise_filter, apply_matrix, edge_enhancement, tone_curve_correction, advanced_demosaic

# 日本語フォントの設定
!apt -y install fonts-ipafont-gothic
plt.rcParams['font.family'] = 'IPAPGothic'

日本語が文字化けしている場合は、以下のセルから冒頭の#を削除した上で実行して、Rntime->Restart Runtimeを選択し、その後ページはじめから実行してみて下さい。

# もし日本語が文字化けしている場合以下の3行の行頭の#を削除して実行後、
#import matplotlib
#target_dir = matplotlib.get_cachedir()
#! rm {target_dir}/*.json
# その後Runtime->Restart Runtime選択してページ全体を再実行

今回はフリーのRAWファイルサンプルを公開しているRAWSMAPLES.CHからデータをダウンロードします。

使うのはCANON EOS70D のデータで、ファイル名はRAW_CANON_EOS70D.CR2です。

# 画像をダウンロードします。
! wget http://www.rawsamples.ch/raws/canon/RAW_CANON_EOS70D.CR2

自分で撮影した画像を使用する場合は以下のセルからコメントを取り除きアップロードします。

#from google.colab import files
#uploaded = files.upload()
# RAWファイルの名前。
# アップロードしたファイルを使う場合はその名前に変更。
raw_file  = "RAW_CANON_EOS70D.CR2"
raw = rawpy.imread(raw_file)

exiftoolを使ってRAWファイルの情報を見てみましょう。

! apt install exiftool
! exiftool RAW_CANON_EOS70D.CR2
ExifTool Version Number         : 10.80
File Name                       : RAW_CANON_EOS70D.CR2
Directory                       : .
File Size                       : 23 MB
File Modification Date/Time     : 2019:04:07 15:52:05+00:00
File Access Date/Time           : 2019:04:07 15:52:33+00:00
File Inode Change Date/Time     : 2019:04:07 15:52:05+00:00
File Permissions                : rw-r--r--
File Type                       : CR2
File Type Extension             : cr2
MIME Type                       : image/x-canon-cr2
Exif Byte Order                 : Little-endian (Intel, II)
Image Width                     : 5472
Image Height                    : 3648
Bits Per Sample                 : 8 8 8

 以下略

沢山の情報が得られます。

まず、ブラックレベルは2049です。

Per Channel Black Level : 2049 2049 2049 2049

また、次の行からホワイトレベル(白をしめす基準値)11765と思われます。

Normal White Level : 11765

Bayerのパターンは「赤・緑」「緑・青」のようです。

CR2 CFA Pattern : [Red,Green][Green,Blue]

残念ながらカラーマトリクスの値がわかりません。もしかするとこのカメラでは単純なカラーマトリクスではない方式で色補正を行っているのかもしれません。 今回は適当な値を設定して使う事にします。

まずはRAWPYの機能を使って最終的な画像を見ておきましょう。

# RAWPYの機能で現像処理。
# use_camera_wbはホワイトバランスにカメラの値を使う指定。
rgb = raw.postprocess(use_camera_wb=True)
plt.title("RAWPYによる現像")
plt.imshow(rgb)
plt.axis('off')
plt.show()

f:id:uzusayuu:20190408035709p:plain

これは、鳥の餌かなにかでしょうか?

ちょっと面食らいましたが気を取り直して、RAWデータの情報を見てみましょう。

print(raw.sizes)
ImageSizes(raw_height=3708, raw_width=5568, height=3670, width=5496, top_margin=38, left_margin=72, iheight=3670, iwidth=5496, pixel_aspect=1.0, flip=6)

画像サイズは5568x3670のようです。約20Mです。

Bayerパターンを確認しましょう。

print(raw.raw_pattern)
[[0 1]
 [1 2]]

左上が赤、右下が青、というそれ以外が緑というパターンで、先程確認したEXIFの情報と一致しています。

ホワイトバランスを確認します。

print(raw.camera_whitebalance)
[2036.0, 1024.0, 1739.0, 1024.0]

これはEXIFの「WB RGGB Levels As Shot」に対応しているようです。

それではRAW現像に入りましょう。

RAW画像データをNumpy配列に読み込みます。

raw_array = raw.raw_image
h, w = raw_array.shape

それでは処理を行いましょう。

今回はデモなのでシェーディング補正や欠陥画素補正、ノイズリダクション、トーンカーブ処理は省略しています。

EXIFでわからなかったカラーマトリクスの値として(1.5, -0.25, -0.25, -0.25, 1.5, -0.25, -0.25, -0.25, 1.5)という物を仮の値としていれています。

また、ホワイトレベルで正規化した場合暗い画像になってしまうので、x2のデジタルゲインを与える事にしました。

処理の詳細については技術書典6で配布する書籍「PythonとColabでできる - ゼロからできるRAW現像」をご覧ください。

blc, pattern = raw.black_level_per_channel, raw.raw_pattern
blc_raw = black_level_correction(raw_array, blc, pattern)
gains, colors = raw.camera_whitebalance, raw.raw_colors
wb_raw = white_balance(blc_raw, gains, colors)
dms_img = advanced_demosaic(wb_raw, pattern)
# カラーマトリクス。EXIFから得られたもの。
color_matrix = np.array(
    [1.5, -0.25, -0.25, -0.25, 1.5, -0.25, -0.25, 0.25, 1.5])
ccm_img = color_correction_matrix(dms_img, color_matrix)
# ホワイトレベル。EXIFから得られた値。
white_level = 11765.0
# デジタルゲイン
digital_gain = 2
gmm_img = gamma_correction(ccm_img / white_level * digital_gain, 2.2)
sigma, edge_intensity = 2, 0.25
shp_img = edge_enhancement(gmm_img, sigma, edge_intensity)

表示してみます。

# 最終画像表示
plt.figure(figsize=(8, 8))
plt.imshow(shp_img)
plt.axis('off')
plt.title(u"最終画像")
plt.show()

f:id:uzusayuu:20190408035610p:plain

先程のRAWPYによる現像と似た画像が得られました。

今回はパラメータを簡易的なものにしたので色合いがことなる、コントラストが違う、などの点がみられます。

このあたりはカラーマトリクスの値の変更、トーンカーブ処理などで改善できると思われます。

まとめ

今回は技術書典6で配布する書籍「PythonとColabでできる-ゼロから作るRAW現像」のデモとして、キヤノンのカメラEOS70DのRAW画像ファイルを現像してみました。

f:id:uzusayuu:20190331124210j:plain:w200

書籍ではRAW画像とは何か?という疑問に答えるところから始まり、各ステップで行われる処理を基本的なところから説明し、実際に実行可能なコードを使って処理を行ってみます。

技術書典について

公式ウェブページによる紹介は以下の通りです。

新しい技術に出会えるお祭りです。

技術書典は、いろんな技術の普及を手伝いたいとの想いではじまりました。

技術書を中心として出展者はノウハウを詰め込み、来場者はこの場にしかないおもしろい技術書をさがし求める、技術に関わる人のための場として『技術書典』を開催します。

  • 日時: 2019/04/14 (日) 11:00〜17:00 (一般参加は11時~13時のみ有料)
  • 開催場所: 池袋サンシャインシティ2F 展示ホールD(文化会館ビル2F)

配布情報

  • ブース: う38「bitnos
  • 書名:「PythonとColabでできる-ゼロから作るRAW現像」
  • フォーマット
    • 書籍版:164ページ(内12ページフルカラー+表紙含む)、予価2000円
    • PDF版:フルカラー164ページ(表紙含む)、予価1000円

書籍版の方はカラーページを含むために若干高めになってしまいましたので、特典としてPDF版ダウンロード権を添付します。

またPDF版は、同等品をイベント後BOOTHでの販売を予定しています(値段など変わる可能性があります)。

サークルbitnosについて

「う38」のサークルbitnosは低レイヤーを中心としたソフトウェアのサークルです。

今回は新刊「Local APICタイマー入門」を配布します。 以下、著者の@uchan_nosさんによる紹介です。

現代のPCにはいくつものタイマーが搭載されています。本書は現代のPCタイマーの主役であるLocal APICタイマーを中心にしつつも、ACPI PMタイマー、TSCUEFI RTCの使い方も紹介します。また、x86-64における割り込みの設定についても詳しく解説します。

他に以下の既巻も頒布します。

  • Linuxカーネルモジュール自作入門」
  • システムプログラミングハンドブック」
  • 「USB 3.0 ホストドライバ自作入門」
  • C++でできる!OS自作入門」