PythonとFlaskで類似画像を検索できるアプリを作ってみようPart2
概要
前回
せっかくなのでgithubリポジトリ作りました 星ください(乞食)
SSAM-SimilaritySearchAppwithMNIST
タイトルの通りです。今回は簡単にデータが手に入ってかつデータサイズも小さいご存知MNISTに対してMNISTの画像を入れると似たMNISTの画像を見つけてくれる、そんなアプリを作ることで近似近傍探索についての話とFlaskを使ったアプリ作りについての話を自分のメモもかねて書いていきます。
今回はいよいよFlaskについて少しづつ触れていきます。
Flask
最初に言っておくと僕はFlaskについてはそんなに詳しくないです。
比較的気軽にwebアプリケーションが作れてデモ用にいいという程度の気持ちしか持っていません。
前回のmain.pyに書き足していく感じで進めていきましょう。
使用するライブラリ
まず、使用するライブラリを前回のmain.pyに書き足しておきましょう
from flask import Flask, render_template
from flask import request
Flaskでハロワ
まずapp.run
前回のMNISTを取ってくるmain()関数の下にapp.runというのを書きましょう。アップがランします。ちなみにdebug=Trueしておくと.pyのファイルをセーブするたびに、ページをリロードして再読み込みしてくれるようになります。.htmlや.cssもそうして欲しいという場合は、なんかそういうのをやる方法があったと思います。詳しくは目の前の箱でググってください。
if __name__ == "__main__":
main()
app.run(debug=True)
実際に作っていく
app.run(debug=True)
実は上のを書いたからと言って、まだランするアプリが何もありません。
ランするアプリを早速作っていきましょう。
前回までに書いたmain()の下あたりにでも
def main():
# 前回までに作った関数(以下略)
#~ ここから書き足し
app = Flask(__name__)
@app.route('/')
def index(): # 最初に動く
return render_template('index.html',
message='ハロワ')
と書きましょう。
とりあえずこれで、index.htmlを開くアプリができたはずです。早速ターミナルで
python main.py
して見ましょう。なんか文字が出ます。よくみると
* Debug mode: on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
と書いてあるのがわかります。つまりローカルの http://127.0.0.1:5000/ にアプリが動いてるぞということです。
おっと、一応言っておくと今回僕はchromeで見てみますので、もしかしたら他のブラウザでは挙動が違うかもしれません、気をつけてください。ちなみに僕は普段は火狐を使います。
それはともかく早速、喜び勇んで http://127.0.0.1:5000/ にアクセスして見ましょう。...んん?
jinja2.exceptions.TemplateNotFound
jinja2.exceptions.TemplateNotFound: index.html
...こんな感じのよくわからない表記が出ると思います。
それもそのはず、アプリではまずindex.htmlを開いてくれと命令してますが、index.htmlを用意してません。うっかりしていました。ということでindex.htmlを作っていきましょう。
index.htmlとlayout.html
まずtemplatesというフォルダを作ってその下にindex.htmlとlayout.htmlというファイルを作りましょう。現在のファイル構成はこんな感じです。
.
├── blog # ブログの記事ようのメモ
├── part1 # part1のアーカイブ
├── part2 # part2のアーカイブ
├── main.py # 実際に動くファイル
├── static # part1で作ったMNISTとかAnnoyのデータが置いてあるやつ
└── templates # 今回作ったもの
├── index.html
└── layout.html
layout.htmlって何?
まずlayout.htmlの中身をいじります。
Flaskでは共通のレイアウトを定義できます。それを定義するのがこいつというわけです。
別に凝ったことをする気はないのでさらっと書きます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>SAMPLE</title>
</head>
<body>
<hr>
{% block content %}
{% endblock %}
</body>
</html>
こんな感じです。
よくあるhtmlでは見かけない
{% block content %}
{% endblock %}
こんな表記がありますが、ここではとりあえず置いておきます。
layout.htmlというのはいわゆるテンプレってやつです。
何度も書くのが面倒なヘッダの設定なんかをここに書いて、他の.htmlファイルで読み込むと楽ちんってわけです。便利ですね。
index.htmlって何?
ではやっと、index.htmlの中身をいじっていきます。
今更になってしまいましたが、これは簡単なデモのつもりなので凝ったものは作る気さらさらありませんし、そもそも僕はhtmlやcss、Javascriptそんなに好きじゃない(仕事にしていけるほど詳しくない)です。あくまでPythonが好きです。
なのでPython以外は雰囲気でコードを書いてます。なんかここ変だよってのがあったらコメントで教えてください。(とはいえ記事を読むであろう対象に自分みたいな素人を想定しているのでくるのかわかりませんが)
少し前置きが長くなってしまいました。index.htmlです。書きましょう。
{% extends "layout.html" %}
{% block content %}
<h3>タイトルです</h3>
{{ message }}
{% endblock %}
手始めにはこんな感じでいいかなと思います。
早速注目したいのが、
{% extends "layout.html" %}
これを見てください。先ほどのlayout.htmlを読み込んでいる部分です。
そして下の中に書いてある、
<h3>タイトルです</h3>
{{ message }}
といったような、layout.htmlに読み込まれて
{% block content %}
{% endblock %}
の間に書いてあるものが、読み込まれてレンダリングされるという流れになっています。
{{ message }}というのはあとで説明しますが(tabun) Jinja2というテンプレートエンジンによって、動いている部分です。
最初のmain.pyのindex()関数に返り値としてmessage='ハロワ'と入れたのを思い出してください。これが表示されているというわけです。
つまり、この変数に違う文字列を渡すとそれが表示されます。
適当に変えて確かにそうだなというのを確認しておくのもプログラミングの勉強では大事になってくるでしょう。試して見てください。
では上のlayout.htmlとindex.htmlを颯爽とコピペしたらmain.pyのエディット画面に入って、ctl+sかcommand+sか、とにかく変更してなくてもファイルを保存しようとしましょう。
すると、下のように何かリロードしてページを更新しようとします。
* Restarting with fsevents reloader
こんな感じで表示されてるんじゃないかな?
次の目標
なんだかんだここまでで、既に4000文字くらいになってしまいました。
記事を描こうと思い立つ前に想像していた以上に全く進んでいないのですが、次の書きたいことを書こうとすると、ここから二倍の長さになりそうなのでここらで止めて続きは次回に回したほうが良さそうです。
漫画を書き出すと、最初に予想してた巻数の何倍も書いてるとどこかで見ましたが実感しました。だいぶ軽い気持ちで始めましたが長丁場になりそうです。
逆にいくつか以前作ったゆっくりゲーム実況の動画は話させることないなーって感じだったんですが、ゲームが主体かどうかの違いなんですかね?まあとにかく雑談はここらでやめて総括に入りましょう。
今回は、Flaskを使ってちょっとウェブアプリっぽいものが作れそうかな?というところまで行きました。
実はこのあとどんな感じで進めて行こうか迷ってるので次は遅くなると思います。そんな感じでまた次会えたら嬉しいです。あとコメントかLGTMください。これ書くだけで2時間かかって疲れました。ではまた。
(僕が飽きたり忙しくなかったら)続く:-> (次のURL)
[追記]
すみません。うp主のエネルギーが尽きたので、ここでこの連載はおしまいということにしたいです。限りなく可能性は低いですが、続きを書くこともありうるかもしれませんが、ここで一度終わりにしたいと思います。
楽しみにしていた方には非常に申し訳ないです。本当に申し訳ないです。
資本主義が悪いよ、資本主義が