Loading
BLOG 開発者ブログ

2021年9月30日

学習済みモデルありで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. 必要なモジュールのインポート
  2. 用意した学習済みのモデルを読み込む
  3. 画像データをバイト列に変換
  4. 推論を実施する
  5. 結果を取り出す

になります。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の例でいうなら、

scores.numpy()[0][0] = 0.0267027 , scores.numpy()[0][1] =  0.04035938ということになります。
ただしlabelsの取得には注意が必要です。labels.numpy()[0][0]の中身は「b’人’」となりますが、これはpythonではバイト列の状態であることを表します。つまりこれは、デコードすれば「人」になるバイト列、ということになります。このままでは扱いづらいのであれば、次のようにデコードして文字列に戻してしまいましょう。
text_byte = labels.numpy()[0][0] 
label = text_byte.decode('utf-8')

これでlabelには、文字列の形で「人」が格納されています。あとはよく使い慣れたStringとして扱えばOKです。

これでTensorFlowに関するコードは以上となります。取得できたscoresやlabelsはcsvに書き出すなどして、使ってみてください。
最後に今回使用したコードの全体を載せます。参考にしてください。
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の使い方について理解のお手伝いになれば幸いです。

以上で本記事を終わります。

改めて読んでいただいてありがとうございました。

 

watanabe.tのブログ

クラウドソリューショングループ所属

昔はモバイルアプリ開発を、今はGCP, AWS, Firebaseなどのクラウド周りの提案/開発を行っているエンジニアです。

AWS認定ソリューションアーキテクト取得しました!