こんにちは。
入社してもうすぐ一年です。髭フェチの中村です。

みなさんは髭が好きですか?私は好きです。
世の中の男性みんな髭が生えればいいのになと思っています。

しかたがないので顔認識を使って、髭合成アプリをつくることにしました。

準備

いつでもどこでも開発できるように、ブラウザでほぼ完結したい、という理由から今回はMonacaを使用することにします。

MonacaはWEBブラウザで開発ができるアプリケーション。
HTML/CSS/JavaScriptでiOS・Androidアプリが作れます。

  • Monacaでユーザ登録をおこなってから、ダッシュボードへ。「新規プロジェクトの作成」をクリック。

  • テンプレートを選択する。
    今回は「Onsen UI」を使用。アプリ感のあるUIを表現できるライブラリです。

  • Cameraプラグインを有効にする。
    設定 -> Cordvaプラグインの管理 より、Cameraを有効にします。

  • JS/CSSコンポーネント -> jQuery(Monacaバージョン)を追加。

  • Monacaデバッガーをインストール。
    お手元のスマートフォンにインストールしてください。実機デバッグができます。これ、保存したソースコードがすぐ同期されます・・ありがたいです・・

これで準備が整いました!

カメラ機能をつかう

準備のときに設定したCordva(Monacaに内包されているフレームワーク)のCameraプラグインを使います。

javascript

<script>
  function getPhoto () {
    navigator.camera.getPicture (onSuccess, onFail, { 
        //0-100で画質を指定
        quality: 50,
        //画像のURIを返す指定
        destinationType: Camera.DestinationType.FILE_URI, 
        //端末のアルバムに画像を保存する
        saveToPhotoAlbum: true
    });

    //撮影に成功した場合
    function onSuccess (imageURI) {
        var image = document.getElementById ("image");
        imageURI = imageURI + "?" + Math.floor( new Date().getTime() / 1000 ) ;
        image.src = imageURI;
    }

    //撮影に失敗した場合
    function onFail (message) {
        alert ("Error occured: " + message);
    }
}
</script>

HTML

<body>
    <figure>
      <!-- 撮影前のダミー画像を置いている 撮影後、ここに画像が反映される -->
      <img src="img/placehold.png" style="width:100%;height:auto;" id="image">
    </figure>
    <br>
    <!-- ボタン -->
    <ons-button modifier="large--cta" should-spin="true" onClick="getPhoto()">撮るよ~</ons-button>
</body>

ボタンだけOnsen UI使ってます。。

modifier="large--cta"
で横いっぱいに広がるボタンを表現。

should-spin="true"
でボタンにスピナー表示するよう指定します。

Onsen UIのボタンコンポーネントに関するドキュメントはこちら

これでカメラで撮影⇒端末に保存&画面に表示ができました。

表示前の画像

撮影したあとの画像

男性の画像はこちらからお借りしています。

顔認識するよ!

顔認識にはFaceDetectionを使用します。
jQueryだけで顔認識ができちゃうライブラリです。とてもたすかります。

ダウンロードしたら jquery.facedetection.js を適切なところにおいて、
ヘッダに下記の記述をしてください。

<script src="js/jquery.facedetection.js"></script>

jsの記述は最終的にこんな感じ

<script>
//先に顔認識でつかうインスタンスを生成する
var img = new Image();

//ここからさっきのカメラ機能
function getPhoto () {
    navigator.camera.getPicture (onSuccess, onFail, { 
        quality: 50,
        destinationType: Camera.DestinationType.FILE_URI,
        saveToPhotoAlbum: true
    });

    //撮影に成功した場合
    function onSuccess (imageURI) {
        var image = document.getElementById ("image");
        //キャッシュを防ぐため画像にパラメータを追加
        imageURI = imageURI + "?" + Math.floor( new Date().getTime() / 1000 ) ;
        //カメラ用画像
        image.src = imageURI;
        //認証用画像
        img.src = imageURI;
    }

    //撮影に失敗した場合
    function onFail (message) {
        alert ("Error occured: " + message);
    }
}

//ここから顔認証
img.onload = function(){
    $("#image").faceDetection({
        complete: function (obj)
        {
         $("#loading").fadeOut();
          // 顔認識できなかった場合
          if(!obj.length)
          {
            alert("顔情報を認識できませんでした。") ;
            return false ;
          }
          // 顔認識できた場合
          else
          {
            for( var i=0 ; i<obj.length ; i++ )
            {
                $("#image").parent().css( {
                    position: "relative" ,
                    top: 0 ,
                    left: 0 ,
                }) ;
                // 画像に顔範囲を示す枠を表示する
                $("#image").after("<div class="facial-image-border"></div>");
                // 顔範囲の場所を動的に指定
                $(".facial-image-border").eq(i).css({
                "position": "absolute",
                "border": "4px solid rgb(255, 69, 0)",
                "left": ( obj[i].x * obj[i].scaleX ) + ( $("#image").offset().left - $("#image").parent().offset().left ) + "px" ,
                "top": ( obj[i].y * obj[i].scaleY ) + ( $("#image").offset().top - $("#image").parent().offset().top ) + "px" ,
                "width": obj[i].width  * obj[i].scaleX + "px" ,
                "height": obj[i].height * obj[i].scaleY + "px"
               });
            }
          }
        }
    });
}
</script>

もういちど撮影する

できたよ~~!

あとはこれに、髭を、生やします・・・後編につづきます・・

はまったこと

jQueryをscriptタグで参照しようとしたんですけどうまくいかず、色々調べてたらOnsen UIとjQueryとの相性が悪いようでみなさま四苦八苦されているようでした。。
結論としては今回の場合はMonacaのJS/CSSコンポーネントでjQueryを追加しただけで解決しました・・・

参考

下記のサイトを参考にさせていただきました!
JavaScriptで画像の顔認識をする方法【Face Detection】
カメラとアルバムの使用方法 – Monaca Docs
カメラ操作 プラグイン – Monaca Docs