IoTのビッグウェーブに乗り遅れないためにIntel Edisonを購入し勉強しているCTO室のJ.Nです。
Intel EdisonとはCPU、WiFi、Bluetoothが入ったSDカードサイズのコンピューターモジュールです。
Linuxがデフォルトで入っているので、SSH接続しすぐにプログラミングができます。
Intel Edison で始めるIoT開発
今回はこの小さいコンピューターの活用事例として、Microsoft Azure APIと組み合わせた年齢性別判定装置を作ってみたいと思います。
構成図は以下です
実際にはタッチセンサーを用いてタッチセンサーにタッチしたら写真を撮り、画像をAzureMLに送信するようにします。
用意するパーツ
購入した装置は以下になります。
- Intel Edison Kit for Arduino ¥13.000
- Grove RGBバックライト液晶モジュール ¥1,750
- GROVE – ベースシールド ¥1,500
- GROVE – タッチセンサ ¥1,500
- WEBカメラ BSW32KM04BK 市場価格¥2,000
組み立て
- Arduinoボードに、Intel Edisonのチップを接続します
- Arduinoボートに、ベースシールドを接続します
- USBカメラを接続します
- ベースシールドの適当なポートにLCDを接続します
- ベースシールドの適当なポートにタッチセンサーを接続します
注意点としてはベースシールドのスイッチをV5にしないとLCDで正しく文字が表示されません。
USBカメラは接続するだけでLinuxが自動的にドライバを読み込み使えるようになります。(dmesgで確認できます)
画像ファイルをAzure ML(Project Oxford)に送信し結果を受け取るプログラム
Project Oxfordとはマイクロソフトのクラウド機械学習サービスの一部で、画像解析に特化したクラウドサービスになります。
REST API形式でAPIを実行することができ、クライアントプログラムは画像を送信しOxfordが瞬時に解析した結果を受け取ることができます。
プログラミング言語としてはIntel EdisonのLinuxでは標準でPython2、Node.jsが利用できます。
RubyやJavaも追加できるのですが、ライブラリが欠損していたりうまく動かなかったりするので最初はPython2 or Node.jsでIntel Edisonを操作するのをお勧めします。
まずはIntel Edisonのpython2で画像をAzureMLに送信するプログラムを作成します
1 2 3 4 5 |
{ "Azure" : { "subscription_key": "" } } |
AzureのAPIキーを格納する設定ファイルになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
########### Python 2.7 ############# import httplib, urllib, base64 import sys import json f = open('./config/application.json', 'r') config = json.load(f) f.close() headers = { # Request headers 'Content-Type': 'application/octet-stream', 'Ocp-Apim-Subscription-Key': config['Azure']['subscription_key'], } params = urllib.urlencode({ # Request parameters 'visualFeatures': 'All', }) try: argv = sys.argv data = open(argv[1], "r+b").read() conn = httplib.HTTPSConnection('api.projectoxford.ai') conn.request("POST", "/vision/v1/analyses?visualFeatures=All", data, headers) response = conn.getresponse() data = response.read() print(data) conn.close() except Exception as e: print("[Errno {0}] {1}".format(e.errno, e.strerror)) |
コマンドラインの第一引数のファイルをAzureMLに送信し、返却されたJSON(年齢性別が入ったデータ)を標準出力にprintします。
次に、タッチセンサーにタッチがあったらWEBカメラを起動し撮影しその画像をAzureMLに送信し結果をLCDに表示するプログラムを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
/*jslint node:true, vars:true, bitwise:true, unparam:true */ /*jshint unused:true */ // Leave the above lines for propper jshinting //Type Node.js Here :) /*jslint node:true, vars:true, bitwise:true, unparam:true */ /*jshint unused:true */ // Leave the above lines for propper jshinting //Type Node.js Here :) // 外部プログラミングを起動させるため必要 var exec = require('child_process').exec; var photo_counter = 0; // mraaはIntel Edisonから機器を操作するためのライブラリ var mraa = require("mraa"); // LCD Classを定義 var LCD = require("jsupm_i2clcd"); // LCDを初期化。0x3EはLCD_ADDRESS,0x62はRGB_ADDRESS。 // !注意! 第一引数のポートは実際にベースシールドに刺したポート番号にすること var myLCD = new LCD.Jhd1313m1(6, 0x3E, 0x62); var gender = ""; var age = 0; var wait = 0; // !注意! 第一引数のポートは実際にベースシールドに刺したポート番号にすること var touch = new mraa.Gpio(2); touch.dir(mraa.DIR_IN); function readTouch() { // タッチセンサーにタッチがあったらここでログが出力される //console.log("Gpio is " + touch.read()); if (touch.read() == 1) { shot(); } } setInterval(readTouch, 1000); // 写真を撮影する function shot() { if (wait == 1) {return;} wait = 1; var time_string = new Date().getTime(); var filename = time_string + ".jpg"; exec("fswebcam -r 1600x1200 /media/sdcard/photo/" + filename, function(err, stdout, stderr){ exec("python /home/root/photo.py /media/sdcard/photo/" + filename, function(err, stdout2, stderr){ console.log(filename); console.log(stdout2); // photo.pyの結果をパースする ret = JSON.parse(stdout2); console.log(ret); myLCD.setColor(0, 200, 0); // 配置(row,clumn)を指定 第一引数の「0」は1行目を示す myLCD.setCursor(0,0); if (ret['faces'].length > 0) { myLCD.write("age:" + ret['faces'][0]['age'] + " " + ret['faces'][0]['gender']) if (ret['faces'][0]['gender'] == 'Male') { // 男性だったらLCDを青 myLCD.setColor(0, 0, 255); } else { // 女性だったらLCDを赤 myLCD.setColor(255, 0, 0); } } else { // LCDに書き出し(写真に人が写ってなかったら「No Faceを表示」) myLCD.write("No Face! -_-"); } wait = 0; }); }); photo_counter++; // LCDの2行目 第一引数の「1」が2行目を示す、第二引数は文字のポジション myLCD.setCursor(1,0); myLCD.write("pc:" + photo_counter); } |
プログラムのポイントを解説すると
- Intel Edisonから機器を制御するにはmraaライブラリを使用する
- LinuxからWEBカメラを制御するコマンドはいくつかあるが今回はfswebcamを使用(Intel Edisonにインストールが必要)
- Azureに画像を送信中にタッチセンサーが動いて再度写真を送信するのを防ぐためwait変数で、画像処理中は再度撮影しないように制御(あまり連続でAzureAPIを叩くと一時的にAPIからBANされます)
node touch_and_shot.js
でプログラムを起動しカメラの前に立ちタッチセンサーを触ると1秒程度でLCDが点灯します。
age:23
Male(男性)
・・と表示されました。
※「Sec~」の部分はテストの時の表示なので無視してください。
今回学んだ事
- Intel EdisonからのWEBカメラ制御
- Intel Edisonからのタッチセンサー制御
- Intel EdisonからのLCDディスプレイ制御
- pythonでのAzureML Project Oxford API操作
まとめ
今回はIntel EdisonとクラウドAPIを使用して年齢性別判定プログラムと装置を開発しました。
このアプリケーションを発展させてデジタルサイネージでその人の年齢・性別に合った商品を紹介するといったものを作ると面白いと思います。
似たようなアプリケーションはスマートフォンのカメラを使っても作成できますが、Intel Edisonの強みの1つとしてLinuxがそのまま入っている自由な環境でのプログラミングが可能と言う点がスマートフォンのアプリ開発と比べて優っていると感じました。
今日の記事をきっかけにIntel Edisonを使って様々なプログラミング言語でのIoTアプリケーション開発を楽しんでいただけると幸いです。