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

5次阅读

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

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 开发的理解,在今后的学习中会持续理解与学习这方面的常识。

正文完
 0