dlib提供了dlib.correlation_tracker()类用于跟踪目标。
官方文档入口:http://dlib.net/python/index.html#dlib.correlation_tracker
不复杂,就不介绍了,后面会直接给出两个程序,有注释。
# -*- coding: utf-8 -*- import sys import dlib import cv2 tracker = dlib.correlation_tracker() # 导入correlation_tracker()类 cap = cv2.VideoCapture(0) # OpenCV打开摄像头 start_flag = True # 标记,是否是第一帧,若在第一帧需要先初始化 selection = None # 实时跟踪鼠标的跟踪区域 track_window = None # 要检测的物体所在区域 drag_start = None # 标记,是否开始拖动鼠标 # 鼠标点击事件回调函数 def onMouseClicked(event, x, y, flags, param): global selection, track_window, drag_start # 定义全局变量 if event == cv2.EVENT_LBUTTONDOWN: # 鼠标左键按下 drag_start = (x, y) track_window = None if drag_start: # 是否开始拖动鼠标,记录鼠标位置 xMin = min(x, drag_start[0]) yMin = min(y, drag_start[1]) xMax = max(x, drag_start[0]) yMax = max(y, drag_start[1]) selection = (xMin, yMin, xMax, yMax) if event == cv2.EVENT_LBUTTONUP: # 鼠标左键松开 drag_start = None track_window = selection selection = None if __name__ == '__main__': cv2.namedWindow("image", cv2.WINDOW_AUTOSIZE) cv2.setMouseCallback("image", onMouseClicked) # opencv的bgr格式图片转换成rgb格式 # b, g, r = cv2.split(frame) # frame2 = cv2.merge([r, g, b]) while(1): ret, frame = cap.read() # 从摄像头读入1帧 if start_flag == True: # 如果是第一帧,需要先初始化 # 这里是初始化,窗口中会停在当前帧,用鼠标拖拽一个框来指定区域,随后会跟踪这个目标;我们需要先找到目标才能跟踪不是吗? while True: img_first = frame.copy() # 不改变原来的帧,拷贝一个新的出来 if track_window: # 跟踪目标的窗口画出来了,就实时标出来 cv2.rectangle(img_first, (track_window[0], track_window[1]), (track_window[2], track_window[3]), (0,0,255), 1) elif selection: # 跟踪目标的窗口随鼠标拖动实时显示 cv2.rectangle(img_first, (selection[0], selection[1]), (selection[2], selection[3]), (0,0,255), 1) cv2.imshow("image", img_first) # 按下回车,退出循环 if cv2.waitKey(5) == 13: break start_flag = False # 初始化完毕,不再是第一帧了 tracker.start_track(frame, dlib.rectangle(track_window[0], track_window[1], track_window[2], track_window[3])) # 跟踪目标,目标就是选定目标窗口中的 else: tracker.update(frame) # 更新,实时跟踪 box_predict = tracker.get_position() # 得到目标的位置 cv2.rectangle(frame,(int(box_predict.left()),int(box_predict.top())),(int(box_predict.right()),int(box_predict.bottom())),(0,255,255),1) # 用矩形框标注出来 cv2.imshow("image", frame) # 如果按下ESC键,就退出 if cv2.waitKey(10) == 27: break cap.release() cv2.destroyAllWindows()
注:如果程序卡了,就调一下cv2.waitKey()中的参数,也就是延时时间,调小即可。
运行结果
初始时,窗口中只会显示第一帧的图像;
使用鼠标拖拽一个框,红框中目标后,按回车,设置框内为识别目标;
实时识别,以橙框标出;
按ESC键退出。
(csdn只能上传2M的图片,真心难受)
程序2
由于前面那个程序,只是熟悉下函数写的,我觉得用起来蛋疼,所以又重新封装了一下。看起来舒服多了。
# -*- coding: utf-8 -*- import sys import dlib import cv2 class myCorrelationTracker(object): def __init__(self, windowName='default window', cameraNum=0): # 自定义几个状态标志 self.STATUS_RUN_WITHOUT_TRACKER = 0 # 不跟踪目标,但是实时显示 self.STATUS_RUN_WITH_TRACKER = 1 # 跟踪目标,实时显示 self.STATUS_PAUSE = 2 # 暂停,卡在当前帧 self.STATUS_BREAK = 3 # 退出 self.status = self.STATUS_RUN_WITHOUT_TRACKER # 指示状态的变量 # 这几个跟前面程序1定义的变量一样 self.track_window = None # 实时跟踪鼠标的跟踪区域 self.drag_start = None # 要检测的物体所在区域 self.start_flag = True # 标记,是否开始拖动鼠标 # 创建好显示窗口 cv2.namedWindow(windowName, cv2.WINDOW_AUTOSIZE) cv2.setMouseCallback(windowName, self.onMouseClicked) self.windowName = windowName # 打开摄像头 self.cap = cv2.VideoCapture(cameraNum) # correlation_tracker()类,跟踪器,跟程序1中一样 self.tracker = dlib.correlation_tracker() # 当前帧 self.frame = None # 按键处理函数 def keyEventHandler(self): keyValue = cv2.waitKey(5) # 每隔5ms读取一次按键的键值 if keyValue == 27: # ESC self.status = self.STATUS_BREAK if keyValue == 32: # 空格 if self.status != self.STATUS_PAUSE: # 按下空格,暂停播放,可以选定跟踪的区域 #print self.status self.status = self.STATUS_PAUSE #print self.status else: # 再按次空格,重新播放,但是不进行目标识别 if self.track_window: self.status = self.STATUS_RUN_WITH_TRACKER self.start_flag = True else: self.status = self.STATUS_RUN_WITHOUT_TRACKER if keyValue == 13: # 回车 #print '**' if self.status == self.STATUS_PAUSE: # 按下空格之后 if self.track_window: # 如果选定了区域,再按回车,表示确定选定区域为跟踪目标 self.status = self.STATUS_RUN_WITH_TRACKER self.start_flag = True # 任务处理函数 def processHandler(self): # 不跟踪目标,但是实时显示 if self.status == self.STATUS_RUN_WITHOUT_TRACKER: ret, self.frame = self.cap.read() cv2.imshow(self.windowName, self.frame) # 暂停,暂停时使用鼠标拖动红框,选择目标区域,与程序1类似 elif self.status == self.STATUS_PAUSE: img_first = self.frame.copy() # 不改变原来的帧,拷贝一个新的变量出来 if self.track_window: # 跟踪目标的窗口画出来了,就实时标出来 cv2.rectangle(img_first, (self.track_window[0], self.track_window[1]), (self.track_window[2], self.track_window[3]), (0,0,255), 1) elif self.selection: # 跟踪目标的窗口随鼠标拖动实时显示 cv2.rectangle(img_first, (self.selection[0], self.selection[1]), (self.selection[2], self.selection[3]), (0,0,255), 1) cv2.imshow(self.windowName, img_first) # 退出 elif self.status == self.STATUS_BREAK: self.cap.release() # 释放摄像头 cv2.destroyAllWindows() # 释放窗口 sys.exit() # 退出程序 # 跟踪目标,实时显示 elif self.status == self.STATUS_RUN_WITH_TRACKER: ret, self.frame = self.cap.read() # 从摄像头读取一帧 if self.start_flag: # 如果是第一帧,需要先初始化 self.tracker.start_track(self.frame, dlib.rectangle(self.track_window[0], self.track_window[1], self.track_window[2], self.track_window[3])) # 开始跟踪目标 self.start_flag = False # 不再是第一帧 else: self.tracker.update(self.frame) # 更新 # 得到目标的位置,并显示 box_predict = self.tracker.get_position() cv2.rectangle(self.frame,(int(box_predict.left()),int(box_predict.top())),(int(box_predict.right()),int(box_predict.bottom())),(0,255,255),1) cv2.imshow(self.windowName, self.frame) # 鼠标点击事件回调函数 def onMouseClicked(self, event, x, y, flags, param): if event == cv2.EVENT_LBUTTONDOWN: # 鼠标左键按下 self.drag_start = (x, y) self.track_window = None if self.drag_start: # 是否开始拖动鼠标,记录鼠标位置 xMin = min(x, self.drag_start[0]) yMin = min(y, self.drag_start[1]) xMax = max(x, self.drag_start[0]) yMax = max(y, self.drag_start[1]) self.selection = (xMin, yMin, xMax, yMax) if event == cv2.EVENT_LBUTTONUP: # 鼠标左键松开 self.drag_start = None self.track_window = self.selection self.selection = None def run(self): while(1): self.keyEventHandler() self.processHandler() if __name__ == '__main__': testTracker = myCorrelationTracker(windowName='image', cameraNum=1) testTracker.run()
运行结果
操作有一些改变:
初始时,会自动从摄像头采集图像显示;
按下空格,暂停;此时若再按空格,恢复实时显示,但不进行目标跟踪;
暂停时,拖动鼠标会显示红框,按下回车,将红框内物体视为目标进行识别;
随后实时识别,以橙框标出;
按ESC键退出。
dlib这个库的确很方便,能够很轻松地让我们实现一些基础的识别任务,比如人脸识别。但是如果想要在各种识别任务中有更好的效果,肯定是不能只用他给的模型的。那也就是说需要自己训练了,看到官方文档中也提供了一些训练以及自己构建神经网络等的api接口,