利用Aidlux落地双向AI人流统计项目的实战心得

1 训练营课程

(1)本节课主要学习智慧安防实战训练营的课程:https://mp.weixin.qq.com/s/3WrTMItNAGt8l2kjjf042w

(2)学习目的

题主研究方向正好是边缘计算相关,最近研究的内容也正好是目标检测相关的内容,之前师兄给我提过尝试使用一下tensorflowlite去在手机上尝试跑一下一些简单的模型,题主尝试后奈何自己是人工智能专业出身,没有接触过Android开发,因此使用过程中遇到很多困难,最后也不了了之了。正好这个时候看到大白发布的实战课程,看了相关的介绍后感觉和我的需求比较接近,正好接触一下边缘计算相关部署的实战项目,因此便报名了。

2 作业题目

(1)题目:

在学习了越界识别的功能后,采用人体检测+人体追踪+业务功能的方式实现人流统计。

(2)实现效果:

Aidlux平台实现人流统计

视频录制的是单向的人流统计,后面修改了代码,可以实现双向的人流统计。

(3)代码实现:

# aidlux相关
from cvs import *
import aidlite_gpu
from utils import detect_postprocess, preprocess_img, draw_detect_res,is_passing_line
import cv2
# bytetrack
from track.tracker.byte_tracker import BYTETracker
from track.utils.visualize import plot_tracking
import requests
import time


# 加载模型
model_path = '/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("/home/lesson5_codes/aidlux/video.mp4")
frame_id = 0
count_person_1 = 0
count_person_2 = 0
while True:
    frame = cap.read()
    if frame is None:
        ###  相机采集结束 ###
        print("camera is over!")
        ### 统计打印人流数量 ###
        # 填写对应的喵码
        id = 'tv1OWTC'
        # 填写喵提醒中,发送的消息,这里放上前面提到的图片外链
        text = "人流统计数(-1到1):" + str(count_person_1) + "人流统计数(1到-1):" + str(count_person_2)
        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.绘制统计人流线
            lines = [[186, 249], [1235, 366]]
            cv2.line(res_img,(186, 249), (1235, 366), (255, 255, 0), 3)

            # 2.计算得到人体下方中心点的位置(人体检测监测点调整)
            pt = [tlwh[0]+1/2*tlwh[2],tlwh[1]+tlwh[3]]
            
            # 3. 人体和违规区域的判断(人体状态追踪判断)
            track_info = is_passing_line(pt, lines)
            
            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 += 1
            
            # 当某个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_2 += 1
    cv2.putText(res_img, "-1 to 1 person_count:" + str(count_person_1), (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 255), 2)
    cv2.putText(res_img, "1 to -1 person_count:" + str(count_person_2), (50, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 255), 2)
    cvs.imshow(res_img)

3 学习心得

由于题主是科班出身,大部分代码内容是比较熟悉的,加上大白老师细致的图文直播(这点非常支持,个人感觉图文教程的形式非常适合,个人也比较偏好这种形式),整个实践过程中基本没有遇到什么困难,实践过程中所使用的yolo,bytetrack,opencv等主要模块之前都过一些相应的使用经验,整个项目中最大的收获还是接触到了aidlux的这个平台,整个平台在使用过程中几乎没有遇到过bug,唯一遇到的问题是偶尔出现过几次连接丢失的问题(可能是题主手机的问题),整体的使用体验是非常良好的。同时也是在整个项目中第一次接触到了使用vscode远程调试手机上的代码,受益匪浅。

4 AidLux使用心得

整个项目体验下来,对Aidlux平台最大的感觉是简单易用,在将安卓设备变成边缘端设备进行AI处理的基础上,不同于tensorflow官方这种平台操作复杂,Aidlux给我的感觉就是部署简单,同时对于新手友好,训练营中许多对相关项目不熟悉的同学也能比较轻松的上手进行实验,虽然这也可能归功于大白老师简单却不繁琐的指导。这样的易上手性,对于平台的广泛推广来说,是非常重要的。

个人改进意见:想法可能不是很成熟感觉平台可以继续往更易上手的方向发展?比如提供一些相关训练好了的轻量化模型,以及可以选配的模块化设置,从而使得整个项目部署的过程更加平民化?

你可能感兴趣的:(人工智能)