"BOKU"のITな日常

還暦越えの文系システムエンジニアの”BOKU”は新しいことが大好きです。

画像を1000カテゴリに分類するデモアプリを作成(tf.kerasの事前学習済VGG16モデル)/Django2.0+Bootstrap4

今回は、django2.0+bootstrap4でWEB入力画面を用意し、指定した画像を1000カテゴリに分類判定するデモ画面を作ります。

f:id:arakan_no_boku:20190320212948j:plain

 

バックエンドはVGG16

 

バックエンドの処理は、kerasで事前学習済VGG16モデルを使います。

画像を1000カテゴリに分類した結果を日本語化したりする方法は以下を参照します。

arakan-pgm-ai.hatenablog.com

arakan-pgm-ai.hatenablog.com

また、入力画面にあたるドラッグ&ドロップ機能等については、以下の記事で用意したサンプル入力画面ものを使います。

arakan-pgm-ai.hatenablog.com

今回は、上記の入力画面に画像を評価し適切なカテゴリを返すロジックを組みこみこんで、一旦完成形をめざします。 

 

動作イメージ確認

 

最初に、今回作成したデモ画面の動作イメージです。

実際に動かして、ハードコピーをとってます。

エクスプローラから、画像ファイルをドロップします。

f:id:arakan_no_boku:20190121010218j:plain

 

ファイル名がはいるので、「画像を分類する」ボタンを押します。

f:id:arakan_no_boku:20190121010510j:plain

 

判定結果とドロップされた画像を表示します。

f:id:arakan_no_boku:20190121010717j:plain

こんな感じ。

 画像は適当に拾ったものなんですが、見事に識別できてます。

ちなみに、アフリカ象である確率が低いのは、次点に「インド象」があるからです。

アフリカ象インド象の識別って、かなり難しいです。

VGG16、すごいですね。

 

デモの実装

 

最初は、画像を評価して該当するカテゴリを返す処理です。 

前回、kerasで事前学習済のVGG16モデルを利用したソースは、あくまで動作確認用の簡単なもので、djangoのviews.pyに組み込んで使うには、ちょっと使いずらいので改造します。

 

keras_cgg16.pyのソースコード

 

クラス化して、汎用的に利用できるようにします。

from tensorflow.keras.applications.vgg16 import VGG16,decode_predictions
from tensorflow.keras.preprocessing import image
from tensorflow.keras.applications.vgg16 import preprocess_input
import numpy as np
import json

class Vgg16k:

    def __init__(self):
        self.model = VGG16(weights='imagenet', include_top=True)

    def predict(self,imgpath,jsonpath):
        fj = open(jsonpath,'r')
        self.tojp = json.load(fj)
        fj.close()
        img = image.load_img(imgpath, target_size=(224, 224))
        x = image.img_to_array(img)
        x = np.expand_dims(x, axis=0)
        x = preprocess_input(x)
        pred = self.model.predict(x)
        results = decode_predictions(pred, top=1)[0]
        return('{:.2f}'.format(results[0][2] * 100.0) + '%の確率で「' +  self.tojp[results[0][1].replace('\'','')] + '(' + results[0][1] + ')」')

 

ソースコードの補足説明

 

初期化でモデルをロードして、後はpredict()で評価するだけです。

 

シングルコーテーションの処理

 

pythonの辞書のキーとして、「'(シングルコーテーション)」がはいった文字列は使えませんので、リプレースで消してます。

辞書をつくるときにも、そうしているので。

self.tojp[results[0][1].replace('\'','')]

 

画像とJSON辞書のパスを受け取る

 

対象となる画像のパスと、日本語化辞書のJSONファイルは引数で受け取るようにしてます。

画像はともなくJSONのファイルまで、引数で受け取るのは、ちょっと妙な仕様なのですが、ローカルフォルダのパス情報をviews.pyだけで管理したかったという理由だけで、こんな感じにしています。

 

処理内容は以下の記事を参考に

 

処理内容自体は、ほぼほぼ前に書いた以下の記事のまんまなので説明しません。 

arakan-pgm-ai.hatenablog.com

 

views.pyのソースコード

 

今回の変更は、上記の画像判定クラスを使った処理をViews.pyに組み込む以外は、サンプル入力画のまんまです。

arakan-pgm-ai.hatenablog.com

 

まずはソースコードから。

from django.http.response import HttpResponse
from django.shortcuts import render, render_to_response
from datetime import datetime as dt
from django.contrib.staticfiles.templatetags.staticfiles import static
from . import forms
from . import keras_vgg16 as vgg
from django.template.context_processors import csrf
import os


def demo(request):
    REAL_DIR = 'C:\\xxxxxxx\\xxxxxx\\static\\'
    if request.method == 'POST':
        vg = vgg.Vgg16k()
        imgpath =  static('images/' + request.POST["textone"])
        real_imgpath = REAL_DIR + 'images\\' + request.POST["textone"]
        real_jsonpath = REAL_DIR + 'json\\keras_vgg16_out.json'
        result = vg.predict(real_imgpath,real_jsonpath)
        c = {
             'textone': imgpath,
             'cnamelabel':'この画像に一番近いカテゴリ',
             'cname':result + 'です。'
        }
    else:
        form = forms.UserForm(label_suffix=':')
        c = {'form': form}
        c.update(csrf(request))
    return render(request,'demo02.html',c)  

補足します。

 

views.pyの補足説明

 

上記のVGG16の処理を書いたクラスは、keras_vgg16.pyという名前で保存しているため、それをインポートして使ってます。

 

ファイルパス取得部分の留意点

 

ちょっと、ごちゃごちゃしているのは、ファイルのパスを取得する部分です。

djangoは静的ファイルをアクセスする仕組みを当然もってます。

その場合、djangoのプロジェクトルートからの相対パス(例 /static/images/test.jp)で取得することになります。

でも。

views.py中で、vgg.predict()みたいな処理に引数で渡すときは、それではエラーになるので、ローカルフォルダの絶対パスを渡してやる必要があるので、うえのような書き方になってます。

 

処理を簡略化した部分

 

かつ、今回は、ドロップされた画像ファイルをdjango管理下のフォルダ(通常ならmediaフォルダとか)にuploadする処理をはしょっているので、staticの下のimagesフォルダに最初から置いて、そこを固定で身に行くという手抜き仕様でやってます。

今回の変更は以上です。

 

まとめ

 

今回の変更は、前回の入力画面の応答の部分を、ちゃんと画像を評価した結果を返すようにしただけです。

画像のカテゴリ分けも、kerasの事前学習済モデルをまんま使っているだけで、非常に簡単に記述できてます。

でも。

こんな簡単なプログラムで、画像1000カテゴリを、かなりの精度で分類するデモができてしまうわけですから・・、凄い時代になったなと、つくづく思いますねえ。

今回はこんなところで。

ではでは。