【コード解説】Keras・MNIST編:Flask(Python)Web機械学習アプリ開発入門 – 画像アップロード判定プログラム

【コード解説】Keras・MNIST編:Flask(Python)Web機械学習アプリ開発入門 - 画像アップロード判定プログラム

 

Contents - 目次(もくじ)

【解説】Keras・MNIST編:Flask(Python)Web機械学習アプリ開発入門 – 画像アップロード判定プログラム

 

 

Google Colaboratoryの環境でKerasを使い、ディープラーニング(深層学習)でおなじみの「畳み込みニューラルネットワーク」(CNN:Convolutional Neural Network)を実装したMNISTの画像認識AIプログラム

flask_keras_mnist_demo.ipynb | Google Colaboratory
(ファイル – ドライブにコピーを保存後にコピー環境で実行)

の学習済みモデルなどを活用して、Flask Web AIアプリを実装出来るようにしたサンプルコードを作成し、コードの解説をしてみました。

* Keras:Pythonで書かれているTensorFlow上等で実行可能な高水準のニューラルネットワークライブラリ

 

機械学習プログラミングを始めたものの、アプリ化の壁が超えられない・・・

機械学習を活用したWebアプリの基本的な仕組みを学びたい!

と考えている方の、何かしらのきっかけになることがありましたら幸いです。
今回のプログラムをきっかけに、Flaskを活用した他の機械学習Webアプリのサンプルコードも読み始められますように

尚、内容に関しては正確に記載するように努めておりますが、個人で学習した範囲の情報ですので、正確な情報等の詳細に関してはご自身でもよくお調べください。

【情報】

このページをPDF化した資料を無料でダウンロードできるように公開しました。
日々の学習にお役立てください。

オリジナルデータセット編のFlask(Python)Web機械学習アプリ開発サンプルコードの日本語解説も公開しました。
【コード解説】自作画像認識編 Flask(Python)Web機械学習アプリ開発入門:画像アップロード判定プログラム

【追記:2023年2月14日】
「keras.preprocessing API」は「Tensorflow 2.9.1」で廃止されたようです。
Tensorflow 2.9.1より上のバージョンを使う場合には
「from keras.preprocessing.image import img_to_array」のところを「from tensorflow.keras.utils import img_to_array」に修正してください。

 




 

 

【コード全体の概略】Keras・MNIST編:Flask(Python)Web機械学習アプリ – 画像アップロード判定プログラムのサンプルコード・サンプルソース

 

 


サンプルコードダウンロード
初版:2021.2.4
最終更新:2021.2.8

Mac・Windowsでの使い方解説はこちら
【サンプルコード】MNIST編 Flask(Python)Web機械学習アプリ開発入門:画像アップロード判定プログラム 

 

 

ファイル構造:サンプルコード概略

 

ファイル構造:サンプルコード【サンプルコード】Keras・MNIST編:Flask(Python)Web機械学習アプリ開発入門 - 画像アップロード判定プログラム

 

Flask-Keras-Simple-MNIST-basic
-app.py(Pythonプログラム)
-mnist_model_weight.h5(Keras:CNN MNISTの学習モデル構造と学習済みの重み)
-requirements.txt(必要なライブラリのインストール)
-README.md(説明など)
:templates
– base.html(HTMLの基本構造となるベースレイアウト)
– index.html(トップページ)
– result.html(予測結果のページ)

 

 

base.html:サンプルコード概略

 

 

<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>【MNIST編】Flask+KerasでシンプルWeb AIアプリ</title>
        {% block head %} {% endblock %}
    </head>
    <body>
        <div style="text-align:center">
            <h2>【MNIST編】Flask+KerasでシンプルWeb AIアプリ</h2>
        </div>

       {% block body %} {% endblock %}
    </body>
</html>

 

Web開発でお馴染みの

・HTML(HyperText Markup Language)

の基本構造(骨格)を記述しています。
ここで「base.html?」(共通テンプレート・ベースレイアウト)と思われる方もいるのではないかと思いますが、Flaskの特徴の1つである

・Jinja2

というPythonのためのテンプレート言語(テンプレートエンジン)を利用することで、

・(1度記述すれば、その後は)少量の記述だけで効率的にWebページを作成

できるようになります。要は使い回せるということです。

{} 内の記述で共通で使える部分を指定しています。
今回は、

・<head>
・<body>

を使い回します。
その他にも、Jinja2を活用することでHTMLの中にPythonを埋め込むことができるようになります。

 

 

index.html:サンプルコード概略

 

index.html:サンプルコード【コード解説】Keras・MNIST編:Flask(Python)Web機械学習アプリ開発入門 - 画像アップロード判定プログラム

 

{% extends 'base.html' %}

{% block body %} 

<form method="POST" action="/predict" enctype="multipart/form-data">
   <div style="text-align:center">
       <input type="file"  name="input_file" aria-label="ファイルの選択">
       <input type="submit" value="予測する">
   </div>
</form>

{% endblock %}

 

Web AIアプリのトップページ(ホームページ)の構造を記述しています。
Jinja2を使い「base.html」で記述したHTMLコードを再利用して

・<head>
・<body>

内の構造を反映させています。
その他に、

・ファイルのアップロード用フォーム
・予測を開始するためのボタン

などを設置しています。

 

 

result.html:サンプルコード概略

 

result.html:サンプルコード【コード解説】Keras・MNIST編:Flask(Python)Web機械学習アプリ開発入門 - 画像アップロード判定プログラム

 

{% extends 'base.html' %}

{% block body %}

 <div style="text-align:center">
    <h2>予測結果は{{ result_output }}です。</h2>
    <button><a href="/">戻る</a></button>
 </div>

{% endblock %}

 

Web AIアプリの予測結果ページの構造を記述しています。
「index.html」の時と同様に、Jinja2を使い「base.html」で記述したHTMLコードを再利用して

・<head>
・<body>

内の構造を反映させています。
機械学習Webアプリ開発で気になる

・予測結果を表示

させるための場所です。
ここまでHTML構造を見ただけでは、

どのように予測させているの?

と疑問に思うのではないかと思います。
次は、いよいよ今回の機械学習アプリの心臓部分を覗いてみましょう。

 

 

app.py:サンプルコード概略

 

 

from flask import Flask, render_template, request
from keras.models import load_model
from PIL import Image, ImageOps 
from keras.preprocessing.image import img_to_array
#追記:「keras.preprocessing API」は「Tensorflow 2.9.1」で廃止。 Tensorflow 2.9.1より上のバージョンを使う場合には
#「from keras.preprocessing.image import img_to_array」のところを「from tensorflow.keras.utils import img_to_array」に修正してください

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/predict', methods=['POST'])
def predict():
    data = request.files['input_file'].stream
    im = Image.open(data)

    model = load_model('mnist_model_weight.h5') 

    img = im.resize((28,28))
    img = img.convert(mode='L')
    img = ImageOps.invert(img) 
    img = img_to_array(img)
    img = img.reshape(1, 28, 28, 1)
    img = img.astype('float32')/255

    result = model.predict_classes(img)
    result = result[0]

    return render_template('result.html',result_output=result)

if __name__ == '__main__':
    app.run(debug=True)

 

ここには、機械学習アプリの核となるPythonプログラムを記述しています。
具体的には、

・Flask Webアプリを実行するために必要な
:Flask関連のインポート
:実装

・アップロード画像を予測するために必要な
:「機械学習モデル構造」「学習済みの重み」や、アップロード画像の処理と予測に必要な各種ライブラリなどのインポート
:実装

などを記述しています。

 

 

【コード解説】Keras・MNIST編:Flask(Python)Web機械学習アプリ – 画像アップロード判定プログラム

 

 

ある程度、Flaskで機械学習アプリを作成する方法を学ばれた方は、上記の概略を見るだけで、アプリの構造が大体わかるのではないかと思いますが、HTMLやPython、Flask初学者の方にとっては、意味不明なのではないかと思います。

以下に詳細を解説していきます。

 

 

base.html:サンプルコード解説

 

 

<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>【MNIST編】Flask+KerasでシンプルWeb AIアプリ</title>
        {% block head %} {% endblock %}
    </head>
    <body>
        <div style="text-align:center">
            <h2>【MNIST編】Flask+KerasでシンプルWeb AIアプリ</h2>
        </div>

       {% block body %} {% endblock %}
    </body>
</html>

 

<!DOCTYPE html>
#コード解説
:
文書型宣言(DOCTYPE宣言)。
HTMLバージョンによって書き方が変わりますが、今回はHTML5の文書型宣言の記述です。
この記述をすることで

・コードがHTMLであること
・HTMLのバージョン
・DTD(Document Type Definition:文書型定義)

などを宣言できるようです。古いバージョンのHTMLの記述方法に比べるとHTML5は、シンプルでいいすね。

 

<html lang=”ja”>
#コード解説
:
HTMLのlang属性。
html要素内で使われている言語は、日本語(ja:japanese)という意味です。

 

<head>〜</head>
#コード解説
:
<head>〜</head>内に文書のヘッダ部分を指定するための記述をします。
ここの記述の大部分は、ページが読み込まれてもWebブラウザには表示されませんが、

・Googleなどの検索結果の説明箇所
:meta description(メタディスクリプション)

・ブラウザのタブに表示されているテキスト(タイトル)
:title

などは、ここに記述されているようです。

 

<meta charset=”UTF-8″>
#コード解説
:
文字コード(文字エンコーディング)の指定。
meta要素のcharset属性を使うと文字コードを指定できます。今回は「UTF-8」を指定しています。
HTMLの世界では、HTMLファイルの文字コードと、HTMLの内容を表示させるブラウザの文字コードが異なると、文字化けが発生する原因になります。

 

<meta name=”viewport” content=”width=device-width, initial-scale=1″>
#コード解説
:
viewport(表示領域)の指定。
以下のように指定するとviewportの幅は実際の解像度ではなく端末やブラウザに合わせた値を返すようになるようです。
<meta name=”viewport” content=”width=device-width”>

initial-scaleで初期倍率を指定できます。今回は「1」を指定していますが、width=device-widthを記述すると、自動的に初期倍率は「1」となるようです。
当初は、サンプルコードをシンプルにするために、このコードを入れていませんでしたが、Edgeのブラウザに注意されたので入れておきました…

 

<title>【MNIST編】Flask+KerasでシンプルWeb AIアプリ</title>
#コード解説
:
コンテンツ(ページ)のタイトルを指定。
<title>〜</title>内に好きなタイトルを入れます。
ここの記述で、

・Googleなどの検索結果のタイトル
・ブラウザのタブに表示されているテキスト(タイトル)

の表示が変わります。
基本的には、コンテンツの内容を上手く反映しているタイトルにすることで、検索エンジンを介して探す方に見つけてもらいやすい名前をつけます。

 

{% block head %} {% endblock %}
#コード解説
:
Jinja2でテンプレートの継承を設定。

・ {% block ブロックの名前 %} {% endblock %}

と記述することで、テンプレートとして他のHTMLページに継承したいブロックを指定できます。
今回は<head>〜</head>内に

・ {% block head %} {% endblock %}

と「head」と書くことで<head>〜</head>内の情報を継承することができるように設定しています。
他にも

<title>{% block title %}{% endblock %}</title>

とした場合、Pythonファイルの中で

return render_template(‘xxx.html’,title=’表示させたいタイトルを記述’)

などと記述することで、各ページの(タイトルの)中身を定義することもできるようです。

 

<body>〜</body>
#コード解説
:
<body>〜</body>の中に記述されたテキストや画像などがブラウザの画面上に表示されます。

 

<div style=”text-align:center”>
 <h2>【MNIST編】Flask+KerasでシンプルWeb AIアプリ</h2>
</div>

 

<div style=”text-align:center”>〜</div>
#コード解説
:
中央揃えをしています。
今回は<h2>〜</h2>内の

・【MNIST編】Flask+KerasでシンプルWeb AIアプリ

を中央に表示させています。

 

<h2>〜</h2>
#コード解説
:
HTMLでマークアップする見出しタグです。

大見出し → 小見出し
h1・h2・h3・h4・h5・h6

などがあります。
<h2>〜</h2>内に、表示させたいテキストを入力します。

 

{% block body %} {% endblock %}
#コード解説
:
Jinja2でテンプレートの継承を設定。
今回は<body>〜</body>内に

・ {% block body %} {% endblock %}

と「body」と書くことで<body>〜</body>内の情報を継承することができるように設定しています。

 

 

index.html:サンプルコード解説

 

index.html解説:サンプルコード【コード解説】Keras・MNIST編:Flask(Python)Web機械学習アプリ開発入門 - 画像アップロード判定プログラム

 

{% extends 'base.html' %}

{% block body %} 

<form method="POST" action="/predict" enctype="multipart/form-data">
   <div style="text-align:center">
       <input type="file"  name="input_file" aria-label="ファイルの選択">
       <input type="submit" value="予測する">
   </div>
</form>

{% endblock %}

 

{% extends ‘base.html’ %}
#コード解説
:
指定したHTMLを拡張。
今回は、ベースレイアウト「base.html」を使い回します。
具体的には、以下の構造

<!DOCTYPE html>
<html lang=”ja”>
<head>
<meta charset=”UTF-8″>
<meta name=”viewport” content=”width=device-width, initial-scale=1″>
<title>【MNIST編】Flask+KerasでシンプルWeb AIアプリ</title>
</head>
<body>
<div style=”text-align:center”>
<h2>【MNIST編】Flask+KerasでシンプルWeb AIアプリ</h2>
</div>
</body>
</html>

を使い回しています。

 

{% block body %}〜{% endblock %}
#コード解説
:
ベースレイアウト「base.html」の<body>〜</body>内の内容に加えて、「〜」の部分に、新たに追加したいコードを記述します。

 

<form method=”POST” action=”/predict” enctype=”multipart/form-data”>
<div style=”text-align:center”>
<input type=”file” name=”input_file” aria-label=”ファイルの選択”>
<input type=”submit” value=”予測する”>
</div>
</form>
#コード解説
:
画像ファイルをアップロード後に、アップロードした画像ファイルをサーバーに送信(HTTPメソッド:POST送信)し、「〜/predict」のページを表示させるための処理です。

<form method=”POST” action=”/predict” enctype=”multipart/form-data”>
form method=”POST” action=”/predict”
:サーバーに送信。入力データを「〜/predict」のページに送信。

form enctype=”multipart/form-data
:データをマルチパートデータとして送信。ファイルを送信するフォームで必要なようです。

<div style=”text-align:center”>〜</div>
:中央揃え。
今回は<h2>〜</h2>内の

・ファイルの選択(画像アップロード用のボタン)
・予測する(予測実行用のボタン)

を中央に表示させています。

<input type=”file” name=”input_file” aria-label=”ファイルの選択”>
:<input>要素のtype属性に「file」を指定すると閲覧者が、自分のパソコン・スマホなどの端末のストレージからファイルを選択できるようになります。
「name=”input_file”」とすることで「app.py」のPythonプログラムで「input_file」という名前で画像ファイルを扱えるように指定しています。
「aria-label=”ファイルの選択”」についてですが、aria-label属性は、画面上には表示されませんがテキストリーダーなどでの読み上げの際に認識しやすいように設定しました。aria-label属性を付けなくても、見かけ上は「ファイルを選択」という表示があったのでよしとしていましたが、Edgeのブラウザで確認したところ、注意されましたので追記することにしました。

<input type=”submit” value=”予測する”>
:<input>要素のtype属性に「submit」を指定し、フォームの送信ボタンを作成します。「value=”予測する”」でボタン名を表示を指定しています。

 

 

result.html:サンプルコード解説

 

result.html解説:サンプルコード【コード解説】Keras・MNIST編:Flask(Python)Web機械学習アプリ開発入門 - 画像アップロード判定プログラム

 

{% extends 'base.html' %}

{% block body %}

 <div style="text-align:center">
    <h2>予測結果は{{ result_output }}です。</h2>
    <button><a href="/">戻る</a></button>
 </div>

{% endblock %}

 

{% extends ‘base.html’ %}
#コード解説
:
指定したHTMLを拡張。
「index.html」と同様に、ベースレイアウト「base.html」を使い回します。
具体的には、以下の構造

<!DOCTYPE html>
<html lang=”ja”>
<head>
<meta charset=”UTF-8″>
<meta name=”viewport” content=”width=device-width, initial-scale=1″>
<title>【MNIST編】Flask+KerasでシンプルWeb AIアプリ</title>
</head>
<body>
<div style=”text-align:center”>
<h2>【MNIST編】Flask+KerasでシンプルWeb AIアプリ</h2>
</div>
</body>
</html>

を使い回しています。

 

{% block body %}〜{% endblock %}
#コード解説
:
ベースレイアウト「base.html」の<body>〜</body>内の内容に加えて、「〜」の部分に、新たに追加したいコードを記述します。

 

<div style=”text-align:center”>〜</div>
#コード解説
:
中央揃えをしています。
今回は<h2>〜</h2>内の

・予測結果は{{ result_output }}です。
・戻る(ボタン)

を中央に表示させています。

 

<h2>予測結果は{{ result_output }}です。</h2>
#コード解説
:
<h2>〜</h2>は、HTMLでマークアップする見出しタグです。

大見出し → 小見出し
h1・h2・h3・h4・h5・h6

などがあります。
<h2>〜</h2>内に、表示させたいテキストを入力します。
今回は

・予測結果は{{ result_output }}です。

と表示させています。
{{ result_output }}の所で「?」となるのではないかと思いますが、二重波括弧{{ }}内の「result_output」は変数名です。
{{ }} 内の記述が、Pythonのコードとして認識されます。

今回のプログラムでは、「index.html」でアップロードされた画像ファイル(変数名:input_file)を、「app.py」のPythonプログラムで予測した結果を「result_output」という変数名にしています。
そのため、{{ result_output }}と記述をすることで、予測結果を表示できます。

 

<button><a href=”/”>戻る</a></button>
#コード解説
:
指定したページに移動するボタンの作成。
「a href=”/”」とすることでトップページ(index.html)に移動するように設定しています。
<button><a href=”/”>〜</a></button>内には、ボタンの意味がわかりやすいようにテキストを入力します。今回は「戻る」ボタンとして機能するように設定しています。

 

 

app.py:サンプルコード解説

 

 

from flask import Flask, render_template, request
from keras.models import load_model
from PIL import Image, ImageOps 
from keras.preprocessing.image import img_to_array 
#追記:「keras.preprocessing API」は「Tensorflow 2.9.1」で廃止。 Tensorflow 2.9.1より上のバージョンを使う場合には
#「from keras.preprocessing.image import img_to_array」のところを「from tensorflow.keras.utils import img_to_array」に修正してください

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/predict', methods=['POST'])
def predict():
    data = request.files['input_file'].stream
    im = Image.open(data)

    model = load_model('mnist_model_weight.h5') 

    img = im.resize((28,28))
    img = img.convert(mode='L')
    img = ImageOps.invert(img) 
    img = img_to_array(img)
    img = img.reshape(1, 28, 28, 1)
    img = img.astype('float32')/255

    result = model.predict_classes(img)
    result = result[0]

    return render_template('result.html',result_output=result)

if __name__ == '__main__':
    app.run(debug=True)

 

【FlaskのHello world!プログラムについて】

以下のコードで、ブラウザ上に「Hello world!」を表示できるようです。

from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return 'Hello world!'

if __name__ == '__main__':
    app.run(debug=True)

これが、FlaskでWebアプリを作成する上での基本的な構造です。
return ‘Hello world!’
の「Hello world!」のテキストを変えると、新たなテキストが表示できるようになります。

from flask import Flask
:flaskパッケージのFlaskクラスのインポート。

app = Flask(__name__)
:Flaskクラスの「app」という変数名のインスタンス作成。「app」という変数に、Flaskを定義して使えるようにする。
「__name__」は、自動的に定義される変数を指し、現在のファイルのモジュール名が入る。(例 app.pyの場合「app」)

@app.route(‘/’)
:「app」に「https://example.com」(URL「https://example.com」の例)のアドレスに処理を追加。
上記のHello world!プログラムでは「https://example.com」のページに、「Hello world!」を表示させる関数(index)を記述することで「Hello world!」をブラウザ上に表示しています。
「@」の行はデコレータと呼ばれるようです。
@app.route()の引数には、(‘/’)や(‘/predict’)などのURLを記述します。(‘/’)の場合は、アドレスのトップ(例 http://127.0.0.1:500/)が表示され、(‘/predict’)の場合には、http://127.0.0.1:500/predict が表示されます。

def index():
return ‘Hello world!’
:「Hello world」とブラウザに表示させる処理。
上記のHello world!プログラムでは「index」という関数名の関数が記述されています。

if __name__ == ‘__main__’:
app.run(debug=True)

if __name__ == ‘__main__’:
:Pythonプログラムを記述したファイル「app.py」が「python app.py というコード入力(コマンド入力)で実行されているかどうか?」を判定。
「import app.py」とコード入力(コマンド入力)した際に、プログラムが実行されることを防ぐ。

app.run(debug=True)
:Flaskの開発用サーバーで 「app」をデバッグモードで起動。

 

from flask import Flask, render_template, request
from keras.models import load_model
from PIL import Image, ImageOps
from keras.preprocessing.image import img_to_array
追記:
「keras.preprocessing API」は「Tensorflow 2.9.1」で廃止。 Tensorflow 2.9.1より上のバージョンを使う場合には
「from keras.preprocessing.image import img_to_array」のところを「from tensorflow.keras.utils import img_to_array」に修正してください

#コード解説
:
今回のプログラム(app.py)のPythonプログラムで必要なライブラリ・モジュールなどをインポートしています。

from flask import Flask, render_template, request
:Flaskを使うために必要なモジュールなどを読み込む。

render_template
:render_template()関数を利用することで、「index.html」「result.html」などのテンプレートにサーバのデータを組み込めるようになります。

request
:methods=[‘POST’]を使う際に必要です。

from keras.models import load_model
:Kerasで作成した機械学習の「モデル構造」「学習済みの重み」などを読み込むために必要です。
model = load_model(‘mnist_model_weight.h5’) #学習済みモデルの読み込み(重みを含む)
で使われています。

from PIL import Image, ImageOps
:PIL(Python Imaging Library)後継の画像処理ライブラリPillowを使います。

im = Image.open(data) #画像の読み込み
img = ImageOps.invert(img) #画像の色を反転

などで使われています。

from keras.preprocessing.image import img_to_array
:読み込んだ画像をPIL形式(Pillow:Python Imaging Libraryから分岐した画像ライブラリのデータフォーマット)からndarray(NumPyの独自のデータ構造。多次元配列)に変換。

img = img_to_array(img)

で使われています。
追記:
「keras.preprocessing API」は「Tensorflow 2.9.1」で廃止。 Tensorflow 2.9.1より上のバージョンを使う場合には
「from keras.preprocessing.image import img_to_array」のところを「from tensorflow.keras.utils import img_to_array」に修正してください

 

@app.route(‘/’)
def index():
return render_template(‘index.html’)
#コード解説
:
:「app」に「https://example.com」(URL「https://example.com」の例)のアドレスに「index.html」のページを表示させる処理を追加。上記のコードでは、「index」と言う関数名が割り当てられています。
簡単に言うと、

・トップページ(ホームページ)に「index.html」に記述してあるHTMLを表示させる

のようなニュアンス。
Flaskでは、「render_template関数」を使い、HTMLファイルを表示させ、HTMLファイル内に値を入れることができます。「render_template」を利用する際の注意点として、Pythonプログラム内に「render_template」をimportすることと、「templates」と言う名前のフォルダを作成し、「templates」フォルダ内にHTMLファイルを入れておく必要があるようです。
「templates」フォルダを作成していないと指定したHTMLファイルを読み込むことが出来ないようです。

 

@app.route(‘/predict’, methods=[‘POST’])
def predict():

return render_template(‘result.html’,result_output=result)
#コード解説
:
「app」に「https://example.com/predict」(URL「https://example.com」の例)のアドレスに「result.html」のページを表示させる処理を追加。また、result.htmlに記述されている「result_output」と言う変数名には、app.pyのPythonプログラムで予測された「result」(変数名)の結果を反映させる。
上記のコードでは、一連の処理を「predict」と言う名前の関数として定義しています。

 

def predict():
data = request.files[‘input_file’].stream
im = Image.open(data)

model = load_model(‘mnist_model_weight.h5′)

img = im.resize((28,28))
img = img.convert(mode=’L’)
img = ImageOps.invert(img)
img = img_to_array(img)
img = img.reshape(1, 28, 28, 1)
img = img.astype(‘float32’)/255

result = model.predict_classes(img)
result = result[0]
#コード解説
:
「index.html」でアップロードされた画像(変数名:input_file)を読み込み、Kerasで作成したMNISTの学習済みモデル(モデル構造+重み)の「mnist_model_weight.h5」を利用できるように画像を処理後に、画像認識結果を出力させています。

 

data = request.files[‘input_file’].stream
:「index.html」でアップロードされた画像(変数名:input_file)を「data」と言う変数名でロードする。

im = Image.open(data)
:「im」と言う変数名で、「data」の画像ファイルを参照する。

model = load_model(‘mnist_model_weight.h5′)
:Kerasで作成したMNISTの学習済みモデル(モデル構造+重み)の「’mnist_model_weight.h5」を読み込む。

img = im.resize((28,28))
:「im」と言う変数名の画像を「縦28×横28ピクセル」に変換し「img」と言う変数に入れる。

img = img.convert(mode=’L’)
:「img」と言う変数名の画像をグレースケール化(白黒画像化)。

img = ImageOps.invert(img)
:「img」と言う変数名の画像の色を反転させる(ネガポジ反転 – 画素値の逆転)。

img = img_to_array(img)
:「img」と言う変数名の画像をPIL形式(Pillow:Python Imaging Libraryから分岐した画像ライブラリのデータフォーマット)からndarray(NumPyの独自のデータ構造。多次元配列)に変換。

img = img.reshape(1, 28, 28, 1)
:「img」と言う変数名の画像データのデータ構造の変換。「縦28×横28ピクセル」の「グレースケール(白黒)」の「画像データが1枚」。
(画像データが1枚:バッチ数, 縦28ピクセル, 横28ピクセル, グレースケール:チャンネル数)
カラー画像の場合は(1, 28, 28, 3)。

img = img.astype(‘float32’)/255
:「img」と言う変数名の画像データを正規化。黒から白までの変化を0〜255で表現しているので、255で割ることでデータを0〜1の範囲に正規化。float型にすることで実数値で表現。
正規化前「0〜255」 正規化実施「0.0〜1.0」(実数値)

result = model.predict_classes(img)
:「img」と言う変数名の正規化された画像データを元に、画像認識(予測)し、「result」と言う変数名に入れる。

result = result[0]:
:[0]を付けないと出力結果に「[]」がついてしまうので[0]を追記。

 

その後、上述のように

return render_template(‘result.html’,result_output=result)

で、予測結果をブラウザ上に表示することができます。

 

予測結果をブラウザ上に表示サンプルコード【コード解説】Keras・MNIST編:Flask(Python)Web機械学習アプリ開発入門 - 画像アップロード

 

上記のコードでは、一連の処理を「predict」と言う名前の関数として定義しています。

 

【おわりに】Keras・MNIST編:Flask(Python)Web機械学習アプリチュートリアルの解説

 

 

お疲れ様でした。
以上、簡単ではありますがFlaskを活用した機械学習Webアプリの解説です。
機械学習で得られた結果をWebアプリ化するためには、基礎的なWebアプリ開発の知識も必要そうです。そのため、
Pythonプログラミングの学習の他に

・HTML(HyperText Markup Language)
:Webサイトの骨格を作るハイパーテキストを記述するためのマークアップ言語

・CSS(Cascading Style Sheets)
:Webサイトのデザイン・見た目を整えるスタイルシート言語

・JavaScript
:Webサイトに動きをつけるオブジェクト指向スクリプト言語

などの基礎や、関連するフレームワーク(Bootstrapなど)を知っていると応用の幅が広がるのではないかと思います。

 

ここ数年、

いつになったら機械学習Webアプリの学習を始めようか・・・

とぼんやりと考えていました。
2020年末にMicrosoftのGitHubアカウントで、HTML・CSS・JavaScriptなどが学べるWeb開発(ウェブ制作)入門者向けのチュートリアル

 

Web-Dev-For-Beiginners(microsoft)| GitHub
(Web Development for Beginners – A Curriculum | MIT License )

 

翻訳中・・・
【Web開発入門】日本人のためのWeb Development for Beginners(microsoft / Web-Dev-For-Beginners:GitHub)by 子供プログラマー

 

が公開されたので、生涯学習を兼ねてチュートリアルを日本語に翻訳し、サイトに公開を始めてから(学習途中ですが…)急に機械学習Webアプリ開発について学びたくなりました。
その他にも、ローカル環境(自分のパソコン)で機械学習Webアプリ開発を学ぶための開発環境を整える際に、Python用の仮想環境を使うと、各種ライブラリのバージョンなどの依存関係問題をクリアできることを知ったので学習に取り掛かる敷居が低くなりました。
機械学習Webアプリ開発について学び始め、様々な先人のコードに触れる機会が増えましたが、やはり機械学習の結果をWebアプリ化するのは面白いですね。
今回のFlaskチュートリアルは、学習の成果を(入れてすぐに…)アウトプットした形になりますが、一連の情報が、自分と同じように機械学習Webアプリについて学び始めたい初学者の方の、何かしらのきっかけになることがありましたら幸いです。

 

 

印刷用PDF:【コード解説】Keras・MNIST編:Flask(Python)Web機械学習アプリ開発入門 – 画像アップロード判定プログラム

 

印刷用PDFの外観:【コード解説】Keras・MNIST編:Flask(Python)Web機械学習アプリ開発入門 - 画像アップロード判定プログラム

 

学習の利便性を考え、印刷しやすいようにPDFも作成しました。
プリンタの印刷設定で、ブックレット等の冊子風に印刷すると読みやすいのではないかと思います。

 


初版:2021年2月8日

 

 

by 子供プログラマー | プログラミング入門ウェブ教室

 

 

オリジナル画像認識AIアプリの作成に挑戦
【コード解説】自作画像認識編 Flask(Python)Web機械学習アプリ開発入門:画像アップロード判定プログラム