AfterEffectsで特定の色が含まれている画像にだけ自動で処理を行うスクリプトを考えてみました。
いきなり特定の色を検出することは出来ないので下記の手順で処理を行います
- レイヤーに対して指定色のカラーキーを適用して指定色部分を透明にする
- sampleImageメソッドを使ってレイヤーのアルファ値の平均値を取得して透明部分があるかどうか調べることで画像に指定色が含まれているか判定する
- 上記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;//判定を返す
実際に適用した画像がこちら
レイヤーにはカラーキーを適用しており、エクスプレッションは判定「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();//カラーキーを削除
}
実行前(左)と実行後(右)
現状、このスクリプトを関数化して従来からのスクリプト内に組み込んで作業を自動化していますが、指定色部分の面積が極端に狭いと検出できなくなるという問題があります。また、この問題を解決しようと画像の分割回数を増やすと処理が重くなり、エクスプレッションがタイムアウトエラーするというジレンマ…。
まだまだ改善の余地があるかなと思います。