Python OpenCV カメラ画像からオプティカルフローを取得して遊んでみました
Python + Opencv3.1 で カメラ画像からオプティカルフロー(移動ベクトル)を取得し、これをパラメータとして利用してちょっと遊んでみました。
移動ベクトルを取得してもじゃもじゃするコードは、OpenCV 3.1 のサンプルコード opt_flow.py を参考にして書いてみました。
■ オプティカルフローを利用して描画する。
def draw_flow(img, gray, flow, step=16): h, w = img.shape[:2] y, x = np.mgrid[step/2:h:step, step/2:w:step].reshape(2,-1).astype(int) fx, fy = flow[y,x].T lines = np.vstack([x, y, x+fx, y+fy]).T.reshape(-1, 2, 2) lines = np.int32(lines) # vis = np.zeros((img.shape[0], img.shape[1], 3), np.uint8) vis = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR) # グレー画像を背景に使用 vis = 255 - vis # ネガ反転 rad = int(step/2) i = 0 # ループカウンタ for (x1, y1), (x2, y2) in lines: pv = img[y1, x1] col = (int(pv[0]), int(pv[1]), int(pv[2])) r = rad - int(rad * abs(fx[i]) *.05) # ドットの半径を移動ベクトルの量に応じて小さくする cv2.circle(vis, (x1, y1), abs(r), col, -1) i+=1 cv2.polylines(vis, lines, False, (255, 255, 0)) return vis
■ カメラのフレームからオプティカルフローを取得して描画関数に渡して画像を表示する。
while(cap.isOpened()): # カメラのフレームをキャプチャ ret, frame = cap.read() gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) flow = cv2.calcOpticalFlowFarneback(prevgray, gray, None, 0.5, 3, 15, 3, 5, 1.2, 0) # flow[縦軸データ, 横軸データ, (x,y)] # print flow[0,0,:] # @ x,y ともに 0 番目のベクトルの大きさ, 角度(であってる?) prevgray = gray # プレビュー cv2.imshow('detect preview', draw_flow(frame, gray, flow, 16)) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()
以前 ActionScript3 で同じようなことをやろうとしたときは途中で挫折したのですが(笑)、Python + OpenCV だと NumPy の配列操作が強力なこともあって短いコードで済むし簡単で楽しいですね。