スクリーンショット_2020-03-15_16.44.14

【コード公開】【Python】中国でコロナ対策に使われている画像認識AIを作ってみよう

【期間限定無料公開中】

みなさんは画像認識という技術をご存知でしょうか?

これはAI技術の一つで、データベースなどに大量に蓄積された画像データをプログラムに学習させることによって、画像に何が写っているのかを認識させることができる技術です。

今回のnoteでは画像認識技術についての概要をまとめていくつかの社会実装例を挙げ、後半の有料部分では中国の武漢でのコロナウイルス封じ込めのために実際に使われている画像認識プログラムを動かしてみたいと思います。

AIに興味があるけど何から手をつけたら良いかわからない、AIエンジニアになりたくて実際にプログラムを動かしてみたい、という方はぜひ最後までお付き合いください!

1. Pythonの画像認識が使われている例

画像認識はAI技術の中でも最近注目が集まっていて、今でもすでにみなさんの身近なところで使われています。例をあげてみましょう。

iPhoneをお持ちの方は、写真アプリを開いて検索タブを押してみてください。すると写真の検索ウィンドウが表示されるので、試しに猫と入力してみましょう。

ご覧のように、自分のスマホに入っている猫の写った画像が検索されて表示されます。似たようなことがGoogle検索でもできますよね。ちなみにこの猫は僕の実家で飼っていた猫です。

画像1

みなさんこの機能がどのような仕組みになっているのか、気になったことはないでしょうか? 画像に一つ一つタグ付けしたわけでもないのに、どうして猫の画像を判別できるのでしょうか? 気になったというそこのあなたは、AIエンジニアの素質があるかもしれません。

簡単に仕組みを説明すると以下のようになります。

スクリーンショット 2020-03-15 18.33.12

ユーザーが撮った写真はクラウドサーバーに送られて、そこで機械学習のプログラムによって被写物が判別されます。今回のように猫の場合には、前もって猫の写った画像とその画像には猫が写っているということを表すラベルの2つをセットで大量にプログラムに与えることで、機械学習モデルという被写物が何かを判別するためのプログラムを作成しているはずです。これを専門用語で教師あり学習と呼びます。

画像認識では新たな画像データは様々な数値的なパラメータ(色調・被写物の形・被写物の数など無数に存在。特徴量と呼ばれる)まで分解され、数学的な処理をした上で機械学習モデルと照合することでその判別結果が得られます。

例えば猫なら顔の面積に対して耳が大きいかどうか、尻尾が長いかどうかなどをプログラムが一つ一つ計算していくわけです。

これ以上の本質的な理解には統計学や数学が入ってくるので、本気でAIエンジニアを目指したいという方はそちらの参考書もぜひどうぞ!

2. Pythonの画像認識はどんな日本企業で使われている?

先ほどの例はAppleやGoogleなどの外資系企業の場合でしたが、それでは日本のサービスではどんな所に画像認識が使われているのでしょうか?

こちらも皆さんの身近な所にあります。

皆さんご存知の通販アプリ、メルカリです。僕は読み終わった本などを売る時にお世話になってましたね。

使ったことがある方ならわかると思いますが、アプリで出品物の写真を取るだけで、商品名やカテゴリなどの出品に必要な情報を自動で入力してくれます。

面倒くさがりな僕としては本当に助かりました。

これも先ほど説明した猫写真の判別と同じように、メルカリのデータベースに送信され続ける大量の出品物画像による教師あり学習が行われています。

さらに都合が良いことに、このような通販アプリサービスでは画像と被写物名(ラベル)をセットで大量に集めることができるので、教師あり学習の際に人力によるラベル付けが必要ないところが素晴らしいビジネスモデルだなと個人的に思います。

ちなみにメルカリはアメリカにもAI研究所を開設して現地の研究者とも提携しているほど、研究開発への投資が積極的な企業です。

このように画像認識による機械学習においては、メルカリやGoogleのように大量の画像データを収集することのできるプラットフォームと相性がとても良いです。

これは機械学習による画像認識の精度を上げるために、大量の学習用サンプルデータが必要だからです。

3. Pythonの画像認識が中国をコロナから救っている

ここまでで画像認識とは一体何なのか、大まかに理解できてきたでしょうか?

それでは記事タイトルについての話に移っていきたいと思います。

最近では日夜TVやSNS上を騒がせている新型コロナウイルス問題ですが、この対策にも画像認識が使われています。

新型コロナウイルスの感染者がマスクを着用していないと、そこから大量の飛沫感染の恐れがあります。中国のウイルス被害が深刻な地域では、監視カメラによる画像認識でマスク着用の有無を検出して警告を出すなどの対策がされています。

こちらは監視社会と言われるほど、大量のカメラが各所に設置されている中国ならではの方法かもしれません。またカメラを搭載したドローンによるチェックも合わせて行われているようです。

基本的人権の尊重される日本に住んでいる身からすると末恐ろしくも見えますが、そのようなリミッターが無い代わりに純粋なテクノロジーの威力を見ることができるのは、どうしてもエンジニアとして興味深くはありますね。

中国ではマスク検出の機械学習モデルを公開する動きが広まっているようです。

少しでも参考になったという方はTwitterでシェアお願いします!

今回のnoteでは後半部分で実際にこのマスク検出モデルを用いて、Pythonによる機械学習プログラムを動かして自分のPCカメラで正しく動作するまでを解説したいと思います!

ここまで読んでいただいて興味を持ってくれた方はぜひご購入ください!

購入が増えると自動的に今後の記事が豪華になります。また購入したことがわかるスクショをTwitterのDMなどでお送りいただければ、エラー解決などの質問にもお1人様3回までお答えします!

前半まとめ

画像認識はAI技術の1つ

・データセットから機械学習モデルを作成する

・データとラベル(標識)をセットで与えるのが教師あり学習

・日本企業のサービスではメルカリなどで使われている。

・中国でのコロナウイルス封じ込めに活躍している。

少しでも参考になったという方はTwitterでシェアお願いします!

ーー

4. Pythonの画像認識でマスク検出プログラム作る準備

購入ありがとうございます!

そして初めて機械学習に触れるという方にはようこそ!

まずは準備を始めましょう。

解説は基本的にMacOSのPython3.7、エディタはAtomを使って行います。Windowsをお使いの方も基本的な手順は同じになると思われますが、不具合がありましたらTwitterのDMまでお願いします。

Pythonのインストールはこちらを参考に↓

Atomのインストールはこちら↓

①GitHubからPythonのプロジェクトファイルをダウンロードします。

スクリーンショット 2020-03-16 14.09.02

「Clone or Download」→「Download ZIP」

②次に機械学習に使う大量の画像データセットをダウンロードしておきます。こちらは時間がかかるので早めにやっておきましょう。

https://drive.google.com/drive/folders/1mbDbdFgejFdgAGLC5GJR-lq8bk1AzyHQ

「データ」→「ダウンロード」

③そしてこちらからモデルファイルをダウンロードすれば、必要なファイルは揃います。

ファイルが揃ったらAtomエディタを開いて以下のように各ファイルを配置していきます。

スクリーンショット 2020-03-16 14.50.28

最初にダウンロードしたmask_checker-master(①)の下層に、画像の通りに足りないフォルダを作成したり各ファイルを配置します。

また先ほどダウンロードした画像データセット(②)は半分ずつtestフォルダとtrainフォルダにそれぞれ分けて格納します。こちらはそれぞれ学習モデルの訓練用とテスト用になります。

5. Pythonの画像認識のプログラムコード解説

次に、実際に画像認識の処理を行うPythonコードを見ていきます。

今回画像認識を行うために実行する必要のあるPythonファイルは次の2つになります。

・train.py(機械学習を行うプログラム

・webcam_demo.py(PCのカメラを起動して画像認識を行うプログラム)

ターミナルを起動してcdコマンドでmask_checker-masterディレクトリまで移動しましょう。(Windowsの場合はコマンドプロンプト)

上記のプログラムを実行する前に、それぞれのファイルで使われているPythonライブラリをインストールする必要があります。

まずtrain.pyを見てみましょう。

import pathlib

import numpy as np
import tensorflow as tf

TRAIN_DATA_PATH = 'dataset/mask_dataset/train/'
TEST_DATA_PATH = 'dataset/mask_dataset/test/'
OUTPUT_MODEL_FOLDER = 'exported/'
CLASS_NAMES = np.array([])
AUTOTUNE = tf.data.experimental.AUTOTUNE

EPOCHS = 5
IMG_SHAPE = (112, 112, 3)
BATCH_SIZE = 40


def get_label(file_path):
   parts = tf.strings.split(file_path, '/')
   one_hot = tf.cast(parts[-2] == CLASS_NAMES, tf.float32)
   return one_hot


def pre_process_img(path):
   img = tf.io.read_file(path)
   img = tf.image.decode_jpeg(img, channels=3)
   img = tf.image.random_brightness(img, 0.2)
   img = tf.image.random_saturation(img, 0.6, 1.6)
   img = tf.image.random_contrast(img, 0.6, 1.4)
   img = tf.image.random_flip_left_right(img)
   img = tf.image.convert_image_dtype(img, tf.float32)
   img = tf.subtract(img, 0.5)
   img = tf.multiply(img, 2.0)
   return img


def process_path(file_path):
   label = get_label(file_path)
   img = pre_process_img(file_path)
   return img, label


def show_label(label_list):
   for idx, label in enumerate(label_list):
       print(f'{idx} : {label}')


def main():
   global CLASS_NAMES

   train_data_dir = pathlib.Path(TRAIN_DATA_PATH)
   train_image_count = len(list(train_data_dir.glob('*/*.jpg')))
   print(f'train img count:{train_image_count}')
   test_data_dir = pathlib.Path(TEST_DATA_PATH)
   test_image_count = len(list(test_data_dir.glob('*/*.jpg')))
   print(f'train img count:{test_image_count}')
   CLASS_NAMES = np.array([item.name for item in train_data_dir.glob('*') if item.name not in [".keep", ".DS_Store"]])
   show_label(CLASS_NAMES)

   train_data_set = tf.data.Dataset.list_files(str(train_data_dir / '*/*.jpg'))
   train_data_set = train_data_set.map(process_path, num_parallel_calls=AUTOTUNE)
   train_data_set = train_data_set.shuffle(buffer_size=2000)
   train_data_set = train_data_set.repeat()
   train_data_set = train_data_set.batch(BATCH_SIZE)
   train_data_set = train_data_set.prefetch(buffer_size=AUTOTUNE)

   test_data_set = tf.data.Dataset.list_files(str(test_data_dir / '*/*.jpg'))
   test_data_set = test_data_set.map(process_path, num_parallel_calls=AUTOTUNE)
   test_data_set = test_data_set.batch(BATCH_SIZE)

   base_model = tf.keras.applications.MobileNetV2(input_shape=IMG_SHAPE, include_top=False, weights='imagenet')

   model = tf.keras.Sequential([
       base_model,
       tf.keras.layers.GlobalAveragePooling2D(),
       tf.keras.layers.Dense(2, activation='sigmoid'),
   ])

   model.compile(optimizer=tf.keras.optimizers.Adam(),
                 loss='binary_crossentropy',
                 metrics=['accuracy'])

   save_cb = tf.keras.callbacks.ModelCheckpoint(OUTPUT_MODEL_FOLDER,
                                                monitor='val_loss',
                                                save_weights_only=False,
                                                save_best_only=True,
                                                mode='auto',
                                                verbose=1)
   model.fit(train_data_set,
             epochs=EPOCHS,
             steps_per_epoch=train_image_count // BATCH_SIZE,
             validation_data=test_data_set,
             callbacks=[save_cb])


if __name__ == '__main__':
   main()

今回はプログラムの実行に必要な最低限の説明に留めます。上部のライブラリが記述された箇所を見てください。

import pathlib

import numpy as np
import tensorflow as tf

特にnumpyは数学的な処理をするライブラリで、tensorflowは機械学習の処理をするライブラリです。この2つは機械学習では頻出するので覚えておきましょう。

この内numpyとtensorflowは前もってインストールしておく必要があります。

ターミナルからpipコマンドでそれぞれインストールしましょう。

pipのインストールはこちら↓

インストールしたら下記のコマンドでライブラリをインストールできます。

pip3 install numpy
pip3 install tensorflow

同様にwebcam_demo.pyについても必要なライブラリをインストールします。

import cv2
import numpy as np
import tensorflow as tf
from mtcnn import MTCNN

先ほどと被っているものもあるので、次の2つをインストールすればOKです。mtcnnは人の顔を認識する機能を含むライブラリです。

pip3 install cv2
pip3 install mtcnn

その後以下の順番で2つのPythonファイルを実行していきます。

python3 train.py
python3 webcam_demo.py

うまく行けば上記のツイートの動画のように、PCカメラが起動して自分の顔が赤枠で認識されるはずです。またお手元のマスクをつけてみてください。画像認識がうまく働けば、赤枠が緑に変わります。

成功した方はおめでとう!!

ちなみにカメラはqキーで終了します。

期待通りの結果が得られない場合は、エラーコードをコピペして検索するなどした上で、どうしてもわからない場合はTwitterからDMください。

少しでも参考になったという方はTwitterでシェアお願いします!

まとめ

いかがだったでしょうか?

今回機械学習についての実践寄りのnoteを初めて書くことに挑戦しました。きっかけとしてはやはり、新型コロナウイルスのパンデミックがありますね。

以前から中国でのAI技術の進歩は目を見張るものがありましたが、今回の件でその底力を肌で感じました。皆さんにもそれが少しでも伝わっていれば幸いです。

今後もPython記事に力をいれて行こうと思っています。

それでは!


サポートは料理好きなのでの食材費にさせていただきます。