sort跟踪算法+opencv模板匹配实现小球跟踪
- 实现结果
- rgb
- 灰度图像假彩色
- 二值化,提取坐标
- SORT多目标跟踪算法
- 基于模板匹配的目标检测
- 模板匹配结果与SORT算法融合
- 完整代码
实现结果
先把最终结果放上来,个人感觉效果还是非常棒的。
rgb
sort+模板匹配实现多目标跟踪
灰度图像假彩色
假彩色反映的是模板匹配的匹配程度,越红代表相似度越高。
sort+模板匹配实现多目标跟踪
二值化,提取坐标
对模板匹配后的结果,进行二值化等操作,获取小球中心点坐标。
sort+模板匹配实现多目标跟踪
SORT多目标跟踪算法
SORT是一种简单的在线实时多目标跟踪算法。文章要点为:
- 以 IoU 作为前后帧间目标关系度量指标;
- 利用卡尔曼滤波器预测当前位置
- 通过匈牙利算法关联检测框到目标;
- 应用试探期甄别虚检;
具体的代码分析,可以参考:SORT 多目标跟踪算法笔记。本人还没有这么深入的理解。
总之我们可以通过:
mot_tracker = Sort()
调用Sort检测算法。
接着使用以下命令进行参数更新:
trackers = mot_tracker.update(match_result)
其中match_result的格式为:
参数dets:格式为[[x1,y1,x2,y2,score],[x1,y1,x2,y2,score],…]的 numpy 检测数组。
返回的trackers 包含最终的结果,主要包括被跟踪物体的位置信息和序号,得到这些之后,我们可以在视频帧中进行标注。
基于模板匹配的目标检测
这里的目标检测使用最基本的基于模板匹配的方法。
result = cv2.matchTemplate(target, tpl, method)
基于模板匹配的代码如下
def template_demo(tpl, target, method = cv2.TM_CCORR_NORMED):
th, tw = tpl.shape[:2]# 取高宽,不取通道 模板高宽
global fake_color
result = cv2.matchTemplate(target, tpl, method) # 每一个点的匹配度
kcf_result = np.copy(result)
kcf_result = np.uint8(np.power((kcf_result+1)/2, 1.5)*250)
ball_center = loc_max(kcf_result, 170) # 得到中心点坐标
im_color = cv2.applyColorMap(kcf_result, cv2.COLORMAP_JET)
match_result = []
for i in range(len(ball_center)):
center_y = int(ball_center[i][0] + ball_center[i][2]/2)
center_x = int(ball_center[i][1] + ball_center[i][3]/2)
match_result.append([ int(center_y),int(center_x), int(center_y+th),int(center_x+tw), result[center_x, center_y]])
cv2.imshow('kcf', im_color)
fake_color.write(im_color)
return match_result # [[x1,y1,x2,y2,score],[x1,y1,x2,y2,score],...]
def loc_max(kcf_result, threshold):
ball_center = []
global erzhi
ret, kcf_threshold = cv2.threshold(kcf_result, threshold, 255, cv2.THRESH_BINARY)
#创建矩形结构单元
g=cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
#形态学处理,开运算
img_open=cv2.morphologyEx(kcf_threshold,cv2.MORPH_OPEN,g)
_, contours, hierarchy = cv2.findContours(img_open, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
bounding_boxes = cv2.boundingRect(cnt)
cv2.rectangle(img_open, (bounding_boxes[0], bounding_boxes[1]), (bounding_boxes[0]+bounding_boxes[2], bounding_boxes[1]+bounding_boxes[3]),(255,0,0))
ball_center.append(bounding_boxes)
cv2.imshow('threshold', img_open)
img_open = np.expand_dims(img_open, 2)
img_open = np.concatenate((img_open, img_open, img_open), axis=2)
erzhi.write(img_open)
return ball_center
模板匹配结果与SORT算法融合
mot_tracker = Sort()
color = np.uint8(np.random.rand(32, 3)*255)
while True:
ok, frame = video.read()
bar.update(1)
if ok:
match_result = template_demo(ROI, frame, method=cv2.TM_CCOEFF_NORMED)
# print(match_result)
match_result = np.array(match_result)
trackers = mot_tracker.update(match_result)
for tracker in trackers:
color_tracker = ( int(color[int(tracker[4]%30)][0]), int(color[int(tracker[4]%30)][1]), int(color[int(tracker[4]%30)][2]))
cv2.rectangle(frame, (int(tracker[0]), int(tracker[1])), (int(tracker[2]), int(tracker[3])), color_tracker, 2)
cv2.putText(frame, str(int(tracker[4])),(int(tracker[0]/2+tracker[2]/2), int(tracker[1]/2+tracker[3]/2)), cv2.FONT_HERSHEY_SIMPLEX, 1, (255,0,0))
result.write(frame)
cv2.imshow('frame', frame)
if cv2.waitKey(3) == 27:
break
else:
break
完整代码
代码我放在了:SORT_matchTemplate 以及演示的原始视频:red_ball.flv 使用的时候直接把这三个文件放在同一文件夹下,执行red_ball.py即可。
如果有什么疑问,还请留言。