Project N: 015 - ブルーバック合成風(つづき)
前回、ColorKeyMaskを使って、ブルーバック合成風の合成(?)に、とりあえず成功しました。ところで、前回紹介できなかった、ColorKeyMaskの引数toleranceについて、少し補足しておきます。
マニュアルには、toleranceについて、次のような説明があります。
何だかよくわかりませんが(汗)、たぶん、色(color)の許容範囲みたいな感じだと思います(toleranceは、寛容、耐久力、許容誤差などの意)。tolerance=0なら、colorで指定した色のみを透過色とし(つまり、誤差0)、tolerance=50なら、colorとの差が50より小さい色も透過色に含めるということかと。
実際、toleranceを変えてみたところ・・・

tolerance=200あたりでは、かなり輪郭がガタガタになり・・・

tolerance=240では、もうボロボロ。さらに、tolerance=255にすると・・・

真っ黒になっちゃった。
さらに、tolerance=256にすると・・・

tolerance=0と一緒?
ちなみに、colorが背景だけでなく、人物にも使われていたら、当然、その部分も透過色になってしまいます。
マニュアルには、toleranceについて、次のような説明があります。
Each pixel with a color differing less than tolerance is set to transparent, otherwise it is left unchanged (it is NOT set to opaque).
(toleranceの値よりも差が小さい色を持つピクセルは、透明に設定されます。それ以外は、変更されません(非透明に設定されるのではない)。)
何だかよくわかりませんが(汗)、たぶん、色(color)の許容範囲みたいな感じだと思います(toleranceは、寛容、耐久力、許容誤差などの意)。tolerance=0なら、colorで指定した色のみを透過色とし(つまり、誤差0)、tolerance=50なら、colorとの差が50より小さい色も透過色に含めるということかと。
実際、toleranceを変えてみたところ・・・

tolerance=200あたりでは、かなり輪郭がガタガタになり・・・

tolerance=240では、もうボロボロ。さらに、tolerance=255にすると・・・

真っ黒になっちゃった。
さらに、tolerance=256にすると・・・

tolerance=0と一緒?
ちなみに、colorが背景だけでなく、人物にも使われていたら、当然、その部分も透過色になってしまいます。
Project N: 014 - ブルーバック合成風(ColorKeyMask)

前回までの画像。
このままでは、当然のことながら、人物画(img)の背景の青色が気になります。そこで、全体の背景(bg)に馴染むように青色を消したいと思います。いわゆるブルーバック合成みたいな感じです。
ここでは、ColorKeyMaskというフィルタを使って行います。
ColorKeyMaskは、以前、紹介したMaskと同じように、アルファチャンネルを追加するフィルタなのですが、Maskとの違いは、用意した画像を使うのではなく、色を比較してアルファチャンネルを作り出す点にあります。
ColorKeyMask(clip clip, int color, int tolerance)ColorKeyMaskの書式です。
colorは、透過色に設定したい色を16進数で指定します。ここでは青色の部分を透過させたいので、color=$0000ffとします(imgの背景は、#0000ffの青色で塗りつぶしてあります)。toleranceは、とりあえず0にしておきます(toleranceについては後述)。
img = ColorKeyMask(img, $0000ff, 0)これを、img = ConvertToRGB32(img)の後に挿入します(スクリプトは前回を参照)。ColorKeyMaskは、RGB32でのみ動作するフィルタです。すると・・・

適当にやった割りに、いい感じじゃないですか!?

この画像を2倍に拡大してみました。輪郭も悪くない・・・ていうか、(・∀・)イイ!!
ちょっと長くなってきたので、次回へつづく。
Project N: 013-Clip Properties(クリップ情報の取得)
前回、次からはLayer以外の話を進めるみたいなことを書きましたが、ひとつだけ書き忘れていたことがありました。

前回までに、Layerフィルタを使って、画像(img)と背景(bg)を合成したクリップです。
見てもらってわかるように、画像(img)はクリップの左上隅にあります。
これをクリップの中心(あたり)に位置するようにしたいのです。
Layerフィルタの書式です。
このうち、xとyが、overlayクリップ(ここではimg)の位置を指定するための引数になります。
どちらも、int型(整数)です。
xはクリップの左端からの距離、yは上端からの距離になります。
xとyを指定しなかった時に、imgが左上に来ていたのは、デフォルトでは、x=0, y=0となっているからです。
さて、xとyを指定すれば、imgの位置を調整できることがわかりました。
では、imgがクリップの中心に来るようにするには、どうすればいいでしょうか?
そこで、次のように考えてみました。

bgの横幅をa、imgの横幅をbとします。
このとき、aとbの差を二等分したものをxとすればいいのではないかと。
もっといい方法があるかもしれませんが、こんなのしか思いつきませんでした。 orz
ここで、クリップの情報(Clip Properties)を取得する関数を使います。
クリップの幅を求める関数はWidth()です。
引数は、clipのみ。
たとえば、imgの幅を知りたい場合、次のように記述します。
bgの幅を知りたい時は、imgの部分をbgにすればいいだけです。
これを利用して、xを表すと、
bgの幅からimgの幅を引いたものを、2で割っています(/は、わり算の演算子。bgとimgの差をカッコで括っていることに注意)。
同様にして、yを求めます。
クリップの高さを求める関数はHeight()なので、
となります。
スクリプトは、このようになりました。

プレビューすると、imgが真ん中に来てますね。
・・・たぶん、真ん中です。

前回までに、Layerフィルタを使って、画像(img)と背景(bg)を合成したクリップです。
見てもらってわかるように、画像(img)はクリップの左上隅にあります。
これをクリップの中心(あたり)に位置するようにしたいのです。
Layer(clip base_clip, clip overlay_clip, string op, int level, int x, int y, int threshold, bool use_chroma)
Layerフィルタの書式です。
このうち、xとyが、overlayクリップ(ここではimg)の位置を指定するための引数になります。
どちらも、int型(整数)です。
xはクリップの左端からの距離、yは上端からの距離になります。
xとyを指定しなかった時に、imgが左上に来ていたのは、デフォルトでは、x=0, y=0となっているからです。
さて、xとyを指定すれば、imgの位置を調整できることがわかりました。
では、imgがクリップの中心に来るようにするには、どうすればいいでしょうか?
そこで、次のように考えてみました。

bgの横幅をa、imgの横幅をbとします。
このとき、aとbの差を二等分したものをxとすればいいのではないかと。
もっといい方法があるかもしれませんが、こんなのしか思いつきませんでした。 orz
ここで、クリップの情報(Clip Properties)を取得する関数を使います。
クリップの幅を求める関数はWidth()です。
引数は、clipのみ。
たとえば、imgの幅を知りたい場合、次のように記述します。
Width(img)
bgの幅を知りたい時は、imgの部分をbgにすればいいだけです。
これを利用して、xを表すと、
x = (Width(bg)-Width(img))/2
bgの幅からimgの幅を引いたものを、2で割っています(/は、わり算の演算子。bgとimgの差をカッコで括っていることに注意)。
同様にして、yを求めます。
クリップの高さを求める関数はHeight()なので、
y = (Height(bg)-Height(img))/2
となります。
img = ImageReader("C:\My Documents\nyatrix\img\nyatrix.png", 0, 0, 24, false)
img = ConvertToRGB32(img)
bg = BlankClip()
x = (Width(bg)-Width(img))/2
y = (Height(bg)-Height(img))/2
Layer(bg, img, "add", 255, x, y)
スクリプトは、このようになりました。

プレビューすると、imgが真ん中に来てますね。
・・・たぶん、真ん中です。
Project N: 012-マスク(Mask/ResetMask)
前回、画像(img)のアルファチャンネルをShowAlphaフィルタで確認したところ、真っ白でした。

真っ白=アルファ値最高、なので、Layerでの合成時にlevelの値がそのまま反映されていたのですが、ではアルファチャンネルが真っ白でなければ、どうなるのでしょうか。
Maskというフィルタを使うと、アルファチャンネルに独自のマスクを指定することができます。
マスクは白黒の画像で、黒が透過、白が非透過になります。
画像処理系のソフトで、特定の範囲にだけ処理を施す場合に使われますね。

試しに、上の画像をマスクとして追加してみます。
そこでスクリプトを、次のように変更します。
これをプレビューすると・・・

さらにShowAlphaでチェックすると・・・

マスクが変更されているのがわかります。
ちなみに、ResetMaskというフィルタを使うと、マスクをリセットして、完全非透過(つまり真っ白け)のクリップをマスクに追加することが出来ます。
試しに、先程のスクリプトの最後に次の1行を追加して、

真っ白になっちゃった!(某マジシャン風)
・・・・・・。
Layer関連の話はこれくらいにして、次回からは、もう少し動画づくりの作業を進めていきたいと思います。

真っ白=アルファ値最高、なので、Layerでの合成時にlevelの値がそのまま反映されていたのですが、ではアルファチャンネルが真っ白でなければ、どうなるのでしょうか。
Maskというフィルタを使うと、アルファチャンネルに独自のマスクを指定することができます。
マスクは白黒の画像で、黒が透過、白が非透過になります。
画像処理系のソフトで、特定の範囲にだけ処理を施す場合に使われますね。

試しに、上の画像をマスクとして追加してみます。
Mask(clip clip, clip mask_clip)Maskの書式です。
そこでスクリプトを、次のように変更します。
img = ImageReader("C:\My Documents\nyatrix\img\nyatrix.png", 0, 0, 24, false)MaskはRGB32でのみ動作するため、mask_clipもConvertRGB32()しています。
img = ConvertToRGB32(img)
mask_clip = ImageReader("C:\My Documents\nyatrix\img\nyatrix_mask.png", 0, 0, 24, false)
mask_clip = ConvertToRGB32(mask_clip)
img = Mask(img, mask_clip)
bg = BlankClip()
Layer(bg, img)
これをプレビューすると・・・

さらにShowAlphaでチェックすると・・・

マスクが変更されているのがわかります。
ちなみに、ResetMaskというフィルタを使うと、マスクをリセットして、完全非透過(つまり真っ白け)のクリップをマスクに追加することが出来ます。
試しに、先程のスクリプトの最後に次の1行を追加して、
ResetMask()ShowAlpha()すると・・・

真っ白になっちゃった!(某マジシャン風)
・・・・・・。
Layer関連の話はこれくらいにして、次回からは、もう少し動画づくりの作業を進めていきたいと思います。
Project N: 011-アルファチャンネル(ShowAlpha)
アルファチャンネルに関しては、用語集などを参考にしてください。
私には、とても説明など出来ません orz
といいつつ、ちょっとだけ話をします(ぉ
RGBは、光の三原色R(Red)、G(Green)、B(Blue)の3つのチャンネルの組み合わせで色を再現します(たぶん)。
このうち、RGB24は、RGB各8bit -> 8*3=24bitだから、RGB24(確か)。
一方、RGB32は、RGB各8bitにアルファチャンネル8bitを加えて、8*3+8=32でRGB32です(きっと)。
RGB32に関しては他の定義もあるようなことをどこかで読んだ(気がする)のですが、AviSynthにおけるRGB32はRGB + アルファチャンネルで合ってます(と言ってみる)。

上は(あくまでも)イメージ図。
で、AviSynthに限定して話をすると、アルファチャンネルは透過度を表すデータとして使われ、黒=透明、白=不透明(非透過)となります。
アルファチャンネルが黒だと背景をそのまま通し、白は通さない、グレーは半透明なので背景とブレンドされたようになる、というわけです(おそらく)。
では、前回、Layerで合成した画像の場合、アルファチャンネルはどうなっているのでしょうか。
そこで、ShowAlphaというフィルタを使って、アルファチャンネルを表示してみましょう。
ShowAlphaは、AviSynth2.5.3から追加されたフィルタです。
書式は次の通り。
ShowAlphaはRGB32でのみ動作します(アルファチャンネルがあるのはRGB32だけなので)。
ただし、pixel_typeを指定した場合、アルファチャンネルを別の色空間(YUY2/YV12)に変換して表示することもできます(AviSynth2.5.4以降)。

level=0

level=128

level=255
上から順にlevel=0, 128, 255、それぞれの場合のアルファチャンネルです。
こんな感じで、スクリプトを書きました。
pixel_typeは指定していません。
level=0の時、アルファチャンネルは黒(真っ黒)なので透明、つまり背景(bg)の色(黒)をそのまま通します。
これに対し、level=255では、アルファチャンネルは白なので非透過、つまり背景の色を通さないので、画像(img)が表示されます。
ちなみに、Layerで合成する前の画像(img)のアルファチャンネルはどうなっているかと言いますと・・・、

真っ白でした。
私には、とても説明など出来ません orz
といいつつ、ちょっとだけ話をします(ぉ
RGBは、光の三原色R(Red)、G(Green)、B(Blue)の3つのチャンネルの組み合わせで色を再現します(たぶん)。
このうち、RGB24は、RGB各8bit -> 8*3=24bitだから、RGB24(確か)。
一方、RGB32は、RGB各8bitにアルファチャンネル8bitを加えて、8*3+8=32でRGB32です(きっと)。
RGB32に関しては他の定義もあるようなことをどこかで読んだ(気がする)のですが、AviSynthにおけるRGB32はRGB + アルファチャンネルで合ってます(と言ってみる)。

上は(あくまでも)イメージ図。
で、AviSynthに限定して話をすると、アルファチャンネルは透過度を表すデータとして使われ、黒=透明、白=不透明(非透過)となります。
アルファチャンネルが黒だと背景をそのまま通し、白は通さない、グレーは半透明なので背景とブレンドされたようになる、というわけです(おそらく)。
では、前回、Layerで合成した画像の場合、アルファチャンネルはどうなっているのでしょうか。
そこで、ShowAlphaというフィルタを使って、アルファチャンネルを表示してみましょう。
ShowAlphaは、AviSynth2.5.3から追加されたフィルタです。
書式は次の通り。
ShowAlpha(clip clip, string pixel_type)
ShowAlphaはRGB32でのみ動作します(アルファチャンネルがあるのはRGB32だけなので)。
ただし、pixel_typeを指定した場合、アルファチャンネルを別の色空間(YUY2/YV12)に変換して表示することもできます(AviSynth2.5.4以降)。

level=0

level=128

level=255
上から順にlevel=0, 128, 255、それぞれの場合のアルファチャンネルです。
Layer(img, bg, "add", 0)
ShowAlpha()
こんな感じで、スクリプトを書きました。
pixel_typeは指定していません。
level=0の時、アルファチャンネルは黒(真っ黒)なので透明、つまり背景(bg)の色(黒)をそのまま通します。
これに対し、level=255では、アルファチャンネルは白なので非透過、つまり背景の色を通さないので、画像(img)が表示されます。
ちなみに、Layerで合成する前の画像(img)のアルファチャンネルはどうなっているかと言いますと・・・、

真っ白でした。



