学習済みモデルありでTensorFlowの画像認識やってみた
もくじ
はじめに
こんにちは、クラウドソリューショングループ所属の、takagirです。
今回はCloud AutoMLで作成した学習済みモデルを用いたTensorFlowの画像認識の簡単な使い方について、お話していこうと思います。
この記事をきっかけに、モデルを利用したTensorFlowの画像認識について少しでも理解の手助けになればと思います。
使用言語
使用する言語は以下のものです。
・python 3.9.6
使用するライブラリはcv2とTensorFlow、numpyになります。インストールはpipを用います。以下コマンドを実行してください
pip install opencv-python pip install --upgrade tensorflow pip install numpy
TensorFlowはpythonのバージョンによって利用可能なバージョンが異なります。
詳しくは公式のサイトのシステム要件から確認してください。
cv2は画像の読み込みやエンコード、デコードなど、画像ファイルの操作のために使用します。
また今回行う画像推論の結果はnumpy配列で返ってくるため、そのデータを扱うのにnumpyが必要になります。加えて日本語パスの画像ファイルを使う場合に、画像ファイル読み込みのためにもnumpyを使用します。
コード説明
コード自体の説明に入る前に、まずは今回行う画像認識の流れについて、説明を行います。今回の流れは、
- 必要なモジュールのインポート
- 用意した学習済みのモデルを読み込む
- 画像データをバイト列に変換
- 推論を実施する
- 結果を取り出す
になります。1,3はTensorFlow、2.のバイト列への変換はcv2(日本語パスの場合はnumpyも利用)、4.の結果の取得の際にはnumpyを利用します。では、次にコードを見ていきましょう。
1.必要なモジュールのインポート
最初に必要なモジュールをインポートします。今回は以下の三つです。
import cv2 import tensorflow as tf import numpy as np
TensorFlowとnumpyについては、少々名称が長いので、asを使ってそれぞれtf、npと省略して宣言してしまいましょう。
2.用意した学習済みのモデルを読み込む
# 学習したモデル読み込み loaded = tf.saved_model.load(export_dir='') # modelを配置しているディレクトリを指定 infer = loaded.signatures["serving_default"]
tf.saved_model.load(export_dir=”)で指定したディレクトリからモデルをロードします。
その後、serving_defaultという今回使用するモデルのシグネチャキーを用いて、inferにloaded.signatures[“serving_default”]で情報を取得します。
3.画像データをバイト列に変換
#画像読み込み(imread()) img_array = np.fromfile(img_path, dtype=np.uint8) img = cv2.imdecode(img_array, cv2.IMREAD_COLOR) #拡張子ごとにメモリバッファに書き込む flag, bts = cv2.imencode("", img)//拡張子を指定 inp = [bts[:,0].tobytes()]
まず最初に画像読み込みについて。本来であればimread()で読み込みが完了します。しかし、imreadは日本語パスの画像ファイルを読み込むことができません。ですので、わざと一度numpy.fromfileを使用してファイルデータを取得し、それをデコードすることで読み込ませています。
画像ファイルを読み込んだらエンコードをしてバイト列に直します。cv2.imencode(“”, img)は返り値として、[成功したか、バイト列]を返します。なので、受け取る変数も二つ用意します。このうち今回使うのはバイト列(bts)のほうだけです。
さらにbufの中でも0列目だけを使用したいので[:,0]でスライスして取得したものをinpに格納します。
4.推論を実施する
out = infer(key=tf.constant('something_unique'), image_bytes=tf.constant(inp))
これが推論を行い、そしてその結果をoutに格納している部分です。
5.結果を取り出す
outの中身はやや複雑ですが、必要な情報はnumpy=arrayの形で格納されています。outの中身の例は以下のようになります。(見やすいように改行しています)
{ 'labels': <tf.Tensor: shape=(1, 4), dtype=string, numpy=array([[b'人', b'犬', b'猿', b'雉']], dtype=object)>, 'key': <tf.Tensor: shape=(), dtype=string, numpy=b'something_unique'>, 'scores': <tf.Tensor: shape=(1, 4), dtype=float32, numpy=array([[0.0267027 , 0.04035938, 0.9028903 , 0.03004756]], dtype=float32)> }
labelとscoreの順番は対応しているので、これは順に「人の可能性2.6%」「犬の可能性4.0%」「猿の可能性90.2%」「雉の可能性3.0%」と推論されたということになります。
この中からscoresとlabelsについて以下のようにそれぞれ取得してしまいましょう。
scores = out["scores"] labels = out["labels"]
これでoutの中から確信度に関する部分(scores)とラベルに関する部分(labels)を全部取得します。この中で、結果としてほしいデータはすべてnumpy=arrayの中にあります。
ですので、上述のoutの例でいうなら、
text_byte = labels.numpy()[0][0] label = text_byte.decode('utf-8')
これでlabelには、文字列の形で「人」が格納されています。あとはよく使い慣れたStringとして扱えばOKです。
import cv2 import tensorflow as tf import numpy as np # 学習したモデル読み込み loaded = tf.saved_model.load(export_dir='') # modelを配置しているディレクトリを指定 infer = loaded.signatures["serving_default"] #画像読み込み(imread()) img_array = np.fromfile(img_path, dtype=np.uint8) img = cv2.imdecode(img_array, cv2.IMREAD_COLOR) #拡張子ごとにメモリバッファに書き込む flag, bts = cv2.imencode("", img)//拡張子を指定 inp = [bts[:,0].tobytes()] #推論結果取得 out = infer(key=tf.constant('something_unique'), image_bytes=tf.constant(inp)) scores = out["scores"] labels = out["labels"]
最後に
読んでくださりありがとうございました。
画像認識の肝となるTensorFlowの使い方について理解のお手伝いになれば幸いです。
以上で本記事を終わります。
改めて読んでいただいてありがとうございました。