以前から開発を進めているピープルカウンタ[1]で, 人物の検出にYOLOv3[2]を試してみたいと思い, Jetson Nanoを購入した.
前回は, Jetson NanoでYOLOv3のセットアップについて紹したが, 今回はD415の出力をYOLOv3の入力として物体検知を動かすところを紹介する.
関連記事:
・Jetson NanoでIntel RealSenseを試してみる(1)
・Jetson NanoでIntel RealSenseを試してみる(2)
・Jetson NanoでIntel RealSenseを試してみる(3)
・Jetson NanoでIntel RealSenseを試してみる(4)
1. ctypes利用
PythonからYOLOv3を利用する方法については, 「YOLOv3を試してみる(3) 」[3]に記載したように, いくつか方法がある.
今回は, ctypes(pythonでC言語のライブラリを操作するためのライブラリ)を利用する方法を用いた.
1.1 PythonからYOLOv3呼び出し
オリジナルのリポジトリ[4]をクローンし, "darknet"のディレクトリ下のpython/darknet.pyなるサンプルコードがあるので, これをベースに, OpenCVの画像データを渡してYOLOv3で物体検出を行い, 検出結果を返すように, 以下のような処理を追加した.
# OpenCVの画像データをYOLOv3の画像データに変換 def cvimage_to_image(img): img = img.transpose(2, 0, 1) c, y, x = img.shape img = (img / 255.).flatten() data = c_array(c_float, img) image = IMAGE(x, y, c, data) return image # YOLOv3を呼び出して, 物体検出を実行 # (detect関数を参照のこと) def detect_cvimage(net, meta, image, thresh=.5, hier_thresh=.5, nms=.45): im = cvimage_to_image(image) num = c_int(0) pnum = pointer(num) predict_image(net, im) dets = get_network_boxes(net, im.w, im.h, thresh, hier_thresh, None, 0, pnum) num = pnum[0] if (nms): do_nms_obj(dets, num, meta.classes, nms); res = [] for j in range(num): for i in range(meta.classes): if dets[j].prob[i] > 0: b = dets[j].bbox res.append((meta.names[i], dets[j].prob[i], (b.x, b.y, b.w, b.h))) res = sorted(res, key=lambda x: -x[1]) free_detections(dets, num) return res
1.2 D415処理ルーチン
D415の入力処理のメインループから, 先のdetect_cvimage関数を呼び出すことで, 物体検出を行う.
############################################# ## D415 + YOLOv3 ############################################# import pyrealsense2 as rs import numpy as np import cv2 import time import darknet WIDTH = 640 HEIGHT = 480 FPS = 15 OUTPUT_VIDEO_FILE = 'output.avi' # Configure depth and color streams pipeline = rs.pipeline() config = rs.config() config.enable_stream(rs.stream.color, WIDTH, HEIGHT, rs.format.bgr8, FPS) # YOLOv3設定 net = darknet.load_net(b'./cfg/yolov3-tiny.cfg', b'./weights/yolov3-tiny.weights', 0) meta = darknet.load_meta(b'./cfg/yolov3-tiny.data') # 結果出力ファイル準備 fourcc = cv2.VideoWriter_fourcc(*'DIVX') output_movie = cv2.VideoWriter(OUTPUT_VIDEO_FILE, fourcc, 15, (WIDTH, HEIGHT)) # ストリーミング開始 profile = pipeline.start(config) try: while True: # フレーム待ち(Color) frames = pipeline.wait_for_frames() color_frame = frames.get_color_frame() if not color_frame: continue # フレーム画像取得 image = np.asanyarray(color_frame.get_data()) rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # YOLOv3物体検出 objs = darknet.detect_cvimage(net, meta, rgb) # 検出結果表示 for obj in objs: x, y, w, h = obj[2] x, y, hw, hh = int(x), int(y), int(w/2), int(h/2) print('{} : {}, {}, {}, {}'.format(obj[0], x, y, hw*2, hh*2)) image = cv2.rectangle(image, (x-hw, y-hh), (x+hw, y+hh), (0, 0, 255), 2) # ファイル出力 output_movie.write(image) # 入力&検出結果表示 cv2.namedWindow('RealSense', cv2.WINDOW_AUTOSIZE) cv2.imshow('RealSense', image) if cv2.waitKey(1) & 0xff == 27: break finally: # ストリーミング停止 pipeline.stop() output_movie.release() cv2.destroyAllWindows()
1.3 動作確認
D415を使って動作検証を行ったところ, 一応物体検出できているようだが, フレーム毎の処理が完全に間に合っていない.
どこの処理で時間がかかっているか, 調べてみた.
(省略) [yolo] params: iou loss: mse, iou_norm: 0.75, cls_norm: 1.00, scale_x_y: 1.00 Total BFLOPS 5.571 Allocate additional workspace_size = 52.43 MB Loading weights from ./weights/yolov3-tiny.weights... seen 64 Done! Loaded - names_list: data/coco.names, classes = 80 c_array 0.4820216559992332 predict_image 0.24248922199967637 detect_cvimage 0.790845716000149 Gtk-Message: 23:04:53.687: Failed to load module "canberra-gtk-module" c_array 0.4701981270000033 predict_image 0.10289384199950291 detect_cvimage 0.6075017419998403 c_array 0.4704276900001787 predict_image 0.0853231870005402 detect_cvimage 0.5848415290001867 c_array 0.47496766799940815 predict_image 0.09125199099980819 detect_cvimage 0.5956493580006281 c_array 0.44825363700056187
その結果, 約0.6s/frameかかっており, OpenCVの画像データからYOLOv3に渡す画像データに変換する処理(c_array in darknet.py)で時間がかかていることが判明.
def c_array(ctype, values): arr = (ctype*len(values))() arr[:] = values return arr
コードがシンプルなだけに, これは簡単には高速できそうにないので, ctypesを使用する方法はいったん中断.
(どなたか, ここ高速化した人があれば教えてくださ~い.)
次回はもう一つのkeras-yolo3を試してみようと思う.
----
参照URL:
[1] ピープルカウンタを考えてみる(1) ~ (5)
[2] YOLO: Real-Time Object Detection
[3] YOLOv3を試してみる(3)
[4] GitHub - pjreddie/darknet: Convolutional Neural Networks
|
|
|