OpenEXRを使ったBlenderからのマスクデータ出力

Blenderでレンダリングした3Dの映像データをやりとりするにあたって
深度情報（z,Depth）やマスクデータを受け渡すことがあります。
参照できる記事がなかったので勉強がてらまとめておきます
（認識違い等あれば指摘いただければ幸いです）

## 画像ファイルのデータ形式
画像データの**色**を表す方式として、PNGやJPEGでは、黒を(0,0,0)、白を(255,255,255)といった具合に、各色を8ビット（256階調）で表現する方法が一般的に使用されてきました。
この方法で特に問題ないことも多く、サイズや処理の効率を考慮すると、Webやゲームなどでは今後もこの形式が主流ででしょう。

一方で　現実世界の光の強さで考えると　室内の紙の色を"白"と定めても
室外に降り注いでいる光の強さは数百倍だったりと　非常に幅広い範囲の光の強さが存在します
そこで　３DCGでもコンピューターで数字を扱う時に利用する**浮動小数点(float)** のデータを使って
通常利用する黒を(0.0,0.0,0.0)　白を（1,0,1.0,1.0）といったように色を表現するようになってきています
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/7f0c569d-5f63-4b5a-8cfb-3a053276ce66.png)
浮動小数点を使うことにより普通の「色」の範囲をより細かい諧調で扱えるだけでなく
色の範囲を超えたマイナスやとても大きい数値も同じ **"データ"** としてやりとりできるようになっています

今回話題にする**OpenEXR**は浮動小数点値で色を扱うファイル形式の一つです
# 深度データの書き出し
3Dのレンダリングでは各ピクセルから対象までの距離データとして取得できます
ファイルとして書き出す場合にはファイルの形式によって変換が必要になります
### PNG等での書き出しの場合
深度をPNGで書き出す場合、指定した範囲内で黒から白までのグレースケールで表現します。
Blenderのミストパスを使用して深度情報を表示してみた例です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/2624175e-11f4-4c4c-8e67-e00d8335e317.png)
「開始」より近い距離を黒　「深度」で指定した奥行を白　中間がグレーの諧調表現になります
それより遠い部分はホワイトアウトしますし、8ビット（256階調）や16ビット（65,536階調）の場合、範囲を指定した場合は諧調が不足することがあります。

また手動で範囲を指定する代わりにコンポジットで「正規化」のノードを使っている例を見かけます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/31c5bab0-e5df-4434-baa1-5df81bf09a3c.png)
正規化では　画像の中の一番遠い部分を0.0から1.0の範囲に収める計算をしますが
画像1枚1枚単位の処理なので　映り込むものが変化した場合　同じ距離でも値が変化してしまい　動画には不向きです。
### EXRでの書き出し
先に触れた通りEXRではコンピュータが計算したままのデータを出力することが可能です。
また、OpenEXRマルチレイヤは複数の画像を名前を付けた上で同一ファイルに記録することもできます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/48a203f8-387b-4bd7-b6da-20192c96b894.png)
ファイル出力ノードのプロパティ上でファイルフォーマットをOpenEXRマルチレイヤーにして
「入力を追加」を押すことでレイヤを増やして　名前も変更できます
Maya等のArnoldレンダーでは"[Z]"というレイヤ名が使用されるようで　画像でもそのように設定しています。
### AfterEffectsでのEXRの読み込み
この設定でシーケンス素材をレンダリングした後　ファイル＞読み込みでEXRのシーケンスを読み込むことになります
ファイルを指定して　**コンポジションを作成** と **OpenEXRシーケンス** をチェックして読み込みをすると
![スクリーンショット 2025-02-19 143153.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/5796cbc3-4908-4d77-b901-d42636210334.png)
のような画像が出ます
Inmport as:を**Composition** で**Pre Pre-compose layers**にチェックを入れた状態でOKすると
このようにEXRのレイヤが1つのコンポジションとなるように読み込まれます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/c51be51f-d0a3-448d-bfcc-cd46b12e219f.png)

::: note
図は階層から「[Z]  source」のコンポジションを開いた状態です
「EXtractoR」のエフェクトは自動的に追加されます
（White Pointの数値は分かりやすくするために変更しました）
:::

このエフェクトを使うことで　3Dレンダリングをやり直すことなくAfterEffects上で深度からマスクを作れます

# Cryptomatteを使ったマスク
動画のコンポジット作業では　オブジェクトやマテリアル毎に切り分けたい場合が出てきます
これまでは オブジェクト毎に色分けしたカラーデータを作成したり　マスク用にグレースケールデータを出力することがありました

2019年頃から**Cryptomatte**という方式が使われるようになってきたようで Blenderも対応しています
まずは使用例でどういったデータなのか確認してみます

## 基本的な使い方
Blenderでは　ビューレイヤプロパティのCryptomatteにある項目にチェックを入れることで
レンダーパスとして利用できるようになります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/777291bc-f145-453d-b1ef-4bf09f49a460.png)
・オブジェクトの項目にチェックを入れるとオブジェクト毎に
・マテリアルにチェックを入れるとマテリアル毎に
・アセットにチェックを入れるとそれぞれのオブジェクトの親毎に
それぞれでマスクをきり分けられる情報が出るようです

レベルの設定は　半透明で重なっているオブジェクトを最大何階層記録するか？という設定のようです。

Blenderのコンポジットノードで使う場合には
マット＞Cryptomatte　のノードを作成して
情報を取得するシーンやオブジェクトを取得する元（オブジェクトかマテリアルか）を指定して
+ボタンを押した後で画像上の目的の対象がある部分をクリックするか　名前を直接入力することで対象を指定できます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/9809a408-412d-46c2-b4a4-952cc8232eed.png)

::: note
Cryptomatteは規格上は半透明にも対応しています
ただし、BlenderのEeveeのアルファブレンド設定では透明物はうまく扱えないようです
:::

## BlenderのCryptomatteデータの出力
OpenEXRマルチレイヤーを使えば　CryptomatteデータをAfterEffectsに渡すことが可能です
ファイル出力のプロパティでノードのレイヤを増やして
レンダーレイヤーの「Crypt」で始まる出力名と同じレイヤ名に設定し 同じ名前同士を接続します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/6e7a7152-58e6-4d6e-993a-2c65a32c7253.png)
このファイルをさっきと同様に　AfterEffectでEXR読み込みをすると
Cryptomatteのデータだと認識された状態でコンポジションとエフェクトが作成されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/5477aa70-103e-4ddd-b6a6-2796dab9d386.png)
どうやらCryptで始まる連番のレイヤ名がある場合に1セットのCryptomatteのデータとして扱うようです
エフェクトコントロールで　エフェクト選択状態で画像をクリックすると
そのクリック位置にIDが割り振られているオブジェクト全てが選択状態になって
Shift押しながらで追加選択　Alt押しながらで減算選択になるようです
![2502501.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/849db089-3945-46a9-980d-a80affbce920.gif)

::: note
選択していない時の色の表示がBlenderと異なるのは
この表示色は決まった「色」としてのデータではなく各ソフトウエアで設定しているためです。
:::


Cryptomatteは一見すると色分けのマスクと違いがないように見えますが
ソフトウエアの機能で正確にどのデータを選ぶかを指定でき　色分けでは不可能な半透明のマスクも設定できます
ただし、現状ではオブジェクトとマテリアルで分けるデータしか出力できません。
（これはArnoldレンダー等でも同じようです）
任意のマスクを作成するために　仕組みについて調べて次の記事にしてみました

https://qiita.com/yukimituki11/items/cb08218b49815d4d713c