Scatter Faces ―Face Detection test in AI–
iPhone6でましたねぇ〜
でもまだまだ動きませんよ〜だてに無印4を使い続けているわけではありません。スマ放題なんて無粋なプランを利用したくないしねw
本題に入りましょう。昨晩、ライブラリがどうこう言っていたのですが、なんか無いかなぁ〜って探してて見つけました。今回のはイラストレータ上での顔認識を組み込んだ処理サンプルです。エクスターナルオブジェクト・ファイルの取り回しだけでなく、メニューコマンドの利用や、バイナリデータの取扱、アフィン変換・XMPメタデータの読み込みなども組み込んでいます。ここからスニペット抜いて利用してみると良いのではないでしょうか。
まず、動作サンプルです。
こちらのリンクにあるムービーを見てみて下さい。
コードはこちら。
var tgt = app.activeDocument.selection[0];
if (ExternalObject.AdobeXMPScript == undefined) {
ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
}
var cascade = "/haarcascades/haarcascade_frontalface_alt_tree.xml"; //Frontal Face
var extObj = new ExternalObject("lib:/faceDetecter64-1.0.2.framework");
var fdr = Folder.selectDialog ("select a Targets...");
var f = fdr.getFiles("*.jpg");
if (tgt.typename=="PathItem"){
var bx = tgt.geometricBounds;
app.cut();
var gp;
var tfm = new Matrix();
tfm.mValueB = 0;
tfm.mValueC = 0;
tfm.mValueTY = 0;
for (var j=0;j<f.length;j++){
gp = placeIMG(f[j], bx);
if(gp==null) continue;
tfm.mValueA = Math.random()*0.7;
tfm.mValueD = tfm.mValueA;
tfm.mValueTX = (Math.random()-0.5)*400;
tfm.mValueTY = (Math.random()-0.5)*400;
gp.transform(tfm,true,true,true,true,1);
tfm = app.getRotationMatrix (Math.random()*180-90);
gp.transform(tfm,true,true,true,true,1);
}
}
extObj.unload();
ExternalObject.AdobeXMPScript.unload();
function placeIMG (f, bx){
var i;
var bxw = bx[2] - bx[0];
var bxh = bx[3] - bx[1];
var b = getDimension(f);
var obj = app.activeDocument.placedItems.add();
obj.file = f;
var bd = obj.geometricBounds;
var tm = new Matrix();
tm.mValueB = 0;
tm.mValueC = 0;
tm.mValueTX = 0;
tm.mValueTY = 0;
try{
var pos = extObj.trackFace(f.fsName, cascade,1.1, 4, 30);
if (pos.length>0){
while (pos.length>4){ //select largest one.
if (pos[pos.length-1]>pos[3])
for (i=0;i<4;i++) pos.shift();
else
for (i=0;i<4;i++) pos.pop();
}
$.writeln(f.fsName + " : " +pos);
var visibleWidth = pos[2] * 1.4; //px
var visibleHeight = pos[3] * 2; //px;
var scale = b[0] / ( bd[2] - bd[0] ) * bxw / visibleWidth;
var resolution = visibleWidth / bxw;
var ctr = [pos[0]+pos[2]/2, pos[1]+pos[3]/2];
tm.mValueA = scale;
tm.mValueD = scale;
obj.transform(tm,true,true,true,true,1);
bd = obj.geometricBounds;
obj.left = bx[0] - ctr[0] / resolution + bxw / 2;
obj.top = bx[1] + ctr[1] / resolution + bxh / 1.9;
app.executeMenuCommand('pasteFront');
obj.selected = true;
extObj.unload();
app.executeMenuCommand('makeMask');
return obj.parent;
}
else {
obj.selected = true;
app.executeMenuCommand('clear');
return null;
}
}catch(o_O){
alert(o_O);
}
}
function getDimension(f){
var xmp = new XMPFile(f.fsName, XMPConst.UNKNOWN, XMPConst.OPEN_FOR_READ);
var dat = xmp.getXMP();
var bds = [];
bds[0] = Number (dat.getProperty(XMPConst.NS_EXIF,"PixelXDimension"));
bds[1] = Number (dat.getProperty(XMPConst.NS_EXIF,"PixelYDimension"));
if (!isNaN(bds[0])) return bds;
f.encoding = 'BINARY';
var str = "";
if (f.open("r")){
while(!f.eof){
var d = readByte(f);
if (d==0xff){
d = readByte(f);
if (d==0xc0){
&
nbsp; bds = getValue(f);
}
}
if (f.tell()>32000) break;
}
f.close();
}
return bds;
}
function getValue(f){
readUShort(f);
readByte(f);
var ht = readUShort(f);
var wd = readUShort (f);
return [wd, ht];
}
function readByte(targetFile){
return targetFile.readch().charCodeAt(0);;
}
function readUShort(targetFile){
var result = targetFile.readch().charCodeAt(0) * 256;
result += targetFile.readch().charCodeAt(0);
return result;
}
個々に実装を解説し始めると10回ぐらいの連載になりそうなのでまたの機会にします。