手を検出してみました
1 はじめに
手を検出してみました。
使用させて頂いたのは、下記です。
Real-time Hand-Detection using Neural Networks (SSD) on Tensorflow.
こちらで公開されているモデルは、SSDによる物体検出モデルで、Tensorflowで作成されています。 今回は、こちらをOpenVINOで利用可能な形式に変換して利用してみました。
最初に動作している様子です。
2 detect_single_threaded.py
githubのリポジトリをcloneして、detect_single_threaded.pyを実行する事で、直ちに動作を確認することができます。
- git clone
% git clone https://github.com/victordibia/handtracking.git % cd handtracking % python3 ./detect_single_threaded.py
なお、Tensorflowのバージョンは、1.4.0-rc0用となっています。
Tensorflow 2.3.2では、いくつかのオブジェクトが見つからないというエラーとなってしまったので、変更して動作を確認しました。
- Version
% python3 >>> import tensorflow >>> tensorflow.__version__ '2.3.2'
- error
AttributeError: module 'tensorflow' has no attribute 'gfile'
tf.gfile.GFile -> tf.io.gfile.GFile
AttributeError: module 'tensorflow' has no attribute 'GraphDef'
tf.GraphDef() -> tf.compat.v1.GraphDef()
AttributeError: module 'tensorflow' has no attribute 'Session'
tf.Session() -> tf.compat.v1.Session()
動作を確認している様子です。
3 モデル変換
OpenVINOルーツキットを使用して、IR 形式へ変換する手順は、以下の通りです。
(1) ツールキットへのパス
OpenVINOツールキットへのパスを環境変数INTEL_OPENVINO_DIRにセットします。
ツールキットのバージョンによって、パスが変わりますので、ご注意ください。
% export INTEL_OPENVINO_DIR=/opt/intel/openvino_2021 % echo $INTEL_OPENVINO_DIR /opt/intel/openvino_2021
(2) Tensorflowのモデル配置場所
モデルは、hand_inference_graphの中にあります。
% ls -la hand_inference_graph total 76392 drwxr-xr-x 10 sin staff 320 5 29 10:26 . drwxr-xr-x 18 sin staff 576 5 29 10:37 .. -rw-r--r-- 1 sin staff 77 5 29 10:26 checkpoint -rw-r--r-- 1 sin staff 19135409 5 29 10:26 frozen_inference_graph.pb -rw-r--r-- 1 sin staff 32 5 29 10:26 hand_label_map.pbtxt -rw-r--r-- 1 sin staff 18594336 5 29 10:26 model.ckpt.data-00000-of-00001 -rw-r--r-- 1 sin staff 14088 5 29 10:26 model.ckpt.index -rw-r--r-- 1 sin staff 1345055 5 29 10:26 model.ckpt.meta -rw-r--r-- 1 sin staff 4276 5 29 10:26 pipeline.config drwxr-xr-x 3 sin staff 96 5 29 10:26 saved_model
こちらへのパスを環境変数MODEL_DIRにセットしています。
% export MODEL_DIR=hand_inference_graph % echo $MODEL_DIR hand_inference_graph
(3) 変換
ツールキットによるTensorflowモデルの変換は以下のとおりです。
% python $INTEL_OPENVINO_DIR/deployment_tools/model_optimizer/mo.py \ --input_model $MODEL_DIR/frozen_inference_graph.pb \ --tensorflow_object_detection_api_pipeline_config $MODEL_DIR/pipeline.config \ --reverse_input_channels \ --transformations_config $INTEL_OPENVINO_DIR/deployment_tools/model_optimizer/extensions/front/tf/ssd_support_api_v1.15.json \ --data_type FP32 --output_dir FP32
.bin, .xmlが出力されていれば成功です。
% ls -la FP32 -rw-r--r-- 1 sin staff 18369096 5 29 13:12 frozen_inference_graph.bin -rw-r--r-- 1 sin staff 69537 5 29 13:12 frozen_inference_graph.mapping -rw-r--r-- 1 sin staff 270972 5 29 13:12 frozen_inference_graph.xml
4 推論
OpenVINOで推論しているコードです。
import numpy as np import cv2 import time from openvino.inference_engine import IECore class Model: def __init__(self, ie, device, model): net = ie.read_network(model=model+'.xml', weights=model+'.bin') self.__input_blob_name = list(net.inputs.keys())[0] self.__output_blob_name = list(net.outputs.keys())[0] self.__exec_net = ie.load_network(network=net, device_name=device, num_requests=1) self.__input_size = net.inputs[self.__input_blob_name].shape def infer(self, data): prob = self.__exec_net.infer(inputs={self.__input_blob_name: data}) return prob[self.__output_blob_name] @property def input_size(self): return self.__input_size class HandDetector(Model): def __init__(self, ie, device, model_path): super().__init__(ie, device, model_path) [_b, _c, h, w] = super().input_size self.__height = h self.__width = w # 入力インターフェースへの画像変換 def __prepare_frame(self, frame): img = cv2.resize(frame, (self.__width, self.__height)) # 800*600 -> 300*300 img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # BGR -> RGB img = img.transpose((2, 0, 1)) # 300,300,3 -> 3,300,300 return img[np.newaxis, :] # 3,300,300 -> 1,3,300,300 def infer(self, frame): height, width = frame.shape[:2] frame = self.__prepare_frame(frame) detections = [] result = super().infer(frame) for obj in result[0][0]: _, clsid, conf, x1, y1, x2, y2 = obj x1 = int(x1 * width/self.__width * self.__width) y1 = int(y1 * height/self.__height * self.__height) x2 = int(x2 * width/self.__width * self.__width) y2 = int(y2 * height/self.__height * self.__height) detections.append([int(clsid), conf, x1, y1, x2, y2]) return detections def main(): # OpenVINO DEVICE = "CPU" MODEL = "./model/FP32/frozen_inference_graph" ie = IECore() hand_detector = HandDetector(ie, DEVICE, MODEL) # OpenCV WIDTH = 640 HEIGHT = 480 DEVICE_ID = 1 FPS = 24 cap = cv2.VideoCapture(DEVICE_ID) cap.set(cv2.CAP_PROP_FRAME_WIDTH, WIDTH) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, HEIGHT) cap.set(cv2.CAP_PROP_FPS, FPS) # フォーマット・解像度・FPSの取得 width = cap.get(cv2.CAP_PROP_FRAME_WIDTH) height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT) fps = cap.get(cv2.CAP_PROP_FPS) print("fps:{} width:{} height:{}".format(fps, width, height)) while(True): _, frame = cap.read() if(frame is None): continue start = time.time() # 時間計測 detections = hand_detector.infer(frame) processing_time = time.time() - start print("processing_time {:.2f}sec".format(processing_time)) for detection in detections: _clsid, conf, x1, y1, x2, y2 = detection if(conf < 0.8): continue color = (0, 255, 255) cls_name = "hand" print("{} {:.1f} ({},{})-({},{})".format(cls_name, conf, x1, y1, x2, y2)) cv2.rectangle(frame, (x1, y1), (x2, y2), color, 3) text = "{} {:.2f}".format(cls_name, conf) cv2.putText(frame, text, (x1, y1), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,255), 1, cv2.LINE_AA) cv2.imshow('frame', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() main()
MacBook Pro 2.3GHz Core i7での推論は、0.01secと高速です。
processing_time 0.01sec processing_time 0.01sec processing_time 0.01sec processing_time 0.01sec processing_time 0.01sec processing_time 0.01sec
5 最後に
今回は、Real-time Hand-Detection using Neural Networks (SSD) on Tensorflow.をOpenVINOで試してみました。
現在、手の検出を起点に、手に取った商品の特定ができないかと模索中です。