【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)

四、实战效果评价

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

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

相关文章
|
3月前
|
机器学习/深度学习 监控 算法
基于计算机视觉(opencv)的运动计数(运动辅助)系统-源码+注释+报告
基于计算机视觉(opencv)的运动计数(运动辅助)系统-源码+注释+报告
80 3
|
2月前
|
机器学习/深度学习 TensorFlow API
机器学习实战:TensorFlow在图像识别中的应用探索
【10月更文挑战第28天】随着深度学习技术的发展,图像识别取得了显著进步。TensorFlow作为Google开源的机器学习框架,凭借其强大的功能和灵活的API,在图像识别任务中广泛应用。本文通过实战案例,探讨TensorFlow在图像识别中的优势与挑战,展示如何使用TensorFlow构建和训练卷积神经网络(CNN),并评估模型的性能。尽管面临学习曲线和资源消耗等挑战,TensorFlow仍展现出广阔的应用前景。
84 5
|
2月前
|
机器学习/深度学习 人工智能 TensorFlow
基于TensorFlow的深度学习模型训练与优化实战
基于TensorFlow的深度学习模型训练与优化实战
118 0
|
5月前
|
机器学习/深度学习 存储 前端开发
实战揭秘:如何借助TensorFlow.js的强大力量,轻松将高效能的机器学习模型无缝集成到Web浏览器中,从而打造智能化的前端应用并优化用户体验
【8月更文挑战第31天】将机器学习模型集成到Web应用中,可让用户在浏览器内体验智能化功能。TensorFlow.js作为在客户端浏览器中运行的库,提供了强大支持。本文通过问答形式详细介绍如何使用TensorFlow.js将机器学习模型带入Web浏览器,并通过具体示例代码展示最佳实践。首先,需在HTML文件中引入TensorFlow.js库;接着,可通过加载预训练模型如MobileNet实现图像分类;然后,编写代码处理图像识别并显示结果;此外,还介绍了如何训练自定义模型及优化模型性能的方法,包括模型量化、剪枝和压缩等。
88 1
|
5月前
|
机器学习/深度学习 数据采集 TensorFlow
使用TensorFlow进行模型训练:一次实战探索
【8月更文挑战第22天】本文通过实战案例详解使用TensorFlow进行模型训练的过程。首先确保已安装TensorFlow,接着预处理数据,包括加载、增强及归一化。然后利用`tf.keras`构建卷积神经网络模型,并配置训练参数。最后通过回调机制训练模型,并对模型性能进行评估。此流程为机器学习项目提供了一个实用指南。
|
4月前
|
机器学习/深度学习 数据挖掘 TensorFlow
解锁Python数据分析新技能,TensorFlow&PyTorch双引擎驱动深度学习实战盛宴
在数据驱动时代,Python凭借简洁的语法和强大的库支持,成为数据分析与机器学习的首选语言。Pandas和NumPy是Python数据分析的基础,前者提供高效的数据处理工具,后者则支持科学计算。TensorFlow与PyTorch作为深度学习领域的两大框架,助力数据科学家构建复杂神经网络,挖掘数据深层价值。通过Python打下的坚实基础,结合TensorFlow和PyTorch的强大功能,我们能在数据科学领域探索无限可能,解决复杂问题并推动科研进步。
80 0
|
5月前
|
API UED 开发者
如何在Uno Platform中轻松实现流畅动画效果——从基础到优化,全方位打造用户友好的动态交互体验!
【8月更文挑战第31天】在开发跨平台应用时,确保用户界面流畅且具吸引力至关重要。Uno Platform 作为多端统一的开发框架,不仅支持跨系统应用开发,还能通过优化实现流畅动画,增强用户体验。本文探讨了Uno Platform中实现流畅动画的多个方面,包括动画基础、性能优化、实践技巧及问题排查,帮助开发者掌握具体优化策略,提升应用质量与用户满意度。通过合理利用故事板、减少布局复杂性、使用硬件加速等技术,结合异步方法与预设缓存技巧,开发者能够创建美观且流畅的动画效果。
100 0
|
5月前
|
UED 开发工具 iOS开发
Uno Platform大揭秘:如何在你的跨平台应用中,巧妙融入第三方库与服务,一键解锁无限可能,让应用功能飙升,用户体验爆棚!
【8月更文挑战第31天】Uno Platform 让开发者能用同一代码库打造 Windows、iOS、Android、macOS 甚至 Web 的多彩应用。本文介绍如何在 Uno Platform 中集成第三方库和服务,如 Mapbox 或 Google Maps 的 .NET SDK,以增强应用功能并提升用户体验。通过 NuGet 安装所需库,并在 XAML 页面中添加相应控件,即可实现地图等功能。尽管 Uno 平台减少了平台差异,但仍需关注版本兼容性和性能问题,确保应用在多平台上表现一致。掌握正确方法,让跨平台应用更出色。
69 0
|
5月前
|
安全 Apache 数据安全/隐私保护
你的Wicket应用安全吗?揭秘在Apache Wicket中实现坚不可摧的安全认证策略
【8月更文挑战第31天】在当前的网络环境中,安全性是任何应用程序的关键考量。Apache Wicket 是一个强大的 Java Web 框架,提供了丰富的工具和组件,帮助开发者构建安全的 Web 应用程序。本文介绍了如何在 Wicket 中实现安全认证,
54 0
|
5月前
|
机器学习/深度学习 数据采集 TensorFlow
从零到精通:TensorFlow与卷积神经网络(CNN)助你成为图像识别高手的终极指南——深入浅出教你搭建首个猫狗分类器,附带实战代码与训练技巧揭秘
【8月更文挑战第31天】本文通过杂文形式介绍了如何利用 TensorFlow 和卷积神经网络(CNN)构建图像识别系统,详细演示了从数据准备、模型构建到训练与评估的全过程。通过具体示例代码,展示了使用 Keras API 训练猫狗分类器的步骤,旨在帮助读者掌握图像识别的核心技术。此外,还探讨了图像识别在物体检测、语义分割等领域的广泛应用前景。
52 0

热门文章

最新文章