VideoProcessor(以下VP)のAPIには描画した画像に対して色変換を行えるものがあります。
とはいえドキュメントを読んでもよく分からないところだらけなのですが、おそらくこうなんじゃないかと分かった(つもり)の部分だけでも書いておこうと思います。
色のチャンネル毎に256個の値のテーブルで3チャンネル分、つまり256 x 3 = 768 個の値(0.0~1.0)を用意して、描画済みの色の値(0~255)をチャンネル毎のインデックスとしてこの配列を参照し変換を行うようです。
各チャンネルは現在のcolorspaceに対応したものを使用(RGBAならR・G・B)。
テーブル内の色の配置は、R0, R1, ... R255, G0, G1, ... G255, B0, B1, ... B255 という感じでしょうか。
下図の例はRGBで色を変えないテーブルを作って使用しているものです。

各色の値の値域は[0, 1]なので、RGBテーブルにvをセットしているところをそれぞれ1-vにしてやると、色が反転します。

これが、

こうなる感じ。
使うAPIは gfx_evalrect() で、これには各画素単位(厳密にはピクセルフォーマットで扱える単位でのアクセスになる)で処理するスクリプトテキストを渡すというものになっています。
なんとなく雰囲気はピクセルシェーダーみたいな感じですね。
ただし隣接ピクセルへのアクセス方法がないようで、シーケンシャルに前に処理したピクセルを保存しておくことで代用するしかないようです(つまり現在の注目位置より先にあるピクセルは読みだせない)。
また、ドキュメントを見るとマルチスレッドで動きそうな切り替えフラグがあるのですが、切り替えても何も変わらないので動作はシングルスレッド固定の模様。
さらに、自分の環境だとcolorspace='RGBA'にして処理しようとすると、動画の大きさによってはかなりCPUを食ってしまい、プレビュー再生時に処理が間に合わないくらいになってしまいました。YV12→RGBA→YV12の全ピクセル変換が入ってしまうからなんですかね? ということで、このAPIを使う時はYV12のまま処理するのがいいかと思います。
(ちなみに動画ファイルにレンダリングすれば、処理負荷ぶっちぎっていようが問題なく画像処理された結果が出るようなので、プレビュー時は諦めてOFFにしておいてレンダリングにだけ使うという逃げ方もなくはないです。面倒ですが。)
YV12の際は、色の保持が2x2ピクセルのブロック単位となるため、1回のスクリプト処理ではこの4ピクセルを処理する必要があります。画像の情報は4ピクセル分の輝度値(y1, y2, y3, y4)と色(u, v)に現在の値が渡されてくるので、これらを新しい値で書き替えてやれば実際の色が変わるという仕組みです。
とりあえず簡単な使い方を示したコード例がこちら。
ピクセル毎に実行するスクリプトが code 変数(文字列)です。
※このcodeという名前である必要はありません

実行結果がこんな感じ
(やってること:1ピクセル行毎に黒線、グレースケール)

あまり解説することもないのですが、y1~y4、u,vのどの値を変えるとどうなるか見てみると分かりやすそうなので、後で自分で実際に簡単な処理を作ってみると理解が深まるのではないかと思います。ここではいくつか例を示しておきますね。
例えば、y1=y2=0かy3=y4=0 にしてやると、1行毎に黒い線が入ります。

同様に y1=y3=0 にすると縦線が入ります。

y1=y4=0 にすると網状に。

色相についても例えば u=v=128 固定にしてやるとグレースケールに変えるといったこともできます。

このようにYV12であれば2x2の4ピクセルにアクセスできるので、例えば簡単なフィルタを実装することが可能になってきます。VPのプリセットにある[Edge detection (vertical)]がまさしくこの用途のいいサンプルプログラムになっているので、参考にしてみて下さい。

↑ Edge detection (vertical) 適用例
今回はピクセル単位で色をコントロールする方法について紹介しました。
gfx_evalrect() はピクセル単位でスクリプトを実行するため、かなり重くなる傾向があるので多用は禁物ですが、思い通りのことをやるための最終手段として覚えておくといいかもしれません。
まぁピクセル単位にスクリプトってのがそもそも処理速度的に無茶なんで、そのうちVPがOpenFXとかに対応になったらいいなー。
とはいえドキュメントを読んでもよく分からないところだらけなのですが、おそらくこうなんじゃないかと分かった(つもり)の部分だけでも書いておこうと思います。
チャンネルカラーテーブルによる色変換
使用するAPIは gfx_procrect() です。色のチャンネル毎に256個の値のテーブルで3チャンネル分、つまり256 x 3 = 768 個の値(0.0~1.0)を用意して、描画済みの色の値(0~255)をチャンネル毎のインデックスとしてこの配列を参照し変換を行うようです。
各チャンネルは現在のcolorspaceに対応したものを使用(RGBAならR・G・B)。
テーブル内の色の配置は、R0, R1, ... R255, G0, G1, ... G255, B0, B1, ... B255 という感じでしょうか。
下図の例はRGBで色を変えないテーブルを作って使用しているものです。

各色の値の値域は[0, 1]なので、RGBテーブルにvをセットしているところをそれぞれ1-vにしてやると、色が反転します。

これが、

こうなる感じ。
スクリプト適用による色変換
テーブルによる色変換では出来ないような色の変化、例えばフィルタなどの画像処理的なことをやりたい場合もあるかと思いますが、これもある程度は出来るようになっています。使うAPIは gfx_evalrect() で、これには各画素単位(厳密にはピクセルフォーマットで扱える単位でのアクセスになる)で処理するスクリプトテキストを渡すというものになっています。
なんとなく雰囲気はピクセルシェーダーみたいな感じですね。
ただし隣接ピクセルへのアクセス方法がないようで、シーケンシャルに前に処理したピクセルを保存しておくことで代用するしかないようです(つまり現在の注目位置より先にあるピクセルは読みだせない)。
また、ドキュメントを見るとマルチスレッドで動きそうな切り替えフラグがあるのですが、切り替えても何も変わらないので動作はシングルスレッド固定の模様。
さらに、自分の環境だとcolorspace='RGBA'にして処理しようとすると、動画の大きさによってはかなりCPUを食ってしまい、プレビュー再生時に処理が間に合わないくらいになってしまいました。YV12→RGBA→YV12の全ピクセル変換が入ってしまうからなんですかね? ということで、このAPIを使う時はYV12のまま処理するのがいいかと思います。
(ちなみに動画ファイルにレンダリングすれば、処理負荷ぶっちぎっていようが問題なく画像処理された結果が出るようなので、プレビュー時は諦めてOFFにしておいてレンダリングにだけ使うという逃げ方もなくはないです。面倒ですが。)
YV12の際は、色の保持が2x2ピクセルのブロック単位となるため、1回のスクリプト処理ではこの4ピクセルを処理する必要があります。画像の情報は4ピクセル分の輝度値(y1, y2, y3, y4)と色(u, v)に現在の値が渡されてくるので、これらを新しい値で書き替えてやれば実際の色が変わるという仕組みです。
とりあえず簡単な使い方を示したコード例がこちら。
ピクセル毎に実行するスクリプトが code 変数(文字列)です。
※このcodeという名前である必要はありません

実行結果がこんな感じ
(やってること:1ピクセル行毎に黒線、グレースケール)

あまり解説することもないのですが、y1~y4、u,vのどの値を変えるとどうなるか見てみると分かりやすそうなので、後で自分で実際に簡単な処理を作ってみると理解が深まるのではないかと思います。ここではいくつか例を示しておきますね。
例えば、y1=y2=0かy3=y4=0 にしてやると、1行毎に黒い線が入ります。

同様に y1=y3=0 にすると縦線が入ります。

y1=y4=0 にすると網状に。

色相についても例えば u=v=128 固定にしてやるとグレースケールに変えるといったこともできます。

このようにYV12であれば2x2の4ピクセルにアクセスできるので、例えば簡単なフィルタを実装することが可能になってきます。VPのプリセットにある[Edge detection (vertical)]がまさしくこの用途のいいサンプルプログラムになっているので、参考にしてみて下さい。

↑ Edge detection (vertical) 適用例
今回はピクセル単位で色をコントロールする方法について紹介しました。
gfx_evalrect() はピクセル単位でスクリプトを実行するため、かなり重くなる傾向があるので多用は禁物ですが、思い通りのことをやるための最終手段として覚えておくといいかもしれません。
まぁピクセル単位にスクリプトってのがそもそも処理速度的に無茶なんで、そのうちVPがOpenFXとかに対応になったらいいなー。
このブログにコメントするにはログインが必要です。
さんログアウト
この記事には許可ユーザしかコメントができません。