需要源码和数据集请点赞关注收藏后评论区留言私信~~~
一、YOLO目标检测算法
YOLO是端到端的物体检测深度卷积神经网络,YOLO可以一次性预测多个候选框,并直接在输出层回归物体位置区域和区域内物体所属类别,而Faster R-CNN仍然是采用R-CNN那种将物体位置区域框与物体分开训练的思想,只是利用RPN网络,将提取候选框的步骤放在深度卷积神经网络内部实现,YOLO最大的优势就是速度快,可满足端到端训练和实时检测要求
二、Deep Sort多目标跟踪算法
算法原理如下图所示,在目标检测算法得到检测结果后,利用目标框来初始化卡尔曼滤波器,使用一个八维空间去刻画轨迹在某时刻的状态分别表示目标框的中心位置,纵横比,高度以及在图像坐标中对应的速度信息,计算卡尔曼滤波器提供的预测框与目标检测框之间的位置关系和外观特征关系,利用两个信息综合判断目标检测与跟踪框之间的关联程度,完成多目标的跟踪匹配
三、实战项目算法流程
实现流程为:首先从视频中分解出图像帧,将图像输入目标检测模块,将检测到的动态目标,输入到目标跟踪模块,而将检测到的静态目标直接输出检测结果,目标跟踪模块为同一动态目标编上同样的编号并显示在目标框的左上角,连接多帧中出现的相同的动态目标,从而画出该动态目标的运动轨迹
效果展示
目标检测与跟踪的结果如下图
三、代码
项目结构如下
代码中主要的模块及步骤如下
1:导入第三方库
2:主函数
3:目标检测部分YOLO
4:目标跟踪部分Deep Sort
部分代码如下 需要全部代码请点赞关注收藏后评论区留言私信~~~
YOLO算法代码
-
import os
-
import numpy
as np
-
import copy
-
import colorsys
-
from timeit
import default_timer
as timer
-
from keras
import backend
as K
-
from keras.models
import load_model
-
from keras.layers
import Input
-
from PIL
import Image, ImageFont, ImageDraw
-
from nets.yolo4
import yolo_body,yolo_eval
-
from utils.utils
import letterbox_image
-
#--------------------------------------------#
-
# 使用自己训练好的模型预测需要修改2个参数
-
# model_path和classes_path都需要修改!
-
#--------------------------------------------#
-
class
YOLO(
object):
-
_defaults = {
-
"model_path" :
'model_data/yolo4_weight.h5',
-
"anchors_path" :
'model_data/yolo_anchors.txt',
-
"classes_path" :
'model_data/coco_classes.txt',
-
"score" :
0.5,
-
"iou" :
0.3,
-
"max_boxes" :
100,
-
# 显存比较小可以使用416x416
-
# 显存比较大可以使用608x608
-
"model_image_size" : (
416,
416)
-
}
-
-
@classmethod
-
def
get_defaults(
cls, n):
-
if n
in cls._defaults:
-
return cls._defaults[n]
-
else:
-
return
"Unrecognized attribute name '" + n +
"'"
-
-
#---------------------------------------------------#
-
# 初始化yolo
-
#---------------------------------------------------#
-
def
__init__(
self, **kwargs):
-
self.__dict__.update(self._defaults)
-
self.class_names = self._get_class()
-
self.anchors = self._get_anchors()
-
self.sess = K.get_session()
-
self.boxes, self.scores, self.classes = self.generate()
-
-
#---------------------------------------------------#
-
# 获得所有的分类
-
#---------------------------------------------------#
-
def
_get_class(
self):
-
classes_path = os.path.expanduser(self.classes_path)
-
with
open(classes_path)
as f:
-
class_names = f.readlines()
-
class_names = [c.strip()
for c
in class_names]
-
return class_names
-
-
#---------------------------------------------------#
-
# 获得所有的先验框
-
#---------------------------------------------------#
-
def
_get_anchors(
self):
-
anchors_path = os.path.expanduser(self.anchors_path)
-
with
open(anchors_path)
as f:
-
anchors = f.readline()
-
anchors = [
float(x)
for x
in anchors.split(
',')]
-
return np.array(anchors).reshape(-
1,
2)
-
-
#---------------------------------------------------#
-
# 获得所有的分类
-
#---------------------------------------------------#
-
def
generate(
self):
-
model_path = os.path.expanduser(self.model_path)
-
assert model_path.endswith(
'.h5'),
'Keras model or weights must be a .h5 file.'
-
-
# 计算anchor数量
-
num_anchors =
len(self.anchors)
-
num_classes =
len(self.class_names)
-
-
# 载入模型,如果原来的模型里已经包括了模型结构则直接载入。
-
# 否则先构建模型再载入
-
try:
-
self.yolo_model = load_model(model_path,
compile=
False)
-
except:
-
self.yolo_model = yolo_body(Input(shape=(
None,
None,
3)), num_anchors//
3, num_classes)
-
self.yolo_model.load_weights(self.model_path)
-
else:
-
assert self.yolo_model.layers[-
1].output_shape[-
1] == \
-
num_anchors/
len(self.yolo_model.output) * (num_classes +
5), \
-
'Mismatch between model and given anchor and class sizes'
-
-
print(
'{} model, anchors, and classes loaded.'.
format(model_path))
-
-
# 画框设置不同的颜色
-
hsv_tuples = [(x /
len(self.class_names),
1.,
1.)
-
for x
in
range(
len(self.class_names))]
-
self.colors =
list(
map(
lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples))
-
self.colors =
list(
-
map(
lambda x: (
int(x[
0] *
255),
int(x[
1] *
255),
int(x[
2] *
255)),
-
self.colors))
-
-
# 打乱颜色
-
np.random.seed(
10101)
-
np.random.shuffle(self.colors)
-
np.random.seed(
None)
-
-
self.input_image_shape = K.placeholder(shape=(
2, ))
-
-
boxes, scores, classes = yolo_eval(self.yolo_model.output, self.anchors,
-
num_classes, self.input_image_shape, max_boxes = self.max_boxes,
-
score_threshold = self.score, iou_threshold = self.iou)
-
return boxes, scores, classes
-
-
'''
-
函数名称:detect_image
-
函数作用:目标跟踪程序(YOLO V4)
-
函数输入:frame: 图像
-
函数输出:
-
boxs_person:行人检测框【x1, y1, w, h】
-
boxs_others:其他类别检测框【x1, y1, x2, y2】
-
labels_others: 其他框的类别
-
-
'''
-
def
detect_image(
self, image):
-
new_image_size = (self.model_image_size[
1],self.model_image_size[
0])
-
boxed_image = letterbox_image(image, new_image_size)
-
image_data = np.array(boxed_image, dtype=
'float32')
-
image_data /=
255.
-
image_data = np.expand_dims(image_data,
0)
# Add batch dimension.
-
boxs_person = []
-
boxs_others = []
-
labels_others = []
-
# 预测结果
-
out_boxes, out_scores, out_classes = self.sess.run(
-
[self.boxes, self.scores, self.classes],
-
feed_dict={
-
self.yolo_model.
input: image_data,
-
self.input_image_shape: [image.size[
1], image.size[
0]],
-
K.learning_phase():
0
-
})
-
-
-
for i, c
in
list(
enumerate(out_classes)):
-
predicted_class = self.class_names[c]
-
box = out_boxes[i]
-
score = out_scores[i]
-
top, left, bottom, right = box
-
###输入deepSort的格式如下###
-
box_deepsort = [left,top,right-left,bottom-top]
-
box_other = [left,top,right,bottom]
-
-
if predicted_class ==
'person':
-
boxs_person.append(box_deepsort)
-
else:
-
boxs_others.append(box_other)
-
labels_others.append(predicted_class)
-
-
-
return boxs_person,boxs_others,labels_others
-
-
def
close_session(
self):
-
self.sess.close()
Deep Sort算法代码
-
#!python3
-
#--coding:utf8--
-
from yolo
import YOLO
-
from PIL
import Image
-
import os
-
import sys
-
import time
-
import logging
-
import random
-
from random
import randint
-
import math
-
import statistics
-
import getopt
-
from ctypes
import *
-
import numpy
as np
-
import cv2
-
from deep_sort
import nn_matching
-
from deep_sort.detection
import Detection
-
from deep_sort.tracker
import Tracker
-
from tools
import generate_detections
as gdet
-
from deep_sort.detection
import Detection
as ddet
-
from collections
import deque
-
from deep_sort
import preprocessing
-
-
-
'''
-
函数名称:track_deepsort
-
函数作用:目标跟踪程序
-
函数输入:frame:图像
-
boxs_person:行人检测框【x1,y1,w,h】
-
boxs_others:其他类别检测框【x1,y1,x2,y2】
-
labels_others:其他框的类别
-
encoder:跟踪器的编码器
-
tracker: 跟踪器
-
pts: 运动点初始化值
-
show_results:是否显示结果
-
-
函数输出:tracker 跟踪器
-
pts 运动轨迹
-
-
'''
-
-
def
track_deepsort(
frame,boxs_person,boxs_others,labels_others,encoder,tracker,pts,show_results=True):
-
nms_max_overlap =
1.0
-
features = encoder(frame, boxs_person)
-
detections = [Detection(bbox,
1.0, feature)
for bbox, feature
in
zip(boxs_person, features)]
-
boxes = np.array([d.tlwh
for d
in detections])
-
scores = np.array([d.confidence
for d
in detections])
-
indices = preprocessing.non_max_suppression(boxes, nms_max_overlap, scores)
-
detections = [detections[i]
for i
in indices]
-
# 跟踪
-
tracker.predict()
-
tracker.update(detections)
-
i =
int(
0)
-
indexIDs = []
-
##########结果显示###########
-
if show_results:
-
for det
in detections:
-
bbox = det.to_tlbr()
-
cv2.rectangle(frame, (
int(bbox[
0]),
int(bbox[
1])), (
int(bbox[
2]),
int(bbox[
3])), (
255,
255,
255),
2)
-
for ii
in
range(
len(boxs_others)):
-
bbox = boxs_others[ii]
-
label = labels_others[ii]
-
cv2.rectangle(frame, (
int(bbox[
0]),
int(bbox[
1])), (
int(bbox[
2]),
int(bbox[
3])), (
0,
255,
255),
2)
-
cv2.putText(frame,
str(label), (
int(bbox[
0]),
int(bbox[
1])), cv2.FONT_HERSHEY_COMPLEX,
0.5, (
0,
255,
255),
2)
-
-
for track
in tracker.tracks:
-
if
not track.is_confirmed()
or track.time_since_update >
1:
-
continue
-
# boxes.append([track[0], track[1], track[2], track[3]])
-
indexIDs.append(
int(track.track_id))
-
bbox = track.to_tlbr()
-
-
cv2.rectangle(frame, (
int(bbox[
0]),
int(bbox[
1])), (
int(bbox[
2]),
int(bbox[
3])), (
0,
255,
0),
3)
-
cv2.putText(frame,
str(track.track_id), (
int(bbox[
0]),
int(bbox[
1] -
50)),
0,
5e-3 *
150, (
0,
255,
0),
2)
-
-
-
i = i +
1
-
center = (
int(((bbox[
0]) + (bbox[
2])) /
2),
int(((bbox[
1]) + (bbox[
3])) /
2))
-
pts[track.track_id].append(center)
-
# draw motion path
-
for j
in
range(
1,
len(pts[track.track_id])):
-
if pts[track.track_id][j -
1]
is
None
or pts[track.track_id][j]
is
None:
-
continue
-
thickness =
int(np.sqrt(
64 /
float(j +
1)) *
2)
-
cv2.line(frame, (pts[track.track_id][j -
1]), (pts[track.track_id][j]), (
0,
255,
255), thickness)
-
-
return tracker,pts
-
-
-
-
if __name__ ==
"__main__":
-
-
yolo = YOLO()
-
####设置跟踪参数###
-
max_cosine_distance =
0.5
-
nn_budget =
20
-
metric = nn_matching.NearestNeighborDistanceMetric(
"cosine", max_cosine_distance,
-
nn_budget)
# 最近邻距离度量,对于每个目标,返回到目前为止已观察到的任何样本的最近距离(欧式或余弦)。
-
tracker = Tracker(metric)
# 由距离度量方法构造一个 Tracker。
-
writeVideo_flag =
False
-
###轨迹点定义##
-
pts = [deque(maxlen=
30)
for _
in
range(
9999)]
-
model_filename =
'./model_data/mars-small128.pb'
###DeepSort 模型位置##
-
encoder = gdet.create_box_encoder(model_filename, batch_size=
1)
-
Obj_centre = [[]
for i
in
range(
200)]
-
Obj_pre_direction = [[]
for i
in
range(
200)]
-
ShowFlag =
True
##是否显示结果
-
####打开摄像机###
-
# 创建VideoCapture,传入0即打开系统默认摄像头
-
# cap = cv2.VideoCapture(0)
-
#######读取视频######################################
-
video_path =
'structure.mp4'
-
video_capture = cv2.VideoCapture(video_path)
-
key =
''
-
count =
0
-
save_path =
'./saveimg/'
-
-
while key !=
113:
# for 'q' key
-
###读取图像###
-
ret, frame = video_capture.read()
-
#######目标检测########################
-
frame2 = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGRA2RGBA))
-
boxs_person,boxs_others,labels_others = yolo.detect_image(frame2)
-
-
#######目标跟踪########################
-
tracker, pts = track_deepsort(frame, boxs_person, boxs_others, labels_others, encoder, tracker, pts)
-
#######显示检测及跟踪结果####
-
cv2.namedWindow(
"YOLO3_Deep_SORT",
0)
-
cv2.resizeWindow(
'YOLO3_Deep_SORT',
1024,
768)
-
cv2.imshow(
'YOLO3_Deep_SORT', frame)
-
cv2.waitKey(
3)
-
count +=
1
-
jpg_name = os.path.join(save_path,
str(count).zfill(
6)+
'.jpg')
-
cv2.imwrite(jpg_name,frame)
-
-
-
-
-
四、实战效果评价
结果显示,在目标检测环节,当人群交叉 光照突变时可能出现漏检的现象,这将导致目标跟踪环节出现跟踪错误,应该进一步地调整目标跟踪策略,使目标跟踪算法具有鲁棒性,尤其是解决人员聚集情况下的目标跟踪问题
创作不易 觉得有帮助请点赞关注收藏~~~
转载:https://blog.csdn.net/jiebaoshayebuhui/article/details/128268985