物体追跡をやってみる(ピンクのボールを追いかける)
やりたいこと:ピンクボールの追跡
OpenCV-Python tutorial
OpenCV-Pythonチュートリアル — OpenCV-Python Tutorials 1 documentation
OpenCVでのHSVの扱い
OpenCVでのHSV色空間lower,upperの取り扱い - Qiita
ピンクの色相の検出
lightsalmon : 255,160,167
lower_pink = np.array([168, 100, 100])
upper_pink = np.array([188, 255, 255])
import numpy as np import cv2 cap = cv2.VideoCapture(0) while(1): _, frame = cap.read() hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) lower_light_pink = np.array([168, 100, 100]) upper_light_pink = np.array([188, 255, 255]) mask = cv2.inRange(hsv, lower_light_pink, upper_light_pink) res = cv2.bitwise_and(frame,frame, mask= mask) cv2.imshow('frame',frame) cv2.imshow('mask',mask) cv2.imshow('res',res) k = cv2.waitKey(5) & 0xFF if k == 27: break cv2.destroyAllWindows()
参考:色名称付色見本[赤、ピンク、茶系] – コピペで出来る!簡単ホームページ作成入門
【Python/OpenCV】カラートラッキング(色追跡)で移動物体の検出
最大矩形を追跡
作成したmaskの中で、一番大きいものだけを追跡する(矩形で囲む)
ROI:Region Of Interest
以下を上記のスクリプトに追加↑
image, contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) rects = [] for contour in contours: approx = cv2.convexHull(contour) rect = cv2.boundingRect(approx) rects.append(np.array(rect)) if len(rects) > 0: rect = max(rects, key=(lambda x: x[2] * x[3])) cv2.rectangle(frame, tuple(rect[0:2]), tuple(rect[0:2] + rect[2:4]), (0, 0, 255), thickness=2)
camshiftで追跡
ヒストグラムとは
ヒストグラムとは画像中の画素値の全体的な分布を知るためのグラフやプロットとみなせます.
ヒストグラム その1: 計算して,プロットして,解析する !!! — OpenCV-Python Tutorials 1 documentation
ヒストグラム逆投影法
各画素が対象物体に属している確率を表す.入力画像と同じサイズで単相の画像を作成します.
ヒストグラム その4: ヒストグラムの逆投影法 — OpenCV-Python Tutorials 1 documentation
パラメータ:
cv2.TERM_CRITERIA_EPS - 指定された精度(epsilon)に到達したら繰り返し計算を終了する.
cv2.TERM_CRITERIA_MAX_ITER - 指定された繰り返し回数(max_iter)に到達したら繰り返し計算を終了する.
かなり適当なコード(TODO:リファクタ、マウスでクリックした箇所のHSV値の利用)
import numpy as np import cv2 cap = cv2.VideoCapture(0) print raw_input("please set the tracking object and input key") # Need adjustment lower_light_pink = np.array([168, 100, 100]) upper_light_pink = np.array([188, 255, 255]) _LOWER_COLOR = lower_light_pink _UPPER_COLOR = upper_light_pink print _LOWER_COLOR[0] def find_rect_of_target_color(image): hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) # Threshold the HSV image to get only pink colors mask = cv2.inRange(hsv, _LOWER_COLOR, _UPPER_COLOR) image, contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) rects = [] for contour in contours: approx = cv2.convexHull(contour) rect = cv2.boundingRect(approx) rects.append(np.array(rect)) return rects def get_max_rect(rects): if len(rects) > 0: rect = max(rects, key=(lambda x: x[2] * x[3])) return rect else: return None def get_track_info(rect): # setup initial location of window r, h, c, w = rect[1], rect[3], rect[0], rect[2] track_window = (c,r,w,h) # set up the ROI for tracking roi = frame[r:r+h, c:c+w] hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV) mask = cv2.inRange(hsv_roi, _LOWER_COLOR, _UPPER_COLOR) # Need adjustment roi_hist = cv2.calcHist([hsv_roi],[0],mask,[int(_UPPER_COLOR[0])],[0,int(_UPPER_COLOR[0])]) cv2.normalize(roi_hist,roi_hist,0,255,cv2.NORM_MINMAX) # Setup the termination criteria, either 10 iteration or move by atleast 1 pt term_crit = ( cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1 ) return roi_hist, track_window, term_crit # Set Initial Value while(1): # take first frame of the video ret,frame = cap.read() rects = find_rect_of_target_color(frame) rect = get_max_rect(rects) if rect is not None: roi_hist, track_window, term_crit = get_track_info(rect) break # Start Tracking while(1): ret ,frame = cap.read() if ret == True: hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) dst = cv2.calcBackProject([hsv],[0],roi_hist,[0,180],1) # apply camshift to get the new location # ret = ([x,y],[width,height],deg) ex: [640, 480],[10,10],30 ret, track_window = cv2.CamShift(dst, track_window, term_crit) # Draw it on image pts = cv2.boxPoints(ret) pts = np.int0(pts) img = cv2.polylines(frame,[pts],True, 255,2) cv2.imshow('img',img) print pts # origin is upper left frame_size = frame.shape print "position_x_rate" print (pts[0][0]+pts[2][0])/2.0/frame_size[1] print "position_y_rate" print (pts[0][1]+pts[2][1])/2.0/frame_size[0] k = cv2.waitKey(60) & 0xff if k == 27: break else: cv2.imwrite(chr(k)+".jpg",img) else: break cv2.destroyAllWindows() cap.release()
参考: Meanshift と Camshift — OpenCV-Python Tutorials 1 documentation
パーティクルフィルタで追跡
import numpy as np import cv2 # Need adjustment lower_light_pink = np.array([168, 50, 50]) upper_light_pink = np.array([188, 255, 255]) _LOWER_COLOR = lower_light_pink _UPPER_COLOR = upper_light_pink def tracking(): cap = cv2.VideoCapture(0) filter = ParticleFilter() filter.initialize() while True: ret, frame = cap.read() hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) # Threshold the HSV image to get only a color mask = cv2.inRange(hsv, _LOWER_COLOR, _UPPER_COLOR) # Start Tracking y, x = filter.filtering(mask) frame = cv2.circle(frame, (int(x), int(y)), 10, (255, 0, 0), -1) # origin is upper left frame_size = frame.shape print "position_x_rate" print x/frame_size[1] print "position_y_rate" print y/frame_size[0] for i in range(filter.SAMPLEMAX): frame = cv2.circle(frame, (int(filter.X[i]), int(filter.Y[i])), 2, (0, 0, 255), -1) cv2.imshow("frame", frame) if cv2.waitKey(20) & 0xFF == 27: break cap.release() cv2.destroyAllWindows() class ParticleFilter: def __init__(self): self.SAMPLEMAX = 1000 # frame.shape self.height, self.width = 480, 640 def initialize(self): self.Y = np.random.random(self.SAMPLEMAX) * self.height self.X = np.random.random(self.SAMPLEMAX) * self.width # Need adjustment for tracking object velocity def modeling(self): self.Y += np.random.random(self.SAMPLEMAX) * 200 - 100 # 2:1 self.X += np.random.random(self.SAMPLEMAX) * 200 - 100 def normalize(self, weight): return weight / np.sum(weight) def resampling(self, weight): index = np.arange(self.SAMPLEMAX) sample = [] # choice by weight for i in range(self.SAMPLEMAX): idx = np.random.choice(index, p=weight) sample.append(idx) return sample def calcLikelihood(self, image): # white space tracking mean, std = 250.0, 10.0 intensity = [] for i in range(self.SAMPLEMAX): y, x = self.Y[i], self.X[i] if y >= 0 and y < self.height and x >= 0 and x < self.width: intensity.append(image[int(y),int(x)]) else: intensity.append(-1) # normal distribution weights = 1.0 / np.sqrt(2 * np.pi * std) * np.exp(-(np.array(intensity) - mean)**2 /(2 * std**2)) weights[intensity == -1] = 0 weights = self.normalize(weights) return weights def filtering(self, image): self.modeling() weights = self.calcLikelihood(image) index = self.resampling(weights) self.Y = self.Y[index] self.X = self.X[index] # return COG return np.sum(self.Y) / float(len(self.Y)), np.sum(self.X) / float(len(self.X)) if __name__ == '__main__': tracking()
参考:
パーティクルフィルタ組んでみた(Python) - コンピュータサイエンス系勉強ノート
python + numpyで緑色の物体を追跡する (パーティクルフィルタ) - Qiita
Particle FilterでOpencvを使った物体追跡 - のんびりしているエンジニアの日記
satomacoto: Pythonでパーティクルフィルタを実装してみる
particlefilter/particlefilter_py.py at master · AriYu/particlefilter · GitHub
pythonでパーティクルフィルタによる物体トラッキング - kohta blog
オプティカルフロー(Lucas-Kanade法)で追跡
cv2.goodFeaturesToTrack
コーナー検出器。8bitの画像とコーナーに関する設定を行うことでコーナーが検出される。
cv2.calcOpticalFlowPyrLK
8bitの画像を前後の二枚と検出したい点の集合(feature)やwinSizeを指定すると、後の画像上の特徴点が抽出される。
cv2.cornerSubPix
コーナー検出の高精度化。
Harrisコーナー検出 — OpenCV-Python Tutorials 1 documentation
cv2.dilate
膨張処理
Python OpenCV3で画素の膨張処理(dilation)と収縮処理(erosion) (ちょっと解説も) | from umentu import stupid
cv2.connectedComponentsWithStats
重心・面積・外接矩形の座標が得らる。
Harrisコーナー検出 — OpenCV-Python Tutorials 1 documentation
参考: qiita.com
OpenCVでオプティカルフローをリアルタイムに描画する(Shi-Tomasi法、Lucas-Kanade法) - Qiita
全体参考
毎日がロボット勉強会: 10.ロボットビジョン(応用編その1)
モーション解析と物体追跡 — opencv 2.2 (r4295) documentation
人追跡
OpenCVで簡単リアルタイム物体検出 | AI coordinator
Nobutobook: 【Python × OpenCV】 はじめての歩行者検知
機械の目が見たセカイ -コンピュータビジョンがつくるミライ (27) 動く人・物を追跡する(1) - OpenCVによるトラッキング | テクノロジー | マイナビニュース
顔追跡
【ライブラリ】pyFaceTracker:顔パーツ追跡「FaceTracker」のpythonラッパー... | DERiVE コンピュータビジョン ブログ
OpenCVで簡単リアルタイム物体検出 | AI coordinator
マーカー
Aruco-with-Python/aruco_testproject/build at master · JanezCim/Aruco-with-Python · GitHub
arucoモジュールでマーカーを検出する · atinfinity/lab Wiki · GitHub
軽量な AR ライブラリの ArUco について調査中 - Qiita
itouh2: OpenCV 画面上の四角の3次元座標をもとめる
GitHub - DebVortex/python-ar-markers: Detection of hamming markers for OpenCV written in python
ROSでARマーカーを追跡するパッケージを使う: マイコン漬け