小嶋秀樹 | 研究室
日本語 | English
Pd で画像処理

Pd + GEM は,3次元グラフィクスを生成するだけでなく,静止画・動画(カメラやファイルから読み込まれた画像)に対するさまざまな画像処理 (image processing) を行なうことができます.たとえば,描画オブジェクトの表面に画像を貼り付けること(テクスチャマッピング)にはじまり,色やサイズの変換や,複数の画像を重ね合わせること,シルエット化や輪郭抽出のためのフィルタを適用することなどが可能です.

ここでは Pd-extended に標準で組み込まれている Pix モジュール(名前が pix_ で始まるオブジェクト群)を中心に,Pd による画像処理の基本を解説します.また,業界標準の画像処理ライブラリである OpenCV の諸機能(顔検出など)を利用する方法についても解説します.

Pix モジュールに含まれるオブジェクトの一覧は,"Ye olde Gem Manual" をご覧ください.個々のオブジェクトの詳しい情報は,そのオブジェクトを(何も接続線を出し入れせずに)生成し,右クリックして Help を参照してください.

画像の取得とテクスチャマッピング

画像を取り込み,加工し,それを描画オブジェクトの表面に貼り付けること,すなわちテクスチャマッピング (texture mapping) することで,GEM(3次元グラフィクス)の世界に画像を表示することができます.ここでは,まず静止画の扱いについて説明し,つぎに動画(ファイルから・カメラから)の扱いについて説明します.

【静止画の取り込みと表示】

ファイルから静止画を読み込み,それを描画オブジェクトの表面に貼り付けます.Mac の場合,静止画なら png, jpeg, tiff, pdf, ai などの形式を読み込めます.Windows でも jpeg や png などを読み込めるでしょう.下の例では,静止画 photo.jpg を正方形 [square] 上に貼り付けています.

[open photo.jpg[ を押すと,[pix_image] によって photo.jpg から画像データが読み込まれます.[pix_image photo.jpg] のように,引数としてファイル名(あるいはパス名)を与えることもできます.[pix_image] は,描画コンテクストが入力されるたびに,既に読み込んである画像データをその描画コンテクストに書き込みます.その下流にある [pix_texture] は,描画コンテクストから取り出した画像データを,描画オブジェクトに貼り付けられるテクスチャに変換します.このテクスチャを含んだ描画コンテクストは,座標変換などを適用された後,描画オブジェクトに送り込まれ,最終的に描画オブジェクトの表面にテクスチャがマッッピングされます.([pix_texture] の置き場所は,描画コンテクストの流れに現われる [pix_something] の最後にするとよいでしょう.)

[square] のような平面だけでなく,立体の表面にもテクスチャマッピングが可能です.下の例では,立方体 [cube] に1枚の静止画を貼り付けています.このように6面に同じ画像が貼り付けられます.([rotateXYZ] に数値ボックスを接続して,立体を回転させてみてください.)

画像ファイルによっては,png や jpeg 形式であるにもかかわらず,Pd でうまく表示できないことがまれにあります.この場合は,画像編集アプリなどで一度そのファイルを開き,新しく保存しなおすことで,解決できる場合があります.試してみてください.

【球面・円錐面・円筒面への貼り付け】

球面 [sphere],円錐面 [cone],円筒面 [cylinder] に投影した場合,外側から見ると左右反転した画像がマッピングされるようです.おそらくバグと思われますが,そういう仕様なのかもしれません.

この「反転」問題に対処する方法を紹介します.まず [sphere] については,テクスチャマッピングのみ逆転しているので,[pix_image] の後に [pix_flip] を入れ,メッセージ horizontal を第1入力端子に与えることで,画像を左右反転させるようにします.

また,[cone], [cylinder] については,照明に対する応答も反転しているので,これら描画オブジェクトの直前に [scale -1 -1 -1] を入れておきます.下図は,これら補正を適用し,また照明を(右上の手前から)当てたときの様子です.

このように,照明機能をオンにすることで,テクスチャを貼り付けた描画オブジェクトに自然な陰影を与えることができます.

【静止画列(ぱらぱらマンガ)の取り込みと表示】

何枚かの静止画を読み込み,それを逐次的に表示することで,ぱらぱらマンガをつくることができます.複数の静止画を格納するのは [pix_multiimage] というオブジェクトです.ここに open で始まるメッセージ(第1入力端子)あるいは引数として,アステリスク "*" を含んだファイル名(パス名)と正整数 N を与えると,ファイル名の "*" を 0, 1, ..., N で置き換えて,N+1 個の画像ファイルが読み込まれます.第2入力端子に正整数(0, 1, ..., N)を入力すると,対応する画像データが描画コンテクストに書き出されるようになります.

上の例では,[metro] で駆動される [count 5] から,0, 1, 2, 3, 4, 0, 1, 2, ... の数列を [pix_multiimage] に与えることで,あらかじめ読み込ませておいた5枚の静止画(keepon0.png, ..., keepon4.png)を順次出力させ,長方形 [rectangle] に貼り付けています.

【動画の取り込みと表示】

Pix モジュールは,静止画やその系列だけでなく,動画(いわゆるムービー)も扱うこともできます.Mac ならば .mov, .mpg などのファイル形式,Windows では .wmv, .avi などのファイル形式をもつ動画を扱うことができます.ただし,音声トラックは再生されません.

[pix_film] は動画ファイルを扱うオブジェクトです.引数または {open test.mov} あるいは {open test.avi} のようなメッセージで,動画ファイルを指定し,読み込ませます.あるいは後続する例のように,[openpanel] によってダイアログ(別ウィンドウ)でファイルを選択させることも可能です.動画をスタートするには,[pix_film] に {auto 1} を送ります.ストップするには {auto 0} を送ります.下の例では,正方形と長方形を「画面」として,同じ動画をテクスチャマッピングしています.このように描画コンテクストが枝分かれしても,上流でセットした画像データは,それぞれの支流にも流れていきます.

{auto 1} で通常再生するだけでなく,[pix_film] の第2入力端子にフレーム番号を入れることで,任意のフレームを再生できます.たとえば左下のパッチで,[metro] の周期を変えることで,スローモーションや早送りなどが可能です.また右下のパッチのように,カウントダウンさせることで逆転再生することもできます.

カメラからのライブ画像の取得も可能です.カメラ(あるいは外部のビデオ機器)を扱うオブジェクトが [pix_video] です.外部接続のカメラがうまく認識されないときは [dialog[ を押して,設定をいじってみてください.

[pix_video] が出力する画像データは,YUV (YCrCb) 形式となる場合が多いようです.一部の画像処理オブジェクト(とくに OpenCV 関係)は YUV 形式を受け付けないようなので,その場合は [pix_rgba] で RGB 形式に変換してから,画像処理オブジェクトに入力してください.

基本的な画像処理
【色の変換】

グレースケール化や色反転(ネガ),2値化などはもちろん,より一般的な行列計算による色変換も可能です.下の例では,元画像(カラー)から,[pix_grey] によってグレースケール画像を,また [pix_invert] によって色反転画像を生成しています.[separator] によって座標変換の作用範囲を切り分けていますが,それと同じように,[pix_separator] によって画像処理の適用範囲を切り分けています

[pix_duotone] は画像を2値化するオブジェクトです.第2入力端子に与えられたリスト {R G B} によって,色空間を C1 = {(r, g, b) | rR  and  gG  and  b ≥ B} とその補集合である C2 = {(r, g, b) | r < R  or  g < G  or  b < B} に分割し,それぞれを第3および第4入力端子に(RGB 形式で)与えた色 (r1, g1, b1), (r2, g2, b2) に置き換えます.下の例では,(0.7, 0.7, 0.7) を閾値として,RGB の各チャネルがこの閾値を超えるピクセルを赤 (1, 0, 0) に,それ以外のピクセルを藍色 (0, 0, 0.3) に変換しています.(これらは RGB 形式を想定しているため,[pix_rgba] によって [pix_film] の出力を RGB 形式に変換しています.)

画面上の各ピクセルについて,元の色 c = (r, g, b) を新しい色 c' = (r', g', b') に線形変換することもできます.これには,3×3 の変換行列 T を与えた [pix_colormatrix] が使えます.全ピクセルについて,c' = Tc のように色変換されます.変換行列 T は,各行を1つにまとめた 9 個の数値からなるリストによって,[pix_colormatrix] に与えます.下の例では,左側には単位行列による恒等変換,中央には R の成分だけを抽出する変換,右側にはグレースケールへの変換を行なっています.(これらは RGB 形式を想定しているため,[pix_rgba] によってカメラ画像を RGB 形式に変換しています.)

【部分画像の切り出し】

画像のある部分を切り出すには [pix_crop] が便利です.元画像から幅 W,高さ H(単位はピクセル)の部分画像を,元画像の左下を原点とするオフセット位置 X, Y から(ここが部分画像の左下と一致するように)切り出し,そのサイズ(W × H)をもつ画像データを出力します.

背景から前景を切り出すことも可能です.[pix_background] は,reset メッセージを受け取ったときの入力画像を「背景」として記録します.その後の入力画像について,この「背景」との差分を計算し,差分が一定の閾値を超えたピクセルのみを透過させ,他のピクセルは黒 (0, 0, 0) とします.閾値は 0〜1 の数値で第2入力端子に与えます.(カメラの多くは自動露光調整をするため,場合によっては背景の明るさが変化してしまい,うまく前景を切り出せない場合もあるようです.)

【画像の演算・フィルタリング】

Pix モジュールには,画像間の演算やフィルタリングのためのオブジェクトが用意されています.たとえば [pix_mix] は,第1入力端子と第2入力端子に与えた2つの画像(同じサイズをもつ)P1P2 を与えられた比率でミックスします.比率 K は 0〜1 の数値で第3入力端子に与えます.出力される画像は,(1 − K) P1 + K P2 のようになります.

この他に,汎用演算オブジェクトとして [pix_add], [pix_subtract], [pix_multiply] などが用意されています.いずれもピクセル単位で各成分を加算・減算・乗算し,その結果が 0 以下であれば 0 に,1 以上であれば 1 に制限します.また,[pix_diff] は差の絶対値を計算します.

このほかにも,汎用フィルタとして [pix_convolve][pix_tIIR] があります.前者は空間フィルタといい,カーネルとよばれる小さなグレースケール画像(たとえば 3 × 3 ピクセル)を元画像上で走査させ,その各位置で元画像とカーネルをピクセルごとに乗算し,その合計値を出力画像の各位置でのピクセル値とします.たとえば画像をぼかしたり,あるいはエッジを強調したり,さまざまな操作が可能です.(下図はエッジ抽出の例です.)

一方,[pix_tIIR]時間フィルタといい,元画像の各ピクセルについて,過去の履歴から出力画像のピクセル値を決定します.尾を引くような動きを与えるなど,さまざまな効果をつくりだすことができます.(詳しくは "IIR", "FIR" などのキーワードで検索してみてください.)

これら空間フィルタ・時間フィルタの詳細はこのチュートリアルの範囲を超えるので割愛させていただきますが,多くの場合,後述する OpenCV を利用することでも,同じ効果が得られるでしょう.

【動きの検出】

動画像から動きのある部分を検出することも可能です.動きの検出には,フレーム差分を計算する [pix_movement] を利用し,得られた差分画像の重心を求める [pix_blob] によってその中心位置を求めるとよいでしょう.下の例では,ウインクを検出し,その位置に正方形を描画しています.

[pix_movement] は,現在の画像と1フレーム前の画像の差分を計算し,ピクセルごとの差分値を A 成分(アルファチャネル)に書き込みます.ただし,引数として与えられた閾値(0〜1)を差分値が超えない場合,0 を差分値として書き込みます.[pix_blob] は,画像の重心を求めるオブジェクトです.デフォルトではグレースケール画像における重心を計算しますが,第2入力端子に計算対象となる成分(R, G, B, A)を 1〜4 の番号で指定することで,特定の成分のみの重心を計算することができます.下の例では,A 成分を計算対象としています.得られた重心の X 座標値・Y 座標値は,画面の左端・下端を 0,右端・上端を 1 とする 0〜1 の連続値として,第2・第3出力端子から出力されます.(第4出力端子からは動き領域のサイズが出力されます.)

【画像のディレイ】

動画像にディレイ(遅れ)を与えるには [pix_delay] を使います.たとえば [pix_delay 100] とすることで,100 フレーム分の画像バッファ列が生成されます.[pix_delay] に画像が入力されると,この画像バッファ列に順次送り込まれます.そして,第2入力端子から与えたインデックス位置にある画像バッファから,出力画像が取り出されます.たとえば 40 を与えた場合,デフォルト(毎秒 20 フレーム)では約 2 秒前の画像が取り出されることになります.

【画像の書き出し】

Pix モジュールでは,動画を直接書き出すことはできませんが,静止画のスナップショットを書き出すことができます.別のアプリケーション(Mac であれば QuickTime Pro など)を使って,この静止画列を動画にまとめることができます.

図:pd-pix-write

上のパッチでは,カメラ画像を [cube] に投影し,GEM ウィンドウの表示内容を [pix_write] によって JPEG 画像の列として書き出しています.まず {file  ベース名  クオリティ値} というメッセージで動作環境を設定します.実際に書き出される静止画ファイルは "ベース名00023.jpg" のようなファイル名をもちます.00023 は録画開始を 00000 とするフレーム番号です.どこか特定のフォルダの中にベース名を指定するといでしょう.一方,クオリティ値は JPEG の画質を設定し,値が大きいほど高画質となります.(クオリティ値が 0 の場合は TIFF 形式(.tiff)で保存します.

これら設定が済んだら録画準備完了です,[toggle] をオンにして {auto 1} を送ると録画開始,オフにして {auto 0} を送ると録画終了です.同じベース名をもつ多数の静止画ファイルが生成されたはずです.また,{auto 1/0} を使わずに,[pix_write] の第1入力端子に bang を送るたびに静止画のスナップショットを書き出すこともできます.

書き出された静止画列を1つの動画ファイルにまとめるには,たとえば Mac 上であれば,QuickTime Pro を使うとよいでしょう.メニューバーから File > Open Image Sequance... を選択し,フレーム番号 "00000" をもつファイルを開きます.すると,すべての静止画ファイルが読み込まれ,動画として再生・保存などができるようになります.

図:pd-pix-write=win

QuickTime Pro は有料のソフトウェアです.無料で使えるソフトウェアとしては,Hand Brake が静止画列から動画への変換に使えます.Hand Brake は Mac, Linux, Windows で利用できます.Hand Brake を起動したら,File > Open Source... のダイアログを開き,静止画列が入ったフォルダを選択してください.

OpenCV の利用

OpenCV は業界標準の画像処理ライブラリです.各種の空間フィルタ,時間フィルタ,ラベリング,顔検出など,さまざまな機能を比較的簡単に利用することができます.ここでは OpenCV の諸機能を利用するパッケージ pix_opencv を,Mac にインストールし利用する方法について解説します.(Linux でも利用できます.)

【インストールと使用方法】

インストール方法 (英語)」に従ってインストールしてください.注意すべきポイントは,Pd-extended のバージョンにあった pix_opencv を選択することです.Pd ウィンドウのコンソールをスクロールさせると,その先頭付近に Pd-extended のバージョン情報(たとえば 0.42.5)が見えるはずです.インストールを済ませ,Pd-extended を起動すれば,あとは通常の Pix モジュールの各オブジェクトと同じように,pix_opencv の各オブジェクトを生成・利用することができます.

オブジェクト解説 (英語)」に,pix_opencv で利用できる機能が解説されています.各オブジェクトについて,入力端子ごとに受け付けるメッセージとその意味,出力端子ごとに出力されるメッセージとその意味が説明されています.たとえば,"second inlet : ..." のような記述で始まる項目は,第2入力端子へのメッセージについて,また,"mode : ..." のような記述で始まる項目は,第1入力端子(描画コンテクストが入力される端子)に {mode 0} のように入力するメッセージについての解説です.(ただし,この形式が統一されていない部分もあるようです.) pix_opencv のオブジェクトを利用する際は,まずそのオブジェクトをパッチに生成し,右クリックして Help を開いてください.より詳しい(正しい)使い方が例示されます.

また,pix_opencv の諸機能を利用する際は,以下の点に注意してください.

【使用例:顔検出】

OpenCV の諸機能のなかでもよく使われるのは顔検出 (face detection) です.ここではパターン検出オブジェクト [pix_opencv_haarcascade] を使った顔検出を紹介します.

まず,カスケード接続された Haar 検出器の列を用意し,多数の正例(顔の画像断片)と負例(顔でない画像断片)を与えて各パラメタを学習させます.とは言っても,これを私たちで実施する必要はありません.すでに学習済みのパラメタセットをダウンロードして使うことができます.たとえば,http://alereimondo.no-ip.org/OpenCV/34 の "Cascade" から "frontalFace10.zip" をダウンロードし,適当なフォルダに展開してください.(併せて,下のパッチの [load ...[ の部分を書き換えてください.)

上のパッチで,[load ...[ を押して,正しくパラメタセットが読み込まれたことを確認してください.エラーがあればコンソールに表示されます.つぎに [create, 1, ...[ を押して GEM ウィンドウを開いてください.画像中に人の正面顔があれば円で囲まれるはずです.もちろん動画についても適用可能ですが,顔検出は計算量が大きいため,高いフレームレートで実行させることは難しいでしょう.(よく使われるテクニックとして,[pix_opencv_haarcascade] で顔を検出した後,テンプレートマッチングなど計算量の少ない手法で追跡する手法が知られています.)