LoginSignup
9

More than 1 year has passed since last update.

posted at

updated at

Organization

Azure画像認識系の機能をいくつか試してみた(Face API / Custom Vision API / Computer Vision API)

私自身初めてMicrosoftのAzureを使ってみました。
ここでは、Azureを使う為にやることと、Face API / Custom Vision API / Computer Vision API の使い方や応用サンプルをまとめます。

1.Microsoft Azureを使ってみる

初めて使う人のための手順を簡単にメモ。

1-1.outlook アドレスを取得する

持ってない場合は下記を参考にアドレスを取得する。
https://qiita.com/TomoyoH/items/fca3f49729d82d9884eb

1-2.Microsoft Learnページにサインインする

下記ページにサインインする。
https://docs.microsoft.com/ja-jp/learn/

1-3.Azureアカウントを作成する

下記ページを参考にAzureアカウントを作成する。
https://docs.microsoft.com/ja-jp/learn/modules/create-an-azure-account/3-exercise-create-an-azure-account
無料版での利用でもクレジットカードの情報も求められる。

これで、Azureを使うための準備はできました!

2.Face API(detect & emotion)

2-0.参考

2-1.準備

ここを参考に「キー1」と「エンドポイント」を取得してメモっておく。
https://docs.microsoft.com/ja-jp/learn/modules/identify-faces-with-computer-vision/7-obtain-subscription-keys

取得できたら、下記ページで使っているリージョンを選択して試してみる。
https://westus.dev.cognitive.microsoft.com/docs/services/563879b61984550e40cbbe8d/
image.png

Ocp-Apim-Subscription-Keyに先ほどの「キー1」を入れる。
image.png

その時、この画像のurlはリンク切れしてるので、自分で適当な画像のurlに張り替えて試してください。
image.png

これで、取得したキーを使ってFace APIを試すことができたので、次に応用です。

2-2.応用サンプル

LINEに画像を送ると、人数と感情を返します。
※時々、うまく結果が返ってこない画像があったり、感情も1人分しかとってません。


↑2倍速に編集してます。
'use strict';

const express = require('express');
const line = require('@line/bot-sdk');
const axios = require('axios');
const PORT = process.env.PORT || 3000;

const config = {
    channelSecret: '{channelSecretを入力}',
    channelAccessToken: '{channelAccessTokenを入力}'
};

const app = express();

app.post('/webhook', line.middleware(config), (req, res) => {
    console.log(req.body.events);
    Promise
      .all(req.body.events.map(handleEvent))
      .then((result) => res.json(result));
});

const client = new line.Client(config);

function handleEvent(event) {
  console.log(event);

  // 今回は画像投稿を通す
  if (event.type !== 'message' || event.message.type !== 'image' ) {
    return Promise.resolve(null);
  }

  let mes = ''
  if(event.message.type === 'image'){
    mes = '何人か数えています...!';
    getFaceDetect2(event.message.id, event.source.userId, config.channelAccessToken );
  } else{
    mes = event.message.text;
  }

  return client.replyMessage(event.replyToken, {
    type: 'text',
    text: mes
  });
}

const getFaceDetect2 = async (messageId , userId, accessToken) => {
  console.log("getFaceDetect2");
  console.log(messageId);
  console.log(accessToken);

  ///////// 画像取得 /////////////////////////////////////////////////////

  const configImageAPI = {
    url: `https://api.line.me/v2/bot/message/${messageId}/content`,
    method: 'get',
    headers: {
        'Authorization': 'Bearer ' + accessToken,
    },
    responseType: 'arraybuffer'
  };

  let responseImageAPI;
  try {
    // axios はRequest Configで受信データのタイプを設定できる。今回は arraybuffer が適切。
    responseImageAPI = await axios.request(configImageAPI);
    console.log('image data get');
  } catch (error) {
    console.log('post Error');
    console.error(error);
  }

  ///////// Face API //////////////////////////////////////////////

  const FACE_API_ENDPOINT_URL = ' {準備で取得したエンドポイント} + /face/v1.0/detect?returnFaceId=true&returnFaceLandmarks=false&returnFaceAttributes=emotion&recognitionModel=recognition_01&returnRecognitionModel=false&detectionModel=detection_01';

  // サブスクリプションをOcp-Apim-Subscription-Keyヘッダーに
  // JSONで送るのでContent-typeヘッダーにapplication/octet-stream指定
  const configFaceAPI = {
    url: FACE_API_ENDPOINT_URL,
    method: 'post',
    headers: {
      'Content-type': 'application/octet-stream',
      'Ocp-Apim-Subscription-Key':'{key1を入力}'
    },
    data: responseImageAPI.data
  };

  // axios
  let responseAzure;
  try {
      // POSTリクエストで送る
      responseAzure = await axios.request(configFaceAPI);
      //console.log('post OK');
      // データ送信が成功するとレスポンスが来る
      console.log(responseAzure.data);

  } catch (error) {
      console.log('post Error');
      // ダメなときはエラー
      console.error(error);
  }

  const countPerson = responseAzure.data.length;

  if(responseAzure.data[0].faceAttributes){
  // とりあえず[0]でひとり目の感情をとってくる。
  var emo = responseAzure.data[0].faceAttributes.emotion;
  var type;
  var val = 0;
  // 一番大きな感情を返す
  for(let key in emo){
      if(emo[key] > val){
          val = emo[key];
          type = key ;
      }
  }
}

  val = Math.round(val *100);
  console.log(emo);

  // 返信
  await client.pushMessage(userId, {
    type: 'text',
    text: `この中には ${countPerson} 人いるよ!` ,
  });

  await client.pushMessage(userId, {
    type: 'text',
    text: `感情は${type}${val}%だよ。` ,
  });

}

app.listen(PORT);
console.log(`Server running at ${PORT}`);

LINEbot自体の基本的な説明は下記を参考にしてみてください。
https://qiita.com/n0bisuke/items/ceaa09ef8898bee8369d

3.Custom Vision API

3-0.参考

3-1.準備

まずは「リソースの作成」からcustom visionのリソースグループやリソースを作ります。
image.png
custom visionを探して、目のアイコンが目印。これを新規作成する。
image.png

そして、custom vision用のプロジェクトを作ります。

プロジェクトを作成できたら、手順に沿ってラベル付け・学習を行っていきます。

手元で試す為には下記ページにurlとPrediction-keyをメモっておきます。
https://docs.microsoft.com/ja-jp/learn/modules/classify-images-with-custom-vision-service/5-call-the-prediction-endpoint-curl

3-2.応用サンプル

上記で学習したデータを使い、複数の写真のうち「最もピカソっぽい写真」を探す。
image.png

picasso.js
const axios = require('axios');

let pic = [
    { 
        name : "A",
        url : "https://www.cnn.co.jp/storage/2018/11/26/97e614a5a80cd9b784f4bdc82b4ec331/rembrandt-study-of-the-head-of-a-young-man.jpg" 
    },
    { 
        name : "B",
        url : "https://artmuseum.jpn.org/nakuonna.jpg" 
    },
    { 
        name : "C",
        url : "https://www.pakutaso.com/shared/img/thumb/MAX76_gjmax20140531_TP_V.jpg" 
    },
    ]

let items = [];
let name,prob,url;
let pic_len = pic.length;

const sendCustomVision = async (imageURL,picname) => {
  // If you have an image URL: にあるエンドポイントを使う
  const CUSTOM_VISION_API_ENDPOINT_URL = '{上記でメモったエンドポイント}';

  // Prediction-Keyの値を Prediction-Key ヘッダーに入れる
  // JSONで送るので Content-type ヘッダーに application/json 指定
  const configCustomVisionAPI = {
    url: CUSTOM_VISION_API_ENDPOINT_URL,
    method: 'post',
    headers: {
      'Content-type': 'application/json',
      'Prediction-Key':'{上記でメモったPrediction-Key}'
    },
    data: {
      url:imageURL
    }
  };

  // axiosの送信設定
  let responseCustomVision;
  try {
    // POSTリクエストで送る
    responseCustomVision = await axios.request(configCustomVisionAPI);
    //console.log("post OK");
    // データ送信が成功するとレスポンスが来る

    let len = responseCustomVision.data.predictions.length;
    var who = 'picasso';
    for(let i = 1; i <= len ; i++){
         // ピカソだけ取得
        const predictions = responseCustomVision.data.predictions[i];
        //console.log(responseCustomVision.data);

        if( predictions && predictions.tagName == who){  
           // console.log('tagName2: ' + predictions.tagName);

            name = picname;
            url = imageURL;
            prob = predictions.probability ;

            items.push({name:name,url:url,prob:prob });
        }
    }

    if(items.length == pic.length ){
        // 全ての画像のpicassoぽさを表示する
            console.log(items);

        // picassoぽさが最大の物だけを抽出  
            let items_len = items.length;
            let max_probability = 0;
            let max_name , max_url;
            for(let k=0; k<=items_len - 1;k++){
                if(max_probability < items[k].prob){
                    max_probability = items[k].prob;
                    max_name = items[k].name;
                    max_url = items[k].url;
                }
            }
        // 最もピカソっぽいものを表示
        console.log('最も'+ who + 'ぽい画像は' + max_name + ' : ' + max_url);  
    }

  } catch (error) {
    console.log("post Error");
    // ダメなときはエラー
    console.error(error);
  }
}

var j;
for(j =0; j <= pic_len - 1 ; j++){
    sendCustomVision(pic[j].url,pic[j].name);
}

結果。
Bがダントツでピカソっぽい。
image.png

判定したい画像を変えたり、変数whoのところを'pollock'や'rembrandt'に変えたりして遊べます。

Computer Vision API

4-0.参考

4-1.準備

基本的に上記参考ページに沿って進めていけばOKですが、ページ通りに進める為にはサンドボックスを使う必要があります。ページ内に書かれている通りやればできるはずなのでお忘れなく。

うまくいくと、右側に Azure cloud shellが表示されます。こんな感じ。
image.png

あとは基本的にページ内に記載されているコードをコピペで進めていけます。
アクセスキーはずっと使うので取得をお忘れなく。

4-2.手元で使うために

Learnページ内のサンドボックス環境で使うのも良いですが、自分の手元で動かすために、これまで同様リソースを追加します。
image.png

リソースを作成して「キーとエンドポイント」から「キー1」と「エンドポイント」をコピペしておきます。

エンドポイントに関しては、これまで
https://westus2.api.cognitive.microsoft.com/vision/v2.0/analyze?visualFeatures=Categories,Description&details=Landmarks

のように使っていた、https://westus2.api.cognitive.microsoft.com/ この部分を今取得したエンドポイントに入れ替えればOKです。

手元で動かすための基本の形

const axios = require('axios');

const ComputerVision = async (imageURL) => {
  // 
  const COMPUTER_VISION_API_ENDPOINT_URL = '{# 実行したい処理のエンドポイント}';
// 例:エンドポイント + vision/v2.0/analyze?visualFeatures=Categories,Description&details=Landmarks

  // Prediction-Keyの値を Prediction-Key ヘッダーに入れる
  // JSONで送るので Content-type ヘッダーに application/json 指定
  const configCustomVisionAPI = {
    url: COMPUTER_VISION_API_ENDPOINT_URL,
    method: 'post',
    headers: {
      'Content-type': 'application/json',
      'Ocp-Apim-Subscription-Key':'{# key1}' // key1
    },
    data: {
      url:imageURL
    }
  };

  // axiosの送信設定
  let response;
  try {
    // POSTリクエストで送る
    response = await axios.request(configCustomVisionAPI);
    //console.log("post OK");
    // データ送信が成功するとレスポンスが来る
    console.log(response.data);

  } catch (error) {
    console.log("post Error");
    // ダメなときはエラー
    console.error(error);
  }

}

var url = '{# 処理したい画像のURL}';
ComputerVision(url);

4-3.応用サンプル

上記の基本コード中の、
COMPUTER_VISION_API_ENDPOINT_URL と url 部分を変えることで色々と試せます。

4-3-1.アダルトコンテンツかどうか見分ける

変更箇所

  • COMPUTER_VISION_API_ENDPOINT_URL : 4-2のエンドポイント + /vision/v2.0/analyze?visualFeatures=Adult,Description

■しみけんさん
image.png

これはアダルトではないらしい。
image.png

■ベッドにいる外人さん
image.png

これはアダルトのようだ。
image.png

4-3-2.OCRで文字を読み取ってみる

変更箇所

  • COMPUTER_VISION_API_ENDPOINT_URL : 4-2のエンドポイント + /vision/v2.0/ocr?language=ja

■ みつをさん
image.png

-url : https://www.hankyu-hanshin-dept.co.jp/image/20150928aidamitsuoten03.jpg

NotDetected... 難易度が高すぎたようだ。
image.png

気を取り直して。

■エヴァの予告
image.png

何やら取れてるっぽい。
regionsの中のlinesにいるようだ。
image.png

さらに深いところにいた...
image.png

ということで、
console.log(response.data);

    for (let l = 0 ;  l <= response.data.regions[0].lines.length -1; l++){
        console.log(response.data.regions[0].lines[l].words);
    }

に変更して全てを取り出してみると、、、取れてる!!!
image.png

が、、、よく見ると。使徒の「使」が抜けてる。
「第壱話 徒、襲来」  惜しい!

終わりに

こんな手軽に、そしてタダで画像認識系の処理ができました。
便利な世の中です。

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
What you can do with signing up
9