マイクロソフトの画像認識APIの Computer Vision API を試してみた。API そのものより
- 「getUserMedia で動画を得る」->「スナップショットを取る」->「APIへアップロード」
って部分が勉強になったのでメモっておく。
Computer Vision APIとは
- Microsoftの画像認識API (site)
- REST で画像を投げると JSON 形式で画像を分析した結果を返してくれる
- 画像の説明文、画像になにが写ってるか、人物の年齢や性別、顔の座標、著名人の名前、有名な建物の名前、などを返してくれる
得られるJSONデータ
例えば以下のような画像をAPIに投げると...
次のようなJSONが返ってくる
{
"categories": [
{
"name": "others_",
"score": 0.0078125
},
{
"name": "outdoor_",
"score": 0.0078125,
"detail": {
"landmarks": []
}
},
{
"name": "people_",
"score": 0.30859375,
"detail": {
"celebrities": []
}
}
],
"adult": {
"isAdultContent": false,
"isRacyContent": false,
"adultScore": 0.0168526079505682,
"racyScore": 0.023264266550540924
},
"tags": [
{
"name": "outdoor",
"confidence": 0.9941964149475098
},
{
"name": "road",
"confidence": 0.9823024868965149
},
{
"name": "ground",
"confidence": 0.9675083756446838
},
{
"name": "boy",
"confidence": 0.920303225517273
},
{
"name": "person",
"confidence": 0.9178870320320129
},
{
"name": "young",
"confidence": 0.803716778755188
}
],
"description": {
"tags": [
"outdoor",
"road",
"boy",
"person",
"child",
"young",
"little",
"small",
"street",
"riding",
"sidewalk",
"man",
"holding",
"standing",
"side",
"baby",
"wearing",
"walking",
"board",
"fire",
"bed",
"hydrant"
],
"captions": [
{
"text": "a little boy that is standing on the side of a road",
"confidence": 0.8269637487808089
}
]
},
"requestId": "d7387e20-3e79-4b9b-b5b0-2eb967a71c7e",
"metadata": {
"width": 1600,
"height": 1200,
"format": "Jpeg"
},
"faces": [
{
"age": 6,
"gender": "Male",
"faceRectangle": {
"left": 777,
"top": 216,
"width": 127,
"height": 127
}
}
],
"color": {
"dominantColorForeground": "Grey",
"dominantColorBackground": "Grey",
"dominantColors": [
"Grey",
"White"
],
"accentColor": "436737",
"isBWImg": false
},
"imageType": {
"clipArtType": 0,
"lineDrawingType": 0
}
}
競合サービス
- 各社類似サービスを出している
- この記事(画像認識対決 ~Microsoft VS Google VS IBM~ - Qiita)を読む限り、この分野ではマイクロソフトが強そう
MicrosoftのAPIサービス郡での位置づけ
- Microsoftでは Cognitive Services という名のAPIサービス群を提供している
- サービスは以下のようにカテゴライズされてる
- Vision
- Speech
- Language
- Knowledge
- Search
- Visionカテゴリは以下で構成される
- Computer Vision
- Emotion (感情を推測する)
- Face (年齢を推測する)
- Video
利用に際して必要なこと
- Cognitive Servicesの利用開始登録(要クレジットカード番号)
- 30日間の無料試用可
- 各APIサービスの url と Subscription Key を得る(コードに記述する)
注意点
- 提示される url が正確でないので補正が必要
- Computer Vision API
- https://westcentralus.api.cognitive.microsoft.com/vision/v1.0/ + analyze
- 末尾に analyze を付け足す
- https://westcentralus.api.cognitive.microsoft.com/vision/v1.0/ + analyze
- Emotion API
- https://westus.api.cognitive.microsoft.com/emotion/v1.0/ + Srecognize
- 末尾に recognize を付け足す
- https://westus.api.cognitive.microsoft.com/emotion/v1.0/ + Srecognize
デモを作った
以下内容で動作するデモを作った
- 画像指定パターン
- ネットにある画像を指定
- ローカルの画像をアップロード
- カメラ(getUserMedia)でキャプチャした動画からスナップショットを取ってアップロード
- 顔認識した場合は顔の位置を囲み予想年齢を表示する
- JSONの表示
- 説明文を Web Speech API で喋らせる
- mobx + template stringで各UIをモジュール化(らしきことをしたがcssも含め結構ぐだぐだ)
- demo
- source
ネットにある画像を指定
const params = [
'visualFeatures=Categories,Tags, Description, Faces, ImageType, Color, Adult',
'details=Celebrities, Landmarks',
'language=en'
].join('&');
fetch('https://westcentralus.api.cognitive.microsoft.com/vision/v1.0/analyze?' + params, {
method: 'POST',
body: JSON.stringify({url: imgageUrl}),
headers: {
"Content-Type": 'application/json',
"Ocp-Apim-Subscription-Key": '260f006a16c04453........
}
}).then(function(response) {
return response.json();
}).then(json => {...})
- Content-Type は application/json を指定
- body は JSON.stringify で文字列変換
画像のアップロード
- Content-Type は application/octet-stream を指定
- body には File オブジェクトを指定
const file = document.querySelector('input[type=file]').files[0];
fetch('https://westcentralus.api.cognitive.microsoft.com/vision/v1.0/analyze?' + params, {
method: 'POST',
body: file,
...
- 画像のプレビューには FileReader を利用する
const reader = new FileReader();
const dataUrl = reader.readAsDataURL(file);
reader.onload = (file => {
return event => {
$img.src = event.target.result;
};
})(file);
getUserMediaでキャプチャしてアップロード
- Content-Type は application/octet-stream を指定
- body は blob に変換した画像を指定
キャプチャ開始
const config = {
video: true,
audio: false
};
navigator.mediaDevices.getUserMedia(config).then(stream => {
$video.src = URL.createObjectURL(stream);
$video.play();
});
静止画のdataUrlを得る
const ctx = $canvas.getContext("2d");
ctx.drawImage($video, 0, 0, 320, 240);
const dataUrl = $canvas.toDataURL(contentType);
dataUrlをblob形式に変換
const bin = atob(dataUrl.split(',')[1]);
const imageBuffer = new Uint8Array(bin.length);
for (let i = 0; i < bin.length; i++) {
imageBuffer[i] = bin.charCodeAt(i);
}
const blob = new Blob([imageBuffer.buffer], {type: contentType});
(追記)これでいけるらしい... 便利!
$canvas.toBlob(blob => {
...
}, contentType);