key合成
今回はキーが適当でもいい感じで合成するってtipsです。
こちら、alexaのサンプル素材。
こちら、photo by:juanRubiano
一つ目の素材(bg)の抜けに、二つ目の素材(fg)を入れたいとする。
もちろん、露出等がちがうので、それは適宜合わせるとする。
さらにfgはalexaの素材でちゃんとダイナミックレンジも保たれている。
で、とりあえずキーをとります。
fgの”抜け”と読んでいる明るい部分は値的に10とか超えているので、こういう場合は通常Keyerを用いるよりもlogに変換してkeyerノードを用います。って一連をgizmoにしたのを使ってます。logに変換する理由は、Keyerノードはデフォルトで0-1でキーイングされており、レンジが広い素材をキーイングするには、rangeの部分で拡張する必要があり、この"範囲決め"が面倒なので、logに変換してキーイングをすることがあります。
logに変換すると大きな値を"丸める"ことになり、その大きい値を0-1に納めることで、その域も利用したキーイングが可能になります。また、逆に暗い部分の階調を広げてくれて、そこにディテールを見つけやすくなります。
で、これでキーをとってみて、少しロトをいれて簡単なマットとして合成してみます。
このままだと・・・
左がbgのまま。右がマットを用いて合成したもの。
"抜け"部分が若干暗くなったのにも関わらず木のボケのディテールがなくなってしまってます・・・
マットを少し調整して
としても、木のディテールは出て来たものの、白く太いボーダーラインが大きくでてしまってます。
exposureを落としてみると顕著です。
こんな感じです。
ではどうするか?
今回のTipsを用いると、
こんな感じになります。
左がbgのまま。右が合成したものです。
exposure落として確認しても、
こんな感じで、ボーダーラインはでていません。
bgの山のボケをfgに合わせたので、分かりづらいかもですが、ボケをとってみると、
こんな感じで、ボケの裏の山を表現出来ているのが確認できました。
では具体的には何をしているか?
は、次回。
ZDefocus 番外編
max値についてです。
sizeは何回かで説明したようにボケの大きさではありましたが、ではmaxは?maxは、そのまんま、最大ボケ幅を示していて、リミッターみたいなモノになっています。
カメラはレンズの焦点距離と、フォーカスまでの距離、あとfilmbackのサイズとF値によってボケ度合いが決まります。どの距離のとき、どれくらいボケて、その距離のとき、それぐらいボケるみたいな感じで。また、そのボケの最大値も 焦点距離とF値から算出出来ます。
また、話をnukeにもどして、そのフレームでdepth値とsizeの値からしてmaxまで到達しないモノも当然あります。
以上をふまえてmaxにどのような値を入れればいいのかを決めれば良いのですが、入れる数値によって処理速度はどうなの?っていう疑問はあると思います。
検証してみました。
引き続き、ramp 0-1をdepthとして、zdefocusでsize 50とします。
また、max値に200をいれたもの(ZDefocus10)、51をいれたもの(ZDefocus11)を用意しまして、処理させます。両者のレンダリング結果はdifferenceで確かめたところ、ほぼほぼ同じです。
この二つをnukeのpythonのPerformanceTimersというファンクションを用いて、CPUタイムでどれぐらい差があるか確認してみました。
用いたコードは、
で、
となり、
ZDefocus10(max:200) の方がZDefocus11(max:51)よりも2倍近く処理に時間を要したのが確認でしました。
max値もおおきければ、すべてカバー出来るので良い って訳には行かないのが分かります。
PerformanceTimersは吉川辰平さんに教わりました。ありがとうございます。便利です:)
ZDefocus #4
続き
今まで計算方法(math)として、「分かり易い」からという理由で"direct"を用いてきた。実際directを用いていると、depthをリマップしてボケて欲しくない部分をdepth値0になるようにしておいて、zdefocusのfocal plane(C)に0を入れておけば、
depth値 x zdefocusのsizeの値 (掛け算)
でボケが決まる。しかし、"direct"はエッジの処理に難がある。実際、far=0をmathとして選んで、depthもアルファでくり抜かれたものを処理してみると、
左がfar=0、右がdirect をmathに選んでいる。
明らかに、far=0 の方がうまく行っているようにみえる。
ちなみに、
depthは上のモノになる。node graphからも見て取れるように、同じdepthを用いている。
さらに実はこの二つの結果、differenceで重ねてみると・・・
となっており、エッジ部分以外はほぼ一致しているように見える。
先に、zdefocusのfar=0は直感的で無いので、directを用いる と言っていたが、実は、directとfar=0の掛かり度合いをだいたい合わせる方法がある。
今回ではdepth値に50を用いているが、この場合は、
math = "direct", focal plane(C) = 0, size=1
と
math = "far=0", focal plane(C) = 1, size=1
とすると、エッジ以外は"ほぼほぼ"同じ結果が得られる。
"ほぼほぼ"と書いたのは、実際の値的に1の差がある。ただ、50のボケに対して、1の差なので分かりづらい。
どういうことかというと、このケースはdepth値が50なのであまり影響が無かったが、試しにdepth値を小さくし、sizeにある程度大きい数値を入れて確認してみることにする。
depthには0-1のrampを用いた。
zdefocusのsizeは50を用いた。
focus plane(C)の値は、先の例と同様である。
ただ、この場合、上の結果のようにボケが合わない。
そこで、far=0 に用いているdepthに1を足してみる。
とエッジの状態が違うので分かりづらいので、differenceで重ねて確認してみる、
よく見ると差はあるのだが、こんな感じで、エッジ以外はだいたい一致している。
far=0(math)の方がエッジは良好である。
つまり、
math = "direct", focal plane(C) = 0
で、ボケが思い通りになるように調整(リマップ)したdepthに1を加えて、
math = "far=0", focal plane(C) = 1
で実行し、場合によっては"automatic layer spacing"をオフにして、"depth layers"に小さめの値を入れて、作業することもスピードアップに繋がると思われる。
さらに、depthにアンチエイリアスが適応されている場合は、それが必要かどうかを見極め、不要な場合は、unpremultiply等でそのアンチエイリアスで発生する階調をキャンセルすることも、スピードアップに繋がる場合があると思われる。
※ちなみに、今回紹介したのは、direct(math)にfar=0の結果を近づける方法である。
ZDefocus #3
続き
前回、
ちなみに、"差"が極端に狭いところであったとしても、ほぼほぼ画面一面、等しい値だけど、とても小さいエリアで値の変化があったとしてら?しかも、そこのアルファチャンネルの値が0でくり抜かれている部分だったとしたら?
残念ながら、これでも遅いままです。差が最終的なボケのサイズ換算で、30%ぐらいまでの差であれば、まだ若干はマシなのですが、50%ぐらいの差が出てしまうと極端に遅くなります。
って文章で終えてますが、これは、一部正しくて、一部間違えています。
ちょっと例を見てみましょう。
depthの一部に、1ピクセルだけ変化を加えます。
というexpressionを用いて、
一見何も変化ありませんが、左下隅(x,y座標で 0,0)のところに、1ピクセルだけ黒ができてます。
これで、zdefocus処理を確認してみたところ、このexpression有無で速度は特に変わりません。
黒ピクセルエリアを増やしてみます。20x20にしてみましたが、それでも、特に速度は変わりません。ストレス無く処理を終えれます。
さらに、depthにblurを掛けてみます。blurの値5で掛けてみました。
こんな感じ。そうすると、zdefocusの速度に変化が現れます。
後半が、depthにblurを適応したものです。前半はblurがdisableになってます。
このように、アルファでくり抜かれている部分で、一見zdefocus処理が行われていないエリアのように思いがちなところでも、速度低下が起こっているの確認出来ます。
しかもscanlineの動き方を見ていると、どうも、そういうエリアがscanlineに当たる部分で遅くなっているように見受けられます。
もう一つテストをしてみます。
前回、同一のdepthの値をアルファでくり抜いただけで遅くなりましたが、今回のblurの有無テストから、それは、くり抜いたエッジ部分にアンチエイリアス処理がはいり、”段階”が出来ているためではないかと推測ができます。
なので、くり抜きに"段階”が出来ないようにくり抜くアルファのエッジを0か1の値にしてみます。
expressionを用いて、
をmask用のrotoの直下に入れました。
結果のキャプチャーは下のムービーです。前半がrint(a)処理なし、後半がありです。
アンチエイリアス処理を無くして、二値化した後半の方が断然速いのが分かると思います。
ココまでことでも、考察されるように、zdefocusはdepthの値の差があると遅くなり、それは、その差の大きさに依存するわけではなく、その値のバリエーションに依存することが推測できます。
では値の差をバリエーションを減らすとどうなるのか?をもう少し検証してみます。
前回用いた、rampで画面一面でdepth値が変化するようにしたモノを用います。
gradeノードとexpressionを用いて、rampで生成した0-1のグラデーションのをガタガタにします。
expressionに入っている式は、
一つ上のgradeノードと連動するにようになっています。例えば、上のgradeので0-1の値を5倍して、0-5にして、それをrint(r)で、すべて整数値にして段階を減らし、それを5で割って0-1にfitさせてます。
depthはこんな感じになります。
左がオリジナル、右が処理したモノです。
結果は下のキャプチャー動画です。前半がガタガタ処理なし、後半がありです。
後半の方が速いということが確認出来ます。
結果としても割と同様のように思えるのですが、これはやはり違いが生じています。
一部によって確認してみると、
左がオリジナル、右がガタガタ処理を加えたものです。
当然ながら、このような違いが発生します。クオリティー的に問題があります。
ともあれ、処理としては、かなり高速化が図れます。作業中だけでも、これを利用するっていうのは、アリかもしれません。
で、実はこの機能、zdefocusのデフォルトの機能として存在します。
この”layer”の部分です。
ココの"automatic layer spacing"のチェックを外して、"depth layers"の値を4とかに落としてみると、かなり結果が表示されるのが速くなります。
先ほどのdepthにガタガタ処理を加えたモノと結果もにかよっています。
zdefocusがどうしても遅くて作業にならないとかの場合、この"depth layers"の値を落として、"automatic layer spacing"に
とかを入れても良いかもです。こうしておけば、ネットワークレンダリングでこのnukescriptが走る際は、自動的にこの"automatic layer spacing"がオン、作業中はオフというふうにできます。
※ただし、ネットワークレンダリング、つまりnuke_rライセンスでnukeが動いている場合のみ"automatic layer spacing"がオンになります。ローカルレンダリングには利きません。
と、zdefocusが遅くなる原因が、これでだいたい理解できるのでは、と思います。
zdefocusの特徴はもう少し説明しないと、細かくコントロールできない部分があるので、それはまた次回。
※まとめ
depthの値にバリエーションが多いと遅くなる。また、個々の値の差が大きいとそれも速度低下につながる。
ZDefocus #2
続き
では何が、zdefocusを遅くしているのか? 簡単にいうと、それは、”差”である。depthの値の差がzdefocusを鈍重にする。”差”と言っても、よくわからないと思うので、実例を示してみよう。
こんな感じでアルファでくり抜かれた画像と、同じアルファでくり抜いたdepthを準備した(2枚目はdepth)。これを、
depth値=50,size=1,focus plane(C)=0
でzdefocusで処理すると、
こんな感じで、このlaptopで30秒以上掛かってしまいます。しかも結果としても、境界がシャープになってしまっている、おかしな結果になっています。
次に、depthをmaskで抜かずに画面一面を同じ値にしてみます。
2枚目はdepthです。一面同じ値かどうかは分かりにくですが、一面同じ値で、くり抜かれてません。
と、こんな感じで、とても速い処理が行われます。
結果も境界がちゃんとボケていて良好に見えます。
なぜ、こうなるのか?
それは、前者(遅い方)のdepthがくり抜かれており、そこで、くり抜かれてるところ(depth値0)とくり抜かれていないところ(depth値50)で、depthの値の差が出来るためです。加えてzdefocusは(くり抜かれた)境界部分で起こるボケで境界が外に押し出される(フェードアウトしているので実際の値ほどは押し出されてるように感じない)が、押し出された先に適当なdepthの値が無いために、前者のような境界がシャープなままの結果を生み出してしまいます。
このケースだと、depth値0とdepth値50の"差"が引き起こす遅さということになります。正確には、depth値0とdepth値50とsize1でボケの"差"が生じるためのでしょうか。
境界に関しては、実際にコンプしている場合だと、depthの境界をエキステンドします。これをしないと今回のように境界がくっきりしたり、エッジにハロと呼ばれる、ダブりイメージのようなものを得てしまったり。ボケることで、境界部分が50ピクセル外に拡張されるのでれば、50ピクセル外にdepthが必要になります。その時のdepthの値は、そのボケを生み出すに適切なdepth値となります。なので、depthの境界をエキステンドすることになります。
また、例として、くり抜いてないdepthでかつ、depthにグラデーションがついてる場合も、やはり"差"があるので、遅くなります。
depthに使用しているrampは0-1で、zdefocus側でsize=50,focus plane(C)=0としています。
また、今度はrampノードの下にmultiplyノードをぶら下げて、depth値を50倍、なのでdepthは0-50のグラデーションということになります。で、zdefocus側でsize=1,focus plane(C)=0として、depthの掛かり方的には同じ結果になるようにしてみます。
処理時間の結果としては、ほぼ同じであると思われます。得れる、見た目の結果も同じであると思われます。
※動画の最初がもたついているのは、zdefocusのせいではなく、quicktimeでキャプチャーを作るために、ボクの操作のもたつきです。
いずれにしても、グラデーションがもたらす"差"でも、やはり遅いです。
ちなみに、"差"が極端に狭いところであったとしても、ほぼほぼ画面一面、等しい値だけど、とても小さいエリアで値の変化があったとしてら?しかも、そこのアルファチャンネルの値が0でくり抜かれている部分だったとしたら?
残念ながら、これでも遅いままです。差が最終的なボケのサイズ換算で、30%ぐらいまでの差であれば、まだ若干はマシなのですが、50%ぐらいの差が出てしまうと極端に遅くなります。
では、zdefocusの処理を速くするためにはどうすれば良いのか?
また次回に。