画像とFieldを処理する#
CNLでは、画像処理も型付きの関数として書きます。画像、パラメータ、自作関数を組み合わせ、選んだ出力に必要な処理を評価します。
画像の関数を使う#
function soften(source: Image<Color,2>): Image<Color,2> {
const radius = vec2(2, 2);
return std.filter.gaussian_blur_auto(source, radius);
}
function main(source: Image<Color,2>): Image<Color,2> {
return soften(source);
}
sourceは入力画像です。ここでは標準のGaussian Blurを呼びます。二軸の半径には、現在の画像関数の署名で使う座標用vec2を渡しています。公開Value型のVectorは三成分なので、両者を同じ意味で扱いません。
この関数を型検査できることと、特定GPUでの処理時間が保証されることは別です。実行できない型・サイズ・処理の組み合わせは、理由を示して停止します。CPUへの無断の切り替えは行いません。
自分でフィルターの中身を書く#
標準ノードを呼ぶだけでなく、係数そのものをCNLで定義できます。次の例は、中心を強調する3×3のフィルターです。
function main(source: Image<Color,2>): Image<Color,2> {
const weights = kernel([3, 3], [-1, -1], [
0, -1, 0,
-1, 5, -1,
0, -1, 0
]);
return convolve(source, weights);
}
最初の配列はサイズ、次は係数の開始オフセットです。係数はX方向から順に並べます。現在のこのConvolveプロファイルは、範囲外をゼロとしてRGBA全成分を処理します。境界で重みを自動的に再正規化しません。Alphaを元のまま残したい処理は、その扱いも明示して組み立てます。
Kernelは有限の係数データです。外部のshaderソースや、新しい公開Value型を意味しません。係数を変えることで、新しい線形フィルターを本体のC++を変更せずに記述できます。適応的な近傍処理や周波数処理まで含めた書きやすさは、引き続き言語の受入対象です。
座標を明示する#
値がpxなのか相対単位なのか、画像の座標なのかAEのコンポ座標なのかを区別します。位置、移動量、サイズも異なる役割です。AEから受け取った位置を、そのまま別の画像の位置として解釈しません。
基準となる解像度や変換は、実行中のエフェクトインスタンスと対象データから決めます。同じWorkspaceを複数レイヤーで使っても、Workspace全体に一つの解像度を固定しません。詳細は座標の基準と単位を参照してください。
サンプリングと有限データ#
座標に応じた値を定義すること、別の場所の値をsampleすること、有限のGrid/Imageとして保存することは異なる操作です。フィルターやFFTなどが必要とする有限領域と、境界のサンプリング方法を明確にします。
Videoは時間によって画像が変わるFieldです。現在フレームをImageとして処理する際は、時刻の依存関係を保って接続します。Videoの画像処理を参照してください。型をImageに偽装したり、キャッシュ済みフレームだけAttributeを落としたりしないことが契約です。
Convolution、FFT/IFFT、独自の画像アルゴリズムもCNLの対象です。既存のノードを呼ぶだけで言語の完成とはしません。自作アルゴリズム・全型・全rank・実行バックエンドの残りの範囲は対応状況に分けて記録します。