16. コンピュテーショナルフォトグラフィ・NPR・可視化

此処までのシリーズの殆どは、1つの目標を目指して来ました。
存在しないシーンを撮った写真の様に見える絵です。
此の章では、同じ道具の別の3つの使い方を扱います。
コンピュテーショナルフォトグラフィは、カメラ其の物をコンピュータにして、1回の露出では撮れない写真を作ります。
ノンフォトリアリスティックレンダリングは、敢えて写真に見えない絵を描きます。
アニメ、テクニカルイラストレーション、ペン画などです。
可視化は、数値(CTスキャン、流れのシミュレーション、売上の表)を、人が理解出来る絵に変えます。

3つとも物理的な正確さより、人が何を見るべきかを考えます。
其の為、シラバスでは此の3つを分野7視覚に訴えるグラフィックスとして纏め、コンピュテーショナルフォトグラフィ、ノンフォトリアリスティックレンダリング、可視化の3項目を挙げています。
此の章では、各部の最後に其の部の検定のポイントを置きます。

殆ど全てが前の章の再利用なので、繰り返さずにリンクします。
第2章のカメラ、露出、ノイズ、第3章の色と知覚、第9章の等値面とマーチングキューブ法、第10章のシェーディングと背面、第12章のライトフィールド、そして第15章のトーンマッピング、畳み込み、エッジ検出、ホモグラフィです。

16.1 コンピュテーショナルフォトグラフィとは

昔ながらのカメラは光学機器です。
レンズが像を作り、センサーが其れを1回記録し、写真は完成です。
コンピュテーショナルフォトグラフィは、撮影と計算を1つのシステムとして扱います。
普通の写真1枚より多くの物(複数の露出、複数のピント位置、ライトフィールド、符号化されたぼけ)を記録し、其の後で本当に欲しい写真を計算します。
結果は、どの1回の露出よりも広いダイナミックレンジ、深い被写界深度、少ないノイズや少ないぶれを持てますし、撮影後に判断(ピント、照明)を変える事も出来ます。

2.11節の3つの分野(コンピュータビジョン、画像処理、カメラモデル)を全て使い、手法は何を変えるかで分類出来ます:

変える物 手法
露出 HDR合成、バースト撮影によるノイズ除去、夜景モード
視点 パノラマと画像のスティッチング
ピントと光学系 深度合成、ライトフィールドカメラ、符号化開口
シャッター 符号化露光、ぶれ除去
照明 フラッシュ/ノーフラッシュ、イメージベーストリライティング
撮影後の画像 超解像、シームカービング、合成ボケ

スマートフォンは、シャッターボタンを押す度に此の内の幾つかを、大抵は何も言わずに行っています。

16.2 露出ブラケットによるHDR合成

問題:1回の露出には広過ぎる範囲

晴れた日に部屋の中から窓を撮ってみて下さい。
部屋が正しく写れば窓は真っ白になり、空が正しく写れば部屋は真っ黒になります。
シーンのダイナミックレンジ(気にする範囲で一番明るい所と一番暗い所の比)が、1回の露出で記録出来る範囲より大きいのです。
深い影のある日向のシーンは100,000:1、約17段(log2100000≈16.6)を超える事があり、8ビットの画像ファイルが持てるのは256段階です。

解決策は、露出時間を変えて何枚か撮る事です。
此の一連の撮影を露出ブラケットと言い、其れらを1枚のハイダイナミックレンジ画像(HDR画像、第2章)に合成し、シーンの放射輝度を浮動小数点数で保存します。
変えるのは絞りではなくシャッター速度です。
絞りを変えると被写界深度も変わり、写真同士が食い違ってしまうからです。

明るい窓のある合成の部屋の3枚の露出、対数目盛で示した合成の放射輝度、部屋も空も見えるトーンマッピングの結果

合成のシーンは暗い箱から太陽まで6,807:1(12.7段)に及び、どの1枚の露出にも収まりません。

モデル

カメラは、露出(放射輝度Eと露出時間tの積)を、応答曲線fを通して画素値Zに変えます:

Z=f(Et)

fが分かっていれば、各露出jから、其の画素の放射輝度の推定値が得られます:

Ej=f−1(Zj)tj

センサーのRAWデータならfは殆ど線型で、Ejは単に(定数倍を除いて)Zj/tjです。
JPEGは非線型な曲線(少なくともsRGBの符号化、多くの場合其れ以上)を通っていて、カメラは其れがどんな曲線かを教えてくれません。
ポール・デベヴェックとジテンドラ・マリク(「Recovering High Dynamic Range Radiance Maps from Photographs」、SIGGRAPH 1997)は、ブラケット写真其の物から曲線を求める方法を示しました。
シーンの同じ点が、露出時間の比が分かっている全ての写真に写っているので、g=lnf−1を(定数倍を除いて)解くのに十分な式が得られます。
其の後、推定値の対数の重み付き平均で合成します:

lnE=∑jw(Zj)(g(Zj)−lntj)∑jw(Zj)

重みは「山形」で、0付近(ノイズ、量子化)と255付近(クリップ)で小さくなります。
z≤127.5でw(z)=z、其れより上でw(z)=255−zです。
飽和した画素(Z=255)の重みは0です。
其の画素から分かるのは、放射輝度が「少なくとも」或る値だったという事だけだからです。

計算例:2枚の露出、2つの画素

線型な応答のカメラで、t1=1/15 sとt2=1/240 sの2枚を撮ります。
比は16、つまり4段です。
画素Pは影の中、画素Qは明るい窓の上にあります:

画素 Z1(1/15 s) Z2(1/240 s) E1=Z1/t1 E2=Z2/t2 w(Z1) w(Z2)
P 80 6 1200 1440 80 6
Q 255 150 (少なくとも3825) 36,000 0 105

Pでは2つの推定値が食い違います。
短い露出ではPは黒から6段階しか上でないので、半段階のノイズが8%の誤差になります。
重みが其れを処理します:

lnEP=80ln1200+6ln144086=80⋅7.0901+6⋅7.272486=7.1028,EP≈1215

結果は信頼出来る長い露出の近くに留まります(対数ではなく値其の物を平均すると1217で、殆ど同じです)。
Qでは長い露出がクリップしているので其の重みは0で、EQ=36000は短い露出だけから来ます。
合成画像はQがPの36000/1215≈30倍明るい事を知っていますが、1枚1枚の写真はどちらかを間違えていました。

実際には

合成には、動かないシーンとカメラが必要です。
撮影の間に動いた物は何度も写ってしまう(ゴースト)ので、実際のソフトはまず画像の位置を合わせ、一致しない画素を除外します。
結果はOpenEXRの様な浮動小数点形式で保存し、普通の画面に表示する前にトーンマッピング(15.4節)しなければなりません。
上の図は大域的な曲線(ラインハルトの物)を1本使っていますが、局所的なトーンマッピングは、例えば対数輝度をエッジを保つバイラテラルフィルタ(第15章)でぼかした物で大まかな明るさだけを圧縮し、局所的な細部は残します。多くのスマートフォンの写真の「HDRらしい見た目」は此れです。
12.13節のライトプローブは丁度此の方法で作ります。
レンダラーは最初から浮動小数点で計算するので、ゲームは単に毎フレームトーンマッピングします。
其れはOpenGLシリーズの第21章で行います。

16.3 パノラマ:何枚もの写真をつなぐ

パノラマ(見せ方は12.13節で扱いました)は、普通画像のスティッチングで作ります。
カメラを回しながら重なり合う写真を撮り、1枚の広い画像にまとめるのです。
手順は次の通りです:

  1. 全ての写真で特徴点を見つけます。角の様な目立つ点で、其々に回転、拡大縮小、明るさの変化に強い周囲の記述子が付きます(SIFT、デビッド・ロウ、2004年が古典的です)。
  2. 重なっている写真同士で、記述子を比べて特徴点を対応付けます。
  3. 各組の間の変換を推定します。カメラが光学的な中心の周りで回転するだけの時、又はシーンが平面の時、2枚の写真は第15章の3×3の射影変換、ホモグラフィで正確に結ばれます。要素は9つですが定数倍の違いは同じ変換なので未知数は8つ、対応点1組から式が2本出るので、4組の対応で決まります。
  4. 間違った対応を除きます。RANSAC(フィッシュラーとボールズ、1981年)を使い、ランダムに4組選んでホモグラフィを計算し、他の対応の内いくつが其れに合うかを数え、此れを繰り返して一番良い物を残します。
  5. 全ての写真を共通の面に変形します(数枚なら平面、1周なら円筒か球)。
  6. 継ぎ目が見えない様に、重なりをブレンドします。

RANSACの試行回数は簡単に見積もれます。
対応の半分が間違っているなら、ランダムな4組が全て正しい確率は0.54=0.0625です。
99%の確実さで少なくとも1回きれいな組を引くには、1−(1−0.0625)N≥0.99、つまりN≥ln0.01ln0.9375≈71.4回、72回の試行が必要です。
1回の試行の計算は殆どタダです。

ブレンド。
一番単純なブレンドはフェザリングです。
重なりを横切って、一方の写真の重みを1から0へ線型に下げ、もう一方を上げます。
幅100ピクセルの重なりで、25ピクセル入った所の画素は重み0.75と0.25になり、其処で写真が120と140なら、結果は0.75⋅120+0.25⋅140=125です。
マルチバンドブレンディング(バートとアデルソン、1983年)は、画像ピラミッドを使い、低い周波数は広い範囲で、細かい部分は狭い範囲でブレンドします。
殆どのスティッチングソフトが此れを使っています。
カメラが回るだけでなく移動すると、近くの物と遠くの物のずれ方が変わり(視差)、1つのホモグラフィでは合わず、ゴーストや途切れた線が出ます。

16.4 深度合成、ライトフィールドカメラ、リフォーカス

深度合成

2.3節で、近くの物を撮ると被写界深度がとても浅くなる事を見ました。
深度合成(フォーカススタッキング)は、ピントの距離を変えて何枚か撮り、画素ごとに一番シャープな写真を残します。
シャープさは例えば局所的なラプラシアン(第15章)の大きさで測ります。
ピントの合った領域は高い周波数を強く含み、ぼけた領域は含みません。

ライトフィールドカメラ

12.13節で、全ての光線の放射輝度である4次元のライトフィールドを紹介しました。
ライトフィールドカメラ(プレノプティックカメラとも言います)は、センサーの前に小さなマイクロレンズを並べた配列を置き、小さなライトフィールドを1回の撮影で捉えます(スタンフォード大学のレン・ン達が2005年に手持ちの物を作りました)。
各マイクロレンズはピクセルの小さなブロックを覆い、其の各ピクセルが主レンズの開口の異なる部分を通してシーンを見るので、カメラは光線が当たった所と来た方向の両方を記録します。

代償は解像度です。
例: 7680×5120のセンサー(3930万画素)で、各マイクロレンズが10×10ピクセルを覆うと、位置ごとに100方向が得られますが、位置は768×512=393216個しかありません。
0.39メガピクセルの画像です。
此のトレードオフの為、ライトフィールドカメラはニッチに留まり、スマートフォンは深度推定(16.6節)で似た効果を実現しています。

シフトして足すリフォーカス

全てのマイクロレンズのブロックから同じ位置のピクセルを拾うと、1枚のサブアパーチャ画像になります。
レンズの小さな一部を通して見たシーンで、少しずれた視点からの写真の様な物です。
ピント面上の点は全てのサブアパーチャ画像で同じ位置に写り、其れ以外の奥行きの点は、サブアパーチャのずれuとピント面からの距離に比例して、画像ごとにずれます。
普通の写真は全てのサブアパーチャ画像を其のまま足すので、ピントの外れた点は広がります。
此れがピンぼけを計算で作った物です。

リフォーカスは、足す前に各サブアパーチャ画像をずらします。
例: 1次元で、3つのサブアパーチャu=−1,0,+1を考えます。
点Aはx=10+2u、つまりピクセル8、10、12に写ります。
其のまま足すと、Aは8〜12に広がってぼけます。
各画像を−2uずらすと3つの写像が全てx=10に集まり、Aはシャープになります。
逆に、元々シャープだった点(3枚で同じ位置)は4ピクセルに広がります。
uあたりのずらし量を選ぶ事は、撮影後にピント面を選ぶ事です。
平均するサブアパーチャを減らすと、絞った時の様に被写界深度が深くなります。

16.5 ぶれ除去、符号化開口、符号化露光

ぶれは畳み込み

露出中にカメラが揺れたり被写体が動いたりすると、全ての点が同じ小さな形に広がります。
此の形が点像分布関数(PSF)です。
ぶれがどこでも同じなら、ぶれた画像bは、シャープな画像sをPSF kで畳み込み(第15章)、ノイズnを足した物です:

b=k∗s+n

ぶれ除去とは此れを元に戻す事、つまり逆畳み込み(デコンボリューション)です。
PSFが分かっていれば「ノンブラインド」逆畳み込み、ぶれた写真からPSFも推定しなければならなければ「ブラインド」逆畳み込みで、後者はずっと難しくなります。

計算例:逆畳み込みは何故壊れやすいか

1次元の信号s=(0,0,0,9,9,9,9)(くっきりした段差)に、3ピクセルの動きぶれbi=13(si+si−1+si−2)を掛けます(始まりの前は0とします):

b=(0,0,0,3,6,9,9)

段差が坂になりました。
元に戻すのはただの代数です。
si=3bi−si−1−si−2で、(0,0,0,9,9,9,9)が正確に戻ります。
次に、4番目の値だけに0.3という小さなノイズを足し、b3=3.3にします。
同じ式から

s=(0,0,0,9.9,8.1,9,9.9,…)

となり、誤差のパターン+0.9,−0.9,0が永遠に繰り返します。
0.3のノイズが、決して消えない0.9の誤差になりました。
理由はパターン其の物に見えています。
(+a,−a,0)を繰り返す数列は、隣り合うどの3つを足しても0なので、此のぶれは其れを完全に消してしまいます。
第15章の言葉で言えば、箱型のカーネルの周波数応答は1ピクセルあたり1/3周期の周波数で0になり、(殆ど)0で割ると其の周波数のノイズが際限無く増幅されます。
其の為、ウィーナーフィルタやリチャードソン・ルーシー法の様な実用的な方法は、闇雲に割り算はしません。
信号がノイズより弱い周波数は諦めるのです。

符号化露光と符号化開口

PSFの周波数応答に0がある事が問題なら、PSFを変えれば良いのです。
符号化露光(ラスカー、アグラワル、タンブリンの「フラッターシャッター」、2006年)は、露出中にシャッターを擬似ランダムな2値のパターンで開け閉めします。
動く物体は箱型ではなく破線状に伸び、上手く選んだパターンなら周波数応答に0が無いので、動きぶれが元に戻せる様になります。
符号化開口(例えばレヴィン、ファーガス、デュラン、フリーマン、2007年)は、ピンぼけについて同じ事をします。
レンズの開口に模様のあるマスクを入れると、ピンぼけのPSFが戻しやすくなり、更に模様の大きさが奥行きで変わるので、シーンの各部分がどれだけ遠いかも推定出来ます。

16.6 フラッシュ、バースト、スマートフォンのカメラ

バースト撮影:平均でノイズを消す

画素値は本当の値にランダムなノイズを足した物です。
光其の物がランダムな数の光子として届き、センサーの電子回路が更に自分のノイズを足します(2.3節では感度を上げると其れが増幅される事を見ました)。
静止したシーンをN枚撮って平均します。
本当の値は変わらず、標準偏差σの独立なノイズは

σN=σN

に縮みます。
例: 1枚のノイズがσ=8段階だとします。
4枚の平均で8/2=4、9枚で8/3≈2.67、16枚で8/4=2です。
ノイズを半分にするには4倍の枚数が要ります。
デシベルで言えば、16枚でSN比が20log104≈12 dB良くなります。

ノイズのある合成画像と、ノイズのある4枚と16枚の平均。測ったノイズは0.100から0.050、0.025へ減る

図で測ったノイズ(0.100、0.050、0.025)は式の通りです。
何故、同じ光の総量で1回長く露出しないのでしょうか?
手持ちの長い露出はぶれ(16.5節)、明るい所はクリップするからです。
短い露出を沢山撮れば両方を避けられ、平均の前にコンピュータが位置を合わせます。
此れがバースト撮影で、スマートフォンの「夜景モード」の中心です。1秒以上の間に沢山のフレームを撮り、局所的に位置を合わせ、頑健に合成し(何かが動いて他と一致しない画素は重みを下げます)、トーンマッピングします。

フラッシュとノーフラッシュ

暗い部屋では、フラッシュの写真はきれいですが平板で冷たく、フラッシュ無しの写真は部屋の雰囲気がありますがノイズだらけです。
フラッシュ/ノーフラッシュ撮影(ペチュニグ達、及びアイゼマンとデュラン、どちらも2004年)は両方を撮ります。
色と大まかな照明はノーフラッシュの写真から、細部と少ないノイズはフラッシュの写真から取ります。
道具は「ジョイント」バイラテラルフィルタ(第15章)で、ノーフラッシュの写真を滑らかにしますが、エッジはきれいなフラッシュ写真から取ります。

ポートレートモード:合成ボケ

スマートフォンの小さなレンズとセンサーでは、被写界深度は殆ど無限です。
ポートレートモードは大きなカメラの浅い被写界深度を真似ます。
深度マップを推定し(ステレオペアとしての2つのカメラ、デュアルピクセルセンサーの画素の左右半分、深度センサー、又はニューラルネットワークで1枚の画像から。センサーは17.5節で扱います)、人物と背景を分け、各画素を其れ自身の錯乱円でぼかします。

2.3節の錯乱円c=Df|a−af|a(af−f)は、次の様に書き直せます:

c=Dfafaf−f|1a−1af|

従って、ピントの距離afが決まっていれば、ぼけは距離の逆数の差と共に大きくなります。
例: af=1.5 mの顔にピントを合わせ、ぼけの半径がr=30|1a−1af|ピクセル(aはメートル)になる様に定数を選びます。
3 mの壁は30⋅|0.333−0.667|=10ピクセル、6 mの木は30⋅0.5=15、無限遠の背景は30⋅0.667=20、前に伸ばした1 mの手は30⋅|1−0.667|=10です。
遠くではぼけは頭打ちになり、カメラの近くでは急に大きくなります。

超解像

センサーは画素ごとに1回像を標本化し、2.6節の標本化定理が記録出来る細かさを制限します。
複数フレームの超解像は、ピクセルの何分の一かずつずれた何枚かのフレームを使います(手ぶれが其れを無料で与えてくれます)。
例: (0,0)、(12,0)、(0,12)、(12,12)ピクセルずれた4枚を合わせると、半分の間隔の格子でシーンを標本化した事になります。
レンズが十分シャープで、ずれが正確に測れれば、各方向に2倍の解像度、4倍の画素数です。
一方、ニューラルネットワークによる1枚の画像からの超解像は、学習した画像から其れらしい細部を作り出します。
説得力がある事が多いですが、測定ではありません。

イメージベーストリライティング

光は線型に足し合わされます(10.10節のフォンの式で光源について和を取るのも其の結果の1つです)。
従って、静止した被写体をK個の光源其々1つだけで1回ずつ撮り、画像I1,…,IKを得れば、其れらの光源をどんな割合で混ぜた時の見え方も重み付きの和になります:

I=∑kwkIk

例: 或る画素が光源1だけで200、光源2だけで50(リニアな値)なら、光源1を70%、光源2を20%にすると0.7⋅200+0.2⋅50=150になります。
此れがイメージベーストリライティングで、数百の方向からの光の下で撮った写真(デベヴェック達のライトステージ、2000年)があれば、重みをHDRの環境マップから取り、俳優の顔をどんなシーンにも合わせて照らし直せます。

16.7 シームカービング

16:9の写真を4:3の画面に表示するには3つの選択肢があります。
拡大縮小する(全てが潰れます)、切り取る(端が失われます)、又は誰も気にしない部分を取り除くかです。
シームカービング(シャイ・アヴィダンとアリエル・シャミア、SIGGRAPH 2007)は3つ目を行います。
内容を考慮したリサイズです。

エネルギーとシーム

まず、全ての画素に、どれだけ大事かを表すエネルギーを与えます。
単純な選び方は画像の勾配の大きさ、第15章のエッジの強さです:

e(i,j)=|∂I∂x|+|∂I∂y|

平らな空のエネルギーは殆ど0で、エッジや模様のエネルギーは高くなります。
例: 左右の隣の明るさが50と90、上下の隣が60と64の画素は、中心差分でe=|90−50|2+|64−60|2=20+2=22になります。

縦のシームは、一番上の行から一番下の行までの画素の道で、各行に丁度1画素、各画素は上の画素と同じ列か隣の列にあります(8連結)。
シームを取り除くと、行が揃ったまま画像は1ピクセル細くなります。
欲しいのは合計エネルギーが一番小さいシームです。
其れは重要でない領域を通り、物体を避けます。

一番安いシームを探す:動的計画法

可能なシームは約W⋅3H−1本あり、全て試すには多過ぎます。
でも、画素(i,j)で終わる一番安いシームは、其の上の3画素の何れかで終わる一番安いシームの続きのはずです。
其処で表Mを、動的計画法で1行ずつ埋めます:

M(0,j)=e(0,j),M(i,j)=e(i,j)+min(M(i−1,j−1),M(i−1,j),M(i−1,j+1))

最後の行の一番小さい値が一番安いシームのコストで、表を最小値に沿って上に辿るとシーム其の物が得られます。
探索全体の計算量は画像を1回なめるだけ、O(WH)です。

計算例

4×5のエネルギーの表と、其処から計算した表Mです:

計算例のエネルギーの表eと累積の表M。列1、2、1、2を通るシームを強調している

0行目は其のまま写します。
1行目、2列目:2+min(1,4,6)=3。
2行目、1列目:2+min(6,8,3)=5。
3行目、2列目:1+min(5,12,6)=6。
最後の行の最小は2列目の6です。
上に戻ります。
2列目の上では、M(2,1..3)=5,12,6の最小は1列目です。
其の上では、M(1,0..2)=6,8,3の最小は2列目です。
其の上では、M(0,1..3)=1,4,6の最小は1列目です。
シームは列1、2、1、2を通り、エネルギーは1+2+2+1=6です。
一番安い真っ直ぐな列(1列目か2列目)は16なので、曲がるシームは、列を1本切り取るよりずっと大事でない内容を取り除きます。

実際には

画像をk列縮めるには、一番安いシームを探して取り除く事をk回繰り返し、毎回エネルギーを計算し直します。横のシームは高さを変え、一番安いシームを複製すれば拡大も出来ます。

ボールと塔:最初に取り除いたシームを描いた元の画像、160ピクセルに縮小して物体が潰れた画像、シームカービングで160ピクセルにして物体が保たれた画像

シームはボールと塔を避けて空と草を通るので、物体は形を保ち、其の間の何も無い空間が縮みます。
重要でない物が残っていない時(人混み)は失敗し、多くのシームを横切る直線は曲がります。
ツールでは領域を守ったり、全てのシームを物体に通して其れを消したり出来ます。

検定のポイント

  • コンピュテーショナルフォトグラフィ=複数の、又は符号化した撮影+計算で、1回の露出では得られない物を得る。
  • HDR合成に必要なのは、動かないシーンの複数の露出(普通はシャッター時間を変える)、カメラの応答曲線(RAWなら線型、JPEGなら推定する。デベヴェックとマリク、1997年)、クリップした画素と暗過ぎる画素を無視する重みです。結果は浮動小数点の放射輝度で、表示にはトーンマッピングが必要です。
  • スティッチング:特徴点→対応付け→RANSACでホモグラフィ(未知数8つ、対応点4組)→変形→ブレンド。ホモグラフィが正確なのは、回転するだけのカメラか平面のシーンの時だけです。
  • N枚を平均するとノイズはN分の1になります。
  • ぶれはPSFとの畳み込みです。逆畳み込みはPSFが抑える周波数のノイズを増幅します。符号化露光と符号化開口はPSFを戻しやすくします。
  • ライトフィールドカメラは空間の解像度を方向と引き換えにし、撮影後のリフォーカスを可能にします。
  • シームカービングは、エネルギー最小の、8連結で各行1画素の道を動的計画法で探して取り除きます。

16.8 ノンフォトリアリスティックレンダリング

ノンフォトリアリスティックレンダリング(NPR)は「何でないか」で定義されます。
写真の様に見える事を目指さないレンダリングです。
此の名前は少し不運で、全く違う目的を含んでいます:

  • イラストレーションと伝達:取扱説明書、特許図面、医学や科学のイラスト。敢えて物を省き、大事な部分がはっきり読める様にします。
  • スタイル:アニメや漫画、絵画、墨絵、独特の見た目を持つゲーム。
  • 抽象化:シーンや写真を大事な物だけに減らします(地図、スケッチ)。

NPRの手法は2つの系統に分かれます。
3次元(モデルベース)の手法はモデルから始まり、法線、深度、辺、曲率といった形状を使えます。トゥーンシェーディングと殆どの線画は此方です。
2次元(画像ベース)の手法は、写真やレンダリングしたフレームの画像から始まり、フィルタを掛けたり、上にストロークを置いたりします。絵画調フィルタ、桑原フィルタ、ニューラルスタイル変換です。
16.10節の輪郭線の様に、両方を混ぜるシステムも多いです。

16.9 トゥーンシェーディング

考え方

手描きのアニメーション(セルアニメーション)は、キャラクターを少しの平らな色で塗ります。
基本色、影色、場合によってハイライトで、其の間の境目はくっきりしています。
トゥーンシェーディング(セルシェーディングとも言います)は、10.10節の拡散反射の項を量子化して其れを真似ます。
滑らかなmax(𝐧⋅𝐥,0)の代わりに、明るさが選んだしきい値で幾つかの段階の間を飛びます。

しきい値を0.2と0.6の2つ、段階を3つにすると:

level(𝐧⋅𝐥)={0.3𝐧⋅𝐥<0.20.60.2≤𝐧⋅𝐥<0.61.0𝐧⋅𝐥≥0.6I=kdILlevel(𝐧⋅𝐥)

一番暗い段階が0ではなく0.3である事に注意して下さい。
アニメでは、影の側は色の暗い版で、決して黒ではありません。

計算例

光は𝐥=(0,0.6,0.8)から来て(長さ1:0.36+0.64=1)、材質の色はkd=(0.8,0.1,0.1)、光は白です。

法線𝐧 𝐧⋅𝐥 ランバートkdmax(𝐧⋅𝐥,0) トゥーンの段階 トゥーンの色
(0,0,1) 0.8 (0.64, 0.08, 0.08) 1.0 (0.8, 0.1, 0.1)
(0.8,0,0.6) 0.48 (0.384, 0.048, 0.048) 0.6 (0.48, 0.06, 0.06)
(0,−0.6,0.8) 0.28 (0.224, 0.028, 0.028) 0.6 (0.48, 0.06, 0.06)
(0,−0.8,0.6) 0 (0, 0, 0) 0.3 (0.24, 0.03, 0.03)

2番目と3番目の法線はランバートの明るさが違います(0.48と0.28)が、トゥーンの色は同じです。
段階の内側では形の情報を敢えて捨て、段階の境目だけが形を見せます。

輪のある球をランバートのシェーディング、3段階のトゥーンシェーディング、輪郭線付きのトゥーンシェーディングで描いた物

中と右の画像は丁度上のしきい値を使っています。
ハイライトは4番目の「段階」で、𝐧⋅𝐡(10.10節のハーフベクトル)が0.985を超える所を白く塗っています。

ランプテクスチャ

コードに書き込んだしきい値は、アーティストには調整しにくい物です。
其の為、殆どのエンジンは段階をランプテクスチャから引きます。
アーティストが描く1次元のテクスチャ(ピクセルの帯)です。
テクスチャ座標はu=𝐧⋅𝐥+12で、−1〜1の範囲を0〜1に写します。
例: 𝐧⋅𝐥=0.28ならu=0.64で、256ピクセルのランプでは0.64⋅255≈163番目のテクセルです。
ランプには幾つでも段階を入れられ、柔らかい境目も硬い境目も、色相の変化(肌の赤みのある影色)も持てます。

// Toon shading: Lambert's n.l quantized into three bands (thresholds 0.2 and 0.6)
float3 toonShade(float3 n, float3 l, float3 baseColor) {
  float nl = dot(normalize(n), normalize(l));
  float level = nl < 0.2 ? 0.3 : (nl < 0.6 ? 0.6 : 1.0);
  return baseColor * level;
}

// The same with an artist-painted ramp texture: u = (n.l + 1) / 2
float3 toonRamp(Texture2D ramp, SamplerState rampSampler, float3 n, float3 l, float3 baseColor) {
  float u = dot(normalize(n), normalize(l)) * 0.5 + 0.5;
  return baseColor * ramp.Sample(rampSampler, float2(u, 0.5)).rgb;
}
// Toon shading: Lambert's n.l quantized into three bands (thresholds 0.2 and 0.6)
vec3 toonShade(vec3 n, vec3 l, vec3 baseColor) {
  float nl = dot(normalize(n), normalize(l));
  float level = nl < 0.2 ? 0.3 : (nl < 0.6 ? 0.6 : 1.0);
  return baseColor * level;
}

// The same with an artist-painted ramp texture: u = (n.l + 1) / 2
vec3 toonRamp(sampler2D ramp, vec3 n, vec3 l, vec3 baseColor) {
  float u = dot(normalize(n), normalize(l)) * 0.5 + 0.5;
  return baseColor * texture(ramp, vec2(u, 0.5)).rgb;
}
// Toon shading: Lambert's n.l quantized into three bands (thresholds 0.2 and 0.6)
float3 toonShade(float3 n, float3 l, float3 baseColor) {
  float nl = dot(normalize(n), normalize(l));
  float level = nl < 0.2 ? 0.3 : (nl < 0.6 ? 0.6 : 1.0);
  return baseColor * level;
}

// The same with an artist-painted ramp texture: u = (n.l + 1) / 2
float3 toonRamp(Texture2D ramp, SamplerState rampSampler, float3 n, float3 l, float3 baseColor) {
  float u = dot(normalize(n), normalize(l)) * 0.5 + 0.5;
  return baseColor * ramp.Sample(rampSampler, float2(u, 0.5)).rgb;
}

ゲームのアニメ調レンダリング

セガの『ジェットセットラジオ』(2000年)は、セルシェーディングを使った最初のゲームとして良く挙げられ、今ではアニメ調の3Dは1つのジャンルです。
顔を単純な𝐧⋅𝐥で照らすと、アニメーターなら決して描かない形の影が出来るので、此の様なゲームは影の境目を絵で描く位置に持って来る法線の編集、キャラクターごとの光、常に影や決して影にならない部分を指定するテクスチャ、時には各ポーズを2〜3フレーム保つアニメーションを加えます。

16.10 輪郭線と線画

数本の線があれば形が分かります。
3次元の線画は4種類の辺を使います:

  • シルエットエッジ(輪郭エッジ):面が視点から背を向ける所。外側の輪郭線と、内側の輪郭(物体の一部が別の部分の前を通る所)を含みます。
  • クリースエッジ:形状の鋭い特徴で、2つの面の角度が大きい所(立方体の辺)。
  • 境界エッジ:開いたメッシュの縁、面が1つしか無い辺。
  • 材質や物体の境目:色や物体IDが変わる所。

シルエットの判定

11.3節では光源から見たシルエットエッジが必要でしたが、線画では視点から見た物が必要です。
メッシュでは、𝐯を辺から視点への方向として、2つの面の一方が表向きで、もう一方が裏向きの時、其の辺はシルエットエッジです:

(𝐧1⋅𝐯)⋅(𝐧2⋅𝐯)<0

10.1節の背面の判定を、辺の両側の面に当てはめた物です。
滑らかな曲面では、シルエットは丁度𝐧⋅𝐯=0の所です。

左:ピーナッツ形の断面でのシルエットの判定。表向きと裏向きの辺と4つのシルエット点。右:見える裏面が輪郭線になる背面法

左半分は計算した物です。
多角形の全ての辺を𝐧⋅𝐯の符号で分類し、符号が入れ替わる所がシルエット点です。
2つではなく4つあります。
上の凹みが内側の輪郭を作り、視点からは片方の膨らみがもう片方の前にある様に見えるのです。

計算例。
2つの面が点𝐩=(1,0,0)を通る辺で接し、法線は𝐧1=(0.8,0,0.6)と𝐧2=(0.8,0,−0.6)です(+x方向を向いた楔です)。

  • 視点が(0,0,10):𝐯=(−1,0,10)(符号だけが大事なので正規化は要りません)。𝐧1⋅𝐯=−0.8+6=5.2>0、𝐧2⋅𝐯=−0.8−6=−6.8<0で、シルエットエッジです。
  • 視点が(10,0,0):𝐯=(9,0,0)で、どちらの積も7.2>0です。両方の面が見えていて、シルエットではありません。

クリースエッジでしょうか?
法線の間の角度はarccos(𝐧1⋅𝐧2)=arccos(0.64−0.36)=arccos0.28≈73.7°です。
クリースのしきい値を60°(cos60°=0.5)にすると、0.28<0.5なのでそうです。
此の辺はどの視点からも描かれますが、シルエットかどうかは視点で変わります。

物体空間の輪郭線:背面法

毎フレームシルエットエッジを探すには、メッシュの辺の隣接情報と、全ての辺に対する計算が要ります。
ゲームで非常に良く使われる安価な技は、其れを丸ごと避けます。
背面法(英語ではinverted hull、「裏返したシェル」)です。

  1. メッシュを複製し、全ての頂点を法線に沿って外側へ小さな距離wだけ押し出します。大きくしたシェルです。
  2. シェルを輪郭線の色で、表面をカリングして描きます。つまり裏面だけが描かれます(普通の背面カリングの逆で、背面カリングの設定はOpenGLシリーズの第16章で行います)。
  3. 物体を普通に描きます。深度テストにより、物体はシルエットのすぐ外側の細い帯を除いてシェルを覆います。

図の右半分が其の結果です。
シェルの裏面は物体の後ろに隠れますが、シルエットより外にはみ出した所だけが見えます。
線の太さはワールド単位のwなので、距離と共に細くなります。
例: w=0.02 m、焦点距離1000ピクセルで、5 m先の物体の輪郭線は約1000⋅0.02/5=4ピクセル、20 m先では1ピクセルだけです。
エンジンは太さを一定に保つ為に、wを距離に比例させる(又はクリップ空間で押し出す)事が多いです。
輪郭の内側のクリースは描かず、法線が分かれた角では隙間が空き、閉じたメッシュが必要です。

画像空間の輪郭線:Gバッファのエッジ

もう1つの方法は、まずシーンをレンダリングし、画像の中で線を探す事です。
斎藤隆文と高橋時市郎(「Comprehensible Rendering of 3-D Shapes」、SIGGRAPH 1990)はGバッファを導入しました。
色の他に、画素ごとに深度、法線、物体IDを保存し、其れらのバッファに2次元のエッジ検出を掛けるのです。

  • 深度の跳びはシルエットを表します(遠い物の前にある物体)。
  • 法線の跳びはクリースを表します。
  • 物体IDの変化は物体の境目を表します。

深度バッファ、法線バッファ、其処から検出したエッジ

エッジ検出器は第15章の物を、色ではなく深度と法線に掛けます。
影の境目もエッジとして数えてしまう陰影付きの画像で探すより、ずっと信頼出来ます。
コストはシーンの複雑さに依りませんが、太さはピクセル単位で、細い物や遠い細部は見逃したりちらついたりします。
トゥーンの図の輪郭線は丁度此の方法で作りました。
此の様なポストプロセスのパスはOpenGLシリーズの第17章で書きます。

16.11 テクニカルイラストレーション:グーチシェーディング

テクニカルイラストレーターは陰影を中間調に留め、黒い輪郭線と白いハイライトが見える様にします。
フォンシェーディングは影の側が殆ど黒になるので、此の決まりを破ります。
エイミー・グーチ、ブルース・グーチ、ピーター・シャーリー、エレイン・コーエン(「A Non-Photorealistic Lighting Model for Automatic Technical Illustration」、SIGGRAPH 1998)は、暗から明への変化を寒色から暖色への変化に置き換えました。
此れがグーチシェーディングです。
光の方を向く面は暖かく(黄色っぽく)、背を向ける面は冷たく(青っぽく)なり、どちらもかなり明るいままです。
目は色相の変化を形として読み取ります。

モデルは2つの色を混ぜます。
其々、決まった色調に物体自身の色kdを少し加えた物です:

𝐤cool=(0,0,b)+α𝐤d,𝐤warm=(y,y,0)+β𝐤d
t=1+𝐧⋅𝐥2,I=t𝐤warm+(1−t)𝐤cool

ランバートと違い、𝐧⋅𝐥を0で切りません。
tは0(丁度背を向ける)から1(光に向く)まで動くので、光と反対の側にも陰影が残ります。
論文の図では、b=y=0.4、α=0.2、β=0.6の様な値が使われています。

計算例

赤い部品𝐤d=(0.8,0.1,0.1)、b=y=0.4、α=0.2、β=0.6とします:

𝐤cool=(0,0,0.4)+0.2(0.8,0.1,0.1)=(0.16,0.02,0.42)
𝐤warm=(0.4,0.4,0)+0.6(0.8,0.1,0.1)=(0.88,0.46,0.06)

𝐧⋅𝐥 t グーチI ランバートkdmax(𝐧⋅𝐥,0)
1 1 (0.88, 0.46, 0.06) (0.8, 0.1, 0.1)
0.6 0.8 (0.736, 0.372, 0.132) (0.48, 0.06, 0.06)
0 0.5 (0.52, 0.24, 0.24) (0, 0, 0)
−1 0 (0.16, 0.02, 0.42) (0, 0, 0)

例えば𝐧⋅𝐥=0.6では、0.8⋅(0.88,0.46,0.06)+0.2⋅(0.16,0.02,0.42)=(0.704+0.032,0.368+0.004,0.048+0.084)=(0.736,0.372,0.132)です。
ランバートでは物体の半分が黒になる所を、グーチシェーディングはオレンジから紫がかった青まで、ぐるりと変化し続けます。

シーンをフォンシェーディング、寒色から暖色へのグーチシェーディング、輪郭線付きのグーチシェーディングで描いた物

黒いシルエットとクリースの線(16.10節)と白いハイライトを加えると、多くのCADツールの「イラスト」表示になります。

16.12 ハッチング、点描、絵画調の様式

ストロークで作る濃淡

ペン画、版画、漫画はインクの濃さを変えられません。
濃淡はストロークの密度で作ります。
面積あたりの線(又は点)が多いほど暗くなります。
其の為、NPRのレンダラーはまず画素ごとのトーン(例えばランバートの明るさ)を計算し、其処にどれだけインクを置くかを決めます。

ハッチングは平行線を使います。
幅wの線を間隔dで引くと、インクの割合はw/dです。
5ピクセルごとに1ピクセルの線を引く層1つで、インクは20%です。
もっと暗いトーンには、別の方向のクロスハッチングの層を加えます。
図は3つの層を使っています。
暗さ(1−トーン)が0.25を超える所に斜めの線、0.5を超える所に逆の斜めの線、0.75を超える所に横線です。

点描は点を使います。
面積Aで暗さDを出すには、面積aの点が(重なりを無視して)約N=DA/a個要ります。
例: 暗さ0.3の20×20ピクセルの領域に、半径1ピクセル(a=π≈3.14 px²)の点で描くなら、0.3⋅400/3.14≈38個です。
図では、3×3ピクセルのマスごとにランダムな位置に点の候補を1つ置き、確率Dで残しています。
従って点の密度は暗さに従います。

同じシーンのランバートのトーン画像、3層のハッチング、点描

此の線は画面に固定されているので、動くと物体が固定された模様の後ろを滑っている様に見えます(「シャワードア効果」)。
実際のシステムはストロークを面に貼り付けます。リアルタイムハッチング(プラウン、ホッペ、ウェッブ、フィンケルシュタイン、SIGGRAPH 2001)の「トーナルアートマップ」は、暗さの順に並んだミップマップ付きのハッチングのテクスチャで、各テクスチャは明るい物のストロークを全て含みます。

絵画調、水彩、鉛筆のレンダリング

絵画調レンダリングはストロークベースで、位置、方向、長さ、色、質感を持つ沢山の筆のストロークで画像を組み立てます(ヘイバリの「Paint by Numbers」、SIGGRAPH 1990。大きさの異なる曲がったストロークを大きい物から置くハーツマンの方法、SIGGRAPH 1998)。
水彩のレンダリングは紙の上の顔料と水をシミュレーションします(カーティス達、SIGGRAPH 1997)。
顔料が溜まって暗くなる縁、粒状の質感、濡れた紙での滲みです。
鉛筆のレンダリングは、ストロークのテクスチャと、凹凸の山にだけ黒鉛が付く紙のテクスチャを組み合わせます。

画像ベースのフィルタとスタイル変換

どんな写真にも使えるNPRフィルタもあります。
桑原フィルタ(桑原道義達、1976年、元は医用画像の為)は、各画素の周りの重なり合う4つの正方形の領域を見て、分散が一番小さい領域の平均を出力します。
平らな領域は滑らかになり、エッジはシャープなままで(選ばれる領域はエッジを跨がないからです)、結果は平らな絵の具の塊の様に見えます。
バイラテラルフィルタ(第15章)を繰り返し掛け、明度を少数の段階に量子化して輪郭線を加えても、写真や動画を似たアニメ調に抽象化出来ます。
ニューラルスタイル変換(レオン・ガティス、アレクサンダー・エッカー、マティアス・ベトゲ、2015年)は、画像認識の為に学習した畳み込みニューラルネットワークを使います。
深い層の特徴が或る画像の「内容」に一致し、特徴の統計が別の画像(絵画)の「スタイル」に一致する画像を探すのです。
「〜風」の生成画像は、18.7節の知的財産権の問題も引き起こします。

検定のポイント

  • NPR:写実を目指さないレンダリング。目的はイラストレーションと伝達、スタイル、抽象化。3次元(モデルベース)の手法と2次元(画像ベース)の手法があります。
  • トゥーン(セル)シェーディングは、𝐧⋅𝐥をしきい値かランプテクスチャで少数の段階に量子化します。影の段階は暗い色で、黒ではありません。
  • メッシュのシルエットエッジ:隣り合う面の一方が表向き、もう一方が裏向き、(𝐧1⋅𝐯)(𝐧2⋅𝐯)<0。滑らかな曲面では𝐧⋅𝐯=0。クリースエッジは面の法線の間の角度で決まり、視点に依存しません。
  • 背面法:法線に沿って大きくした複製を、表面をカリングして描きます。画像空間の輪郭線:深度、法線、IDのバッファ(Gバッファ)でのエッジ検出。
  • グーチシェーディング:t=(1+𝐧⋅𝐥)/2で寒色から暖色へ混ぜ、中間調だけを使います。黒い線と白いハイライトのテクニカルイラストレーション用です。
  • ハッチングと点描は、ストロークや点の密度で濃淡を作ります。暗いほどストロークが多くなります。

16.13 可視化:データと目的

可視化はデータを画像に変え、数値の表では見えない構造、パターン、外れ値を人が見られる様にします。
2つの流れがあります:

  • 科学的可視化:測定やシミュレーションから得た、空間と時間の中に自然な位置を持つデータ。CTスキャン、車の周りの空気の流れ、エンジンブロックの中の温度。問いは主に「何処で何が起きているか」です。
  • 情報可視化:自然な形を持たない抽象的なデータ。地域ごとの売上、ソーシャルネットワーク、ファイルシステム、ゲノム。配置は設計者が選ばなければなりません。

科学的なデータは、各点に何が保存されているかで分類します:

  • スカラー場:点ごとに1つの数(温度、密度、CT値)。
  • ベクトル場:点ごとに方向と大きさ(速度、磁場)。
  • テンソル場:点ごとに行列(材料の応力。神経線維の方向を示す拡散MRIの拡散テンソル)。

又、点の並び方で分類します:

  • 構造格子:規則的な配列で、隣が添字で分かります(CTのボクセルや、翼の周りに巻き付けた格子)。
  • 非構造格子:任意の形のセル(四面体、六面体)と明示的な接続情報で、有限要素法のシミュレーションに典型的です。
  • 散在点:格子の無い測定(気象観測所)で、まず補間します。

流れは可視化パイプラインとして描かれる事が多いです。
データ→フィルタリング(選択、再標本化)→マッピング(形と色へ)→レンダリングです。

16.14 スカラー場:カラーマップ、等値線、等値面

カラーマップ

2次元のスカラー場を見せる一番直接的な方法は、各点を其の値で色付けする事です。
其の関数をカラーマップと言います(疑似カラー表示とも言います)。
3種類が使われます:

  • シーケンシャル:低い値から高い値へ、明度が一方向に変わります(密度、高さ)。
  • ダイバージング:中央の中間色で出会う2つの色相(基準より高い温度と低い温度、正と負の誤差)。
  • カテゴリカル:順序の無い異なる色相で、分類に使います。

量に対する一番大事な条件は第3章から来ます。
目は順序と大きさを主に明度から読み取るので、明度は値と共に一様に増え、値の等しい差は色の等しい差に見えるべきです。
CIELAB(3.4節)の様な知覚的に均等な空間で設計したカラーマップなら其れが出来ます。
此の様なマップを知覚的に均等なカラーマップと言います。

古典的なレインボーのマップ(青→シアン→緑→黄→赤。MATLABや古いMatplotlibの「jet」)は此の条件を満たしません:

滑らかなスカラー場をグレースケール、レインボーのjet、viridisのカラーマップで示した物。レインボーには偽の輪が見える

3つのカラーマップのCIELABの明度をデータの値に対して描いた物。グレースケールとviridisは一様に上がり、jetは上がって平らになり下がる

各マップの色の明度L∗を、第3章の式で計算しました:

値 0 0.25 0.5 0.625 0.75 1
jetのL∗ 13.0 54.7 90.5 95.2 71.2 25.5
viridisのL∗ 14.9 35.7 54.5 63.6 72.9 90.9

jetには3つの問題があります:

  • 単調でない:明度は0.64付近(黄色)で最大になり、又下がるので、一番高い値(暗い赤)は低い値(暗い青)と同じ位暗く、白黒では高い値と低い値が同じに見えます。
  • 不均等:0.37から0.64の間では明度が殆ど変わらず、他の所では急に変わり、急な色相の変化(シアン、黄色)が滑らかな場に境界の様に見える帯を作ります。図の輪が其れです。
  • 色覚異常:情報が赤と緑の区別に頼っており、3.2節の最も多い色覚異常に当たります。

可視化の研究者は長い間此れを警告して来ました(「Rainbow Color Map (Still) Considered Harmful」、ボーランドとテイラー、2007年)。
Matplotlib 2.0(2017年)は既定のカラーマップをjetからviridisに変えました。
明度は約15から91へ単調に上がり、白黒でも、殆どの色覚異常でも読めます。
分類には異なる色相で構いませんが、連続的な量には知覚的に順序のあるマップを使いましょう。

等値線と等値面

等値線は同じ値の点を結んだ線で、地図の等高線の様な物です。
一定の間隔で何本か描くと等値線図になります。
其の3次元版が等値面です。
どちらも9.3節のマーチングスクエア法とマーチングキューブ法で取り出します。
格子の角をしきい値で分類し、ケースを引き、辺に沿って交点を補間するのでした。
等値面は普通の三角形メッシュで、表示が速く計測もしやすいですが、1つの値を不透明な面として見せます。
他の値は消え、内側は全て隠れます。

16.15 ボリュームレンダリング

直接ボリュームレンダリング

狭い意味のボリュームレンダリング、つまり直接ボリュームレンダリング(DVR)は、面を作らず、ボリューム其の物を半透明で光る媒質として描きます。
1988年に、マーク・レヴォイ(「Display of Surfaces from Volume Data」、IEEE Computer Graphics and Applications)と、ロバート・ドレビン、ローレン・カーペンター、パット・ハンラハン(「Volume Rendering」、SIGGRAPH 1988)が導入しました。
一番一般的な方法は、ボリュームを通すレイキャスティング法です:

  1. 画素ごとに、視点からボリュームを通るレイを飛ばします。
  2. レイに沿って一定の間隔で進み、周りの8つのボクセルの間を3線型補間(第11章の双線型補間の3次元版)して、場を標本化します。
  3. 各サンプルを伝達関数で分類します。値を色と不透明度に写す関数です。
  4. (任意で)シェーディングします。場の勾配を法線として照明モデルを当てはめ、構造が立体的に見える様にします。
  5. レイに沿ったサンプルを画素の色に合成します。

伝達関数

何が見えるかは伝達関数が決めます。
消したい値には不透明度0を、大事な値には高い不透明度と目立つ色を与えます。
CTデータ(9.3節のハウンスフィールド値)なら、典型的には空気を透明に、皮膚と軟部組織を薄い赤みに、骨を不透明な白にします。
同じスキャンでも別の伝達関数なら、造影剤で満たされた血管だけを見せる事も出来ます。
其の設計が難しい所なので、ソフトはプリセットと曲線の編集画面を用意しています:

伝達関数:データの値に対する不透明度。殻の値では低く中心部では高い。下に色の帯

前から後ろへの合成

レイに沿った各サンプルi(近い物から順)は、伝達関数から色Ciと不透明度αiを持ちます。
10.12節のover演算子を、薄い層の重なりに当てはめた物です。
前から後ろへ進む時は、累積の色Cと不透明度Aを持ち、どちらも0から始めます:

C←C+(1−A)αiCi,A←A+(1−A)αi

(1−A)は、後ろからの光の内、手前の全てのサンプルを通り抜けて来る割合なので、新しいサンプルは残った分を通してしか寄与しません。
最後に、残った透明度で背景を加えます:Cpixel=C+(1−A)Cbg。
後ろから前への順では、背景から始めて普通のover演算子C←αiCi+(1−αi)Cを使います。
どちらも同じ結果になります。

計算例。
3つのサンプル、α1=0.3の赤、α2=0.5の緑、α3=0.6の青が、白い背景の前にあります:

サンプル後 重み(1−A)αi C A
1(赤) 1⋅0.3=0.3 (0.3, 0, 0) 0.3
2(緑) 0.7⋅0.5=0.35 (0.3, 0.35, 0) 0.65
3(青) 0.35⋅0.6=0.21 (0.3, 0.35, 0.21) 0.86

背景を加えると:(0.3,0.35,0.21)+0.14⋅(1,1,1)=(0.44,0.49,0.35)。
後ろから前へで確かめます。
白の上に青で0.6(0,0,1)+0.4(1,1,1)=(0.4,0.4,1)、其の上に緑で0.5(0,1,0)+0.5(0.4,0.4,1)=(0.2,0.7,0.5)、其の上に赤で0.3(1,0,0)+0.7(0.2,0.7,0.5)=(0.44,0.49,0.35)。
同じです。
青のサンプルの寄与の小ささに注目して下さい。
一番不透明なのに、手前のサンプルを通り抜けて来る光は35%しか残っていないのです。

前から後ろへには、実用上の大きな利点があります。
Aが1に近くなれば、後ろの物はもう画素を変えられないので、レイを止められます。
此の早期レイ終了で、密なボリュームでは仕事の大部分が省ける事が良くあります。

MIPと比較

最大値投影法(MIP)は伝達関数を全く必要としません。
各画素はレイに沿った最大の値を表示します。
造影剤で満たされた血管が一番明るい構造になるCTやMRの血管撮影で標準的ですが、奥行きの手がかりがありません。
手前の明るい構造と奥の明るい構造が同じに見えます。

2つの塊を中に持つ殻を、等値面、直接ボリュームレンダリング、MIPで描いた物

等値面 直接ボリュームレンダリング MIP
見せる物 1つの値を不透明な面として 多くの値を同時に、半透明で 各レイに沿った最大値
前処理 マーチングキューブ法でメッシュ 無し(伝達関数) 無し
毎フレーム 三角形の高速なラスタライズ 高価:画素ごとに多くのサンプル 画素ごとのサンプル、単純
奥行きの印象 良い(シェーディング) シェーディングすれば良い 乏しい
典型的な用途 骨の表面、計測、3Dプリント 医療と科学の探索 血管撮影

CTやMRIの医用可視化は、此の3つを2次元の断面(体軸、矢状、冠状)と組み合わせて使います。
放射・吸収モデルやGPUでの実装は第2部で扱い、GPUでのレイマーチングはGLSLシリーズの第14章に出て来ます。

16.16 ベクトル場:グリフ、流線、LIC

グリフ

直接的な方法は、標本点に小さな矢印、グリフを描く事です。
矢印の向きが場の向きを、長さや色が大きさを示します。
単純で其の点では正確ですが、矢印はすぐにごちゃごちゃし、其の間の流れは推測に任されます。

2つの渦を持つ流れを、矢印のグリフ、流線、線積分畳み込みで示した物

流線

流線は、至る所で場に接する曲線です。
定常な流れに放した質量の無い粒子は其れに沿って動きます。
数学的には、種の点𝐱0から始まる微分方程式

d𝐱ds=𝐯(𝐱)

の解です。
解くには14.2節の数値積分を使い、一番単純なのは陽的オイラー法です。
今の方向に少しだけ進みます:

𝐱k+1=𝐱k+h𝐯(𝐱k)

計算例。
回転する場𝐯(x,y)=(−y,x)の正確な流線は、原点を中心とする円です。
𝐩0=(1,0)からh=0.5で始めます:

  • 𝐯(𝐩0)=(0,1)なので、𝐩1=(1,0)+0.5(0,1)=(1,0.5)。
  • 𝐯(𝐩1)=(−0.5,1)なので、𝐩2=(1−0.25,0.5+0.5)=(0.75,1)。
  • 𝐯(𝐩2)=(−1,0.75)なので、𝐩3=(0.75−0.5,1+0.375)=(0.25,1.375)。

原点からの距離は1、1.118、1.25、1.398です。
半径1の円ではなく、オイラー法は外へ渦を巻いて行きます。
各歩は半径に垂直に進むので、半径は1歩ごとに1+h2=1.25≈1.118倍になり、12歩後には1.11812≈3.81です。

回転する場、其の正確な円形の流線、外へ渦を巻くオイラー法の歩、殆ど円の上にあるRK2の1歩

14.2節の中点法(RK2)ならずっと良くなります。半歩で(1,0.25)に着き、其処で𝐯=(−0.25,1)なので、𝐩1=(1,0)+0.5(−0.25,1)=(0.875,0.5)、半径は0.765625+0.25≈1.008で、誤差は11.8%ではなく0.8%です。
普通は4次のルンゲ=クッタ法(RK4)を使い、上の図の流線も其れで描いています。

種の点の選び方は其れ自体が設計の問題です(少な過ぎると特徴を見逃し、多過ぎるとごちゃごちゃします)。
時間と共に変わる流れでは、流線(或る瞬間で止めた場)、流跡線(1つの粒子が時間と共に辿る道)、流脈線(1点から放した全ての粒子、煙の筋の様な物)が異なりますが、定常な流れでは一致します。

線積分畳み込み

LIC(線積分畳み込み、ブライアン・カブラルとリース・リードム、SIGGRAPH 1993)は、場の全体を画素の細かさで一度に見せます。
白いノイズの画像から始めます。
各画素について、其処を通る流線を前後に少しだけ辿り、画素を其の流線の断片に沿ったノイズの平均にします。
同じ流線上の画素は殆ど同じノイズの値を平均するので似た明るさになり、隣の流線上の画素は違う明るさになります。
結果は流れに沿った細かい筆の跡の様に見えます。
上の図の3つ目のパネル(各方向に0.5ピクセルを20歩平均)が其れです。
LICは方向は見せますが、向き(前か後ろか)や速さは見せないので、普通は大きさのカラーマップと組み合わせます。

16.17 情報可視化

抽象的なデータには自然な位置が無いので、設計者がデータの属性を視覚変数に割り当てます。
ジャック・ベルタン(『Sémiologie graphique(図の記号学)』、1967年)は其れらを挙げました。
位置、大きさ、形、明度、色相、向き、きめです。
量には共通の軸に沿った位置と長さが一番正確に読み取れ、面積、角度、色はずっと劣ります(円グラフより棒グラフが良い理由です)。
分類には色相と形が、順序には明度と大きさが良く働きます。

良く使われる形式は、グラフ(棒、折れ線、散布図、ヒストグラム)、ネットワーク(ノードリンク図。バネと反発をシミュレーションする力指向の配置が多いです)、階層(木、そして長方形を値に比例する面積の入れ子の長方形で埋めるツリーマップ、ベン・シュナイダーマン、1992年)、平行座標の様な多次元の表示です。

計算例:スライス・アンド・ダイスのツリーマップ。
10×6の長方形(面積60)で、3つの項目A=30、B=18、C=12を見せ、BはB1=12とB2=6を含みます。
長方形を値に比例して縦に切ります。
幅は10⋅3060=5、10⋅1860=3、10⋅1260=2、高さは全て6です。
次に、B(幅3、高さ6)を横に切ります。
高さは6⋅1218=4と6⋅618=2です。
確かめると、3⋅4=12、3⋅2=6です。

計算例のスライス・アンド・ダイスのツリーマップ。A 30、B1 12、B2 6、C 12

スライス・アンド・ダイスは単純ですが、比べにくい細長い長方形を作ります(Cは2×6で、縦横比3)。
「スクウェアリファイド」の配置は、項目を並べ替えたり纏めたりして、長方形を正方形に近く保ちます。

ビジュアルアナリティクスは、対話的な可視化(シュナイダーマンの言葉で「まず概観、拡大と絞り込み、そして必要に応じて詳細」)と、統計や機械学習による自動的な分析を組み合わせます。
正直な目盛(棒は0から始める)と、長さや面積を歪める飾りの3Dを使わない事も仕事の内です。

検定のポイント

  • 科学的可視化:空間の位置を持つデータ(構造格子や非構造格子の上のスカラー場、ベクトル場、テンソル場)。情報可視化:抽象的なデータで、配置は設計者が選びます。
  • カラーマップ:明度は値と共に単調に増えるべきです。レインボーのマップは単調でも均等でもなく、偽の境界を作り、赤と緑の区別に頼っています。知覚的に均等なマップ(viridis)や、符号のあるデータにはダイバージングのマップを選びます。
  • 等値線と等値面(マーチングスクエア法とマーチングキューブ法)は、1つの値を線や不透明な面として見せます。直接ボリュームレンダリングは、伝達関数(値→色、不透明度)を通して多くの値を半透明で見せます。
  • 前から後ろへの合成:C←C+(1−A)αiCi、A←A+(1−A)αi。早期レイ終了が出来ます。over演算子で後ろから前へ合成しても同じ結果です。MIPは各レイに沿った最大値を見せ、奥行きの手がかりはありません。
  • 流線は場に接します。陽的オイラー法𝐱k+1=𝐱k+h𝐯(𝐱k)はずれて行き(回転では外へ渦を巻き)、ルンゲ=クッタ法の方が正確です。LICはノイズを流線に沿って塗り広げます。
  • ツリーマップは階層を、値に比例する面積の入れ子の長方形で見せます。

16.18 まとめ

  • コンピュテーショナルフォトグラフィは、複数の、又は符号化した撮影と計算を組み合わせます:HDR合成とトーンマッピング、スティッチング、深度合成、ライトフィールドのリフォーカス、逆畳み込み、バースト撮影(1/N)、フラッシュ/ノーフラッシュ、合成ボケ、超解像、リライティング、シームカービング。
  • NPRはイラストレーション、スタイル、抽象化を目指します:トゥーンシェーディングは𝐧⋅𝐥を量子化し、線はシルエット、クリース、境界から、物体空間(メッシュの辺、背面法)か画像空間(Gバッファのエッジ)で描きます。グーチシェーディングは寒色から暖色へ混ぜ、ハッチングと点描はストロークの密度で濃淡を作り、絵画調のフィルタやスタイル変換は画像に働きます。
  • 可視化は、スカラー場、ベクトル場、テンソル場(科学的)や抽象的なデータ(情報)を画像に写します:知覚的に順序のあるカラーマップ、等値面、伝達関数と合成による直接ボリュームレンダリング、MIP、グリフ、流線、LIC、グラフ、ネットワーク、ツリーマップ。

16.19 用語

English 日本語
computational photography コンピュテーショナルフォトグラフィ
dynamic range ダイナミックレンジ
exposure bracketing 露出ブラケット
HDR image ハイダイナミックレンジ画像(HDR画像)
response curve 応答曲線
tone mapping トーンマッピング
image stitching 画像のスティッチング
feature point 特徴点
homography ホモグラフィ
focus stacking 深度合成(フォーカススタッキング)
light field camera ライトフィールドカメラ
refocusing リフォーカス
point spread function (PSF) 点像分布関数(PSF)
deconvolution 逆畳み込み(デコンボリューション)
coded exposure 符号化露光
coded aperture 符号化開口
burst photography バースト撮影
super-resolution 超解像
image-based relighting イメージベーストリライティング
seam carving シームカービング
seam シーム
dynamic programming 動的計画法
non-photorealistic rendering (NPR) ノンフォトリアリスティックレンダリング(NPR)
toon shading, cel shading トゥーンシェーディング、セルシェーディング
ramp texture ランプテクスチャ
silhouette edge シルエットエッジ(輪郭エッジ)
crease edge クリースエッジ
inverted hull 背面法
G-buffer Gバッファ
Gooch shading グーチシェーディング
hatching ハッチング
stippling 点描
painterly rendering 絵画調レンダリング
Kuwahara filter 桑原フィルタ
visualization 可視化
scientific visualization 科学的可視化
information visualization 情報可視化
scalar field, vector field, tensor field スカラー場、ベクトル場、テンソル場
structured grid, unstructured grid 構造格子、非構造格子
color map カラーマップ
isoline (contour line) 等値線
isosurface 等値面
volume rendering ボリュームレンダリング
transfer function 伝達関数
early ray termination 早期レイ終了
maximum intensity projection (MIP) 最大値投影法(MIP)
glyph グリフ
streamline 流線
explicit Euler method 陽的オイラー法(前進オイラー法)
line integral convolution (LIC) 線積分畳み込み(LIC)
visual variables 視覚変数
treemap ツリーマップ
visual analytics ビジュアルアナリティクス

16.20 課題

  1. ★ 線型な応答のカメラで、t=1/60、1/250、1/1000 sの3枚を撮りました。或る画素の値はZ=255、200、52です。各露出の放射輝度の推定値と山形の重みを計算し、16.2節の対数の重み付き平均で合成して下さい。1枚目の露出から、放射輝度について何が分かりますか?
  2. ★★ 行が(4, 2, 5, 7)、(6, 3, 1, 8)、(2, 9, 5, 3)、(7, 1, 6, 5)のエネルギーの表で、表Mを埋めて一番安い縦のシームを探して下さい。其の列とコストを答え、一番安い真っ直ぐな列と比べて下さい。
  3. ★★ 𝐤d=(0.2,0.6,0.3)の緑の部品を𝐥=(0,0.6,0.8)から照らします。法線(0,0,1)、(0,−0.6,0.8)、(0,−1,0)について、16.9節のしきい値0.2と0.6でトゥーンの色を、b=y=0.4、α=0.2、β=0.6でグーチの色を計算して下さい。3つの点の内、ランバートのシェーディングで黒になるのはどれですか?
  4. ★★ 𝐯(x,y)=(1,x)の流線を(0,0)からx=1.5まで、h=0.5とh=0.25のオイラー法で辿って下さい。正確な流線はy=x2/2です。x=1.5での誤差を比べて下さい。歩幅を半分にすると誤差はどうなりますか?
  5. ★★★ 頭部のCTスキャンで、頭蓋骨を不透明に、皮膚を薄く見せる伝達関数(ハウンスフィールド値に対する不透明度と色)を描いて下さい。1つの等値面では何故両方を見せられないか、MIPなら何が見えるか、2次元の断面に何故レインボーのカラーマップが良くないかを説明して下さい。

選択問題

問1 ★ 次のうち、露出ブラケットからHDR画像を作る事について正しい物はどれか。

あ 各露出は、線型化した画素値を露出時間で割る事で放射輝度の推定値を与え、合成ではクリップした画素や暗過ぎる画素の重みを小さく、又は0にする。
い ブラケットの全ての露出は同じシャッター速度でなければならず、露出の間で変えるのは絞りだけである。
う 合成したHDR画像は、トーンマッピング無しで普通の8ビットのディスプレイに其のまま表示出来る。
え 全てのカメラは光に比例した画素値を保存するので、カメラの応答曲線は決して問題にならない。
お 画素ごとに独立に合成するので、露出の間に動く物体は何の問題も起こさない。

問2 ★ 次のうち、NPRの手法について正しい物はどれか。

あ トゥーンシェーディングは、鏡面反射のハイライトを画素ごとに評価してぼかし、滑らかなグラデーションを作る。
い グーチシェーディングでは、輪郭線と対比させる為に、物体の光と反対側を黒く描く。
う 閉じたメッシュの辺は、視点から見て2つの面の一方が表向き、もう一方が裏向きの時にシルエットエッジである。
え 背面法は、大きくしたメッシュの複製を、裏面をカリングして描く。
お ハッチングは、面が明るい所ほど多くのストロークを描く。

問3 ★★ 直接ボリュームレンダリングで、1本のレイが前から順に2つのサンプルに出会う。1つ目は強さ1.0、不透明度0.4、2つ目は強さ0.6、不透明度0.5である。前から後ろへの合成をC=0、A=0から始めた時(背景はまだ加えない)、累積の強さCと不透明度Aはどれか。

あ C=0.70、A=0.90
い C=0.76、A=0.70
う C=0.50、A=0.70
え C=0.40、A=0.40
お C=0.58、A=0.70

16.21 実践課題

方眼紙の上で削り、塗り、合成する。
方眼紙、定規、コンパス、色鉛筆、電卓を用意して下さい。
章の各部から1つずつ、小さな作業を手で行います。
シームカービングで画像の大きさを変え、球をトゥーンシェーディングし、ボリュームのレイを1本レンダリングします。

パートA:シームカービング。
5×6のグレースケール画像です(0=黒、9=白)。
明るい8と9が物体です:

行 列0 列1 列2 列3 列4 列5
0 1 1 3 8 9 1
1 2 1 2 8 9 1
2 1 3 2 8 9 2
3 1 3 3 8 9 3
4 3 1 1 1 3 1

  1. エネルギー。 簡略化したエネルギーe(i,j)=|I(i,j+1)−I(i,j−1)|(横の差だけ)を使い、左右の端では無い隣の代わりに其の画素自身を使います。5×6のエネルギーの表を書いて下さい。
  2. 動的計画法。 表Mを1行ずつ埋め、最後の行の一番小さい値から上に辿って一番安いシームを探して下さい。
  3. 削る。 各行からシームの画素を取り除き、新しい5×5の画像を書いて下さい。物体の画素に色を塗ります。
  4. 比べる。 真っ直ぐな各列のエネルギーの合計を計算し、画像を5列に縮小したら物体がどうなるかを答えて下さい。

パートB:球のトゥーンシェーディング。
半径R=5 cmの円を描きます。
正面から見た球です(平行投影、𝐯=(0,0,1))。
円板の点(x,y)の法線は𝐧=(xR,yR,1−x2+y2R2)です。
光は𝐥=(0.6,0,0.8)から来ます。

  1. 横の直径に沿って。 x=−5,−4,…,5 cm(つまりx/R=−1,−0.8,…,1)、y=0で、𝐧⋅𝐥、ランバートの値max(𝐧⋅𝐥,0)、16.9節のしきい値0.2と0.6でのトゥーンの段階を計算して下さい。段階の境目が直径を横切る所に印を付けます。
  2. 段階の境目。 𝐧⋅𝐥=cの点は、中心(0.6cR,0)、縦の半径1−c2R、横の半径0.81−c2Rの楕円に投影されます。c=0.6で描いて下さい。c=0.2では左の部分だけが見える側にあるので、直径から輪郭上の(0.333R,±0.943R)まで描きます。3つの段階に色を塗ります。
  3. シルエット。 描いた図で𝐧⋅𝐯=0なのは何処ですか? 其の線を太い黒鉛筆でなぞって下さい。

パートC:ボリュームを通る1本のレイ。
レイが前から順に、値0.1、0.45、0.8、0.5の4つのサンプルに出会います。
伝達関数は、0.3未満の値に強さ0と不透明度0を、0.3〜0.6の値に強さ0.5と不透明度0.2を、0.6より上に強さ1.0と不透明度0.7を与えます。
背景は黒です。

  1. 前から後ろへ。 16.15節の様な表を作り、4つのサンプルを合成して下さい。次に、A≥0.75になった時点でレイを止め(早期レイ終了)、結果がどれだけ変わるかを書き留めて下さい。
  2. 後ろから前へ。 黒い背景から始めて、同じサンプルをover演算子で合成して下さい。
  3. 他の描き方。 此のレイでMIPは何を見せますか? 値0.6の等値面は、レイに沿って何処(サンプル単位、線型補間)で当たりますか?

自分で確認する方法:

  • パートA:シームは各行に丁度1画素で、行ごとに高々1列しか動きません。コストは3で、一番安い真っ直ぐな列(7)の半分未満です。削った画像でも、物体は2列の幅を全て保っています。
  • パートB:𝐧⋅𝐥は、𝐧=𝐥となるx=0.6R=3 cmで最大値1になります。直径に沿った境目はx=−0.28R(c=0.6)とx≈−0.664R(c=0.2)にあり、c=0.6の楕円は(R,0)で輪郭に接します。シルエットは円其の物です。
  • パートC:Aは決して減らず、1を超えません。前から後ろへと後ろから前への結果は一致し(0.684)、早期レイ終了では画素が少し暗くなります(0.66)。MIPは0.8を見せ、等値面は2つ目と3つ目のサンプルの間にあります。


コメント(0)

まだコメントはありません。