やったもん勝ち

主にプログラミングのこと。生産性向上の某とかも。

顔認識・画像認識ライブラリAPIを使ってみる

経緯

個人的な趣味で、顔認識のAPIを使いたいなと思い立ちました。
OpenCVで自前でできないかなーとも思ったのですが、なかなか難しいっぽく、諦めてAPIを使うという選択になった次第です。

どこがAPIを提供しているのか、以下のリンクがとても参考になりました。
qiita.com

このリンクをもとに、それぞれ調べてみました。
調べる際の観点は「口の開閉が判別できるか」「その精度は確かか」という2点で調査をしました。
なお、調査したのは2017年の年末頃なので、この記事を書いている時点ですでに仕様が更新されている可能性があります。

目次

detectFace()

detectFace(); - 顔検出Webサービス → 2018.04.04にサービス提供終了になりました。

何より簡単に使えて、しかも無料というのがいい。 こんな感じのページ。
f:id:benzenetarou:20171125232836p:plain
このAPIでは50個の特徴量を返してくれるみたいだ。
f:id:benzenetarou:20171125232850p:plain
その結果、笑ってるか怒ってるかとかを判定したいと思ったらこっちで別途実装しなきゃいけないみたいだ。
それはそれで問題はないけども。

丁寧にサンプルページがあるので、実装する前に雰囲気確かめられる。
f:id:benzenetarou:20171125233223p:plain 早速でもページから画像を投げてみる。

帰ってくるxmlはこんな感じ

<?xml version='1.0'?>
<faces>
  <face id='0'>
    <bounds x='328' y='550' width='100' height='100'/>
    <right-eye x='365' y='591'/>
  </face>
  <face id='1'>
    <bounds x='292' y='549' width='106' height='106'/>
  </face>
  <face id='2'>
    <bounds x='706' y='256' width='709' height='709'/>
    <right-eye x='907' y='538'/>
    <left-eye x='1196' y='527'/>
    <features s-avg='0.83' s-min='0.66' s-max='0.95'>
      <point id='PR' x='921' y='536' s='0.80'/>
      <point id='PL' x='1192' y='525' s='0.94'/>
      <point id='BR2' x='1004' y='447' s='0.67'/>
      <point id='BL2' x='1111' y='431' s='0.82'/>
      <point id='N1' x='1057' y='531' s='0.78'/>
      <point id='N5' x='1064' y='689' s='0.86'/>
      <point id='M1' x='1068' y='796' s='0.85'/>
      <point id='M5' x='1071' y='895' s='0.74'/>
      <point id='M3' x='965' y='831' s='0.74'/>
      <point id='M7' x='1176' y='830' s='0.82'/>
      <point id='EL4' x='1257' y='534' s='0.93'/>
      <point id='EL1' x='1139' y='545' s='0.92'/>
      <point id='ER1' x='969' y='556' s='0.82'/>
      <point id='ER4' x='871' y='538' s='0.84'/>
      <point id='M2' x='1011' y='797' s='0.87'/>
      <point id='M8' x='1109' y='793' s='0.91'/>
      <point id='M4' x='1014' y='882' s='0.71'/>
      <point id='M6' x='1145' y='872' s='0.75'/>
      <point id='BR3' x='948' y='428' s='0.70'/>
      <point id='BL3' x='1187' y='409' s='0.84'/>
      <point id='N2' x='965' y='706' s='0.87'/>
      <point id='N4' x='1149' y='703' s='0.92'/>
      <point id='F1' x='1043' y='196' s='0.70'/>
      <point id='F2' x='842' y='260' s='0.89'/>
      <point id='F10' x='1252' y='286' s='0.69'/>
      <point id='ER2' x='949' y='525' s='0.82'/>
      <point id='ER3' x='891' y='522' s='0.81'/>
      <point id='ER5' x='897' y='560' s='0.83'/>
      <point id='ER6' x='936' y='567' s='0.81'/>
      <point id='EL2' x='1164' y='508' s='0.92'/>
      <point id='EL3' x='1231' y='508' s='0.93'/>
      <point id='EL5' x='1229' y='547' s='0.94'/>
      <point id='EL6' x='1170' y='551' s='0.92'/>
      <point id='BR1' x='994' y='489' s='0.72'/>
      <point id='BR4' x='890' y='436' s='0.79'/>
      <point id='BR5' x='841' y='492' s='0.82'/>
      <point id='BR6' x='919' y='449' s='0.77'/>
      <point id='BL1' x='1111' y='468' s='0.81'/>
      <point id='BL4' x='1240' y='414' s='0.83'/>
      <point id='BL5' x='1298' y='450' s='0.90'/>
      <point id='BL6' x='1226' y='437' s='0.85'/>
      <point id='N3' x='1068' y='737' s='0.92'/>
      <point id='M9' x='1068' y='834' s='0.83'/>
      <point id='F3' x='779' y='558' s='0.87'/>
      <point id='F9' x='1346' y='535' s='0.95'/>
      <point id='F4' x='817' y='741' s='0.81'/>
      <point id='F8' x='1323' y='720' s='0.90'/>
      <point id='F6' x='1041' y='1041' s='0.66'/>
      <point id='F5' x='849' y='880' s='0.78'/>
      <point id='F7' x='1307' y='879' s='0.83'/>
    </features>
  </face>
</faces>

自分の使いたい用途に合わせるとしたら、どこか口以外の基準点から標準化するポイントを複数見つけておいて、画像のサイズを標準化してから、口の周りの特徴点の距離を調べるという方法だろうか。

AWS Rekognito

画像認識に関連したいろいろなサービスがある感じ。
これが人工知能というくくりのサービスなのはちょっと変な感じするが。
f:id:benzenetarou:20171125235645p:plain
デモページもあった。
f:id:benzenetarou:20171125235803p:plain
ただ、これを見ると、でもページの画像でさえ口開いてるのに閉じてるって判定されてたので(しかも信頼度72%)、精度はそこまで良くないのかもしれない。
試しに自分で取った写真をアップロードしてみても、ちょくちょく誤判定されてしまっている。

JSONも返してくれるが、特徴量が少ない気がする。特に口周り。

{
    "FaceDetails": [
        {
            "BoundingBox": {
                "Width": 0.2618750035762787,
                "Height": 0.3930581510066986,
                "Left": 0.14937500655651093,
                "Top": 0.13414634764194489
            },
            "AgeRange": {
                "Low": 26,
                "High": 43
            },
            "Smile": {
                "Value": true,
                "Confidence": 99.0987319946289
            },
            "Eyeglasses": {
                "Value": true,
                "Confidence": 99.99999237060547
            },
            "Sunglasses": {
                "Value": true,
                "Confidence": 95.7325439453125
            },
            "Gender": {
                "Value": "Female",
                "Confidence": 100
            },
            "Beard": {
                "Value": false,
                "Confidence": 99.90460205078125
            },
            "Mustache": {
                "Value": false,
                "Confidence": 92.63785552978516
            },
            "EyesOpen": {
                "Value": true,
                "Confidence": 85.72091674804688
            },
            "MouthOpen": {
                "Value": false,
                "Confidence": 72.2423095703125
            },
            "Emotions": [
                {
                    "Type": "HAPPY",
                    "Confidence": 99.69184112548828
                },
                {
                    "Type": "CALM",
                    "Confidence": 1.0618865489959717
                },
                {
                    "Type": "ANGRY",
                    "Confidence": 0.44966936111450195
                }
            ],
            "Landmarks": [
                {
                    "Type": "eyeLeft",
                    "X": 0.2459116131067276,
                    "Y": 0.2963947355747223
                },
                {
                    "Type": "eyeRight",
                    "X": 0.32498690485954285,
                    "Y": 0.28320804238319397
                },
                {
                    "Type": "nose",
                    "X": 0.2972606122493744,
                    "Y": 0.338502436876297
                },
                {
                    "Type": "mouthLeft",
                    "X": 0.24349376559257507,
                    "Y": 0.43834927678108215
                },
                {
                    "Type": "mouthRight",
                    "X": 0.32762306928634644,
                    "Y": 0.4251043200492859
                },
                {
                    "Type": "leftPupil",
                    "X": 0.2514769434928894,
                    "Y": 0.2966562509536743
                },
                {
                    "Type": "rightPupil",
                    "X": 0.3339778780937195,
                    "Y": 0.28375154733657837
                },
                {
                    "Type": "leftEyeBrowLeft",
                    "X": 0.2145199030637741,
                    "Y": 0.2463952600955963
                },
                {
                    "Type": "leftEyeBrowUp",
                    "X": 0.2372017651796341,
                    "Y": 0.22838076949119568
                },
                {
                    "Type": "leftEyeBrowRight",
                    "X": 0.26641586422920227,
                    "Y": 0.2389357089996338
                },
                {
                    "Type": "rightEyeBrowLeft",
                    "X": 0.2992517352104187,
                    "Y": 0.23876728117465973
                },
                {
                    "Type": "rightEyeBrowUp",
                    "X": 0.3239707052707672,
                    "Y": 0.22483669221401215
                },
                {
                    "Type": "rightEyeBrowRight",
                    "X": 0.3491824269294739,
                    "Y": 0.23105363547801971
                },
                {
                    "Type": "leftEyeLeft",
                    "X": 0.22946621477603912,
                    "Y": 0.3019390404224396
                },
                {
                    "Type": "leftEyeRight",
                    "X": 0.2616650462150574,
                    "Y": 0.29498758912086487
                },
                {
                    "Type": "leftEyeUp",
                    "X": 0.24515913426876068,
                    "Y": 0.2873624563217163
                },
                {
                    "Type": "leftEyeDown",
                    "X": 0.24701011180877686,
                    "Y": 0.3033584654331207
                },
                {
                    "Type": "rightEyeLeft",
                    "X": 0.30755841732025146,
                    "Y": 0.2871529757976532
                },
                {
                    "Type": "rightEyeRight",
                    "X": 0.3417114317417145,
                    "Y": 0.2818377912044525
                },
                {
                    "Type": "rightEyeUp",
                    "X": 0.3245350122451782,
                    "Y": 0.27441540360450745
                },
                {
                    "Type": "rightEyeDown",
                    "X": 0.3257909119129181,
                    "Y": 0.2907133102416992
                },
                {
                    "Type": "noseLeft",
                    "X": 0.2787094712257385,
                    "Y": 0.38133224844932556
                },
                {
                    "Type": "noseRight",
                    "X": 0.308928519487381,
                    "Y": 0.37534570693969727
                },
                {
                    "Type": "mouthUp",
                    "X": 0.2901398241519928,
                    "Y": 0.4091244339942932
                },
                {
                    "Type": "mouthDown",
                    "X": 0.29399216175079346,
                    "Y": 0.4643388092517853
                }
            ],
            "Pose": {
                "Roll": -8.045867919921875,
                "Yaw": 17.916576385498047,
                "Pitch": 13.156755447387695
            },
            "Quality": {
                "Brightness": 40.16537857055664,
                "Sharpness": 99.9980239868164
            },
            "Confidence": 99.82343292236328
        }
    ]
}

Google Cloud Vision

顔認識もできるし、いろいろな情報も併せてくれる。
f:id:benzenetarou:20171126002419p:plain こんな感じでJSONを返してくれたりもするみたいだ。

dandaIMGL5048_TP_V.jpg
 {
  "faceAnnotations": [
    {
      "boundingPoly": {
        "vertices": [
          {
            "x": 583,
            "y": 49
          },
          {
            "x": 1029,
            "y": 49
          },
          {
            "x": 1029,
            "y": 567
          },
          {
            "x": 583,
            "y": 567
          }
        ]
      },
      "fdBoundingPoly": {
        "vertices": [
          {
            "x": 649,
            "y": 161
          },
          {
            "x": 975,
            "y": 161
          },
          {
            "x": 975,
            "y": 487
          },
          {
            "x": 649,
            "y": 487
          }
        ]
      },
      "landmarks": [
        {
          "type": "LEFT_EYE",
          "position": {
            "x": 719.5262,
            "y": 253.72295,
            "z": 0.000031506435
          }
        },
        {
          "type": "RIGHT_EYE",
          "position": {
            "x": 849.03937,
            "y": 267.75647,
            "z": -36.321598
          }
        },
        {
          "type": "LEFT_OF_LEFT_EYEBROW",
          "position": {
            "x": 686.8778,
            "y": 221.65237,
            "z": 27.712809
          }
        },
        {
          "type": "RIGHT_OF_LEFT_EYEBROW",
          "position": {
            "x": 754.03094,
            "y": 225.36835,
            "z": -30.87542
          }
        },
        {
          "type": "LEFT_OF_RIGHT_EYEBROW",
          "position": {
            "x": 816.0152,
            "y": 231.25845,
            "z": -48.467567
          }
        },
        {
          "type": "RIGHT_OF_RIGHT_EYEBROW",
          "position": {
            "x": 902.0392,
            "y": 247.53323,
            "z": -33.053932
          }
        },
        {
          "type": "MIDPOINT_BETWEEN_EYES",
          "position": {
            "x": 780.317,
            "y": 254.34734,
            "z": -45.376167
          }
        },
        {
          "type": "NOSE_TIP",
          "position": {
            "x": 760.82666,
            "y": 325.50342,
            "z": -93.64924
          }
        },
        {
          "type": "UPPER_LIP",
          "position": {
            "x": 758.0111,
            "y": 379.47757,
            "z": -70.47521
          }
        },
        {
          "type": "LOWER_LIP",
          "position": {
            "x": 750.76904,
            "y": 417.12973,
            "z": -67.296265
          }
        },
        {
          "type": "MOUTH_LEFT",
          "position": {
            "x": 709.657,
            "y": 398.31903,
            "z": -23.435837
          }
        },
        {
          "type": "MOUTH_RIGHT",
          "position": {
            "x": 818.4644,
            "y": 414.50378,
            "z": -52.383175
          }
        },
        {
          "type": "MOUTH_CENTER",
          "position": {
            "x": 756.7259,
            "y": 397.63107,
            "z": -63.729393
          }
        },
        {
          "type": "NOSE_BOTTOM_RIGHT",
          "position": {
            "x": 805.1426,
            "y": 346.799,
            "z": -55.52658
          }
        },
        {
          "type": "NOSE_BOTTOM_LEFT",
          "position": {
            "x": 733.29297,
            "y": 340.7746,
            "z": -35.59469
          }
        },
        {
          "type": "NOSE_BOTTOM_CENTER",
          "position": {
            "x": 763.22516,
            "y": 350.47217,
            "z": -67.04768
          }
        },
        {
          "type": "LEFT_EYE_TOP_BOUNDARY",
          "position": {
            "x": 721.1245,
            "y": 244.94334,
            "z": -8.15667
          }
        },
        {
          "type": "LEFT_EYE_RIGHT_CORNER",
          "position": {
            "x": 747.6377,
            "y": 259.79794,
            "z": -7.71021
          }
        },
        {
          "type": "LEFT_EYE_BOTTOM_BOUNDARY",
          "position": {
            "x": 718.8527,
            "y": 263.2192,
            "z": -2.942062
          }
        },
        {
          "type": "LEFT_EYE_LEFT_CORNER",
          "position": {
            "x": 699.73505,
            "y": 254.79391,
            "z": 18.149515
          }
        },
        {
          "type": "LEFT_EYE_PUPIL",
          "position": {
            "x": 719.1574,
            "y": 254.79868,
            "z": -3.427162
          }
        },
        {
          "type": "RIGHT_EYE_TOP_BOUNDARY",
          "position": {
            "x": 849.89404,
            "y": 260.44193,
            "z": -44.4995
          }
        },
        {
          "type": "RIGHT_EYE_RIGHT_CORNER",
          "position": {
            "x": 883.94965,
            "y": 276.54755,
            "z": -32.000946
          }
        },
        {
          "type": "RIGHT_EYE_BOTTOM_BOUNDARY",
          "position": {
            "x": 849.20135,
            "y": 277.8363,
            "z": -39.35131
          }
        },
        {
          "type": "RIGHT_EYE_LEFT_CORNER",
          "position": {
            "x": 823.90643,
            "y": 269.1588,
            "z": -29.444563
          }
        },
        {
          "type": "RIGHT_EYE_PUPIL",
          "position": {
            "x": 851.3009,
            "y": 270.67163,
            "z": -40.867477
          }
        },
        {
          "type": "LEFT_EYEBROW_UPPER_MIDPOINT",
          "position": {
            "x": 720.2593,
            "y": 205.07675,
            "z": -7.762258
          }
        },
        {
          "type": "RIGHT_EYEBROW_UPPER_MIDPOINT",
          "position": {
            "x": 859.88257,
            "y": 221.919,
            "z": -47.19713
          }
        },
        {
          "type": "LEFT_EAR_TRAGION",
          "position": {
            "x": 670.9434,
            "y": 339.6975,
            "z": 171.91898
          }
        },
        {
          "type": "RIGHT_EAR_TRAGION",
          "position": {
            "x": 963.58167,
            "y": 374.80206,
            "z": 89.242195
          }
        },
        {
          "type": "FOREHEAD_GLABELLA",
          "position": {
            "x": 783.9658,
            "y": 224.99454,
            "z": -44.277527
          }
        },
        {
          "type": "CHIN_GNATHION",
          "position": {
            "x": 748.6527,
            "y": 486.20532,
            "z": -57.60541
          }
        },
        {
          "type": "CHIN_LEFT_GONION",
          "position": {
            "x": 658.22473,
            "y": 415.8591,
            "z": 103.73505
          }
        },
        {
          "type": "CHIN_RIGHT_GONION",
          "position": {
            "x": 922.45325,
            "y": 447.898,
            "z": 29.103714
          }
        }
      ],
      "rollAngle": 9.122541,
      "panAngle": -15.808093,
      "tiltAngle": 7.937726,
      "detectionConfidence": 0.8733366,
      "landmarkingConfidence": 0.5498749,
      "joyLikelihood": "VERY_UNLIKELY",
      "sorrowLikelihood": "VERY_UNLIKELY",
      "angerLikelihood": "VERY_UNLIKELY",
      "surpriseLikelihood": "VERY_UNLIKELY",
      "underExposedLikelihood": "VERY_UNLIKELY",
      "blurredLikelihood": "VERY_UNLIKELY",
      "headwearLikelihood": "VERY_UNLIKELY"
    }
  ],
  "labelAnnotations": [
    {
      "mid": "/m/01xyhv",
      "description": "suit",
      "score": 0.855479
    },
    {
      "mid": "/m/01qkbx",
      "description": "professional",
      "score": 0.84650135
    },
    {
      "mid": "/m/0n5szg6",
      "description": "business executive",
      "score": 0.81015223
    },
    {
      "mid": "/m/012t_z",
      "description": "businessperson",
      "score": 0.7535335
    },
    {
      "mid": "/m/01kq3x",
      "description": "white collar worker",
      "score": 0.67039
    },
    {
      "mid": "/m/0289fz",
      "description": "executive officer",
      "score": 0.6614492
    },
    {
      "mid": "/m/09x_r",
      "description": "entrepreneur",
      "score": 0.638664
    },
    {
      "mid": "/m/09s1f",
      "description": "business",
      "score": 0.5803496
    },
    {
      "mid": "/m/05s9tm",
      "description": "talent manager",
      "score": 0.51430815
    },
    {
      "mid": "/m/019p5q",
      "description": "gentleman",
      "score": 0.50934017
    }
  ],
  "safeSearchAnnotation": {
    "adult": "VERY_UNLIKELY",
    "spoof": "VERY_UNLIKELY",
    "medical": "VERY_UNLIKELY",
    "violence": "VERY_UNLIKELY"
  },
  "imagePropertiesAnnotation": {
    "dominantColors": {
      "colors": [
        {
          "color": {
            "red": 230,
            "green": 230,
            "blue": 237
          },
          "score": 0.5333071,
          "pixelFraction": 0.5140667
        },
        {
          "color": {
            "red": 26,
            "green": 26,
            "blue": 28
          },
          "score": 0.21879509,
          "pixelFraction": 0.26526666
        },
        {
          "color": {
            "red": 205,
            "green": 203,
            "blue": 213
          },
          "score": 0.1390053,
          "pixelFraction": 0.11186667
        },
        {
          "color": {
            "red": 45,
            "green": 43,
            "blue": 47
          },
          "score": 0.029963521,
          "pixelFraction": 0.0282
        },
        {
          "color": {
            "red": 225,
            "green": 190,
            "blue": 189
          },
          "score": 0.01627379,
          "pixelFraction": 0.012933333
        },
        {
          "color": {
            "red": 164,
            "green": 159,
            "blue": 165
          },
          "score": 0.014597795,
          "pixelFraction": 0.0132
        },
        {
          "color": {
            "red": 226,
            "green": 183,
            "blue": 174
          },
          "score": 0.007874987,
          "pixelFraction": 0.014666666
        },
        {
          "color": {
            "red": 123,
            "green": 118,
            "blue": 121
          },
          "score": 0.0060422462,
          "pixelFraction": 0.0058
        },
        {
          "color": {
            "red": 246,
            "green": 214,
            "blue": 214
          },
          "score": 0.005779971,
          "pixelFraction": 0.0045333332
        },
        {
          "color": {
            "red": 86,
            "green": 83,
            "blue": 85
          },
          "score": 0.005673399,
          "pixelFraction": 0.0055333334
        }
      ]
    }
  },
  "cropHintsAnnotation": {
    "cropHints": [
      {
        "boundingPoly": {
          "vertices": [
            {
              "x": 351
            },
            {
              "x": 1215
            },
            {
              "x": 1215,
              "y": 1065
            },
            {
              "x": 351,
              "y": 1065
            }
          ]
        },
        "confidence": 1,
        "importanceFraction": 0.95
      },
      {
        "boundingPoly": {
          "vertices": [
            {
              "x": 255
            },
            {
              "x": 1343
            },
            {
              "x": 1343,
              "y": 1065
            },
            {
              "x": 255,
              "y": 1065
            }
          ]
        },
        "confidence": 1,
        "importanceFraction": 0.98999995
      },
      {
        "boundingPoly": {
          "vertices": [
            {
              "x": 127
            },
            {
              "x": 1423
            },
            {
              "x": 1423,
              "y": 1065
            },
            {
              "x": 127,
              "y": 1065
            }
          ]
        },
        "confidence": 1,
        "importanceFraction": 0.98999995
      }
    ]
  },
  "webDetection": {
    "webEntities": [
      {
        "entityId": "/g/12bprj7th",
        "score": 1.1322
      },
      {
        "entityId": "/g/1tgwpw14",
        "score": 1.0244
      },
      {
        "entityId": "/m/09s1f",
        "score": 0.7011,
        "description": "Business"
      },
      {
        "entityId": "/m/01m2bt",
        "score": 0.6569,
        "description": "Venture capital"
      },
      {
        "entityId": "/m/03bxgrp",
        "score": 0.6054,
        "description": "Company"
      },
      {
        "entityId": "/m/018s5w",
        "score": 0.5943,
        "description": "Capital"
      },
      {
        "entityId": "/m/02_7t",
        "score": 0.5428,
        "description": "Finance"
      },
      {
        "entityId": "/g/1203l_bt9",
        "score": 0.5194
      },
      {
        "entityId": "/m/02nwq",
        "score": 0.5148,
        "description": "Entrepreneurship"
      },
      {
        "entityId": "/m/03m3ym9",
        "score": 0.5101,
        "description": "Angel investor"
      },
      {
        "entityId": "/m/023k2",
        "score": 0.4496,
        "description": "Corporation"
      },
      {
        "entityId": "/m/03jzl9",
        "score": 0.4287,
        "description": "Share"
      },
      {
        "entityId": "/m/0dlrgy",
        "score": 0.4206,
        "description": "All China Lawyers Association"
      },
      {
        "entityId": "/m/0h3z7",
        "score": 0.4193,
        "description": "Initial public offering"
      },
      {
        "entityId": "/m/0lbmv",
        "score": 0.20668001,
        "description": "Shenzhen"
      }
    ],
    "fullMatchingImages": [
      {
        "url": "http://timscholten.com/wp-content/uploads/2017/05/TimScholten-5.jpg"
      },
      {
        "url": "https://www.pakutaso.com/shared/img/thumb/dandaIMGL5048.jpg"
      },
      {
        "url": "http://stat.profile.ameba.jp/profile_images/20130317/19/1e/9f/j/o180025201363516460689.jpg"
      },
      {
        "url": "http://www.gdszlvshi.com/UploadFiles/201662015263786.jpg"
      },
      {
        "url": "https://www.pakutaso.com/shared/img/thumb/dandaIMGL5048_TP_V.jpg"
      },
      {
        "url": "https://image.jimcdn.com/app/cms/image/transf/none/path/s4684c34cfcc8a80d/image/i400bb0104d9c3726/version/1454214695/image.jpg"
      },
      {
        "url": "http://felvidek.ma/wp-content/uploads/2017/10/Becse-Norbert-fot%C3%B3-MKP.jpg"
      },
      {
        "url": "http://www.wscom.com.br/arqs/arquivos/arquivos/201303081003240000008330.jpg"
      },
      {
        "url": "http://upload-images.jianshu.io/upload_images/2548788-875d2c3997d23c47.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"
      },
      {
        "url": "https://www.pakutaso.com/shared/img/thumb/dandaIMGL5048_TP_V4.jpg"
      },
      {
        "url": "http://www.prachachat.net/online/2016/10/14775681281477568341l.jpg"
      },
      {
        "url": "http://www.yemacaijing.com/kindeditor/attached/image/20160212/20160212155959_73709.jpg"
      },
      {
        "url": "https://www.pakutaso.com/shared/img/thumb/dandaIMGL5048_TP_V1.jpg"
      },
      {
        "url": "http://stat.profile.ameba.jp/profile_images/20160930/02/f3/Ot/j/o045204531475169331139.jpg"
      },
      {
        "url": "https://image.jimcdn.com/app/cms/image/transf/dimension=210x1024:format=jpg/path/s4684c34cfcc8a80d/image/i400bb0104d9c3726/version/1454214695/image.jpg"
      },
      {
        "url": "http://happymakeproject.com/wp-content/uploads/2016/02/image.jpg"
      },
      {
        "url": "https://media.licdn.com/mpr/mpr/shrinknp_200_200/AAEAAQAAAAAAAATyAAAAJDEyMmM3MWY3LTQwZmYtNGI1Yi05ZjA1LTIxNzJhOGM1NjU4Ng.jpg"
      },
      {
        "url": "https://media.licdn.com/mpr/mpr/shrinknp_200_200/AAEAAQAAAAAAAA3VAAAAJGY0ZThlMDg3LTdlMTYtNDAxMC05NzZhLTJiYWRmNjA5OTM0Yw.jpg"
      },
      {
        "url": "http://img2.cyzone.cn/uploadfile/2015/0710/fa4005041f412e73d576693097584382.jpg"
      },
      {
        "url": "https://media.licdn.com/mpr/mpr/shrink_100_100/AAEAAQAAAAAAAAxMAAAAJDliODg1ZWJmLTM5OTctNDk1Yi1iMTg0LTc5MWQ4YjAxZGQ3Yw.jpg"
      }
    ],
    "partialMatchingImages": [
      {
        "url": "https://www.pakutaso.com/shared/img/thumb/dandaIMGL5048_TP_V2.jpg"
      }
    ],
    "pagesWithMatchingImages": [
      {
        "url": "https://www.linkedin.com/in/andrewbwillis"
      },
      {
        "url": "http://timscholten.com/media-sheet/images/"
      },
      {
        "url": "https://sg.linkedin.com/in/amy-aw-1804433a"
      },
      {
        "url": "https://holaconnect.com/profile/margaux-lefort-email-phone-93fee623"
      },
      {
        "url": "http://felvidek.ma/2017/10/becse-norbert-mindent-megtesz-a-komaromi-jaras-fellenditese-erdekeben/"
      },
      {
        "url": "http://www.yemacaijing.com/index/view/id/84.html"
      },
      {
        "url": "http://www.yemacaijing.com/Index/view/id/84.html"
      },
      {
        "url": "http://www.wscom.com.br/noticias/economia/JOAO+PESSOA+GANHA+CONCESSIONARIA+AUDI+-145150"
      },
      {
        "url": "https://www.pakutaso.com/person/"
      },
      {
        "url": "http://www.cyzone.cn/d/20150601/470.html"
      },
      {
        "url": "http://happymakeproject.com/8678/"
      },
      {
        "url": "https://dandashokai.com/8667"
      },
      {
        "url": "http://www.cyzone.cn/f/20150710/1664.html"
      },
      {
        "url": "https://www.prachachat.net/news_detail.php?newsid=1477568128"
      },
      {
        "url": "https://www.pakutaso.com/person/man/"
      },
      {
        "url": "http://www.jianshu.com/p/3580429d0a50"
      },
      {
        "url": "http://m.prachachat.net/news_detail.php?newsid=1477568128"
      },
      {
        "url": "http://profile.ameba.jp/dramamaster/"
      },
      {
        "url": "http://profile.ameba.jp/panicgekitai"
      },
      {
        "url": "http://www.gdszlvshi.com/showteam_1.html"
      },
      {
        "url": "http://www.gdszlvshi.com/team.html"
      },
      {
        "url": "https://panickaiketsu.jimdo.com/%E4%B8%89%E6%9C%A8%E3%83%92%E3%83%AD%E3%82%B7%E3%81%AE%E3%83%97%E3%83%AD%E3%83%95%E3%82%A3%E3%83%BC%E3%83%AB/"
      },
      {
        "url": "http://hyperacy.site/%E0%B9%82%E0%B8%A1%E0%B8%A1%E0%B8%B9%E0%B8%AB%E0%B8%B0-%E0%B8%A3%E0%B8%B2%E0%B8%84%E0%B8%B2/"
      },
      {
        "url": "http://www.10800.com/investor/details/id/14309"
      },
      {
        "url": "https://holaconnect.com/profile/maman-bureau-email-phone-acf2ca62"
      }
    ],
    "visuallySimilarImages": [
      {
        "url": "http://www.realestateforachangingworld.co.uk/wp-content/uploads/2017/10/andy_martin-500x500.jpg"
      },
      {
        "url": "https://www.irep.co.jp/global/wp-content/uploads/2016/03/Samuel3-e1485150192823.png"
      },
      {
        "url": "http://www.bu.ac.th/wp-content/uploads/2016/07/%E0%B8%84%E0%B8%B8%E0%B8%93%E0%B8%A8%E0%B8%B8%E0%B8%A0%E0%B8%8A%E0%B8%B1%E0%B8%A2.jpg"
      },
      {
        "url": "https://ireward.superghs.com/resource/htoo/page/Mr-Manish-Gupta.jpg"
      },
      {
        "url": "http://www.recruit-rgf.com/csr/img/csr_common_president01.jpg"
      },
      {
        "url": "https://www.capitalfirst.com/front-end/img/board-members/bm2.jpg"
      },
      {
        "url": "https://www.dialog.lk/dialogdocroot/content/images/pr/supun.jpg"
      },
      {
        "url": "https://lookaside.fbsbx.com/lookaside/crawler/media/?media_id=1116763798456374"
      },
      {
        "url": "https://8iholdings.com/wp-content/uploads/2017/02/Profile-Joshua-440x440.jpg"
      }
    ]
  }
}

Microsoft Face API

返ってくるJSONはこんな感じらしい。

Response:
[
  {
    "faceAttributes": {
      "accessories": [],
      "age": 22.9,
      "blur": {
        "blurLevel": "low",
        "value": 0.06
      },
      "emotion": {
        "anger": 0.0,
        "contempt": 0.0,
        "disgust": 0.0,
        "fear": 0.0,
        "happiness": 0.0,
        "neutral": 0.986,
        "sadness": 0.009,
        "surprise": 0.005
      },
      "exposure": {
        "exposureLevel": "goodExposure",
        "value": 0.67
      },
      "facialHair": {
        "beard": 0.0,
        "moustache": 0.0,
        "sideburns": 0.0
      },
      "gender": "female",
      "glasses": "NoGlasses",
      "hair": {
        "bald": 0.0,
        "hairColor": [
          {
            "color": "brown",
            "confidence": 1.0
          },
          {
            "color": "black",
            "confidence": 0.87
          },
          {
            "color": "other",
            "confidence": 0.51
          },
          {
            "color": "blond",
            "confidence": 0.08
          },
          {
            "color": "red",
            "confidence": 0.08
          },
          {
            "color": "gray",
            "confidence": 0.02
          }
        ],
        "invisible": false
      },
      "headPose": {
        "pitch": 0.0,
        "roll": 0.1,
        "yaw": -32.9
      },
      "makeup": {
        "eyeMakeup": true,
        "lipMakeup": true
      },
      "noise": {
        "noiseLevel": "low",
        "value": 0.0
      },
      "occlusion": {
        "eyeOccluded": false,
        "foreheadOccluded": false,
        "mouthOccluded": false
      },
      "smile": 0.0
    },
    "faceId": "49d55c17-e018-4a42-ba7b-8cbbdfae7c6f",
    "faceRectangle": {
      "height": 162,
      "left": 177,
      "top": 131,
      "width": 162
    }
  }
]

あまり詳細な表情の情報は渡してくれないみたいだ。
もうこっちがやっとくから、君たちは結果だけ見てればいいの。感が強い。ヤダ。

Face++

Face Landmark SDK - Face++ Cognitive Services

なんと顔の特徴料が106個あると。
しかも無料だと。
なんやかんやこれが一番良さそうだ。

ただ、使ってみるまでがちょっと面倒くさいです。
まずアカウントを登録して(メールが届くのが5分くらいかかった!)、携帯電話番号とかも登録しなくちゃAPIKeyが取得できません。
これで使い物にならなかったら腹立ちますね。 中国のサービスなので、電話番号とか悪用されないかなと心配してたのですが、この会社割りと有名な会社だったみたいですね。恥ずかしい。

中国の顔認証スタートアップFace++が2500万米ドルを調達、Jack Ma(馬雲)氏も顔認証決済を導入へ - THE BRIDGE(ザ・ブリッジ)

{
  "image_id": "5XkklHlGoc1WTKaw25w5ww==",
  "request_id": "1511624338,e08986b0-891b-46fb-9b1a-2c77a83dccbb",
  "time_used": 427,
  "faces": [
    {
      "landmark": {
        "mouth_upper_lip_left_contour2": {
          "y": 384,
          "x": 719
        },
        "mouth_upper_lip_left_contour3": {
          "y": 396,
          "x": 728
        },
        "mouth_lower_lip_right_contour3": {
          "y": 415,
          "x": 772
        },
        "mouth_upper_lip_left_contour1": {
          "y": 372,
          "x": 743
        },
        "left_eye_upper_left_quarter": {
          "y": 248,
          "x": 706
        },
        "left_eyebrow_lower_middle": {
          "y": 220,
          "x": 716
        },
        "contour_chin": {
          "y": 511,
          "x": 750
        },
        "left_eyebrow_lower_left_quarter": {
          "y": 219,
          "x": 699
        },
        "right_eyebrow_lower_left_quarter": {
          "y": 235,
          "x": 832
        },
        "mouth_lower_lip_right_contour1": {
          "y": 402,
          "x": 783
        },
        "mouth_lower_lip_left_contour2": {
          "y": 408,
          "x": 717
        },
        "left_eye_bottom": {
          "y": 260,
          "x": 717
        },
        "mouth_lower_lip_bottom": {
          "y": 412,
          "x": 753
        },
        "contour_left9": {
          "y": 497,
          "x": 717
        },
        "mouth_lower_lip_top": {
          "y": 394,
          "x": 755
        },
        "right_eyebrow_upper_middle": {
          "y": 217,
          "x": 859
        },
        "right_eyebrow_left_corner": {
          "y": 232,
          "x": 806
        },
        "right_eye_bottom": {
          "y": 279,
          "x": 849
        },
        "contour_left7": {
          "y": 448,
          "x": 680
        },
        "contour_left6": {
          "y": 416,
          "x": 673
        },
        "contour_left5": {
          "y": 382,
          "x": 671
        },
        "contour_left4": {
          "y": 349,
          "x": 671
        },
        "contour_left3": {
          "y": 317,
          "x": 672
        },
        "contour_left2": {
          "y": 287,
          "x": 677
        },
        "contour_left1": {
          "y": 257,
          "x": 684
        },
        "left_eye_lower_left_quarter": {
          "y": 258,
          "x": 705
        },
        "mouth_upper_lip_top": {
          "y": 376,
          "x": 757
        },
        "contour_right3": {
          "y": 371,
          "x": 992
        },
        "contour_right2": {
          "y": 328,
          "x": 997
        },
        "mouth_left_corner": {
          "y": 405,
          "x": 701
        },
        "contour_right4": {
          "y": 414,
          "x": 982
        },
        "contour_right7": {
          "y": 504,
          "x": 893
        },
        "left_eyebrow_left_corner": {
          "y": 219,
          "x": 683
        },
        "nose_right": {
          "y": 346,
          "x": 814
        },
        "right_eye_upper_right_quarter": {
          "y": 266,
          "x": 867
        },
        "nose_tip": {
          "y": 321,
          "x": 757
        },
        "contour_right5": {
          "y": 453,
          "x": 963
        },
        "nose_contour_lower_middle": {
          "y": 354,
          "x": 762
        },
        "right_eye_top": {
          "y": 261,
          "x": 850
        },
        "mouth_lower_lip_left_contour3": {
          "y": 410,
          "x": 735
        },
        "right_eye_right_corner": {
          "y": 275,
          "x": 881
        },
        "right_eye_lower_right_quarter": {
          "y": 278,
          "x": 866
        },
        "mouth_upper_lip_right_contour2": {
          "y": 393,
          "x": 794
        },
        "right_eyebrow_lower_right_quarter": {
          "y": 239,
          "x": 883
        },
        "left_eye_left_corner": {
          "y": 253,
          "x": 695
        },
        "mouth_right_corner": {
          "y": 417,
          "x": 811
        },
        "mouth_upper_lip_right_contour3": {
          "y": 402,
          "x": 784
        },
        "right_eye_lower_left_quarter": {
          "y": 276,
          "x": 834
        },
        "left_eyebrow_right_corner": {
          "y": 224,
          "x": 752
        },
        "left_eyebrow_lower_right_quarter": {
          "y": 223,
          "x": 734
        },
        "right_eye_center": {
          "y": 272,
          "x": 850
        },
        "left_eye_upper_right_quarter": {
          "y": 251,
          "x": 731
        },
        "mouth_lower_lip_left_contour1": {
          "y": 396,
          "x": 728
        },
        "contour_left8": {
          "y": 475,
          "x": 695
        },
        "nose_left": {
          "y": 336,
          "x": 726
        },
        "right_eyebrow_lower_middle": {
          "y": 236,
          "x": 858
        },
        "left_eye_top": {
          "y": 247,
          "x": 718
        },
        "left_eye_center": {
          "y": 255,
          "x": 718
        },
        "left_eye_lower_right_quarter": {
          "y": 260,
          "x": 729
        },
        "nose_contour_right1": {
          "y": 269,
          "x": 805
        },
        "contour_right9": {
          "y": 516,
          "x": 798
        },
        "right_eye_left_corner": {
          "y": 272,
          "x": 819
        },
        "left_eyebrow_upper_left_quarter": {
          "y": 207,
          "x": 698
        },
        "left_eye_pupil": {
          "y": 253,
          "x": 718
        },
        "right_eyebrow_upper_left_quarter": {
          "y": 219,
          "x": 831
        },
        "contour_right8": {
          "y": 514,
          "x": 846
        },
        "right_eyebrow_right_corner": {
          "y": 243,
          "x": 906
        },
        "right_eye_upper_left_quarter": {
          "y": 264,
          "x": 833
        },
        "left_eyebrow_upper_middle": {
          "y": 206,
          "x": 718
        },
        "right_eyebrow_upper_right_quarter": {
          "y": 223,
          "x": 886
        },
        "nose_contour_left1": {
          "y": 265,
          "x": 758
        },
        "nose_contour_left2": {
          "y": 312,
          "x": 738
        },
        "mouth_upper_lip_right_contour1": {
          "y": 375,
          "x": 771
        },
        "contour_right1": {
          "y": 285,
          "x": 999
        },
        "nose_contour_right2": {
          "y": 320,
          "x": 806
        },
        "mouth_lower_lip_right_contour2": {
          "y": 417,
          "x": 792
        },
        "contour_right6": {
          "y": 484,
          "x": 933
        },
        "nose_contour_right3": {
          "y": 352,
          "x": 788
        },
        "nose_contour_left3": {
          "y": 346,
          "x": 742
        },
        "left_eye_right_corner": {
          "y": 258,
          "x": 740
        },
        "left_eyebrow_upper_right_quarter": {
          "y": 211,
          "x": 737
        },
        "right_eye_pupil": {
          "y": 269,
          "x": 849
        },
        "mouth_upper_lip_bottom": {
          "y": 395,
          "x": 755
        }
      },
      "attributes": {
        "emotion": {
          "sadness": 0.044,
          "neutral": 31.453,
          "disgust": 21.391,
          "anger": 47.017,
          "surprise": 0.032,
          "fear": 0.032,
          "happiness": 0.032
        },
        "gender": {
          "value": "Male"
        },
        "age": {
          "value": 37
        },
        "eyestatus": {
          "left_eye_status": {
            "normal_glass_eye_open": 1.785,
            "no_glass_eye_close": 0,
            "occlusion": 0.355,
            "no_glass_eye_open": 97.712,
            "normal_glass_eye_close": 0.003,
            "dark_glasses": 0.145
          },
          "right_eye_status": {
            "normal_glass_eye_open": 0.004,
            "no_glass_eye_close": 0,
            "occlusion": 0.005,
            "no_glass_eye_open": 99.991,
            "normal_glass_eye_close": 0,
            "dark_glasses": 0
          }
        },
        "glass": {
          "value": "None"
        },
        "headpose": {
          "yaw_angle": 22.35016,
          "pitch_angle": -8.229241,
          "roll_angle": 9.0831785
        },
        "blur": {
          "blurness": {
            "threshold": 50,
            "value": 0.378
          },
          "motionblur": {
            "threshold": 50,
            "value": 0.378
          },
          "gaussianblur": {
            "threshold": 50,
            "value": 0.378
          }
        },
        "smile": {
          "threshold": 30.1,
          "value": 3.299
        },
        "facequality": {
          "threshold": 70.1,
          "value": 6.392
        },
        "ethnicity": {
          "value": "Asian"
        }
      },
      "face_rectangle": {
        "width": 316,
        "top": 201,
        "left": 657,
        "height": 316
      },
      "face_token": "06ae41e4d9d9fe3f614ea82bfbdeb289"
    }
  ]

まずはDetect APIで顔を検出してから、その顔のIDを渡すことでAnalyze APIが使えるようです。

IBM

デモページはこんな感じ
f:id:benzenetarou:20171127231201p:plain
Sweetheart(恋人)かどうか判定できるってのはすごいな〜
男女二人組を恋人なのかどうか見分けられるってすごいな〜

でも特徴量とかはくれないみたいだ。
JSONはこんな感じ。

結果とスコアしかくれない。

{
  "classes": [
    {
      "class": "person",
      "score": 0.851
    },
    {
      "class": "sweetheart",
      "score": 0.581,
      "type_hierarchy": "/person/sweetheart"
    },
    {
      "class": "people",
      "score": 0.597,
      "type_hierarchy": "/person/people"
    },
    {
      "class": "couple",
      "score": 0.518,
      "type_hierarchy": "/person/couple"
    },
    {
      "class": "woman",
      "score": 0.556,
      "type_hierarchy": "/person/female/woman"
    },
    {
      "class": "female",
      "score": 0.5
    },
    {
      "class": "Indian red color",
      "score": 0.988
    }
  ],
  "classifier_id": "default",
  "name": "default"
}

結論

結論は、Face++を使ってみることにしました。
理由としては、特徴量が一番多く、精度も高そうだったためです。
(と、まとめるにあたってもう一度見渡してみたら、無料だしdetectFaceでも良かったのではないかな…と思っています。
と思って改めて見てみたら2018/0404にサービス終了していました。そういえば、これを採用しなかった理由は、提供元があまり聞いたことない会社だったのとで、いつサービス終了するかわからなかったのと、http通信なので、自分の顔写真を送るのには抵抗があったからでした。あの時の自分は正しかった!) あとGoogle Cloud APIも悪くなかったと思うのですが、若干Face++よりもお高かったので、お見送りになりました。
次回は実際にFace++を用いて自己満サービスを作りたいと思います。