车流量统计(3)

多目标追踪

实现一个多目标跟踪器,管理多个卡尔曼滤波器对象,主要包括以下内容:
初始化:最大检测数,目标未被检测的最大帧数
目标跟踪结果的更新,即跟踪成功和失败的目标的更新。

def __init__(self,max_age=1,min_hit=3)
	#最大检测数:目标未被检测到的帧数,超过之后会被删除
	self.max_age=max_age
	#目标命中的最小次数,小于该次数不返回
	self.min_hits=min_hits
	#卡尔曼跟踪器
	self.trackers=[]
	#帧计数
	self.frame_count=0

目标跟踪结果的更新
该方法实现了SORT算法,输入时当前帧中所有物体检测框的几何,包括score,输出是当前帧标的跟踪框集合,包括目标的跟踪框的id要求即使检测框为空,也必须对每一帧调用此方法,返回一个列类似的数组输出数组,最后一列是目标对象的id,返回的目标对象数量可能与检测框不同

def update(self,dets):
	self.frame_count+=1
	#在当前帧逐个预测轨迹位置,记录状态异常的跟踪器的索引
	#根据当前所有的卡尔曼跟踪器(即上一帧中跟踪器的目标个数)创建二维数组,行号为卡尔曼滤波器的标识索引,列向量为跟踪框的位置和ID
	trks=np.zeros(len(self.trackers,5))#存储跟踪器的预测
	to_del=[]#存储要删除的目标框
	ret=[]#存储要返回的追踪目标框
	#循环遍历卡尔曼滤波跟踪器列表
	for t,trk in enumerate(trks):
		#使用卡尔曼滤波跟踪器t产生对应目标的跟踪框
		pos=self.trackers[t].predict()[0]
		trk[:]=[pos[0],pos[1],pos[2],pos[3],0]
		if np.any(np.isnan(pos)):
			to_del.append(t)
	
	#trks中存储了上一帧中跟踪的目标并且在当前帧中的预测跟踪框
	trks=np.ma.compress_rows(np.ma.masked_invalid(trks))
	#逆向删除异常跟踪器防止破坏索引
	for t in reversed(to_del):
		self.trackers.pop(t)
	 matched, unmatched_dets, unmatched_trks = associate_detections_to_trackers(dets, trks)
	#将跟踪成功的目标框更新到对应的卡尔曼滤波器中
	for t, trk in enumerate(self.trackers):
		if t not in unmatched_trks:
			d = matched[np.where(matched[:, 1] == t)[0], 0]
			trk.update(dets[d, :][0])
	# 为新增的目标创建新的卡尔曼滤波器对象进行跟踪
	for i in unmatched_dets:
		trk = KalmanBoxTracker(dets[i, :])
		self.trackers.append(trk)
	# 自后向前遍历,仅返回在当前帧出现且命中周期大于self.min_hits(除非跟踪刚开始)的跟踪结果;如果未命中时间大于self.max_age则删除跟踪器。
	i = len(self.trackers)
	for trk in reversed(self.trackers):
		# 返回当前边界框的估计值
		d = trk.get_state()[0]
		# 跟踪成功目标的box与id放入ret列表中
		if (trk.time_since_update < 1) and (trk.hit_streak >= self.min_hits or self.frame_count <= self.min_hits):
		ret.append(np.concatenate((d, [trk.id + 1])).reshape(1, -1))
		i -= 1
		if trk.time_since_update > self.max_age:
			self.trackers.pop(i)
		# 返回当前画面中所有目标的box与id,以二维矩阵形式返回
		if len(ret) > 0:
			return np.concatenate(ret)
		return np.empty((0, 5))

yoloV3模型

改进:利用多尺度特征进行目标检测,先验框更丰富,调整了网络结构,对象分类使用logistic代替了softmax,更适用于多标签分类任务。

基于yoloV3的目标检测

基于opencv的利用yolov3进行目标检测,只是利用训练好的模型进行目标检测。
基于opencv的DNN模块:
加载已训练好的yolov3模型及其权重参数
将要处理的图像转换为输入到模型的blobs
利用模型对目标进行检测
遍历检测结果
应用非极大值抑制
绘制最终检测结果,并存入到ndarray,供目标追踪使用

#加载可以识别物体的名称,将其存放在LABELS中,一共有80种,在这里我们使用car
labelsPath='./yolo-coco/coco.names'
LAEBLS=open(labelsPath).read().strip().split("\n")

#设置随机数种子,生成多种不同的颜色,当一个画面中有多个目标时,使用不同颜色的框将其框起来
np.random.seed(42)
COLORS=np.random.randint(0,255,size=(200,3),dtype='unit8')
#加载已经训练好的yolov3网络的权重和相应的配置数据
weightsPath='./yolo-coco/yolov3.weights'
configPath='./yolo-coco/yolov3.cfg'
#加载好数据之后,开始利用上述数据恢复yolo神经网络
net=cv2.dnn.readNetFromDarknet(configPath,weightsPath)
ln=net.getLayerNames()
#获取输出层在网络中的索引位置,并以列表的形式:['yolo_82', 'yolo_94', 'yolo_106']
ln = [ln[i[0] - 1] for i in net.getUnconnectedOutLayers()]
#读取图像
frame=cv2.imread('./car.jpg')
#视频的宽度和高度,即帧尺寸
(W,H)=(None,None)
if W is None or H is None:
	(H,W)=frame.shape[:2]
#根据输入图像构造blob,利用OPenCV进行深度网络的计算时,一般将图像转换为blob形式,对图片进行预处理
#包括缩放,减均值,通道交换等,还可以设置尺寸,一般设置为在进行网络训练时的图像的大小。
blob=cv.dnn.blobFromImage(frame,1/255.0,(416,416),swapRB=True,crop=False)

利用模型对目标进行检测

net.setInput(blob)
start=time.time()
layerOutputs=net.forward(ln)

遍历检测结果,获得检测框

boxes=[]  #用于存放识别物体的框的信息
confidences=[]  #表示识别目标时某种物体的可信度
classIDs=[]  #表示识别的目标归属哪一类
for output in layerOutputs:
	#遍历某个输出层中的每个目标
	for detection in output:
		scores=detection[5:] #当前目标属于某一类别的概率
		classID=np.argmax(scores)#目标的类别
		confidence=scores[clssID] #得到目标属于该类别的置信度
		
		#只保留置信度大于0.3的边界框,若图片质量较差,可以将置信度调低一些
		if confidence>0.3:
			#将边界框的坐标还原至原图片匹配,YOLO返回的是边界框的中心坐标以及边界框的宽度和高度
			box=detection[0:4]*np.array([W,H,W,H])
			(centerX,centerY,width,height)=box.astype('int')
			x = int(centerX - (width / 2))
			y = int(centerY - (height / 2))
			boxes.append([x, y, int(width), int(height)])
			confidences.append(float(confidence))
			classIDs.append(classID) 
			

非极大值抑制

idx=cv2.dnn.NMSBoxes(boxes,confidence,0.5,0.3)

最终检测结果,绘制并存入ndarray,供目标追踪使用

dets=[]
if len(idx)>0:
	for i in idx.flatten():
		if LABELS[classIDs[i]] == "car":
			(x, y) = (boxes[i][0], boxes[i][1]) 
			(w, h) = (boxes[i][2], boxes[i][3]) 
			cv2.rectangle(frame, (x, y), (x+w, y+h), (0,255,0), 2) 
			dets.append([x, y, x + w, y + h, confidences[i]])
np.set_printoptions(formatter={'float': lambda x: "{0:0.3f}".format(x)})
dets = np.asarray(dets)
plt.imshow(frame[:,:,::-1])
			

SORT目标跟踪

dets=np.asarray(dets)  #yolo检测到的检测框
tracker = Sort()
memory = {}
tracks=tracker.update(dets)
#跟踪框
boxes=[]
#置信度
indexIDs=[]
#前一帧跟踪结果
previous=memory.copy()
for track in tracks:
	boxes.append([track[0],track[1],track[2],track[3]])
	indexIDs.append(int(tracks[4]))
	memory[indexIDs[-1]]=boxes[-1]

未完。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值