Bluemix上で展開されているWatsonサービスの1つにAlchemyAPIがあります。
今回はこのAlchemyAPIとRaspberry Piを使って、簡単な画像解析(顔解析)システムを作って見たいと思います。

Alchemy APIとは

現在、IBMが提供しているWatsonサービスの1つとして提供されています。
元々は2015年IBMが買収した企業で、ディープ・ラーニングテクノロジやAIといったAPIサービスを提供しておりました。
IBM製PaaSサービスであるBluemixでもこのAlchemyAPIを利用する事ができ、現在では以下の3つの機能を提供しています。
今回はAlchemyVisionで提供されている、Face Detection機能(与えられた画像から人の顔を認識し、性別・年齢を返す)を使って、顔解析システムを作って行きます。

  • AlchemyLanguage:テキスト分析機能
  • AlchemyData:ブログ・ニュースサイトの検索機能
  • AlchemyVision:画像解析機能

Alchemy APIのデモサイトより抜粋
WS000000

必要な機器

今回のデモ開発では以下の機器が必要になります。

資材 備考
Raspberry Pi2 B Raspberry Piのセットアップはこちらの記事をご確認下さい
Webカメラ 本記事ではバッファロー製BSWHD06Mを利用します

顔認識システムの概要図

今回の顔認識システの動作概要は以下の通りです。全てPythonプログラムにて制御しております。
・ラズパイに接続されたカメラを使い写真を撮影
・撮影した写真をAlchemyAPIにPOST
・AlchemyAPIより実行結果(JSON)を取得
・JSONから得られた結果を元に、顔と認識した箇所へ「枠」と「年齢・性別」を写真に描写
WS000001

環境準備

Alchemy APIの検証環境を構築

まずは、Bluemix上でAlchemyAPIの検証環境を構築します。
Bluemixにログイン後、ページ右上にあるカタログから「AlchemyAPI」をクリックして下さい。
WS000002

オーダー画面が表示されたら、デフォルトのまま「作成」ボタンをクリックして下さい。
WS000003

以上で環境構築は終了です。
後は環境の構築完了後に、資格情報からAPIKeyをメモして下さい。
WS000004

Raspberry Pi側の事前作業

今回、ラズパイ側で必要な作業としては以下の通りです。
・ 「OpenCV」のインストール
・ カメラを操作するためのモジュール(fswebcam/guvcview)のインストール
・ cv2(OpenCVをPythonで利用するためのモジュール)のインストール
・ リモートデスクトップ用にVNCサーバのインストール

OpenCVのインストール

TeraTerm等でラズパイにログイン後、以下のコマンドを実行して下さい。

$ sudo apt-get update
$ sudo apt-get install libopencv-dev
$ sudo apt-get install python-opencv

カメラを操作するためのモジュール(fswebcam/guvcview)のインストール

続いて「fswebcam/guvcview」のインストールを行います。以下のコマンドを実行して下さい。

$ sudo apt-get install fswebcam
$ sudo apt-get install guvcview
$ sudo reboot

cv2(OpenCVをPythonで利用するためのモジュール)のインストール

再起動完了後、再度Raspberry Piにログインを行い、作業用ディレクトリを作成します。
以下のコマンドを実行して下さい。
(必要が無ければスキップして下さい)

$ sudo mkdir -pm 755 /work/watson

続いて、PythonでOpenCVを使うためのモジュールをインストールしていきます。
以下のコマンドを実行して下さい。

$ cd /work/watson
$ sudo pip install cv2

VNCサーバのインストール

以下のコマンドを実行して下さい。

$ sudo apt-get install tightvncserver

サーバのインストールが完了したら、VNCサーバにリモートログインするためのクライアントをインストールします。
以下リンクからVNC Viewerをダウンロード。
https://www.realvnc.com/download/viewer/

以上で準備完了です。
お疲れ様でした。

プログラムの作成と実行

プログラムの作成

作業ディレクトリに以下のソースコードを記載したPythonプログラムを作成して下さい。

[demo_watson.py]

#!/usr/bin/env python
#coding:utf-8
# ライブラリーの定義(cv2は前提条件としてOpenCVのインストールが必要)
import subprocess
import json
import requests
import cv2
requests=requests.Session()

# 変数設定 (key before_img after_img は環境に合わせて編集)
key="API Key"
base_url="https://gateway-a.watsonplatform.net/calls/image/ImageGetRankedImageFaceTags"
post_url="%(base_url)s?apikey=%(key)s&imagePostMode=raw&outputMode=json" % locals()
before_img="ファイルパス(例:/work/watson/test1.jpg)"
after_img="ファイルパス(例:/work/watson/test2.jpg)"
takepic_cmd="fswebcam -r 1280 960 --no-banner %s" % before_img

###########################
# 関数宣言
###########################
class Process:
  # 空関数
  def __init__(self):
    pass

  # 写真撮影関数
  def take_photo(self):
    print "##写真撮影"
    while True:
      print "Please Enter the [y] when you are ready"
      input_line = raw_input()
      if input_line=="y":
        #subprocessは配列でコマンドと引数を渡すため,stripで前後の空白削除,splitで空白で文字列を分割
        subprocess.call(takepic_cmd.strip().split(" "))
        break
      else:
        print "入力ミス"

  # 顔解析関数
  def search_face(self,img):
    # 撮影した写真を変数へ格納
    post_img=open(img, 'rb').read()

    # POST先のURLを表示
    print "##POST先のURLを表示"
    print post_url

    # APIへPOSTし、実行結果のJSONを変数にパース
    result=requests.post(url=post_url, data=post_img)
    text=json.loads(result.text)

    # APIの実行結果(Status)を表示
    print "##APIの判定結果(Status)を表示"
    print 'Execution result='+text['status']

    # 撮影した写真をOpenCVで処理するために変数へ格納
    img=cv2.imread(before_img, 1)
    # 認識した顔数ぶんの処理を行うため,カウント変数にAPIの実行結果(JSON)を格納
    count=text['imageFaces']

    print "##実行結果を基に,人の顔に枠と年齢を描画(OpenCVのライブラリを利用)"
    for cnt in count:
      # APIの実行結果から認識した顔の座標と範囲、年齢、性別情報を変数に格納(座標と範囲は数値に変換)
      x_position=int(cnt['positionX'])
      y_position=int(cnt['positionY'])
      x_width=int(cnt['width'])
      y_height=int(cnt['height'])
      text_age=cnt['age']['ageRange']
      text_gender=cnt['gender']['gender']
      print 'X='+str(x_position)+', width='+str(x_width)+', Y='+str(y_position)+\
               ', height='+str(y_height)+', age='+text_age+', gender='+text_gender

      # pythonのOpenCVライブラリを利用して認識した顔に枠と年齢・性別を描画
      cv2.rectangle(img,(x_position, y_position),(x_position+x_width,y_position+y_height),(0,167,113),2)
      cv2.putText(img, text_age+":"+text_gender,(x_position+x_width,y_position+y_height),cv2.CV_AA,1,(0,167,113),3)

    # 保存処理
    cv2.imwrite(after_img,img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

# メイン関数
def main():
  p=Process()
  p.take_photo()
  p.search_face(before_img)

###########################
# main処理
###########################
if __name__ == "__main__":
  print "####START####"
  main()
  print "####END####"

※補足
撮影した写真は「/work/watson/test1.jpg」、AlchemyAPIの実行結果を基に加工した写真は「/work/watson/test2.jpg」として保存しています。必要があれば変更して下さい。

プログラムの実行

プログラムを実行する前にWebカメラのピント合わせを行いたいと思います。
VNCを使いラズパイにリモートログインします。

#初回起動時はログイン用のパスワード入力を求められますので、入力をお願い致します。
$ tightvncserver
New 'X' desktop is raspberrypi:1

Starting applications specified in /root/.vnc/xstartup
Log file is /root/.vnc/raspberrypi:1.log

コマンドの実行が完了したらVNC Viewerを起動し、Raspberry PiのIPアドレスを入力・リモートログインを行います。
※「<IPアドレス>:1」という形で入力して下さい。
WS000007

リモートログイン後、メニューから「Run」を実行し、テキストボックスに「guvcview」と入力して下さい。
WS000005
WS000006

「guvcview」を起動するとリモートデスクトップ上にWebカメラからの撮影画像が表示されますので、カメラのピントを合わせて下さい。
(カメラのピント合わせが完了したら、必ず「guvcview」は終了しておいて下さい)
WS000008

それではカメラのピント合わせも完了致しましたので、プログラムを実行してみましょう。
以下のコマンドを実行して下さい。

$ sudo chmod 755 /work/watson/demo_watson.py
$ sudo python /work/watson/demo_watson.py

今回の例では、「/work/watson/test2.jpg」が解析結果となり、WinSCP等を使って画像を表示してみると解析結果を確認する事が出来ます。
上手く顔認識できていますか?
(AlchemyAPIの顔解析では「横顔」・「斜め顔」がまだ苦手みたいです)

~実行結果例~
test3

まとめ

如何だったでしょうか。
画像解析システムを作ろうとすると、以前でしたらOpenCVを使ってがりがりプログラムを書く必要がありましたが、今はWatsonで簡単に解析出来るようになりました。
また、今回利用したAlchemyAPIについてはアイディア次第で以下の様なシステムも作成可能であり、まさにプロトタイプを早期に作り体験できる力を持っています。
 ・簡易監視システム
 ・(店舗に設置されたカメラを使って)来客者の自動性別・年齢推定システム
 ・(AlchemyAPIの文字認識機能を使って)名刺やレシート等の文書読取りシステム

今後もBluemixで利用できるサービスを使ってデモシステムを作って行きたいと思いますので
お時間有るときに見て頂けたら幸いです。