スポンサーリンク

【TensorFlow】自作物体検出モデル読み込みと領域検出・切り取りのご紹介。

TensorFlow
スポンサーリンク

今回の記事はTensorFlow形式の(今回でいうと「Object Detection API」で転移学習させたモデル)自作物体検出モデルの読み込みと領域検出・領域の切り取りを行うPythonコードのご紹介記事です。初心者にも分かりやすいように分かりやすく解説していきますので是非参考にして見て下さい。

TFRecord形式のデータを使って既存学習モデルに転移学習を行う方法に関しての記事は下記で記載しているので下記記事を参考にして下さい。

TFRecord形式のデータを既存学習モデルに転移学習させる手順ご紹介。

スポンサーリンク

TensorFlowで自作物体検出モデル読み込みに必要なライブラリ

import numpy as np
import os, sys
import six.moves.urllib as urllib
import tensorflow as tf
from collections import defaultdict
from io import StringIO
from PIL import Image
sys.path.append("..")
from research.object_detection.utils import label_map_util
from research.object_detection.utils import visualization_utils as vis_util
import cv2

TensorFlowによる学習済みモデルの読み込み

#pbグラフの読み込みパス
MODEL_NAME = '/models/research/exported_graphs'
PATH_TO_CKPT = os.path.join(MODEL_NAME, 'frozen_inference_graph.pb')
#モデルマップのパス
TFRec_Dir = '/models/research/object_detection_tools/data'
PATH_TO_LABELS = os.path.join(TFRec_Dir, 'tf_label_map.pbtxt')
#NUM_CLASSESは分類するモデルマップの数、今回は「非常口」の表示かどうかを認識させるので1、仮に犬とねこを認識させるのなら2になります。
NUM_CLASSES = 1

#今回の読み込み対象の画像のデイレクトリの指定
imgPath = '/test_image/'
imgLst = os.listdir(imgPath)
#画像の最終的な大きさ指定
height = 840
width  = 1240
#detection_graphをtfのデフォルトグラフに設定
detection_graph = tf.Graph() 

#そのグラフで下記を行なっていきます。
with detection_graph.as_default(): 

#od_graph_defをプロトコルバッファに
od_graph_def = tf.GraphDef() 

with tf.gfile.GFile(PATH_TO_CKPT, 'rb') as fid:
    #その上で今回の自己学習モデルをfidという名前で読み込んでいく
    serialized_graph = fid.read()#serialized_graphを読み込んだfidグラフ
    od_graph_def.ParseFromString(serialized_graph)
    #プロトコルバッファに変換?
    tf.import_graph_def(od_graph_def, name='')

#プロトコルバッファに変換したod_graph_defの読み込み(import)

#ラベルマップの読み込み
label_map = label_map_util.load_labelmap(PATH_TO_LABELS)
categories = label_map_util.convert_label_map_to_categories(label_map, max_num_classes=NUM_CLASSES, use_display_name=True)
category_index = label_map_util.create_category_index(categories)

こちら丸写しで使用できます。

TensorFlowによる物体検知

image_num = 0 #最後に画像に名前をつける際の変数
for imgName in imgLst:
    base, ext = os.path.splitext(imgName)
    if ext != '.jpg':
        continue
  #上記でjpg画像以外を弾く
   #下記でopencvによる画像の読みこみとリサイズ等の処理
    image_np = cv2.imread(os.path.join(imgPath, imgName))
    image_np = cv2.resize(image_np, (300,300))
    showimg = cv2.resize(image_np, (300,300))
    original_image = showimg.copy()
    image_width, image_height = original_image.shape[1] , original_image.shape[0]
       
    with detection_graph.as_default():
    #下記で学習モデルを動かすtensorflowのお決まりの記述
        with tf.Session(graph=detection_graph) as sess:
            #下記で次元を合わせた
       image_np_expanded = np.expand_dims(image_np, axis=0)
            #下記で今回の枠取りの際に使用する変数を定義
            image_tensor = detection_graph.get_tensor_by_name('image_tensor:0')
            boxes = detection_graph.get_tensor_by_name('detection_boxes:0')
            scores = detection_graph.get_tensor_by_name('detection_scores:0')
            classes = detection_graph.get_tensor_by_name('detection_classes:0')
            num_detections = detection_graph.get_tensor_by_name('num_detections:0')

            #学習モデルがsess.runにて起動
            (boxes, scores, classes, num_detections) = sess.run(
               [boxes, scores, classes, num_detections],
               feed_dict={image_tensor: image_np_expanded})

            #下記が検出した領域の情報を記載してくれる関数
            vis_util.visualize_boxes_and_labels_on_image_array(
                image_np,
                np.squeeze(boxes),
                np.squeeze(classes).astype(np.int32),
                np.squeeze(scores),
                category_index,
                use_normalized_coordinates=True,
                line_thickness=8)
    #今回の操作にて検出した領域の上から座標、モデルマップのクラス、そのクラスに属する確率
    real_boxes = np.squeeze(boxes)
    real_classes = np.squeeze(classes).astype(np.int32)
    real_scores = np.squeeze(scores)

最終的に取り出せる情報は最後の三つですがそれぞれが配列になっているので最も確率の高いところを取り出すや、〜以上の確率を出力している座標を全て取得など活用方法は色々です。今回は画像を切り取りますので最も確率の高い座標を取り出し、その座標を活用していきます。

TensorFlowとOpenCVによる物体検知画像の枠取り

    z = real_boxes[0] #確率の最も高いものが[0]のものなのでそれを取得
    ymin, xmin, ymax, xmax = z[0],z[1],z[2],z[3]
  #上記のものをそれぞれxy座標の最大最小値を取得しております。
  #また下記で最終的に元の画像の大サイズとして指定したheight等をかけ大きさを戻す。
    (left, right, top, bottom) = (xmin * image_width, xmax * image_width, ymin * image_height, ymax * image_height)
    cut_image = original_image[int(top) : int(bottom), int(left): int(right), :]          
    #画像の保存
    cv2.imwrite("/models/result/test" + str(image_num) + ".jpg", cut_image)
    image_num += 1

これでresultに画像が保存されています。今回の私のモデルでは新しいモデルでも比較的うまく切り取れていました。元画像と切り取ったもの確率2番目に高いものをあげておきます。

左が確率高いもので右が2番目です。反転したものでもうまく撮れることがわかりました。
また非常口のみを検出をできていない点からもう少し学習が必要ということもわかりましたがまあ今回はこんなもんです。

では今回の記事は以上です。他にも多数の機械学習関連の記事を記載しているので是非そちらも参考にして見てください。

おすすめ情報ご紹介。

下記リンクよりU-NEXTの契約をすると31日間無料でU-NEXTの全動画約21万作品を見放題です。31日期間に解約すれば0円です。今だけのおすすめ情報なのでまだ登録していない人は是非!

スポンサーリンク
TensorFlow
スポンサーリンク
シェアする
スポンサーリンク
SunnyDayTravel-Blog

コメント

  1. […] 【Python】TensorFlowで自作学習モデルを用いて任意画像の物体検知を行う方法… […]

  2. […] 【Python】TensorFlowで自作学習モデルを用いて任意画像の物体検知を行う方法… […]

  3. […] 【Python】TensorFlowで自作学習モデルを用いて任意画像の物体検知を行う方法… […]

  4. […] 【Python】TensorFlowで自作学習モデルを用いて任意画像の物体検知を行う方法… […]

タイトルとURLをコピーしました