[番外編]機械学習プログラミング 日向坂46で顔認識してみた。@Python (4)
(番外編)日向坂46で顔認識
最近流行のAI(機械学習)でプログラムを書いてみました。
尚、この一連の記事ではOracleは全く登場しません。
この記事は、前回までの続きです。
- (番外編)日向坂46で顔認識@Python(1) 概要~学習用画像のスクレイピング
- (番外編)日向坂46で顔認識@Python(2) 概要~顔部分抽出、顔画像増幅処理
- (番外編)日向坂46で顔認識@Python(3) 学習~モデル作成~顔認識処理
6. 認識実行画面
さて、メインとなる認識処理のプログラムは出来上がりました。
あとはこれを表示する画面です。
Pythonで画面を構築するフレームワークというと、django(ジャンゴ)かflask(フラスク)が有名ですが、今回はflaskから派生した新しいフレームワーク「Responder」(レスポンダー)を使用します。
画面仕様は至ってシンプルなものです。
python3 facerecg_run.py
を実行すると、コンソールに
Using TensorFlow backend. INFO: Started server process [XXXX] INFO: Uvicorn running on http://127.0.0.1:5042 (Press CTRL+C to quit) INFO: Waiting for application startup. INFO: Application startup complete.
というような表示が出てきます。
ここで表示されたURLにアクセスすると、下記のような画面が出てきます。

検証したい画像ファイルをダイアログから選び、「送信」を押すと、顔認識処理が動き、認識結果が表示されます。

画像がアップロードされると、アップロード先のパスを、前回作成した顔認識処理に引数として渡して、認識処理を実行します。
結果を受け取り、画面にHTML表形式で表示するという仕組みです。
全体構成
下記のようなディレクトリ・ファイル構成になります。
app +--- facerecg_run.py
+--- facerecg5_recog.py
+--- facerecg_image_comn.py
+--- static ---+-- uploaded
| +-- main.css
| +-- reset.css
|
+--- template -+-- index.html
| +-- layout.html
| +-- success.html
|
+--- model ----+-- images_obj.npy
+-- model_hitanazaka.h5
認識画面の制御を行うfacerecg_run.pyのソースコードは以下のようになります。
#========================================
# 日向坂46メンバーの顔認識
# 7.認識 画面表示
#========================================
from pathlib import Path
import io
import responder
import requests
import datetime
import numpy as np
import pandas as pd
import facerecg6_recog as fr
def parentdir(path='.', layer=0):
return Path(path).resolve().parents[layer]
def imgfilename(nowdt):
return 'i' + nowdt + '.jpg'
BASE_DIR = parentdir(__file__, 0)
IMAGE_DIR = './static/uploaded/'
upldtime = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
# staticファイルを使用するときは、APIを定義するときに「static_dir」を指定します。
api = responder.API(
static_dir=str(BASE_DIR.joinpath('static')),
)
@api.route("/")
async def greet_world(req, resp):
resp.content = api.template('index.html')
@api.route("/upload")
async def upload_file(req, resp):
@api.background.task
def process_data(data):
file=data['file']
f = open(IMAGE_DIR + imgfilename(upldtime), 'wb')
f.write(file['content'])
f.close()
data = await req.media(format='files')
# アップロード処理
process_data(data)
# 顔認識処理
frr = fr.predict(IMAGE_DIR + imgfilename(upldtime))
# Dataframeに変換
df = pd.DataFrame(frr)
df.columns = ['score', 'name']
df = df.iloc[0:5,:] # 上位5位までを表示。ヘッダも含むので0-5で指定
df = df.astype({'score': 'float'}, copy=True)
df['score'] = ((df['score']*10000//1)/100) # 小数点以下2位まで保持
# HTML出力用のパイプを定義
buffer = io.StringIO()
df.to_html(buf=buffer, index=False, justify='center', escape=False)
# バッファに格納された文字列を取得し、変数に代入
frtag = buffer.getvalue()
topname = df.loc[0, 'name']
resp.content = api.template('success.html', inf=upldtime, top=topname , result=frtag)
if __name__ == '__main__':
api.run(debug=False)
ファイルのアップロード
ファイルアップロード部分の処理は、下記のサイトを参考にさせて頂きました。
Python+ResponderでWEBアプリケーションを構築する 4.File Upload
(https://qiita.com/t-iguchi/items/5c4294efffbba9a6bb84)
ファイル選択画面の表示にPythonは不要です。
下記の設定で、staticディレクトリにあるindex.htmlファイルが開かれますが、この中にファイルダイアログの記述があります。
<form id="fileupload" action="/upload" method="post" enctype="multipart/form-data">
<input name="file" type="file" required/>
<button type="submit">送信</button>
</form>
最初にindex.htmlを表示するのは、facerecg_run.pyにある下記の記述です。
@api.route(“/") の記述で、トップディレクトリへアクセスがあった場合のルーティングを制御します。
@api.route("/")
async def greet_world(req, resp):
resp.content = api.template('index.html')
submit時のアクションはformタグ中のactionの記述「/upload」と、python側にあるルーティング「@api.route(“/upload")」で制御されます。
この記述により、アップロード時には「@api.route(“/upload")」以下の処理が実行されます。
ファイルのアップロードとデータの読込みを行う process_data は下記の記述により、バックグラウンドタスクとして実行されます。
@api.background.task def process_data(data):
そのため、ファイルのアップロード実行中に画面が遷移し、認識処理結果を待機することになります。
ファイルのアップロードは、
data = await req.media(format='files')
以下で行います。
process_data で受けとったファイルの書込みを行います。
認識処理の実行と結果の表示
認識処理は下記の記述で行われます。
fr.predict(IMAGE_DIR + imgfilename(upldtime))
結果はndarray型の配列で戻ってきますが、これはdataframe型に変換し、2次元の表データとして保持します。
dataframeには、to_html というメソッドが有り、HTML文字列を出力することが出来ます。
この出力結果を、io.StringIO()を使ってioモジュールの文字列バッファに保存します。
そしてこのHTMLを api.template を使用して、"success.html" に埋め込むことができます。
呼出時の引数"inf","top","result" が、下記"success.html"中の{{ }} で囲まれた箇所に対応しています。
{% extends "layout.html" %}
{% block content %}
<h1>日向坂46誰に似てる?</h1>
<p>アップロードした写真は、<span class="topname"> {{ top }} </span>ちゃんに 似ていますね。</p>
<!-- a href="#" onclick="history.back(-1); return false;">戻る</a -->
<p><img src="/static/uploaded/i{{ inf }}.jpg"></p>
{{ result | safe }}
<p><a href="./">戻る</a></p>
{% endblock %}
最近のコメント