关于深度学习:基于AidLux平台的医院出入口人流量统计案例的开发与测试

1、环境配置

1.1、跨平台零碎利用设置
AIdlux零碎是基于ARM架构的跨生态(Android/鸿蒙+Linux)一站式AIOT利用开发平台。理论利用到现场的时候,通常会以几种状态:GPU服务器、嵌入式设 备(比方Android手机、人脸识别闸机等)、边缘设施。GPU服务器等,而Android 嵌入式设施的底层芯片,通常是ARM架构。而Linux底层也是ARM架构,并且Android又是 基于Linux内核开发的操作系统,两者能够共享Linux内核。因而就产生了从底层开发一套利用零碎的形式,在此基础上同时带来原生Android和原生Linux应用体验。所以在基于Linux零碎和ARM架构上,咱们能够在安卓手机上间接下载Aidlux软件,应用安卓手机充当边缘设施,进行代码的调试与案例的实现。

图1
1.2、软件下载
安卓手机关上利用市场搜寻AidLux软件并下载,这里须要满足以下的条件:

●Android 版本≥6.0.1(目前只有安卓零碎兼容,鸿蒙3.0零碎设置须要在AidLux在 Android12/鸿蒙3 服务过程被杀解决方案- AidLux开发者社区查看,大家有任何问题都能够在社区留言的,会有工程师来帮忙解决。)

●cpu 反对arm64-v8a架构

●手机存储空间短缺

●1.0以上版本须要装置空间>600M

●初始化空间>1.7G

1.3、手机端相干软件的设置
下载实现后–>应用本人的手机号进行注册(图2)–>零碎开始初始化–>进入登录界面–>应用cloud_ip中的网址进行映射到电脑网页(留神:安卓手机和电脑要在同一个局域网下,并且留神网站别输错,比方http://192.164.42.42:8000,这里的http后没有s,如果不行的话,换成手机热点连贯。)–>输出网站进入电脑端(初始密码为aidlux)。

1.4、电脑端下载VScode软件
VScode 在官网https://code.visualstudio.com/点击download进行下载,官网下载可能速度会很慢,解决办法看这篇文章vscode下载办法,下载实现后,依照提醒步骤始终进行实现装置就能够了。

图2

1.5、VScode的相干环境的配置
1.装置本地版的python与opencv,点击extensions,进入搜寻栏输出python,点击install,期待下载实现即可。

再下载一个Remote-SSH,同样的步骤,在前面连贯手机端Aidlux时会用到。

图3
2.装置opencv
在深度学习中,opencv是图像界面的十分重要的软件,咱们这里关上软件左上方菜单栏的Terminal终端,点击New Terminal ,而后输出pip install opencv-python -i https://pypi.tuna.Tsinghua.ed…进行包的下载。

3.测试
创立一个python文件video_pc.py,在同一个文件夹下放入检测文件,我这里是jiankong.mp4,之后点击RUN->RUN without debugging进行运行,运行失常,页面会呈现你的监控文件的画面。

##此代码用于测试本地的环境是否配置实现
#导入库
import cv2

cap = cv2.VideoCapture("jiankong.mp4")  #这里输出检测文件
frame_id = 0
while cap.isOpened():
    ok, image = cap.read()
    if not ok:
        print("Camera cap over!")
        continue
    frame_id += 1
    if not int(frame_id) % 5 == 0: continue
    image = cv2.resize(image,(900,600))
    cv2.imshow("image",image)
    cv2.waitKey(5)  #调整读帧速度

2、PC端近程调试AidLux
在第一节中咱们实现了根本的手机端与PC端的环境的利用,接下来咱们就是应用PC端作为次要的窗口来对Aidlux进行近程的代码编写与调试。

2.1、VScode近程连贯Aidlux
之前曾经在本地下载了Remote-SSH,接下来咱们点击Remote Explorer,如图4,点击左下角的“Open a Remote Window”(图5),再抉择“Open SSH Configuration file”(图6)

图4

图5

图6

图7

图8
上面对config进行配置

##配置config
# Read more about SSH config files: https://linux.die.net/man/5/ssh_config
Host AidLux   #服务器别名个别不须要改变
    HostName 192.168.43.43  #这是你的cloud_ip地址
    Port 9022    #这里将8000改为9022
    User root    #近程登录的用户名,个别默认即可

保留,之后在左侧框里会生成一个SSH服务器,鼠标放在下面,他的右侧会呈现一个文件夹一样的图标,点击它,而后会弹出框,抉择Linux,点击抉择“Continue”,再输出明码,aidlux,回车。当左下角呈现SSH AidLux是示意与手机端连贯胜利。
到这里,电脑端VScode与手机的Aidlux曾经连贯好了,上面就是开始执行并实现咱们的案例了。

3、AI案例:医院出入口人流量统计

医院出入口的人流量统计能够分为⼈体检测+⼈体追踪+人流统计三个方面进行串联实现。

3.1、筹备数据集
在本次的案例中,咱们应用的是旷视的Crowdhuamn数据集,官网http://www.crowdhuman.org/去下载,Crowdhuman数据集,总共蕴含三个子数据集:15000张的训练数据集,4370张的验证数据集,5000张的测试数据集。其中训练集和验证集都是有标注信息的,测试集没有标注信息。

图9

1.数据集格局的转换:

在本次的案例中,咱们选用了4370张的val数据集来做为训练集,咱们晓得在不同的代码中进行检测是须要将数据集的格局转换为所选训练模型对应的格局,这里Crowhuman数据集的val数据集的标注为annotation_val.odgt,接下来咱们须要进行数据集格局的转换(咱们这里先将其转换为VOC格局,在将其转换为txt格局),这里,为了节约工夫,咱们能够间接关注“”AidLux“”公众号,回复lesson3,取得了lesson3材料包的连贯之后进入百度网盘进行下载。下载后如图10

图10

在VScode中点击”File”,而后点击“open Folder”,点击下载好的lesson3进入lesson3_codes文件夹,在进入data_prepare_code关上data_code.py文件。

from xml.dom import minidom
import cv2
import os
import json
from PIL import Image
 #将这里的门路改为本人的对应文件门路
roadlabels = "E:/360MoveData/Users/26337/Desktop/Lesson3/lesson3_data/Crowdhuman_data/Annotations" 
roadimages = "E:/360MoveData/Users/26337/Desktop/Lesson3/lesson3_data/Crowdhuman_data/JPEGImages"
fpath = "E:/360MoveData/Users/26337/Desktop/Lesson3/lesson3_data/Crowdhuman_data/annotation_val.odgt"
 ........

之后点击运行,生成一系列的xml文件

图11
在lesson3_data下新建一个文件夹train_data,,在其中再新建一个train和test文件夹,将之前的数据集中的val验证集和Annotations,别离复制到train_data下的train文件夹中别离命名为JPEGImages和Annotations

关上data_prepare_code下的train_data_split.py,咱们分阶段运行代码,会在train_data中别离保留了train文件以及test文件,train_txt以及test_txt。

##依照上面的步骤一个阶段一个阶段顺次执行
def get_image_txt(opt):
   ##分阶段运行,不要全副一起运行,不运行时将其与性能的代码正文掉

    ## 阶段一:对于数据集进行荡涤梳理
    # 第一步:依据images_label_split中的图像删除多余的xml
    print("V1")
    compare_image_label_remove_xml(opt.train_data)
    # # # 第二步:依据images_label_split中的图像删除多余的image
    print("V2")
    compare_image_label_remove_image(opt.train_data)
    # # 第三步:将各个文件夹中的xml不满足条件的文件删除
    print("V3")
    remove_not_satisfied_xml(opt.train_data)
    # # 第四步:查找xml是否为空,空的话删除xml,也删除对应的image
    print("V4")
    remove_image_null_xml(opt.train_data,label_list)
    # # 第五步:对照image和xml中数据,显示图片看画得框是否正确
    show_label(opt.train_data,label_list)


    ## 阶段二:将数据依照肯定比例分成训练和验证集 
    # 将train和test随机离开,将image和xml别离保留到train和test所在的文件夹中
    # 依据后面能够失去xml和image,每个场景下抉择10%的数据,作为验证集, 生成train和test两个文件夹
    #yolov3_get_train_test_file(opt.train_data,0.2)

    ## 阶段三:将train和test的xml,转换成txt
    # 第一步:将train和test中的xml文件生成txt文件,都放到image_txt文件夹中
    #yolov3_get_txt(opt.train_data,label_list)
    # #  第二步:将所有的image文件一起挪动到image_txt中
    #yolov3_move_image(opt.train_data)
    # # 第三步:将train/Annotations和test/Annotations的xml主动生成train.txt和test.txt文件,并保留到train_test_txt中
    #yolov3_get_train_test_txt(opt.train_data)

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
#批改本人数据集所在的文件夹,能够间接找到文件夹复制其文件地址
    parser.add_argument('--train_data', type=str, default='E:/360MoveData/Users/26337/Desktop/Lesson3/lesson3_data/train_data', help='data dir')
    opt = parser.parse_args()
    get_image_txt(opt)

3.2、训练数据集

将train_data数据集和yolov5_code包进行打包发送到服务器的云端,对其一些文件的配置进行批改

1.关上yolov5_code包中的person.yaml(局部代码)

# Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
path: ./lesson3_data/train_data  # dataset root dir
train: image_txt  # train images (relative to 'path') 
val: image_val_txt  # val images (relative to 'path') 
#test: test-dev2017.txt  

# Classes
nc: 1  # number of classes
names: ['person']  # class names

2.关上yolov5s.yaml

批改其中的类别数量,因为人体就⼀个类别,批改成1

3.关上train.py,并进行批改(这里放上了须要批改的局部),咱们这里应用情轻量级的yolov5s.pt进行训练进行,须要提前去下载,(yolov5s权重 下载https://github.com/ultralytic…)批改数据门路,设置epoch为100。

def parse_opt(known=False):
    parser = argparse.ArgumentParser()
    parser.add_argument('--weights', type=str, default=ROOT / 'yolov5s.pt', help='initial weights path')
    parser.add_argument('--cfg', type=str, default='models/yolov5s.yaml', help='model.yaml path')
    parser.add_argument('--data', type=str, default=ROOT / 'data/person.yaml', help='dataset.yaml path')
    parser.add_argument('--hyp', type=str, default=ROOT / 'data/hyps/hyp.scratch-low.yaml', help='hyperparameters path')
    parser.add_argument('--epochs', type=int, default=100)
    parser.add_argument('--batch-size', type=int, default=16, help='total batch size for all GPUs, -1 for autobatch')
    parser.add_argument('--imgsz', '--img', '--img-size', type=int, default=640, help='train, val image size (pixels)')
    parser.add_argument('--rect', action='store_true', help='rectangular training')
.....

4.输出命令行:python train.py

5.可能会报一些没有库的错,(因为我的曾经装好了),能够先输出pip install -r requirements.txt,再运行看看。

切实有的安装包没有的,去清华镜像寻找https://pypi.tuna.tsinghua.ed… ,或者间接在终端输出pip3 install xxx -i https://pypi.tuna.tsinghua.ed…去下载xxx包。

6.运行完结后最优模型权重会放在runs/train/exp/weights/best.pt,将它下载下来,放入VScode的lesson3_code中的models文件夹下

3.3、转化best.pt为tensorflow格局
因为在Aidlux中次要运⾏的是tflite的⽅式,所以咱们须要将pt转化为tflite,关上lesson3_code中的eport.py

#批改如下
def parse_opt():
    parser = argparse.ArgumentParser()
    parser.add_argument('--data', type=str, default=ROOT / 'data/person.yaml', help='dataset.yaml path')
    parser.add_argument('--weights', nargs='+', type=str, default=ROOT / 'models/best.pt', help='model.pt path(s)')
    parser.add_argument('--imgsz', '--img', '--img-size', nargs='+', type=int, default=[640, 640], help='image (h, w)')
...

输出命令:pip3 install tensorflow -i https://pypi.tuna.Tsinghua.ed…,

下载实现后,执行 python export.py,在models⽂件夹下⾯,能够看到⽣成的best-fp16.tflite⽂件。

3.4、实现Aidlux上的人体检测
依照之前的操作,点击Remote Explore,输出明码,连贯SSH,关上网页版的Aidlux->点击左下角第一个文件->点击home->右上角有个向上的箭头为upload->导入桌面上下载好的lesson3_code,将models文件夹下的best-fp16.tflite拖到aidlux文件夹中,批改aidlux中的model门路

图12
批改视屏读取门路
点击RUN,会看到手机上会呈现人体检测视屏

图13

3.5、实现Aidlux人体轨迹追踪

指标追踪算法包含单指标追踪和多指标追踪,多指标追踪次要针对的是多个指标的静止轨迹,而单指标追踪次要 针对的某⼀个指标的静止轨迹。目前用的较多的是多指标追踪算法,多指标追踪算法包含(1)sort多指标算法(2)deepsort多指标算法(3)Bytetrack多指标追踪算法。该实例中咱们应用Bytetrack多指标追踪算法,会尽量的缩小人物之间的遮挡而带来的指标的失落。

# 实现目标追踪相干性能函数,tracker函数接口能够在公众号Aidlux里回复lesson4获取
    det = []   #给予检测一个空间
    # Process predictions
    for box in pred[0]:  # per image
        box[2] += box[0]
        box[3] += box[1]
        det.append(box)   det.append()示意将这个数组写入det中
    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信息,赋予指标框一个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)

运行RUN

图14

3.6、实现Aidlux平台的医院进出口人流量统计

1.越线辨认以及计数性能的实现

因为该监控图像是正对着出入口的,咱们以检测指标的头部为验证对象,所以咱们在抉择点的时候须要思考到摄像机的视角与角度问题。如图18中所示,咱们以检测框的上边中心点为越界辨认点。

### 越界单边辨认性能实现 ###
            # 1.绘制越界监测区域
            #上面的坐标代表直线的两端的坐标
            line = [[167,541],[1191,539]]
            cv2.line(res_img,(167,541),(1191,539),(255,255,0),3)

            # 2.计算失去人体下方中心点的地位(人体检测监测点调整),
            # (x,y,w,h)->(tlwh[0],tlwh[1],tlwh[2],tlwh[3])
            pt = [tlwh[0]+1/2*tlwh[2],tlwh[1]]    #越界辨认点   
            
            # 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   #后面记得count_person初始化

        ###再判断以后一个状态为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到1的状况,②则思考到了进出两个方向(-1 到1 1到-1)的状况

①左上角标注人数流量统计后果为23(只思考了-1到1),并通过微信公众号喵揭示进行提醒(。

②左上角标注人数流量统计后果为28(思考了-1到1,以及1到-1两个方向的状况,满足进出门的要求,更贴合理论),并通过微信公众号喵揭示进行揭示。

图15

图16

图17

图18

3.7、最终性能的源码

# aidlux相干
#上面的utils函数包和track函数包要到公众号“AidLUx”上回复lesson5
from cvs import *
import aidlite_gpu
from utils import detect_postprocess, preprocess_img, draw_detect_res, scale_coords,process_points,is_in_poly,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/lesson4_codes/aidlux/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/lesson4_codes/aidlux/jiankong.mp4")
frame_id = 0
count_person = 0
while True:
    frame = cap.read()
    if frame is None:
        print("Camera is over!")
        # 填写对应的喵码
        id = 'ti184WH'
        # 填写喵揭示中,发送的音讯,这里放上后面提到的图片外链
        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.绘制统计人流线
            lines =[[167,541],[1191,539]]
            cv2.line(res_img,(167,541),(1191,539),(255,255,0),3)

            # 2.计算失去人体下方中心点的地位(人体检测监测点调整)
            pt = [tlwh[0]+1/2*tlwh[2],tlwh[1]]#以人头为辨认点
            
            #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)
                    #cv2.imwrite("overstep.jpg",res_img)
                    count_person += 1   #之前曾经定义count_person=0,不然会报未定义的错
                    
               #5.再判断以后一个状态为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)
                    #cv2.imwrite("overstep.jpg",res_img)
                    count_person += 1 
    cv2.putText(res_img,"Pereson_count in the gate of Hospital:"+ str(count_person), (50,50), cv2.FONT_HERSHEY_SIMPLEX, 1 ,(255, 0, 255), 3)
    cvs.imshow(res_img)

4、总结
通过本次的案例学习,学会了通过手机端的Aidlux平台来尝试AI智能场景的部署,进一步加深了对深度学习以及分布式AIOT开发的理解,在今后的学习中会持续理解与学习这方面的常识。