LoginSignup
10
19

More than 3 years have passed since last update.

Raspberry Pi のカメラモジュールとFACE++で顔識別する

Last updated at Posted at 2016-11-19

先日RaspberryPiにOpecCVをインストールしてみました。(Raspberry Pi のカメラモジュールとOpen CV3で顔認識する - Qiita

OpenCVの特徴分類器を利用すれば顔識別も出来るようなのですが、少々難易度が高そうなので、今回は中国製API、FACE++ を利用しました。

face++.gif

環境

IMG_8879.jpg

  • Raspberry Pi3 (RASPBIAN JESSIE WITH PIXEL 4.4 / node.js v6.8.1)
  • Raspberry Pi カメラモジュール Raspberry Pi Camera Board
  • Raspberry Pi カメラモジュール専用 Blackケース
  • パルプ・フィクション/ サミュエル・L・ジャクソン ジュールス・ウィンフィールド 13インチ トーキングフィギュア
  • パルプ・フィクション/ ジョン・トラボルタ ビンセント・ベガ 13インチ トーキングフィギュア

FACE++

結構以前に話題になったWebサービスで、APIも公開されています。パラメーターはこちらで詳しく解説されています。

Face++のAPIを使って、PHPで顔認証をする方法 - Syncer

さらに認識した顔をグルーピングし、識別するAPIがありました。こちらで詳しく解説されています。

無料API「face++」で顔から双子を判別 - FaMirror Project

OpenCVを利用してRasPiから顔画像の抽出が出来るようになったので、それを利用します。今回読み込む画像は各10枚づつにしました。

Jules face 1 - Cloudup 2016-11-19 19-59-40.png

ちなみに画像をGETリクエストするとこんなレスポンスが得られます。

{
    "face": [
        {
            "attribute": {
                "age": {
                    "range": 7, 
                    "value": 42
                }, 
                "gender": {
                    "confidence": 99.9747, 
                    "value": "Male"
                }, 
                "race": {
                    "confidence": 97.8304, 
                    "value": "Black"
                }, 
                "smiling": {
                    "value": 0.734695
                }
            }, 
            "face_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 
            //略
}

黒人男性で42歳前後、と識別されました。

Vincent face 1 - Cloudup 2016-11-19 20-00-09.png

{
    "face": [
        {
            "attribute": {
                "age": {
                    "range": 7, 
                    "value": 34
                }, 
                "gender": {
                    "confidence": 96.3747, 
                    "value": "Male"
                }, 
                "race": {
                    "confidence": 99.90299999999999, 
                    "value": "White"
                }, 
                "smiling": {
                    "value": 9.09543
                }
            }, 
            "face_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 
            //略
}

白人男性で34歳前後と出ました。

これらのidを名前毎に分類し、さらにグループとして登録します。今回はサミュエル・L・ジャクソン、ジョン・トラボルタ、私の3名を登録しました。

登録したグループに撮影した写真をGETリクエストするとこのようなレスポンスが得られます。

face.jpg

{
    "face": [
        {
            "candidate": [
                {
                    "confidence": 75.559387, 
                    "person_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 
                    "person_name": "samuel", 
                    "tag": ""
                }, 
                {
                    "confidence": 2.307938, 
                    "person_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 
                    "person_name": "travolta", 
                    "tag": ""
                }, 
                {
                    "confidence": 0.967236, 
                    "person_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 
                    "person_name": "pon_dad", 
                    "tag": ""
                }
            ], 
            "face_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 
            //略
    "session_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}

samuelの確率75.5%、travoltaの確率2.3%、pon_dadの確率0.9%と出ました。まあ、間違いなく私では無いということが分かります。

curl -X POST コマンドでリクエスト

RasPiとOpenCVで撮影・保存した画像をGETリクエストで送信するのにrequestモジュールを使おうと思ったのですが、上手くいかなかったのでここはchild_prosesscurl -X POSTコマンドを利用することにしました。

app.js

//略 OpenCVで顔画像を切り出して保存
im2.save('./public/images/face_2.jpg')

var filename = "./public/images/face_2.jpg"

var facepp = exec('curl -X POST "https://apicn.faceplusplus.com/recognition/identify?api_key=<API KEY>e&api_secret=<API Secret>&group_name=pulp_fiction" -F "img=@' + filename + '"'

jsonデータの抽出

配列と連想配列が混在したjsonデータを抽出すると訳が分からなくなるのですが、こちらの記事(【js】jsonデータの配列を取得して取り出すお話 - 仕事の事やプライベートな事を適当に書いていくブログ)を参考になんとか欲しいデータを抽出することが出来ました。

こんな感じです。

app.js

//略 OpenCVで顔画像を切り出して保存
im2.save('./public/images/face_2.jpg')

var filename = "./public/images/face_2.jpg"

var facepp = exec('curl -X POST "https://apicn.faceplusplus.com/recognition/identify?api_key=<API KEY>e&api_secret=<API Secret>&group_name=pulp_fiction" -F "img=@' + filename + '"',
        function (error, res) {
          console.log(res)
          var identify = JSON.parse(res)
          var a = identify.face
          var b = []
          var c = []

          for (var i = 0; i < a.length; i++) {
            for (var j = 0; j < a[i]["candidate"].length; j++) {
              b.push(a[i]["candidate"][j].person_name);
              c.push(a[i]["candidate"][j].confidence);
            };
          };
          if(c[0] > 60){
          console.log(b[0])
          console.log(c[0])
          io.sockets.emit('msg', b[0] + ' ' + c[0]);
          }

今回のグループは3人なので、レスポンスデータの3人を配列に入れて一番最初の人名と割合を抽出しました。

今回は確率が60%以上で本人と判断し、本人に場合はsocket.ioemitを利用してクライアントサイドにその内容を送信します。

QT 2016-11-19 15-21-37.png

QT 2016-11-19 15-22-21.png

 まとめ

今回は対象がフィギュアということもあり、またRasPiのカメラを使って正面から撮影しているので、学習させる写真が10枚位でも判別がつきました。(本人認証を思いつきで60%以上と設定したのですが、根拠は特ありません。一般的には何%位で本人だと判断するのでしょうか…。)

スナップ写真やインターネット上の画像などを利用する際は、トリミングの加工・変形などもう少し工夫が必要だと思います。

ロボットに取り付けた固定式のカメラなどでは、結構使えるかもしれませんね。ではまた。

10
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
19