DiaryException このページをアンテナに追加 RSSフィード Twitter

2005 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2006 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2012 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |

2010-05-05(水) ゴールデンウィーク最終日。

[][]face.comの顔認識APIim.kayac.comを使ってPCに人(の顔)が近付いたらiPod touchに知らせる

face.comの顔認識APIが公開された( 1年で70億枚の顔写真をスキャンしたFace.comが顔認識APIを無料で一般公開 )。珍しいAPIなので、何に使えるか考えて、とりあえず、カメラに近付いた人の顔の認識に使ってみることにした。

ただ近付いたと分かるだけでもつまらないので、Arduinoの状態をim.kayac.comに送信してiPod touchで確認する - DiaryExceptionネタを流用して、顔が近付いたらiPod touchに知らせる。

少し長いエントリーになったが、以下の4つの章に分けられる。

画像アップローダの設置

face.comの顔認識API画像URL引数に取るため、PC(ローカル)にある画像を解析対象とさせることは出来ない。そこで、予め画像アップローダを設置し、PCからURLで参照出来る位置に画像アップロードして顔認識APIに読ませる。

アップローダとなるCGIスクリプト(Python)は以下のようにした。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import cgi
import os.path
import sys

print "Content-Type: text/html\n"

html = """

<html>
<head>
  <meta  http-equiv="content-type" content="text/html; charset=utf-8" />
  <title>File uploader</title>
</head>
<body>
<h1>File uploader</h1>
<form action="%s" method="post" enctype="multipart/form-data">
  <input type="file" name="file" />
  <input type="submit" />
</form>
</body>
</html>"""

form = cgi.FieldStorage()
if "file" in form:
    item = form["file"]
    if item.file:
        out = open(os.path.join('uploader_images', item.filename), "wb")
        out.write(item.file.read())
        out.close()
print html % sys.argv[0]

このスクリプトを、face.comが参照出来るWebサーバに設置する。スクリプトと同じ場所に、uploader_imagesという名前ディレクトリを作り、CGIディレクトリ内にファイルを書き込めるようにパーミッションを変更しておく。

f:id:LaclefYoshi:20100505143408p:image

face.comとim.kayac.comのアカウント登録(APIキー取得)

face.com developers site. face.com for developersim.kayac.comアカウント登録をすることが出来る。

face.comはアプリケーション登録を適当にしておけば、API keyAPI Secretを取得出来る。

iPod touchにはim.kayac.comのアプリを入れておくこと。

PC接続したカメラからカメラ画像を読み取り、画像アップローダ転送、face.comで顔認識結果を取得し、もし顔があればim.kaya.comでiPod touchに知らせる

Webカメラ画像を取得するために、バーコードリーダ/ライタと同じくProcessingライブラリを用いた。WebカメラにはiSightを用いる。

スクリプトJythonで書き、外部ライブラリとしてProcessingの他にJSONIC - simple json encoder/decoder for javaを使っている。

画像アップローダ画像転送するために、横着をしてcurlコマンドを使っている。Macならデフォルトで入っているので気にしない。

#!/opt/usr/bin/jython
# -*- coding: utf-8 -*-

from processing.core import PApplet
from processing.video import Capture
from net.arnx.jsonic import JSON
from javax.swing import JFrame, JPanel, BoxLayout
from java.util import Timer, TimerTask
from java.io import File
from javax.imageio import ImageIO
import os
import time
import urllib
import hashlib

CHECK_INTERVAL = 30  # (sec)
# カメラ画像をチェックする時間間隔 / 短すぎるとface.comのAPIアクセス回数制限に引っかかる

UPLOADER_URL = "http://MYCGISERVER/uploader.py"
# アップローダのURL
UPLOADER_IMAGEURL = "http://MYCGISERVER/uploader_images/%s"
# アップローダに転送された画像の位置 / %sに画像ファイル名が入る

FACE_URL = "http://api.face.com/faces/detect.json"
FACE_APIKEY = "YOUR_FACE_COM_API_KEY"
FACE_APISECRET = "YOUR_FACE_COM_API_SECRET"

IMKAYACCOM_USER = "YOUR_IM_KAYAC_COM_USER"
IMKAYACCOM_SECRETKEY = "YOUR_IM_KAYAC_COM_SECRET_KEY"

## im.kayac.com
# im.kayac.com -> iPod touch

def postImkayaccom(faces, imgurl):
    url = "http://im.kayac.com/api/post/" + IMKAYACCOM_USER
    msg = u""
    for face in faces:
        msg += u"「%s」" % face
    msg += u"がお前のPCに近付いているッ!"
    message = msg.encode("UTF-8")
    
    signature = hashlib.sha1(message+IMKAYACCOM_SECRETKEY).hexdigest()
    opt = urllib.urlencode({
        "message": message,
        "handler": imgurl,
        "sig": signature,
        })
    res = urllib.urlopen(url, opt)
    # print res

## Processing

WIN_W = 320
WIN_H = 240

class FacePanel(PApplet):
    def __init__(self):
        self.mC = None
    def setup(self):
        self.size(WIN_W, WIN_H)
        self.background(255)
        self.frameRate(12)
        self.mC = Capture(self, self.width, self.height, 12)

        class FaceCheck(TimerTask):
            def __init__(self, mc):
                super(FaceCheck, self).__init__()
                self.mC = mc
            def run(self):
                if self.mC.available():
                    IMAGE_FILENAME =  "out_" + time.strftime("%Y%m%d%H%M%S") + ".jpg"  # 画像ファイル名
                    out = File(IMAGE_FILENAME)
                    ImageIO.write(self.mC.getImage(), "jpg", out)
                    os.system("curl -F file=@" + IMAGE_FILENAME + " " + UPLOADER_URL)  # アップローダに画像を転送
                    print("Upload a shot")
                    params = urllib.urlencode({
                        "api_key": FACE_APIKEY,
                        "api_secret": FACE_APISECRET,
                        "urls": UPLOADER_IMAGEURL % IMAGE_FILENAME,
                    })
                    time.sleep(2)
                    request = urllib.urlopen(FACE_URL + "?%s" % params )
                    response = request.read()
                    json_data = JSON.decode(response)  # face.comからのレスポンスをJSONデータとして読み込み
                    faces = json_data["photos"][0]["tags"]
                    if len(faces) != 0:  # 認識される顔は0個以上
                        genders = []
                        for face in faces:
                            gender = face["attributes"]["gender"]["value"]  # 顔の性別を取得
                            genders.append(gender)
                        postImkayaccom(genders, UPLOADER_IMAGEURL % IMAGE_FILENAME)  # im.kayac.comで知らせる

        timer = Timer()
        timer.schedule(FaceCheck(self.mC), 0, CHECK_INTERVAL * 1000)

    def draw(self):
        if self.mC.available():
            self.mC.read()
            self.image(self.mC, 0, 0)

## main

mainframe = JFrame(title="FaceReader", resizable=0,
    defaultCloseOperation=JFrame.EXIT_ON_CLOSE)

frame = JPanel()
frame.setLayout(BoxLayout(frame, BoxLayout.Y_AXIS))

fpanel = FacePanel()
frame.add(fpanel)
fpanel.init()
while fpanel.defaultSize and not fpanel.finished:
    pass

mainframe.add(frame)
mainframe.pack()
mainframe.visible = 1

実行

実行するためには、外部ライブラリCLASSPATHに追加しておく必要がある。

$ export CLASSPATH=/Applications/Processing.app/Contents/Resources/Java/libraries/video/library/video.jar:/Applications/Processing.app/Contents/Resources/Java/core.jar:./jsonic-1.2.0/jsonic-1.2.0.jar:$CLASSPATH
$ jython facetotouch.py -d32

動作チェックのために、自分の顔も使ったが、顔を晒すのは恥ずかしいので、本棚にあった眞鍋かをりブログ本を使って動作チェックをした様子を公開する。

f:id:LaclefYoshi:20100505143403p:image

上記スクリプトでは、30秒毎にカメラ画像をチェックしている(クリティカルな場面では長過ぎる間隔だが)。しばらくすると、face.comから顔認識結果が返ってきて、眞鍋かをりの顔が認識されたので、iPod touchにそれを知らせるメッセージがプッシュされてくる。

f:id:LaclefYoshi:20100505143404p:image f:id:LaclefYoshi:20100505143405p:image

im.kayac.comのアプリを開き、リストからメッセージクリックすると、Safari画像URLが開く。

f:id:LaclefYoshi:20100505143406p:image f:id:LaclefYoshi:20100505143407p:image

face.comはWebアプリで顔認識APIを用いることを想定しているようだが、このようにデスクトップアプリでも使える可能性を示すことが出来た。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト

コメントを書くには、なぞなぞ認証に回答する必要があります。