【爆速】OpenCVで複数の物体検出 -ラズパイ- を参考に、物体認識を試してみた。
単一オブジェクトの動き検出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
import numpy as np import cv2 ESC_KEY = 27 def get_bounding_box(X, Y): x_max = int(np.max(X)) x_min = int(np.min(X)) y_max = int(np.max(Y)) y_min = int(np.min(Y)) return (x_min, y_min, x_max, y_max) def draw_bounding_box(img, bbox): img = cv2.rectangle(img, (bbox[0], bbox[1]), (bbox[2], bbox[3],), (0, 255, 0), 3) return img fgbg = cv2.bgsegm.createBackgroundSubtractorMOG() cap = cv2.VideoCapture(0) w = cap.get(cv2.CAP_PROP_FRAME_WIDTH) h = cap.get(cv2.CAP_PROP_FRAME_HEIGHT) fps = cap.get(cv2.CAP_PROP_FPS) while True: ret, frame = cap.read() if frame is None: break frame = cv2.GaussianBlur(frame, (7,7), 0) fgmask = fgbg.apply(frame) img1=frame img2=fgmask Y, X = np.where(fgmask > 200) if len(X) == 0 or len(Y)==0 : continue bbox = get_bounding_box(X, Y) img2 = draw_bounding_box(img1, bbox) cv2.imshow('img1', img2) cv2.imshow('fgmask', fgmask) if cv2.waitKey(30) == ESC_KEY: break cap.release() cv2.destroyAllWindows() |
KMeans を使って複数オブジェクトを認識をしてみたところ、ノイズがあると重心がうまく分離できず、Bounding Box が大きくずれてしまう。また、同一の物体であっても、複数のクラスターから構成されてしまうという問題点があった。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
import numpy as np import cv2 from sklearn.cluster import KMeans CLUSTER=10 colorlist = [(0,0,0),(0,0,255),(0,255,0),(0,255,255),(255,0,0),(255,0,255),(255,255,0),(255,255,255)] ESC_KEY = 27 def get_bounding_box(X, Y, result, cluster): NO = np.where(result==cluster) x_max = int(np.max(X[NO])) x_min = int(np.min(X[NO])) y_max = int(np.max(Y[NO])) y_min = int(np.min(Y[NO])) return (x_min, y_min, x_max, y_max) def draw_bounding_box(img, bbox): img = cv2.rectangle(img, (bbox[0], bbox[1]), (bbox[2], bbox[3],), (0, 255, 0), 3) return img def draw_circle(img, X, Y, result, cluster): NO = np.where(result==cluster) for p in NO[0] : img = cv2.circle(img, (X[p], Y[p]), 5, colorlist[cluster%8],-1) return img font = cv2.FONT_HERSHEY_SIMPLEX def draw_number(img, X, Y, result, cluster): NO = np.where(result==cluster) for p in NO[0] : img = cv2.putText(img, str(cluster),(X[p], Y[p]), font, 1,colorlist[cluster%8],1,cv2.LINE_AA) return img fgbg = cv2.bgsegm.createBackgroundSubtractorMOG() cap = cv2.VideoCapture("video/vtest.avi") w = cap.get(cv2.CAP_PROP_FRAME_WIDTH) h = cap.get(cv2.CAP_PROP_FRAME_HEIGHT) fps = cap.get(cv2.CAP_PROP_FPS) while True: ret, frame = cap.read() if frame is None: break frame = cv2.GaussianBlur(frame, (5,5), 0) fgmask = fgbg.apply(frame) img1=frame img2=fgmask Y, X = np.where(fgmask > 200) if X.size < w : continue means = KMeans(n_clusters=CLUSTER, init='k-means++', n_jobs=1).fit_predict(np.array([X,Y])) for i in range(CLUSTER) : bbox = get_bounding_box(X, Y, means, i) img2 = draw_bounding_box(img1, bbox) img2 = draw_circle(img1, X, Y, means, i) <em># img2 = draw_number(img1, X, Y, means, i)</em> cv2.imshow('img1', img2) cv2.imshow('fgmask', fgmask) keyboard = cv2.waitKey(30) if keyboard == ESC_KEY: break cap.release() cv2.destroyAllWindows() |
次に、オブジェクト輪郭検出 を参考に 複数のオブジェクトの動き認識してみた。 動いていないと認識できない、物体の特定ができない、といった問題があり、 正確ではないけれど、ある程度認識することができる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
import numpy as np import cv2 ESC_KEY = 27 fgbg = cv2.bgsegm.createBackgroundSubtractorMOG() cap = cv2.VideoCapture("video/vtest.avi") w = cap.get(cv2.CAP_PROP_FRAME_WIDTH) h = cap.get(cv2.CAP_PROP_FRAME_HEIGHT) fps = cap.get(cv2.CAP_PROP_FPS) while True: ret, frame = cap.read() if frame is None: break frame = cv2.GaussianBlur(frame, (7,7), 0) fgmask = fgbg.apply(frame) # find contours labels, contours, hierarchy = cv2.findContours(fgmask, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) for i in range(0, len(contours)): if len(contours[i]) > 0: # remove small objects if cv2.contourArea(contours[i]) < 500: continue # Draw Bounding Box rect = contours[i] x, y, w, h = cv2.boundingRect(rect) cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 3) # Draw Contours # frame = cv2.drawContours(frame, contours, i, (0,255,0), 3) cv2.imshow('frame', frame) cv2.imshow('fgmask', fgmask) keyboard = cv2.waitKey(int(1000/fps)) if keyboard == ESC_KEY: break cap.release() cv2.destroyAllWindows() |
drawContours だけで輪郭を描画できる。