5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

FlashAir+Face API+FlashAir IoT Hubで人物カウンターを作ってみた

Last updated at Posted at 2017-01-07

 昨年10月に東芝無線LAN内蔵SDカード「FlashAir」をIoTデバイスとして活用するためのプラットフォームとして「FlashAir IoT Hub」が発表されました。現在、プレビュー公開が行われています。今回は、これにFlashAirからデータを送信して、グラフ表示することを試してみます。
 送信するデータは、デジタルカメラで撮影した写真画像ファイルをLuaスクリプトでFace APIを呼び出して、写った人物の男女別人数、年齢層別人数をカウントしたデータを送信することにします。

 ただ、今回、Cognitive ServicesのFace APIをFlashAirのLuaスクリプトから呼び出そうとしたのですが、どうしてもHTTP 415エラーとなり呼び出せませんでした。そのため、Computer Vision APIのvisualFeaturesに「Faces」を指定して、Face APIと同等の結果を得ることにしました。
 REST APIの仕様は、こちらのドキュメントComputer Vision API - v1.0を参照してください。

#全体概要
FlashAirFaceAPI.png

#FlashAir IoT Hubの準備
 こちらのFlashAir IoT Hubチュートリアルを参考に、準備してください。今回は、ご利用の流れのFlashAir登録まで済んでいれば大丈夫です。

###FlashAirのファイル配置
 以下のファイルを配置しておきます。

・iothub.lua
 取得した「スクリプト」ファイルのひとつ、FlashAir IoT Hub SDKファイルです。
・credentials.json
 FlashAir IoT Hubのアクセストークン取得で取得したJSONファイルです。

###今回利用するコマンド
 FlashAir IoT Hub SDK(iothub.lua)のなかのデータ送信機能addMeasurementを利用します。

iothub.addMeasurement(arg1, arg2, arg3, arg4, arg5)

使い方は簡単で、addMeasurementの引数に最大5個まで送信するデータを指定するだけです。

#サブスクリプションキーの取得
 次に、Microsoft Cognitive Services - Computer Vision APIを利用するためのサブスクリプションキーを入手します。現時点では、月間5,000リクエストまで、または1分間に20リクエストまでは無料で利用できます。
 Microsoft Cognitive Services サブスクリプションに、自分のMicrosoftアカウント(もし、お持ちでなければ無料で作成できます)でログインします。すると、以下のようなページで各種APIのサブスクリプションキーを入手することができます。今回は、「Computer Vision API」のチェックをつけて、Subscribeボタンを押します。

subscriptions取得画面1.png

 つぎの画面で、以下のようにサブスクリプションキーが生成されます。Key 1のCopyという文字列をクリックすると、キー文字列がクリップボードにコピーされますので、どこかに保存しておいてください。後ほど使います。

subscriptions取得画面2.png

#CONFIGファイルの設定
 FlashAirのSD_WLANフォルダ内のCONFIGファイルに、以下のLuaスクリプト起動オプションを付加します。

LUA_RUN_SCRIPT=/faceapi_sample.lua

 ※SD_WLANフォルダとCONFIGファイルは不可視属性ファイルなので注意してください。

#Luaスクリプトファイル
 FlashAirのルートフォルダに以下のコードを記述したテキストファイル(faceapi_sample.lua)をコピーします。
 このスクリプトでは、最新の画像ファイルをDCIMフォルダ配下に探しに行きファイル名を取得、このファイルをComputer Vision APIに投げて、Facesの結果を得ます。得たJSONファイルのなかから必要なデータを取り出して、FlashAir IoT Hubに送信します。その後、1分待機して、同じ処理を繰り返します。
 処理を繰り返す中で、画像ファイルが更新されていない場合は、Face APIの呼び出しはスキップしますが、FlashAir IoT Hubには前回を同じデータを送信するようにしています。

faceapi_sample.lua
cjson = require "cjson"
iothub = require("iothub")
latest_fpath = ""
faces_num_00 = 0
faces_num_20 = 0
faces_num_60 = 0
faces_num_male = 0
faces_num_female = 0
	  
function funcfacecount()
	last_fname = ""
	last_fpath = ""
	last_modif = 0
	
	last_moddir = 0
	last_dirname = "/DCIM"
	
	fpath = "/DCIM"
	for dirname in lfs.dir(fpath) do
	  dirpath = fpath .. "/" .. dirname
	  mod_dir = lfs.attributes( dirpath, "mode" )
	  if mod_dir == "directory" then
		dir_modifficate = lfs.attributes( dirpath, "modification" )
		if dir_modifficate > last_moddir then
		  last_moddir = dir_modifficate
		  last_dirname = dirpath
		end
	  end
	end
	
	for filename in lfs.dir(last_dirname) do
	  if(string.sub(filename, 1, 1) ~= ".") then
		filepath = last_dirname .. "/" .. filename
		mod = lfs.attributes( filepath, "modification" )
		if mod > last_modif then
		  last_modif = mod
		  last_fname = filename
		  last_fpath = filepath
		end
	  end
	end
	
	if(latest_fpath == last_fpath) then
	  return
	end
	latest_fpath = last_fpath
	
	boundary = "1234567890"
	contenttype = "multipart/form-data; boundary=" .. boundary
	mes = "--" ..  boundary .. "\r\n"
	  .."Content-Disposition: form-data; name=\"file\"; filename=\""..last_fname.."\"\r\n"
	  .."Content-Type: image/jpg\r\n\r\n"
	  .."<!--WLANSDFILE-->\r\n"
	  .."--" .. boundary .. "--\r\n"
	
	blen = lfs.attributes(last_fpath,"size") + string.len(mes) - 17
	b, c, h = fa.request{url = "https://api.projectoxford.ai/vision/v1.0/analyze?visualFeatures=Faces",
	  method = "POST",
	  headers = {["Content-Length"] = tostring(blen),
	  ["Content-Type"] = contenttype,
	  ["Ocp-Apim-Subscription-Key"] = "ここにサブスクリプションキーを記述する",
	  file = last_fpath,
	  body = mes
	}
	
	if(c == 200) then
	  res = cjson.decode(b)
	  
	  for idx=1,#res.faces do
		local agenum = tonumber(res.faces[idx].age)
		  if(agenum < 20) then
		  faces_num_00 = faces_num_00 + 1
		elseif(agenum >= 20 and agenum < 60) then
		  faces_num_20 = faces_num_20 + 1
		elseif(agenum >= 60) then
		  faces_num_60 = faces_num_60 + 1
		end
		
		if( res.faces[idx].gender == "Female" ) then
		  faces_num_female = faces_num_female + 1
		else
		  faces_num_male = faces_num_male + 1
		end
	  end
	end
end

while(1) do
  funcfacecount()
  iothub.addMeasurement({faces_num_00, faces_num_20, faces_num_60, faces_num_male, faces_num_female})
  sleep(60000)
  collectgarbage("collect")
end

#動作確認
 今回は、著作権フリー写真・イラスト素材集のサンプル画像で動作確認をしてみました。まずはFlashAirに適当な画像ファイルをコピーしてみます。1分ごとに画像ファイルをComputer Vision APIで分析して、その画像に写っている人物の認識結果がうまくグラフに表示されました。
 FlashAir IoT Hubでは5つのデータまでしか送信できないため、今回は、(1)20歳以下の人数、(2)20〜60歳の人数、(3)60歳以上の人数、(4)男性の人数、(5)女性の人数の5つのデータを送信しています。

faceapi_sample1.png

#まとめ
 FlashAirからCognitive ServicesのComputer Vision APIを呼び出して、写真に写っている人物の男女別人数と年齢層別人数をカウントすることができるようになりました。
 デジタルカメラでインターバル撮影を行えば、定点観測による人物カウンターが実現できますね。

#参考資料
 FlashAir IoT Hubチュートリアル
 Microsoft Cognitive Services - Computer Vision API
 Microsoft Cognitive Services - Computer Vision API - Document

5
6
0

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
  3. You can use dark theme
What you can do with signing up
5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?