【Keras+计算机视觉+Tensorflow】实现基于YOLO和Deep Sort的目标检测与跟踪实战(附源码和数据集)

简介: 【Keras+计算机视觉+Tensorflow】实现基于YOLO和Deep Sort的目标检测与跟踪实战(附源码和数据集)

需要源码和数据集请点赞关注收藏后评论区留言私信~~~

一、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)

四、实战效果评价

结果显示,在目标检测环节,当人群交叉 光照突变时可能出现漏检的现象,这将导致目标跟踪环节出现跟踪错误,应该进一步地调整目标跟踪策略,使目标跟踪算法具有鲁棒性,尤其是解决人员聚集情况下的目标跟踪问题

创作不易  觉得有帮助请点赞关注收藏~~~

相关文章
|
4月前
|
机器学习/深度学习 TensorFlow 算法框架/工具
深度学习之格式转换笔记(三):keras(.hdf5)模型转TensorFlow(.pb) 转TensorRT(.uff)格式
将Keras训练好的.hdf5模型转换为TensorFlow的.pb模型,然后再转换为TensorRT支持的.uff格式,并提供了转换代码和测试步骤。
129 3
深度学习之格式转换笔记(三):keras(.hdf5)模型转TensorFlow(.pb) 转TensorRT(.uff)格式
|
1天前
|
机器学习/深度学习 PyTorch TensorFlow
深度学习工具和框架详细指南:PyTorch、TensorFlow、Keras
在深度学习的世界中,PyTorch、TensorFlow和Keras是最受欢迎的工具和框架,它们为研究者和开发者提供了强大且易于使用的接口。在本文中,我们将深入探索这三个框架,涵盖如何用它们实现经典深度学习模型,并通过代码实例详细讲解这些工具的使用方法。
|
4月前
|
机器学习/深度学习 TensorFlow API
使用 TensorFlow 和 Keras 构建图像分类器
【10月更文挑战第2天】使用 TensorFlow 和 Keras 构建图像分类器
|
4月前
|
机器学习/深度学习 移动开发 TensorFlow
深度学习之格式转换笔记(四):Keras(.h5)模型转化为TensorFlow(.pb)模型
本文介绍了如何使用Python脚本将Keras模型转换为TensorFlow的.pb格式模型,包括加载模型、重命名输出节点和量化等步骤,以便在TensorFlow中进行部署和推理。
196 0
|
5月前
|
人工智能 并行计算 PyTorch
AI计算机视觉笔记十八:Swin Transformer目标检测环境搭建
本文详细记录了Swin Transformer在AutoDL平台上的环境搭建与训练过程。作者从租用GPU实例开始,逐步介绍了虚拟环境的创建、PyTorch安装、mmcv及mmdetection的配置,并解决了安装过程中遇到的各种问题,如cython版本冲突等。最后,通过修改代码实现目标检测结果的保存。如需了解更多细节或获取完整代码,请联系作者。原文链接:[原文链接](请在此处插入原文链接)。
|
5月前
|
机器学习/深度学习 人工智能 算法
AI计算机视觉笔记十一:yolo5+Deepsort实现目标检测与跟踪(CPU版)
DeepSORT是一种基于深度学习的计算机视觉跟踪算法,扩展了SORT算法,通过添加外观描述符减少身份切换,提高跟踪效率。本文档提供了DeepSORT环境搭建步骤,包括创建虚拟环境、安装依赖及解决常见错误等,最终实现人员和车辆的跟踪计数功能。适合无GPU设备的学习者参考。
|
6月前
|
UED 开发工具 iOS开发
Uno Platform大揭秘:如何在你的跨平台应用中,巧妙融入第三方库与服务,一键解锁无限可能,让应用功能飙升,用户体验爆棚!
【8月更文挑战第31天】Uno Platform 让开发者能用同一代码库打造 Windows、iOS、Android、macOS 甚至 Web 的多彩应用。本文介绍如何在 Uno Platform 中集成第三方库和服务,如 Mapbox 或 Google Maps 的 .NET SDK,以增强应用功能并提升用户体验。通过 NuGet 安装所需库,并在 XAML 页面中添加相应控件,即可实现地图等功能。尽管 Uno 平台减少了平台差异,但仍需关注版本兼容性和性能问题,确保应用在多平台上表现一致。掌握正确方法,让跨平台应用更出色。
83 0
|
6月前
|
Apache 开发者 Java
Apache Wicket揭秘:如何巧妙利用模型与表单机制,实现Web应用高效开发?
【8月更文挑战第31天】本文深入探讨了Apache Wicket的模型与表单处理机制。Wicket作为一个组件化的Java Web框架,提供了多种模型实现,如CompoundPropertyModel等,充当组件与数据间的桥梁。文章通过示例介绍了模型创建及使用方法,并详细讲解了表单组件、提交处理及验证机制,帮助开发者更好地理解如何利用Wicket构建高效、易维护的Web应用程序。
80 0
|
9月前
|
机器学习/深度学习 计算机视觉
AIGC核心技术——计算机视觉(CV)预训练大模型
【1月更文挑战第13天】AIGC核心技术——计算机视觉(CV)预训练大模型
708 3
AIGC核心技术——计算机视觉(CV)预训练大模型
|
5月前
|
人工智能 测试技术 API
AI计算机视觉笔记二十 九:yolov10竹签模型,自动数竹签
本文介绍了如何在AutoDL平台上搭建YOLOv10环境并进行竹签检测与计数。首先从官网下载YOLOv10源码并创建虚拟环境,安装依赖库。接着通过官方模型测试环境是否正常工作。然后下载自定义数据集并配置`mycoco128.yaml`文件,使用`yolo detect train`命令或Python代码进行训练。最后,通过命令行或API调用测试训练结果,并展示竹签计数功能。如需转载,请注明原文出处。