[番外編]機械学習プログラミング 日向坂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 %}
最近のコメント