OpenCVをExtendscriptで利用するなんとか…
水もぬるみ始め、そろそろお花見の予定を考えないと行けない時期となりました。皆様に於かれましてはご清祥の事とお慶び申し上げますです、はい。
そんなこんななのですが、日曜日の昼下がりはうちの子がピアノを練習してたりするのです。このところメヌエットとかやってて、なまじ知っている曲ということで今このテキスト入力中にも頭の中を回り続けている次第です。しょうがないので他の曲聞いたりしているのですが止めるとまた例の曲が戻ってきて……なんだかこのループは当分続きそうです。今週は違う曲やってたから止まるかなって思ったのですが相変わらずわたしの頭の中はアレがエンドレスでりぴーとしているというw
話は全く関連しませんが、今回お届けするのはおなじみの顔認識なのです。今回はMac版のライブラリを更新します。OpenCVのバージョンは2.4.5です。
さて、先ずはライブラリから。こちらはFrameworkになっていますから/Library/Frameworksフォルダに投入します。haarcascadesフォルダは起動ディスクの第一階層にコピーしておきましょう。いずれもdmgファイルを開くとエイリアスを用意してあります。
OpenCV.Framework(ver.2.4.5)+haarcascadeFiles
https://goo.gl/Pi5agd
そしてExtendscript用のエクスターナル・オブジェクトはこちら
https://goo.gl/v7GLxK
利用例です。Indesign上で顔を適切な状態で配置するスクリプトです。どんな画像サイズ、位置であっても顔を検出して適切に調整してくれる優れものです。
if (ExternalObject.AdobeXMPScript == undefined) {
ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
}
var cascade = "/haarcascades/haarcascade_frontalface_alt2.xml";
var i;
var f = File.openDialog ("select a file...");
var tgtFile = f.fsName;
var b = [];
var xmp = new XMPFile( tgtFile, XMPConst.UNKNOWN, XMPConst.OPEN_FOR_READ);
var obj = xmp.getXMP();
b[0] = Number(obj.getProperty(XMPConst.NS_EXIF,"PixelXDimension"));
b[1] = Number(obj.getProperty(XMPConst.NS_EXIF,"PixelYDimension"));
if (isNaN(b[0])){
b = getDimension(f);
}
var tgt = app.activeDocument.selection[0];
var bx = tgt.geometricBounds;
var bxw = bx[3] - bx[1];
var bxh = bx[2] - bx[0];
tgt.place(f);
var extObj = new ExternalObject("lib:/faceDetecter64-1.0.2.framework");
var pos = extObj.trackFace(tgtFile, cascade,1.11, 4, 50);
$.writeln(pos);
if (pos.length>0){
try{
while (pos.length>4){
if (pos[pos.length-1]>pos[3])
for (i=0;i<4;i++) pos.shift();
else
for (i=0;i<4;i++) pos.pop();
}
var visibleWidth = pos[2] * 1.4; //px
var visibleHeight = pos[3] * 2; //px;
var scale = bxw / visibleWidth;
var imgWidth = b[0] * scale;
var imgHeight = b[1] * scale;
var xofst = bx[1] + pos[2] * scale * 0.2 - pos[0] * scale;
var yofst = bx[0] + pos[3] * scale * 0.4 - pos[1] * scale;
if (!isNaN(xofst)){
tgt.graphics[0].geometricBounds = [
yofst, xofst,
imgHeight + yofst, imgWidth + xofst];
}
extObj.unload();
}catch(o_O){
alert(o_O);
}
}
else {
tgt.fit (FitOptions.proportionally);
tgt.fit (FitOptions.centerContent);
}
function getDimension(f){
f.encoding = 'BINARY';
var str = "";
var bds = [];
if (f.open("r")){
while(!f.eof){
var d = readByte(f);
if (d==0xff){
d = readByte(f);
if (d==0xc0){
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;
}
テスト…
こちらのお嬢さんMaiaちゃんです。
FreeImages.comよりの引用です。
http://www.freeimages.com/photo/maia-2-1436576
こちらをFaceDetectorに通すと
こんな具合に顔のエリアサイズとTop-Leftの位置が返ります。
こちらはこのエリアを可視化したものです。この情報を基に画像をInDesignに配置したものがこちらです。