自己紹介
株式会社digitalbigmoのパイプラインエンジニアの小池@plinecomです。
これは何?
VFXをやっていると、3DCG屋さんが気を利かせて、レンダーレイヤー毎にチャンネルを分けて、深度情報やスペキュラーやリフレクションやGIなどをOpenEXRに書き込んでくれることがある。とてもありがたい。感謝。通常の手順ではコンポジットでこれをNukeとかでバラして加工するわけだが、Nuke無いとか、そういう時のために、Pythonでバラバラに分割する方法を記す。
とりあえず、コード
import OpenEXR
import Imath
import glob
import os
if __name__ == '__main__':
for path in glob.glob('/foo/bar/*.exr'):
print(path)
dir_name = os.path.dirname(path)
base_name = os.path.basename(path)
ret = OpenEXR.InputFile(path) # Read EXR file
header = ret.header() # Get OpenEXR header info
pix = {}
ch_info = header['channels'] # Get channel info from header
for ch in header['channels']: # Get channel name from header
pix[ch] = ret.channel(ch) # Get channel image data
ret.close() # Close Read File handler
for ch, v in pix.items():
header['channels'] = {ch: ch_info[ch]} # Renew header channel info
# Open write file and Set header info
exr = OpenEXR.OutputFile(dir_name + '/' + ch + '_' + base_name, header)
exr.writePixels({ch: v}) # Write Pixel Data
exr.close() # Close Write File handler
必要なPython外部モジュール
- OpenEXR
pip install OpenEXR
pipを使ってPyPIからダウンロードしてくる。Imathモジュールも一緒にインストールされる。
ただし、インストール時のビルドの際Python自身のheaderファイルが必要になるので、Linuxではpython-develなパッケージを管理ソフトで突っ込むこと。用意できない環境の場合は、いっそのことPythonからビルドした方が楽。
コードの説明
EXRファイルの読み込み
ret = OpenEXR.InputFile(path) # Read EXR file
分割処理
for ch in header['channels']: # Get channel name from header
pix[ch] = ret.channel(ch) # Get channel image data
読み出した画像データを辞書に貯めておく。
ファイルの書き出し
for ch, v in pix.items():
header['channels'] = {ch: ch_info[ch]} # Renew header channel info
# Open write file and Set header info
exr = OpenEXR.OutputFile(dir_name + '/' + ch + '_' + base_name, header)
exr.writePixels({ch: v}) # Write Pixel Data
exr.close() # Close Write File handler
流用したヘッダを元に、チャンネル毎にヘッダ情報を修正し、書き出し先を指定してファイルを作成し、画素データを書き込んでファイルを閉じる。
宣伝
株式会社digitalbigmoでは美肌プラグインの販売や映像VFXの制作業務を行なっています。ご興味のある方は、webページを見にきてください。一緒にお仕事しましょう。
参考文献
PythonのOpenEXRモジュールについて(英語)
OpenEXR本家(英語)
WikipediaのOpenEXRのページ(英語)
WikipediaのOpenEXRのページ(日本語)