Extend ScriptにComputer Visionを導入する

細かく説明すると、OpenCVを利用したExternal Objectを使った、Extend Script上でのFace Trackingテストの結果。というのがこの一連のテストの詳細です。
OpenCVというのは世界中の研究者がよってたかって開発しているライブラリで、画像認識の世界ではそれはそれはとてもポピュラーなものです。あんなカメラやあんなスマホで顔を認識させているフレームワークの基本となっているものです。
先日のフレームワークはこのライブラリをExtend Scriptから呼び出せるExternal Objectとして実装したものでした。長々と書き連ねていますが、それ程ややこしい事ではございません。要は「Adobeの各種アプリケーションで人間の顔を認識して、その情報を基に編集を自動化出来たら便利じゃね???」ってことです。
しかしながら、このフレームワーク自体はお約束に従って検出作業を進める類いの物ですので、性能はcascadeファイルに依存します。そこらへんをちょっとテストしてみたのでご覧下さい。

snapFit1.png

まずはこの様になります。もう一つ…

snapFit2.png

M100の線で囲まれているものは検出に失敗した物です。しかしながらフェイクデータも多々含まれていますので全てで検出されるのは問題があったりするのです。
さて、以前haar-likeはブーストされたカスケードの性能に依存するといった事を書いたかもしれないし、書いてないかもしれませんが、このカスケードの違いがどの程度の性能差を生じさせるのか検証してみましょう。

profileCmp.png

試験するカスケードファイルは4点。ターゲットイメージは40点でフェイクなし。これらはそこそこ顔の判別が出来そうなものを揃えています。ここで使ったカスケードはOpenCVに添付されているものですが、容量にかなりの差があったりします。
まあ、ご覧の通りなのですが、カスケードは鍛えれば鍛えるほど性能が上がるのかな?一番下のalt_treeはミスなしで配置出来ています。
配置と同時にtrackFaceファンクションの返り値を記録してありますのでご覧下さい。左からファイル名称、左肩X座標、Y座標、幅、高さの順で並んでいます。最後の行は40点自動配置時の実行時間です。

#haarcascade_profileface.xml
8403851879_7219bf57bb_b.jpg 265,136,265,265
8409726577_51ca235bfa_b.jpg 215,184,155,155
8426354668_99af80c688_b.jpg 488,101,47,47
8426375050_fe1e821c41_b.jpg 189,284,111,111
8466704325_efb1d32118_b.jpg 288,269,384,384
8466720689_1cee35e27d_b.jpg 338,360,115,115
8467754858_560fe5c57c_b.jpg 172,135,295,295
8467757350_6b94a22fe3_b.jpg 368,249,217,217
8467757664_4bbd8e140d_b.jpg 195,98,217,217
8467758428_bbfeb91949_b.jpg 500,183,111,111
8467759334_97d2225cc7_b.jpg 678,361,288,288
8467759694_e3d285ce86_b.jpg 364,172,404,404
8467763178_46a534f5d0_b.jpg 466,206,66,66
8467766538_8447913e16_b.jpg 452,209,338,338
8467766652_a1b42babb5_b.jpg 98,179,163,163
8467767036_de6386ca37_b.jpg 192,154,384,384
8467767214_57eab94c37_b.jpg 498,197,262,262
8467767848_8809bb587f_b.jpg 194,134,141,141
8467772098_6286d1de4f_b.jpg 537,192,384,384
8467772512_7bd69560d3_b.jpg
8467776598_74f99b735e_b.jpg 99,91,405,405
8467778682_fc04196214_b.jpg 136,76,158,158
8467779030_d8261e844c_b.jpg 354,104,586,586
8467780152_464a3c38d3_b.jpg 448,183,204,204
8467781396_d0b4923ee4_b.jpg 565,744,92,92
8467793474_9b2fe55a11_b.jpg 210,155,342,342
8467795498_8226f5bcf3_b.jpg 167,119,238,238
8467795572_45f8ed70f1_b.jpg 38,77,384,384
8467796076_5dc626c563_b.jpg 375,187,171,171
8467797724_da53fc1f44_b.jpg 254,314,63,63
8467799672_165c45dd83_b.jpg 196,38,302,302
8467805822_81e50239fe_b.jpg 600,67,223,223
8467805902_747bc68f04_b.jpg 302,116,465,465
8467810402_afbaec8379_b.jpg 87,297,349,349
8467811526_2cfc42ef36_b.jpg 391,121,266,266
8467811762_86411f6f81_b.jpg 680,87,249,249
8467815306_5c9480efa8_b.jpg 440,182,246,246
8467816264_b28552f567_b.jpg 423,157,261,261
8467816586_eb55b5bbe0_b.jpg 37,354,92,92
8467819370_1428e0f1ae_b.jpg 0,48,384,384
executionTime= 27.332 sec

こちらのプロファイルは1点、座標が帰ってません。

#haarcascade_frontalface_default.xml
8403851879_7219bf57bb_b.jpg 222,152,245,245
8409726577_51ca235bfa_b.jpg 0,114,195,195
8426354668_99af80c688_b.jpg 26,695,315,315
8426375050_fe1e821c41_b.jpg 158,197,236,236
8466704325_efb1d32118_b.jpg 167,242,456,456
8466720689_1cee35e27d_b.jpg 315,367,119,119
8467754858_560fe5c57c_b.jpg 187,166,238,238
8467757350_6b94a22fe3_b.jpg 352,6,156,156
8467757664_4bbd8e140d_b.jpg 229,360,369,369
8467758428_bbfeb91949_b.jpg 360,96,298,298
8467759334_97d2225cc7_b.jpg 639,401,260,260
8467759694_e3d285ce86_b.jpg 326,208,348,348
8467763178_46a534f5d0_b.jpg 341,151,204,204
8467766538_8447913e16_b.jpg 505,216,346,346
8467766652_a1b42babb5_b.jpg 130,204,120,120
8467767036_de6386ca37_b.jpg 236,181,343,343
8467767214_57eab94c37_b.jpg 391,163,321,321
8467767848_8809bb587f_b.jpg 160,135,151,151
8467772098_6286d1de4f_b.jpg 400,175,475,475
8467772512_7bd69560d3_b.jpg 83,220,190,190
8467776598_74f99b735e_b.jpg 84,133,337,337
8467778682_fc04196214_b.jpg 137,98,128,128
8467779030_d8261e844c_b.jpg 327,172,490,490
8467780152_464a3c38d3_b.jpg 400,182,216,216
8467781396_d0b4923ee4_b.jpg 207,387,254,254
8467793474_9b2fe55a11_b.jpg 137,162,333,333
8467795498_8226f5bcf3_b.jpg 157,158,195,195
8467795572_45f8ed70f1_b.jpg 150,146,311,311
8467796076_5dc626c563_b.jpg 277,157,255,255
8467797724_da53fc1f44_b.jpg 153,276,165,165
8467799672_165c45dd83_b.jpg 192,82,219,219
8467805822_81e50239fe_b.jpg 601,98,166,166
8467805902_747bc68f04_b.jpg 423,192,302,302
8467810402_afbaec8379_b.jpg 155,293,195,195
8467811526_2cfc42ef36_b.jpg 389,72,346,346
8467811762_86411f6f81_b.jpg 215,104,178,178
8467815306_5c9480efa8_b.jpg 431,216,190,190
8467816264_b28552f567_b.jpg 394,168,217,217
8467816586_eb55b5bbe0_b.jpg 112,100,300,300
8467819370_1428e0f1ae_b.jpg 250,36,286,286
executionTime= 27.221 sec

全部座標が帰れば良いと言うわけではありませんが…

#haarcascade_frontalface_alt.xml
8403851879_7219bf57bb_b.jpg 222,149,248,248
8409726577_51ca235bfa_b.jpg 191,190,149,149
8426354668_99af80c688_b.jpg 244,228,244,244
8426375050_fe1e821c41_b.jpg 167,157,166,166
8466704325_efb1d32118_b.jpg 196,260,416,416
8466720689_1cee35e27d_b.jpg 313,368,120,120
8467754858_560fe5c57c_b.jpg 192,169,230,230
8467757350_6b94a22fe3_b.jpg 788,251,179,179
8467757664_4bbd8e140d_b.jpg 232,361,358,358
8467758428_bbfeb91949_b.jpg 361,102,287,287
8467759334_97d2225cc7_b.jpg 649,346,288,288
8467759694_e3d285ce86_b.jpg 317,203,354,354
8467763178_46a534f5d0_b.jpg 344,156,194,194
8467766538_8447913e16_b.jpg 385,219,345,345
8467766652_a1b42babb5_b.jpg 311,97,127,127
8467767036_de6386ca37_b.jpg 255,184,332,332
8467767214_57eab94c37_b.jpg 409,173,292,292
8467767848_8809bb587f_b.jpg 154,129,159,159
8467772098_6286d1de4f_b.jpg 408,182,454,454
8467772512_7bd69560d3_b.jpg 81,224,179,179
8467776598_74f99b735e_b.jpg 109,151,284,284
8467778682_fc04196214_b.jpg 139,98,125,125
8467779030_d8261e844c_b.jpg 309,160,526,526
8467780152_464a3c38d3_b.jpg 410,189,196,196
8467781396_d0b4923ee4_b.jpg 203,393,240,240
8467793474_9b2fe55a11_b.jpg 148,165,326,326
8467795498_8226f5bcf3_b.jpg 159,161,190,190
8467795572_45f8ed70f1_b.jpg 151,150,306,306
8467796076_5dc626c563_b.jpg 277,156,258,258
8467797724_da53fc1f44_b.jpg 155,274,164,164
8467799672_165c45dd83_b.jpg 183,78,233,233
8467805822_81e50239fe_b.jpg 601,96,167,167
8467805902_747bc68f04_b.jpg 434,196,287,287
8467810402_afbaec8379_b.jpg 291,225,155,155
8467811526_2cfc42ef36_b.jpg 378,149,201,201
8467811762_86411f6f81_b.jpg 208,107,179,179
8467815306_5c9480efa8_b.jpg 430,212,195,195
8467816264_b28552f567_b.jpg 398,168,210,210
8467816586_eb55b5bbe0_b.jpg 228,141,217,217
8467819370_1428e0f1ae_b.jpg 98,103,263,263
executionTime= 24.519 sec

ここまでくるとあと一歩の感じです。実行時間も充分早い。実際のリアルタイムトラッキングでは重宝しそうです。

#haarcascade_frontalface_alt_tree.xml
8403851879_7219bf57bb_b.jpg 227,153,240,240
8409726577_51ca235bfa_b.jpg 185,185,160,160
8426354668_99af80c688_b.jpg 236,223,262,262
8426375050_fe1e821c41_b.jpg 161,152,173,173
8466704325_efb1d32118_b.jpg 178,238,457,457
8466720689_1cee35e27d_b.jpg 311,365,123,123
8467754858_560fe5c57c_b.jpg 187,165,240,240
8467757350_6b94a22fe3_b.jpg 517,195,140,140
8467757664_4bbd8e140d_b.jpg 202,346,402,402
8467758428_bbfeb91949_b.jpg 386,125,227,227
8467759334_97d2225cc7_b.jpg 486,81,210,210
8467759694_e3d285ce86_b.jpg 312,190,380,380
8467763178_46a534f5d0_b.jpg 343,153,202,202
8467766538_8447913e16_b.jpg 381,220,349,349
8467766652_a1b42babb5_b.jpg 134,203,121,121
8467767036_de6386ca37_b.jpg 237,168,363,363
8467767214_57eab94c37_b.jpg 401,165,311,311
8467767848_8809bb587f_b.jpg 160,133,152,152
8467772098_6286d1de4f_b.jpg 338,134,557,557
8467772512_7bd69560d3_b.jpg 90,224,179,179
8467776598_74f99b735e_b.jpg 83,128,353,353
8467778682_fc04196214_b.jpg 98,69,197,197
8467779030_d8261e844c_b.jpg 311,146,532,532
8467780152_464a3c38d3_b.jpg 405,185,208,208
8467781396_d0b4923ee4_b.jpg 206,393,247,247
8467793474_9b2fe55a11_b.jpg 125,153,361,361
8467795498_8226f5bcf3_b.jpg 161,163,183,183
8467795572_45f8ed70f1_b.jpg 157,154,297,297
8467796076_5dc626c563_b.jpg 273,155,268,268
8467797724_da53fc1f44_b.jpg 452,176,158,158
8467799672_165c45dd83_b.jpg 193,80,227,227
8467805822_81e50239fe_b.jpg 602,93,171,171
8467805902_747bc68f04_b.jpg 432,194,288,288
8467810402_afbaec8379_b.jpg 616,280,133,133
8467811526_2cfc42ef36_b.jpg 372,145,216,216
8467811762_86411f6f81_b.jpg 687,134,165,165
8467815306_5c9480efa8_b.jpg 427,208,206,206
8467816264_b28552f567_b.jpg 394,161,224,224
8467816586_eb55b5bbe0_b.jpg 184,118,262,262
8467819370_1428e0f1ae_b.jpg 104,107,257,257
executionTime= 28.411 sec

しかしながら私たちの仕事では精度がモノをいいますのでこちらが現実的な選択肢となるでしょう。
もちろん実行時間とのトレードオフの関係なのですが、External Objectは元々充分に速いので問題にはならないでしょう。
最後にこちらが今回使用した自動配置スクリプトです。

var pg = app.activeDocument.pages;
var sec = new Date();
var dx = 25, dy = 30;
var pageNum = 0;
var fdr = Folder.selectDialog (“select Targets…”);
var f = fdr.getFiles(“*.jpg”);
var cascade = “/faceDetecter/haarcascades/haarcascade_frontalface_alt_tree.xml”;
try {
     var extObj = new ExternalObject(“lib:faceDetecter.framework”);
     } catch(o_O){
          alert(o_O);
          }

var pos = new Array();
var i,bx,wd;
var tgtFile,bnds,dpi,wth,hgt,rslt;
var pw,ph,scale,ctr,x,y,imgWd,imgHgt;

for (var j=0;j<f.length;j++){
     tgt = pg[pageNum].rectangles.add();
     bx = [dy-25,dx-20,dy,dx];
     tgt.geometricBounds = bx;
     wd = bx[1] – bx[3];
     tgtFile = f[j].fsName;
     tgt.place(f[j]);
     bnds = tgt.graphics[0].geometricBounds;
     dpi = tgt.graphics[0].actualPpi[0];
     wth =  (bnds[3] – bnds[1]) ;
     hgt =  (bnds[2] – bnds[0]) ;
     var pos = extObj.trackFace(tgtFile, cascade);
     if (pos.length>0) {
          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();
               }
          $.write(f[j].name +” “+pos + “\n”);
          pw = pos[2] * 1.6 / dpi * 25.4;
          ph = pos[3] * 2 / dpi * 25.4;
          scale = wd / pw;
          ctr = [(pos[0]+pos[2]/2)/dpi*25.4,
                         (pos[1]+pos[3]/2)/dpi*25.4];

          x = ( ctr[0] – pw / 2 ) * scale;
          y = ctr[1] * scale – ( bx[0] – bx[2] ) * 0.6;
          imgWd = wth * scale;
          imgHgt = hgt * scale;

          tgt.graphics[0].geometricBounds = [
               y-imgHgt+bx[0],
               x-imgWd+bx[1],
               y+bx[0],
               x+bx[1]
               ];
          } else {
               tgt.fit (FitOptions.proportionally);
               tgt.fit (FitOptions.centerContent);
               tgt.strokeWeight =1;
               tgt.strokeColor = app.activeDocument.swatches[5];
               $.write(f[j].name + “\n”);
               }
     dx += 20;
     if (dx>210){
          dx = 25;
          dy += 25;
          }
     if (dy>297){
          pageNum++;
          app.activeDocument.pages.add();
          dx = 25;
          dy = 30;
          }
     }
var m = sec.getTime();
sec = new Date();
m = (sec.getTime() – m) / 1000;
$.write(“executionTime= ” + m +” sec\n”);
extObj.unload();

xmpからexifのプロパティぬくともっと単純なコードになります。機会があればやってみます。

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google フォト

Google アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中