AfterEffects エクスプレッションとスクリプトで色を自動で検出する

AfterEffectsで特定の色が含まれている画像にだけ自動で処理を行うスクリプトを考えてみました。

 

いきなり特定の色を検出することは出来ないので下記の手順で処理を行います

  1. レイヤーに対して指定色のカラーキーを適用して指定色部分を透明にする
  2. sampleImageメソッドを使ってレイヤーのアルファ値の平均値を取得して透明部分があるかどうか調べることで画像に指定色が含まれているか判定する
  3. 上記1,2+自動で行いたい処理を記述したスクリプトで作業を自動化する

 

まず、レイヤーの透明部分の有無を調べるエクスプレッションですが、コンポ内に画像(インデックス2)とエクスプレッション記述用にテキストレイヤーを用意し、テキストレイヤーのソーステキストにエクスプレッションを記述します。

hantei = 0;//判定
p =5;//画像の分割回数
zurashi = 0;

for(i=0;i<thisComp.duration*24;i++){//コンポのフレーム数だけ繰り返す(24fps)
for(j=1;j<=(p-1);j+=2){//画像の分割分だけ繰り返す
if(j==(p-1)){//ラスト1回で端をはみ出して画面外をアルファ検出してしまうので1pixelずらす
zurashi = 1;
}
alfa = Math.floor(thisComp.layer(2).sampleImage([thisComp.width/2,(thisComp.height/p)*j],
radius=[thisComp.width/2,(thisComp.height/p)-zurashi],true,i/24)[3]);
if(alfa != 1){
hantei = 1;
break;//透明部分があれば判定を1にしてループから抜ける
}
}
}
hantei;//判定を返す

実際に適用した画像がこちら

temp

レイヤーにはカラーキーを適用しており、エクスプレッションは判定「1」を返しています。

即ち、レイヤーがカラーキーで指定した色を含んでいることがわかります。

画像を分割しているのはサンプル範囲に対して指定色の面積が小さすぎると平均値で透明部分を検出できないことがあるためです。

 

このエクスプレッションを使って選択しているレイヤーに指定の色が含まれているかどうかを判定するスクリプトが以下になります。

var activeComp = app.project.activeItem;//アクティブアイテム
var selectLayer = activeComp.selectedLayers[0];//選択レイヤー
var keyColor = [0/255,255/255,255/255];//色の指定
var n = “5”;//画像を分ける回数

//指定色のカラーキーを追加
selectLayer.property(“Effects”).addProperty(“ADBE Color Key”);
selectLayer.property(“Effects”)(“ADBE Color Key”)(“ADBE Color Key-0001”).setValue(keyColor);

//エクスプレッション用のレイヤーを追加し、エクスプレッションを記述
dText = activeComp.layers.addText();
sLayerIndex = selectLayer.index;//選択レイヤーのインデックスを取得

//エクスプレッションを記述
var exp = “hantei = 0;”
+ “p =”+n+”;”
+ “zurashi = 0;”
+ “for(i=0;i<thisComp.duration*24;i++){”
+     “for(j=1;j<=(p-1);j+=2){”
+         “if(j==(p-1)){”
+             “zurashi = 1;”
+         “}”
+         “alfa = Math.floor(thisComp.layer(“+sLayerIndex+”).sampleImage([thisComp.width/2,(thisComp.height/p)*j],”
+         “radius=[thisComp.width/2,(thisComp.height/p)-zurashi],true,i/24)[3]);”
+         “if(alfa != 1){”
+             “hantei = 1;”
+             “break;”
+         “}”
+     “}”
+ “}”
+ “hantei;”;

dText.property(“Source Text”).expression = exp;
var hantei = Number(dText.property(“Source Text”).value);//エクスプレッションの結果を数値にして格納
dText.remove();//不要になったエクスプレッション用のレイヤーを削除

if(hantei==1){
alert(“指定色がありました”);

}else{
alert(“指定色がありませんでした”);
selectLayer.property(“Effects”)(“ADBE Color Key”).remove();//カラーキーを削除
}

レイヤーを選択した状態で実行するとアラートし、指定色のカラーキーを適用します。

alert(“指定色がありました”);の部分を自動で行いたい処理に変えることで、好きな処理を自動で実行できます。

 

レイヤーに指定色がある場合に白部分の色抜き、指定色部分を影ダブラし処理するスクリプトが以下。

var activeComp = app.project.activeItem;//アクティブアイテム
var selectLayer = activeComp.selectedLayers[0];//選択レイヤー
var keyColor = [0/255,255/255,255/255];//色の指定
var n = “5”;//画像を分ける回数

//指定色のカラーキーを追加
selectLayer.property(“Effects”).addProperty(“ADBE Color Key”);
selectLayer.property(“Effects”)(“ADBE Color Key”)(“ADBE Color Key-0001”).setValue(keyColor);

//エクスプレッション用のレイヤーを追加し、エクスプレッションを記述
dText = activeComp.layers.addText();
sLayerIndex = selectLayer.index;//選択レイヤーのインデックスを取得

//エクスプレッションを記述
var exp = “hantei = 0;”
+ “p =”+n+”;”
+ “zurashi = 0;”
+ “for(i=0;i<thisComp.duration*24;i++){”
+     “for(j=1;j<=(p-1);j+=2){”
+         “if(j==(p-1)){”
+             “zurashi = 1;”
+         “}”
+         “alfa = Math.floor(thisComp.layer(“+sLayerIndex+”).sampleImage([thisComp.width/2,(thisComp.height/p)*j],”
+         “radius=[thisComp.width/2,(thisComp.height/p)-zurashi],true,i/24)[3]);”
+         “if(alfa != 1){”
+             “hantei = 1;”
+             “break;”
+         “}”
+     “}”
+ “}”
+ “hantei;”;

dText.property(“Source Text”).expression = exp;
var hantei = Number(dText.property(“Source Text”).value);//エクスプレッションの結果を数値にして格納
dText.remove();//不要になったエクスプレッション用のレイヤーを削除

if(hantei==1){
newLayer = selectLayer.duplicate();//レイヤーを複製

//白を抜くカラーキーを追加
colorKey2 = selectLayer.property(“Effects”).addProperty(“ADBE Color Key”);
colorKey2(“ADBE Color Key-0001”).setValue([255/255,255/255,255/255]);

//複製したレイヤーの指定色部分のみを抽出し、影色にする
invert = newLayer.property(“Effects”).addProperty(“ADBE Invert”);
invert(“ADBE Invert-0001”).setValue(16);
colorFill = newLayer.property(“Effects”).addProperty(“ADBE Fill”);
colorFill(“ADBE Fill-0002”).setValue([0/255,0/255,0/255]);
newLayer.property(“ADBE Transform Group”)(“ADBE Opacity”).setValue(50);

}else{
selectLayer.property(“Effects”)(“ADBE Color Key”).remove();//カラーキーを削除
}

実行前(左)と実行後(右)

 

現状、このスクリプトを関数化して従来からのスクリプト内に組み込んで作業を自動化していますが、指定色部分の面積が極端に狭いと検出できなくなるという問題があります。また、この問題を解決しようと画像の分割回数を増やすと処理が重くなり、エクスプレッションがタイムアウトエラーするというジレンマ…。

まだまだ改善の余地があるかなと思います。

広告

にじみエフェクトを使ってみる

After Effects 標準エフェクトで水が紙ににじむようなエフェクトをつくりたくて試してみました。

 

まずはシェイプレイヤーで円を用意します。
にじみ1

 

早速、エフェクト>ディストーション>にじみ を選択しますが…

にじみ1

何も起きません(´・ω・`)

にじみエフェクトには下準備が必要なようです。

 

まず、シェイプレイヤーと同じ形のパスをコピー、レイヤーにctrl+vでペーストして、マスクにします。全く同じ操作をもう一度行って、同じマスクを作ります。2番目のマスクは「反転」にチェックを入れましょう。

キャプチャ2

ようやく、にじみエフェクトを適用。「変形元マスク」にマスク2、「境界マスク」にマスク1が設定されます。

sfa

「パーセント」の値を上げると…

キャプチgfャ

にじみました。

safasd

にじみエフェクトとは「対象の画像を変形元マスクと境界マスクの間の範囲で歪ませる」エフェクトのようです。エフェクトコントロールの残りの項目は次の様な感じです。

  • マスクオフセット : 変形元マスクの位置を調整します。
  • マスク回転 : 変形元マスクを回転させます。
  • マスクスケール : 変形元マスクの大きさを調整します。境界マスクより小さい範囲で調整しましょう。境界マスクに対して小さいほどにじみが大きくなります。
  • 弾性 : にじみの弾性を調整します。硬いほどにじみが小さく、多角形に近くなり、軟らかくするほどにじみが大きく、液状になります。軟らかくするほど重いエフェクトになるのでほどほどに。

 

後は色々アニメーションされるとこうなりました。

コンポ-2

意外にもこのエフェクトのTipsは見つからなかったので結構苦労しました。とりあえず、目的とする表現が出来た気がするのでドンドン使っていこうと思います。