关于深度学习:基于yolov5框架实现人流统计目标检测算法目标追踪算法以及越界识别功能手机获取统计人数

38次阅读

共计 9487 个字符,预计需要花费 24 分钟才能阅读完成。

次要实现的 AI 算法有:指标检测、指标追踪

次要实现 AI 算法性能:越界辨认性能(次要是获取统计人流量)

平台:基于 Aidlux 平台

根底库装置:
(1)lap 装置:
先 sudo apt-get update,再输出 sudo apt-get install -y cmake build-essential python3-dev;最初 pip install lap -i https://pypi.tuna.tsinghua.ed…。
(2)cython_bbox 装置:
先装置 cython:pip install cython -i https://pypi.tuna.tsinghua.ed…
再装置 cython_bbox:pip install cython_bbox -i https://pypi.tuna.tsinghua.ed…
(3)torch 装置:
pip install torch -i https://pypi.tuna.tsinghua.ed…,如果有装置过则跳过。
(4)torchvision 装置:
pip install torchvision -i https://pypi.tuna.tsinghua.ed…,如果有装置过,则跳过。
(5)thop 装置:
pip install thop -i https://pypi.tuna.tsinghua.ed…

一、前提:

咱们通常学习的 AI 视觉算法,次要是底层的利用技术,比方指标检测、人脸识别、图像宰割、关键点检测、语音辨认、OCR 辨认等算法。通常而言,在各个行业理论利用中,不同的场景,对应不同的算法性能,而不同的算法性能则由不同利用技术组合而成。如下图:

而明天这个人流量的统计利用次要用到的 AI 算法性能是越界辨认,它次要是由基于 yolov5 框架的指标检测算法和基于 Bytetrack 多指标追踪算法(当然应用 Deepsort 多指标追踪算法也是能够的)

以下是论文地址分享:

Deepsort 多指标追踪算法论文 PDF:

http://extension//idghocbbaha…

Bytetrack 多指标追踪算法论文 PDF:

http://extension//idghocbbaha…

代码实现:

指标检测模块(次要是基于 yolov5):
关上 yolov5.py 进行视频推理测试

# aidlux 相干
from cvs import *
import aidlite_gpu
from utils import detect_postprocess, preprocess_img, draw_detect_res
 
import time
import cv2
 
# AidLite 初始化:调用 AidLite 进行 AI 模型的加载与推理,需导入 aidlite
aidlite = aidlite_gpu.aidlite()
# Aidlite 模型门路
model_path = '/home/lesson4_codes/aidlux/yolov5n_best-fp16.tflite'
# 定义输入输出 shape
in_shape = [1 * 640 * 640 * 3 * 4]
out_shape = [1 * 25200 * 6 * 4]
# 加载 Aidlite 检测模型:反对 tflite, tnn, mnn, ms, nb 格局的模型加载
aidlite.ANNModel(model_path, in_shape, out_shape, 4, 0)
 
cap = cvs.VideoCapture("/home/lesson4_codes/aidlux/market.mp4")
frame_id = 0
while True:
    frame = cap.read()
    if frame is None:
        continue
    frame_id += 1
    if not int(frame_id) % 5 == 0: continue
    # 预处理
    img = preprocess_img(frame, target_shape=(640, 640), div_num=255, means=None, stds=None)
    # 数据转换:因为 setTensor_Fp32()须要的是 float32 类型的数据,所以送入的 input 的数据需为 float32, 大多数的开发者都会遗记将图像的数据类型转换为 float32
    aidlite.setInput_Float32(img, 640, 640)
    # 模型推理 API
    aidlite.invoke()
    # 读取返回的后果
    pred = aidlite.getOutput_Float32(0)
    # 数据维度转换
    pred = pred.reshape(1, 25200, 6)[0]
    # 模型推理后处理
    pred = detect_postprocess(pred, frame.shape, [640, 640, 3], conf_thres=0.5, iou_thres=0.45)
    # 绘制推理后果
    res_img = draw_detect_res(frame, pred)
    cvs.imshow(res_img)

成果截图:

标签中的 person 代表是人,分数代表的是置信度也等同于说这个框内的物体是人的概率值。

指标追踪模块(次要是基于 Bytetrack 多指标追踪算法):

关上 yolov5_bytetrack.py 进行视频推理测试

from cvs import *
import aidlite_gpu
from utils import detect_postprocess, preprocess_img, draw_detect_res #scale_coords,process_points,isInsidePolygon,is_in_poly
import cv2
# bytetrack
from track.tracker.byte_tracker import BYTETracker
from track.utils.visualize import plot_tracking
 
 
# 加载模型
model_path = r'/home/lesson5_codes/aidlux/yolov5n_best-fp16.tflite'
in_shape = [1 * 640 * 640 * 3 * 4]
out_shape = [1 * 25200 * 6 * 4]
 
# 载入模型
aidlite = aidlite_gpu.aidlite()
# 载入 yolov5 检测模型
aidlite.ANNModel(model_path, in_shape, out_shape, 4, 0)
 
tracker = BYTETracker(frame_rate=30)
track_id_status = {}
cap = cvs.VideoCapture(r"/home/lesson5_codes/aidlux/videotest1.mp4")
frame_id = 0
while True:
    frame = cap.read()
    if frame is None:
        continue
    frame_id += 1
    if frame_id % 3 != 0:
        continue
     # 预处理
    img = preprocess_img(frame, target_shape=(640, 640), div_num=255, means=None, stds=None)
    # 数据转换:因为 setTensor_Fp32()须要的是 float32 类型的数据,所以送入的 input 的数据需为 float32, 大多数的开发者都会遗记将图像的数据类型转换为 float32
    aidlite.setInput_Float32(img, 640, 640)
    # 模型推理 API
    aidlite.invoke()
    # 读取返回的后果
    pred = aidlite.getOutput_Float32(0)
    # 数据维度转换
    pred = pred.reshape(1, 25200, 6)[0]
    # 模型推理后处理
    pred = detect_postprocess(pred, frame.shape, [640, 640, 3], conf_thres=0.4, iou_thres=0.45)
    # 绘制推理后果
    res_img = draw_detect_res(frame, pred)
 
    # 指标追踪相干性能
    det = []
    # Process predictions
    for box in pred[0]:  # per image
        box[2] += box[0]
        box[3] += box[1]
        det.append(box)
    if len(det):
        # Rescale boxes from img_size to im0 size
        online_targets = tracker.update(det, [frame.shape[0], frame.shape[1]])
        online_tlwhs = []
        online_ids = []
        online_scores = []
        # 取出每个指标的追踪信息
        for t in online_targets:
            # 指标的检测框信息
            tlwh = t.tlwh
            # 指标的 track_id 信息
            tid = t.track_id
            online_tlwhs.append(tlwh)
            online_ids.append(tid)
            online_scores.append(t.score)
            # 针对指标绘制追踪相干信息
            res_img = plot_tracking(res_img, online_tlwhs, online_ids, 0,0)
    cvs.imshow(res_img)

成果截图:
![上传中 …]()
标签上的蓝色数字为 track_id,能够了解为每个人框的 id 号,代表着一个物体,红色数字则为置信度。

实现人流数量统计性能:

将物体检测模块与物体追踪模块相结合:
代码如下:

from cvs import *
import aidlite_gpu
from utils import detect_postprocess, preprocess_img, draw_detect_res, process_points,is_passing_line    #scale_coords,isInsidePolygon,
import cv2
# bytetrack
from track.tracker.byte_tracker import BYTETracker
from track.utils.visualize import plot_tracking
import requests
import time
 
# 加载模型
model_path = '/home/lesson4_codes/aidlux/yolov5n_best-fp16.tflite'
in_shape = [1 * 640 * 640 * 3 * 4]
out_shape = [1 * 25200 * 6 * 4]
 
# 载入模型
aidlite = aidlite_gpu.aidlite()
# 载入 yolov5 检测模型
aidlite.ANNModel(model_path, in_shape, out_shape, 4, 0)
 
tracker = BYTETracker(frame_rate=30)
track_id_status = {}
cap = cvs.VideoCapture(r"/home/lesson5_codes/aidlux/videotest1.mp4")
frame_id = 0
count_person=0
while True:
    frame = cap.read()
    if frame is None:
        ### 相机采集后果 ###
        print("camer is over!")
        ### 统计打印人流数量 ###
        # 填写对应的喵码
        id = '******'
        # 填写喵揭示中,发送的音讯,这里放上后面提到的图片外链
        text = "人数统计:"+str(count_person)
        ts = str(time.time())  # 工夫戳
        type = 'json'  # 返回内容格局
        request_url = "http://miaotixing.com/trigger?"
        headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36 Edg/87.0.664.47'}
        result = requests.post(request_url + "id=" + id + "&text=" + text + "&ts=" + ts + "&type=" + type,headers=headers)
        break
    frame_id += 1
    if frame_id % 3 != 0:
        continue
     # 预处理
    img = preprocess_img(frame, target_shape=(640, 640), div_num=255, means=None, stds=None)
    # 数据转换:因为 setTensor_Fp32()须要的是 float32 类型的数据,所以送入的 input 的数据需为 float32, 大多数的开发者都会遗记将图像的数据类型转换为 float32
    aidlite.setInput_Float32(img, 640, 640)
    # 模型推理 API
    aidlite.invoke()
    # 读取返回的后果
    pred = aidlite.getOutput_Float32(0)
    # 数据维度转换
    pred = pred.reshape(1, 25200, 6)[0]
    # 模型推理后处理
    pred = detect_postprocess(pred, frame.shape, [640, 640, 3], conf_thres=0.4, iou_thres=0.45)
    # 绘制推理后果
    res_img = draw_detect_res(frame, pred)
 
    # 指标追踪相干性能
    det = []
    # Process predictions
    for box in pred[0]:  # per image
        box[2] += box[0]
        box[3] += box[1]
        det.append(box)
    if len(det):
        # Rescale boxes from img_size to im0 size
        online_targets = tracker.update(det, [frame.shape[0], frame.shape[1]])
        online_tlwhs = []
        online_ids = []
        online_scores = []
        # 取出每个指标的追踪信息
        for t in online_targets:
            # 指标的检测框信息
            tlwh = t.tlwh
            # 指标的 track_id 信息
            tid = t.track_id
            online_tlwhs.append(tlwh)
            online_ids.append(tid)
            online_scores.append(t.score)
            # 针对指标绘制追踪相干信息
            res_img = plot_tracking(res_img, online_tlwhs, online_ids, 0,0)
            ### 越界辨认性能实现 ###
            # 1. 绘制越界监测区域
            points = [[204,453],[1274,455]]
            color_light_green=(255, 0, 0)  ## 绿色
            res_img = process_points(res_img,points,color_light_green)
            
 
            # 2. 计算失去人体下方中心点的地位(人体检测监测点调整)pt = [tlwh[0]+1/2*tlwh[2],tlwh[1]+tlwh[3]]
            
            # 3. 人体和违规区域的判断(人体状态追踪判断)track_info = is_passing_line(pt, points)
            if tid not in track_id_status.keys():
                track_id_status.update({tid:[track_info]})
            else:
                if track_info != track_id_status[tid][-1]:
                    track_id_status[tid].append(track_info)
            # 4. 判断是否有 track_id 越界,有的话保留成图片
            # 当某个 track_id 的状态,上一帧是 -1,然而这一帧是 1 时,阐明越界了
            if track_id_status[tid][-1] == 1 and len(track_id_status[tid]) >1:
                # 判断上一个状态是否是 -1,是否的话阐明越界,为了避免持续判断,随机的赋了一个 3 的值
                if  track_id_status[tid][-2] == -1:
                    track_id_status[tid].append(3)
                    count_person+=1
    cv2.putText(res_img,"-1 to 1 person_count:"+str(count_person),(50,50),cv2.FONT_HERSHEY_SIMPLEX,1,(255,0,0),2)
    cvs.imshow(res_img)

实现成果:

每有一个人通过那条绿线,person_count 就会增 1,最初人数统计完后,会通过喵揭示性能,将统计人数发送到手机微信端:

其实整体实现的逻辑也很简略,次要分为五个局部:
(1)人流统计越界限段绘制

# 1. 绘制越界监测区域
            points = [[204,453],[1274,455]]
            color_light_green=(255, 0, 0)  ## 绿色
            res_img = process_points(res_img,points,color_light_green)

(2)人体检测统计点调整

次要剖析人体下方中心点,和人流统计线段的地位关系。检测框的四个点信息,[左上角点 x,左上角点 y,宽 w,高 h]。所以咱们须要通过代码,转换成人体下方的点,即[左上角点 x +1/2* 宽 w,左上角点 y + 高 h]。

# 2. 计算失去人体下方中心点的地位(人体检测监测点调整)pt = [tlwh[0]+1/2*tlwh[2],tlwh[1]+tlwh[3]]

3)人体和线段的地位状态判断
这里次要剖析人体下方点,和统计线段的地位关系,这部分的代码在 utils.py 的 is_passing_line 函数中。当人体在线段的下方时,人体状态是 -1。当人体在线段的上方时,人体状态是 1。

 # 3. 人体和违规区域的判断(人体状态追踪判断)track_info = is_passing_line(pt, points)
            if tid not in track_id_status.keys():
                track_id_status.update({tid:[track_info]})
            else:
                if track_info != track_id_status[tid][-1]:
                    track_id_status[tid].append(track_info)

(4)人流统计分析判断
那么当人体的状态,从 - 1 变动到 1 的时候,就统计成为人员越线了。

 4. 判断是否有 track_id 越界
            # 当某个 track_id 的状态,上一帧是 -1,然而这一帧是 1 时,阐明越界了
            if track_id_status[tid][-1] == 1 and len(track_id_status[tid]) >1:
                # 判断上一个状态是否是 -1,是否的话阐明越界,为了避免持续判断,随机的赋了一个 3 的值
                if  track_id_status[tid][-2] == -1:
                    track_id_status[tid].append(3)
                    count_person+=1

(5)喵揭示发送
当整个视频跑完后,就能够失去人流统计整体的数据了。为了及时晓得人流的信息状态,咱们也能够将最初的后果,以喵揭示的形式进行发送。

if frame is None:
        ### 相机采集后果 ###
        print("camer is over!")
        ### 统计打印人流数量 ###
        # 填写对应的喵码
        id = '******'
        # 填写喵揭示中,发送的音讯,这里放上后面提到的图片外链
        text = "人数统计:"+str(count_person)
        ts = str(time.time())  # 工夫戳
        type = 'json'  # 返回内容格局
        request_url = "http://miaotixing.com/trigger?"
        headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.67 Safari/537.36 Edg/87.0.664.47'}
        result = requests.post(request_url + "id=" + id + "&text=" + text + "&ts=" + ts + "&type=" + type,headers=headers)
        break

目前只是简略的介绍了各个模块的相应性能,因为篇幅较多,后续会对每个相应模块进行搭建和具体代码解释。

学习心得

刚开始进行代码实际操作时,对我的项目的搭建有点吃力,尤其是刚开始对 AidLux 平台中的环境配置时,因为第一次应用,不太熟悉操作,破费了很多工夫,不过幸好江大白老师十分急躁的给予解答,才事倍功半,同时通过一阵子的学习也造就了我 debug 程序的能力,这段时间通过对 yolo 框架源码的学习以及论文的浏览,大大的进步了我对 yolo 框架的认知和应用(尽管用的并不是那么纯熟)

AidLux 应用心得

先介绍下什么是 AidLux?
本次人流统计我的项目应用到了 AidLux 平台,等同于大家所说的边缘设施,尽管用的是边缘设施,然而却是以安卓和 Linux 双系统的形式,只应用 Python 就能对算法减速优化。通常 AI 我的项目边缘设施落地计划有很多,AI 边缘设施是十分重要的算力载体设施。其中十分要害的,就是 AI 芯片,当然市面上的销售形式,次要有两种:

(1)AI 芯片模组:公司自研 AI 芯片,比方寒武纪,对外销售的次要是 AI 芯片模组,由一些内部的设施公司再集成到边缘设施或者工控机,以设施公司的品牌对外销售;

(2)AI 边缘设施:以销售 AI 边缘设施为主,比方英伟达,算能科技,阿加犀。通常会自研或者洽购 AI 芯片,并以 AI 边缘设施的状态对外销售,为很多 AI 解决方案公司提供算力设施;当然其中的一些自研 AI 芯片的公司,除了边缘设施之外,也会提供 AI 芯片 / 模组方面的产品,间接对外销售,比方算能科技。

当然一般来说,想要玩转边缘设施,通常会开发一整套的视频结构化性能。通过 C ++ 的形式调用算力,将须要解决的结构化信息输入,比方编程 Json 模式,为前面的业务解决提供剖析的信息。惯例来说,市面上所有的边缘设施,次要是以 C ++ 的形式来进行开发。不过这里应用的另外一种边缘设施开发的计划,即以 Python 的形式。益处在于,算法工程师应用 Python 开发的模型,能够间接无缝连接来持续开发利用了。比方采纳 AidBox GS865 边缘设施。

这里所说的边缘设施 AidBox,次要是采纳高通 ARM 端芯片开发的。不过咱们在学习的时候,都没有 AidBox 边缘设施硬件。因而也能够采纳另外一种思路,即 AidLux 边缘设施软件,这个环境和事实的边缘计算设施 AidBox 根本一样。

当然 AidLux 中还存在着一些小 bug 和适配的问题,比方我的手机是安卓 12 的,当 AidLux 后端运行时经常会被手机零碎清理掉,就算我设置为白名单也不行。前面须要应用开发者调试进行批改。当运行了代码时,你会在手机版本的 Aidlux 和 PC 端网页的 Aidlux 中,都能够看到推理的显示后果,须要留神的是,在运行的时候,须要把手机版本外面的 aidlux 页面叉掉,不然可能会有抵触,运行的线程会间接被 killed 掉。刚开始我就是没留神到这点,十分苦楚的在那儿找错。

正文完
 0