Pythonサンプルコード:ソケット通信サーバー/クライアントでNWを介してAIに画像認識させる【socket,Keras,ラズパイ,ディープラーニング】

Raspberry Pi(ラズパイ)をAIサーバー化し、画像認識させたいファイルをネットワークを介してAIに認識させるシステムを作ってみました。

今回は画像認識AIに加えて、ソケット通信が登場します。簡単のため、ラズパイ内でサーバー、クライアントを作成し、ソケット通信を介した画像認識をやってみました。

開発環境


■ハードウェア

・Raspberry Pi 3 Model B



■OS

・Raspbian GNU/Linux 9.11 (stretch)


■プログラミング言語、主なライブラリとバージョン

・Python 2.7.13
・socket
・Keras 2.1.5
・numpy 1.12.1
・theano 1.0.1
・matplotlib 2.0.0


※ラズパイのAI環境開発は以下の本が参考になります。


プログラム


GitHubにサンプルプログラムを公開します。

https://github.com/kotetsu99/cnn_socket


■各プログラム等の概要

(1)01-cnn_train.py: 画像学習プログラム
・画像をAIに学習させ、画像認識AIモデルを生成。
・AIモデルは、CIFAR-10 画像データセット向けのAIモデル(9層畳み込みネットワーク)

(2)02-cnn_server.py: 画像認識AIソケットサーバー
・ソケット通信サーバー。(3)のクライアントから画像ファイルを受信し保存。
・受信した画像ファイルに対し、(1)で作ったAIで画像認識させ、結果をクライアントに返す。

(3)03-socket_client.py: 画像送信ソケットクライアント
・ソケット通信クライアント。画像ファイルを(2)のサーバーにバイナリデータで送信。
・サーバーの画像認識結果を受信して、コンソール画面に表示。

(4)dataset: 画像データセット保存ディレクトリ
・train:
 -学習用の画像ファイルを保存。
 -サブディレクトリが存在し、配下に画像データセットを保存しておく。

・validation:
 -検証用の画像ファイルを保存。
 -サブディレクトリが存在し、配下に画像データセットを保存しておく。

・sc:
 -(2)が受信した画像ファイルの保存先ディレクトリ。


(5)model: 画像認識AIモデル保存ディレクトリ


プログラム使用方法


例として、

・スマホブラウザのスクリーンショット画像をサーバーにソケット通信
・サーバー側で画像認識、認識結果をクライアントに返す。
・クライアント側で、認識結果をコンソール画面に表示。

という流れで実行していきます。
# スマホ画面の認識を取り上げてるのは、↓の記事で記したモバイルテスト自動化の件とつながってます。
https://nine-num-98.blogspot.com/2020/03/katalon-studio-ai-01.html


(1)データセットの準備

スクリーンショット画像ファイルを、dataset/trainおよびvalidationの各サブディレクトリ配下に保存します。

・dataset/train:
 -apple
 -google
 -rakuten
 -yahoo

・dataset/validation:
 ※以下のディレクトリ構成は、trainと同じ

ディレクトリ名を見れば何となく分かると思いますが、各サイト名をサブディレクトリ名としています。yahooディレクトリであれば、以下のような画像ファイルを複数枚保存しておきます。



サブディレクトリ名は画像認識で分類するクラス名に一致します。
[apple, google, rakuten, yahoo]
認識する画像が↑の4クラスのいずれかに分類されるわけです。


(2)画像学習プログラムの実行

以下のコマンドを実行します。

$ nohup python 01-cnn_train.py model/cnn_model.h5 &

バックグランドで画像学習処理が進みます。進捗状況は、nohup.outファイルに出力されるので、以下のコマンドで確認できます。

$ tail -f nohup.out

以下のようなログが確認できます。

Using Theano backend.
クラス名リスト =  ['google', 'apple', 'rakuten', 'yahoo']
モデル新規作成
Found 33 images belonging to 4 classes.
Found 4 images belonging to 4 classes.
('trgen_len(train_steps)=', 5)
('vagen_len(val_steps)=', 1)
Epoch 1/200

1/5 [=====>........................] - ETA: 2:44 - loss: 1.4584 - acc: 0.3750
2/5 [===========>..................] - ETA: 2:03 - loss: 3.2370 - acc: 0.3125
3/5 [=================>............] - ETA: 58s - loss: 2.2783 - acc: 0.5417
4/5 [=======================>......] - ETA: 32s - loss: 1.7240 - acc: 0.6562
5/5 [==============================] - 179s 36s/step - loss: 2.3537 - acc: 0.5600 - val_loss: 1.6856 - val_acc: 0.2500


・・・(中略)・・・


Epoch 31/200

1/5 [=====>........................] - ETA: 2:42 - loss: 0.0607 - acc: 1.0000
2/5 [===========>..................] - ETA: 2:02 - loss: 0.0446 - acc: 1.0000
3/5 [=================>............] - ETA: 1:21 - loss: 0.0551 - acc: 1.0000
4/5 [=======================>......] - ETA: 37s - loss: 0.0441 - acc: 1.0000
5/5 [==============================] - 202s 40s/step - loss: 0.0522 - acc: 1.0000 - val_loss: 0.0194 - val_acc: 1.0000
Epoch 00031: early stopping
('process_time = ', 105.34722700119019, '[min]')


最後の学習に要した所要時間結果

('process_time = ……)

が確認されたらプログラム終了です。



(3)画像認識AIサーバープログラムを実行

以下のコマンドを実行します。

$ python 02-cnn_server.py model/cnn_model.h5

ソケットサーバーが準備できたら、以下のような画面出力になります。

Using Theano backend.
クラス名リスト =  ['google', 'apple', 'rakuten', 'yahoo']
クライアントからの接続待ち...



(4)画像送信ソケットクライアントプログラムを実行

画像認識させたい画像ファイル「file.png」を準備して、実行プログラム「03-socket_client.py」と同一ディレクトリに置きます。



さっきのyahooのページ画像を送ってみます。
以下のコマンドを実行します。

$ python 03-socket_client.py file.png

以下の結果が表示されます。

file.pngをサーバーに送信
認識結果: yahoo


認識結果がサーバーから返ってきましたね。送った画像ファイルを見事、正解通り画像認識して、「これはyahooのページです。」と応えてくれました。

一方のサーバー側では以下のように結果が出ています。

$ python 02-cnn_server.py model/cnn_model.h5
Using Theano backend.
クラス名リスト =  ['google', 'apple', 'rakuten', 'yahoo']
クライアントからの接続待ち...
受信ファイル認識結果:
[('yahoo', 0.9910015), ('apple', 0.008614799), ('google', 0.00036144815), ('rakuten', 2.2250342e-05)]
=======================================

4つのクラスが、可能性の高い順にが表示されています。一番可能性(確率)の高いクラス名(サイト名)が「yahoo」です。この結果をクライアント側にソケット通信で返してくれています。

ラズパイとは別のPCでこのソケットクライアントを使う場合は、

# サーバーIPアドレス定義
host = "0.0.0.0"

の箇所のhostのIPアドレスを、ラズパイのものに変更すればOKです。


プログラムの使用方法については以上です。

画像データセットを、目的に合わせて変更したり、サーバー-クライアントをラズパイの中だけで完結させずに、別々のPCで動かしたりと、色々使い道はあるのかなと思います。

各プログラムの解説は以下の記事にアップしました。

画像学習プログラム解説:
https://nine-num-98.blogspot.com/2020/03/ai-socket-02.html

ソケット通信プログラム解説:
https://nine-num-98.blogspot.com/2020/03/ai-socket-03.html

スポンサーリンク