Jetson Xavier NX上部署PaddleDetection吸烟检测
基于生活中的禁止吸烟场景进行检测,减少吸烟现象
·
一、项目介绍
笔者的学校经常出现公共区域的抽烟现象,在贴有禁止吸烟的厕所里也有同学吸烟的情况,导致下课去一次洗手间,回来就是一身的烟味! 吸烟可以去合适的场所避免对大家的影响,类似的现象在生活的很多场景中都存在,没有好的方法可以缓解这个现象,为了大学生的美好未来,为了大家的身心健康,基于飞桨的吸烟检测它来了,我在PaddleDetection上训练了这次项目的吸烟检测,为了更好的体现实际,并部署在了Jetson Xavier NX上。(出自本小白项目
,大佬路过可留下宝贵意见)。
这次项目所参考的文档及大佬项目
二、硬件准备
准备好一块新鲜出炉的Jetson Xavier NX,并配好基础的开发环境,当然Jetson系列的部署是基本一致的(出自某PPDE-高学长的说法),如果没有可以用Jetson nano代替。不过越贵的板子跑起来越轻松,我便白嫖的实验室小伙伴的硬件(毕竟没有这经济实力),你的Jetson Xavier NX就是我的
。
三、环境搭建
安装PaddlePaddle环境
去官网链接下载最新即可 编译库下载连接
下载后传到Jetson Xavier NX上并运行如下指令
pip3 install paddlepaddle_gpu-2.1.1-cp36-cp36m-linux_aarch64.whl
完成编译库的安装
测试Paddle Inference
此处可以参考开头提到参考项目中的第二个连接里的测试流程。(我也是这样测试的)
测试成功大致环境搭建已经完成,可以开始做自己的吸烟检测任务
四、吸烟检测
数据集采用大佬Niki_173的吸烟检测数据集,感谢大佬的数据集,此处小白引用。
首先拉取PaddleDetection
放入data文件夹中便于之后启动环境,避免内存大时启动不方便
#从gitee上克隆PaddleDetection
! git clone https://gitee.com/paddlepaddle/PaddleDetection.git
! mv PaddleDetection data
Cloning into 'PaddleDetection'...
remote: Enumerating objects: 2854, done.[K
remote: Counting objects: 100% (2854/2854), done.[K
remote: Compressing objects: 100% (1193/1193), done.[K
remote: Total 17429 (delta 1861), reused 2529 (delta 1654), pack-reused 14575[K
Receiving objects: 100% (17429/17429), 141.74 MiB | 6.43 MiB/s, done.
Resolving deltas: 100% (12604/12604), done.
Checking connectivity... done.
#解压数据集
import os
os.mkdir('data/voc')
! unzip -oq /home/aistudio/data/data94796/pp_smoke.zip -d data
! mv data/images data/voc
! mv data/Annotations data/voc
Paddlex的分解VOC数据集,十分方便,并且将训练集,验证集,测试集划分好,生成对应的txt文件
运行下面的代码前,先把解压的数据集目录下的data/voc/images 修改为data/voc/JPEGImages,不然会报错
#paddlex 一键分解voc数据真香
!pip install paddlex==2.0rc
#JPEGImages
!paddlex --split_dataset --format VOC --dataset_dir data/voc --val_value 0.2 --test_value 0.1
#进行环境配置,不然无法训练
!pip install --upgrade -r data/PaddleDetection/requirements.txt -i https://mirror.baidu.com/pypi/simple
对应的yml文件修改大致如下,可以根据自己的想法修改,可以训练出更好的模型。写好的yml文件已经保存在work的config目录下,直接调用训练即可
yolov3_mobilenet_v1_ssld_270e_voc.yml:
_BASE_: [
'../datasets/voc.yml',
'../runtime.yml',
'_base_/optimizer_270e.yml',
'_base_/yolov3_mobilenet_v1.yml',
'_base_/yolov3_reader.yml',
]
snapshot_epoch: 5
pretrain_weights: https://paddledet.bj.bcebos.com/models/pretrained/MobileNetV1_ssld_pretrained.pdparams
weights: output/yolov3_mobilenet_v1_ssld_270e_voc/model_final
# set collate_batch to false because ground-truth info is needed
# on voc dataset and should not collate data in batch when batch size
# is larger than 1.
EvalReader:
collate_batch: false
LearningRate:
base_lr: 0.000125
schedulers:
- !PiecewiseDecay
gamma: 0.1
milestones:
- 216
- 243
- !LinearWarmup
start_factor: 0.
steps: 1000
voc.yml:
metric: VOC
map_type: 11point
num_classes: 1
TrainDataset:
!VOCDataSet
dataset_dir: data/voc
anno_path: train_list.txt
label_list: labels.txt
data_fields: ['image', 'gt_bbox', 'gt_class', 'difficult']
EvalDataset:
!VOCDataSet
dataset_dir: data/voc
anno_path: val_list.txt
label_list: labels.txt
data_fields: ['image', 'gt_bbox', 'gt_class', 'difficult']
TestDataset:
!ImageFolder
anno_path: data/voc/test_list.txt
runtime.yml:
use_gpu: true
log_iter: 10
save_dir: output
snapshot_epoch: 5
print_flops: false
optimizer_270e.yml:
epoch: 800
LearningRate:
base_lr: 0.000125
schedulers:
- !PiecewiseDecay
gamma: 0.1
milestones:
- 216
- 243
- !LinearWarmup
start_factor: 0.
steps: 4000
OptimizerBuilder:
optimizer:
momentum: 0.9
type: Momentum
regularizer:
factor: 0.0005
type: L2
yolov3_reader.yml:
worker_num: 0
TrainReader:
inputs_def:
num_max_boxes: 50
sample_transforms:
- Decode: {}
- Mixup: {alpha: 1.5, beta: 1.5}
- RandomDistort: {}
- RandomExpand: {fill_value: [123.675, 116.28, 103.53]}
- RandomCrop: {}
- RandomFlip: {}
batch_transforms:
- BatchRandomResize: {target_size: [320, 352, 384, 416, 448, 480, 512, 544, 576, 608], random_size: True, random_interp: True, keep_ratio: False}
- NormalizeBox: {}
- PadBox: {num_max_boxes: 50}
- BboxXYXY2XYWH: {}
- NormalizeImage: {mean: [0.485, 0.456, 0.406], std: [0.229, 0.224, 0.225], is_scale: True}
- Permute: {}
- Gt2YoloTarget: {anchor_masks: [[6, 7, 8], [3, 4, 5], [0, 1, 2]], anchors: [[10, 13], [16, 30], [33, 23], [30, 61], [62, 45], [59, 119], [116, 90], [156, 198], [373, 326]], downsample_ratios: [32, 16, 8]}
batch_size: 64
shuffle: true
drop_last: true
mixup_epoch: 250
use_shared_memory: true
EvalReader:
inputs_def:
num_max_boxes: 50
sample_transforms:
- Decode: {}
- Resize: {target_size: [608, 608], keep_ratio: False, interp: 2}
- NormalizeImage: {mean: [0.485, 0.456, 0.406], std: [0.229, 0.224, 0.225], is_scale: True}
- Permute: {}
batch_size: 64
TestReader:
inputs_def:
image_shape: [3, 608, 608]
sample_transforms:
- Decode: {}
- Resize: {target_size: [608, 608], keep_ratio: False, interp: 2}
- NormalizeImage: {mean: [0.485, 0.456, 0.406], std: [0.229, 0.224, 0.225], is_scale: True}
- Permute: {}
batch_size: 1
如果不打算自己修改,直接运行下面的命令就可以进行模型训练
# 进行模型训练
#因为笔的设置会产较多epoch会产生比较多的模型文件,文件太多时过于占内存,运行一下 remove.py即可(就是简单的删除文件而已)
!python data/PaddleDetection/tools/train.py -c work/config/yolov3/yolov3_mobilenet_v1_270e_voc.yml --eval -o use_gpu=true
#模型训练好以后随机选择一张图片
#选择一张图片进行预测效果测试
#运行命令进行模型预测
!python data/PaddleDetection/tools/infer.py -c work/config/yolov3/yolov3_mobilenet_v1_270e_voc.yml --infer_img=data/voc/JPEGImages/smoke_a325.jpg -o weights=output/yolov3_mobilenet_v1_270e_voc/best_model.pdparams
看看预测效果,放上星爷的帅照
#训练完成之后,既可导出
!python data/PaddleDetection/tools/export_model.py -c work/config/yolov3/yolov3_mobilenet_v1_270e_voc.yml --output_dir=./inference_model \
ference_model \
-o weights=output/yolov3_mobilenet_v1_270e_voc/best_model
四、模型部署
创建一个自己的工作文件夹(如 demo),我把模型文件传上Jetson Xavier NX存放在demo/voc下
推荐大家使用 vs code 远程登陆操作,更改代码,传输或删除文件,都很方便!
文件传送好的格式大致如下(只看demo文件目录即可)
再编写python预测,放在demo的目录下即可
这个程序的编写可以参考文档给的示例,我的程序就是简单修改例程。链接在这yolov3模型示例
python预测中的文件读取路径,改成自己部署时的路径
infer.py
import cv2
import numpy as np
import paddle.inference as paddle_infer
from paddle.inference import Config
from paddle.inference import create_predictor
#############图像预处理##########################
def resize(img, target_size):
"""resize to target size"""
if not isinstance(img, np.ndarray):
raise TypeError('image type is not numpy.')
im_shape = img.shape
im_size_min = np.min(im_shape[0:2])
im_size_max = np.max(im_shape[0:2])
im_scale_x = float(target_size) / float(im_shape[1])
im_scale_y = float(target_size) / float(im_shape[0])
img = cv2.resize(img, None, None, fx=im_scale_x, fy=im_scale_y)
return img
def normalize(img, mean, std):
img = img / 255.0
mean = np.array(mean)[np.newaxis, np.newaxis, :]
std = np.array(std)[np.newaxis, np.newaxis, :]
img -= mean
img /= std
return img
def preprocess(img, img_size):
mean = [0.485, 0.456, 0.406]
std = [0.229, 0.224, 0.225]
img = resize(img, img_size)
img = img[:, :, ::-1].astype('float32') # bgr -> rgb
img = normalize(img, mean, std)
img = img.transpose((2, 0, 1)) # hwc -> chw
return img[np.newaxis, :]
#########进行模型配置###################################
def Config(prog_file,params_file):
# 创建 config
config = paddle_infer.Config()
# 通过 API 设置模型文件夹路径
#config.set_prog_file("./mobilenet_v2/__model__")
#config.set_params_file("./mobilenet_v2/__params__")
config.set_prog_file(prog_file)
config.set_params_file(params_file)
# 根据 config 创建 predictor
config.enable_use_gpu(1000, 0)
config.switch_ir_optim()
config.enable_memory_optim()
#config.enable_tensorrt_engine(workspace_size=1 << 30, precision_mode=paddle_infer.PrecisionType.Float32,max_batch_size=1, min_subgraph_size=5, use_static=False, use_calib_mode=False)
predictor = paddle_infer.create_predictor(config)
return predictor
def predic(predictor, img):
# copy img data to input tensor
input_names = predictor.get_input_names()
for i, name in enumerate(input_names):
input_tensor = predictor.get_input_handle(name)
input_tensor.reshape(img[i].shape)
input_tensor.copy_from_cpu(img[i].copy())
# do the inference
predictor.run()
results = []
# get out data from output tensor
output_names = predictor.get_output_names()
for i, name in enumerate(output_names):
output_tensor = predictor.get_output_handle(name)
output_data = output_tensor.copy_to_cpu()
results.append(output_data)
return results
def draw_bbox(img, result,label_list, threshold=0.5):
"""draw bbox"""
for res in result:
id, score, bbox = res[0], res[1], res[2:]
if score < threshold:
continue
xmin, ymin, xmax, ymax = bbox
cv2.rectangle(img, (int(xmin),int(ymin)), (int(xmax), int(ymax)), (255,0,255), 2)
print('category id is {}, bbox is {}'.format(id, bbox))
try:
label_id = label_list[int(id)]
cv2.putText(img, label_id, (int(xmin), int(ymin-2)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,0,0), 2)
cv2.putText(img, str(round(score,2)), (int(xmin-35), int(ymin-2)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,255,0), 2)
except KeyError:
pass
if __name__ == '__main__':
print("开始进行预测")
#摄像头读取
cap = cv2.VideoCapture(0)
# 图像尺寸相关参数初始化
ret, img = cap.read()
#模型文件路径
prog_file = './voc/model.pdmodel'
params_file = './voc/model.pdiparams'
predictor = Config(prog_file,params_file)
img_size = 224
scale_factor = np.array([img_size * 1. / img.shape[0], img_size * 1. / img.shape[1]]).reshape((1, 2)).astype(np.float32)
im_shape = np.array([img_size, img_size]).reshape((1, 2)).astype(np.float32)
while True:
ret, img = cap.read()
pro_data = preprocess(img,img_size)
result = predic(predictor, [im_shape, pro_data, scale_factor])
draw_bbox(img,result[0],label_list)
cv2.imshow("pred", img)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
此项目导出的模型文件已经放在inference_model下,可以直接下载本地后部署
部署效果
不抽烟,只能拿只激光笔骗一骗模型![](https://img-blog.csdnimg.cn/img_convert/45bb9c0eb887bad8ff09291cdcfcc523.png)
简单的吸烟检测部署就完成了,小白项目,如有错误请多包涵
个人简介
吴世君 东北大学秦皇岛分校 测控技术与仪器 本科在读
感兴趣方向:计算机视觉
请点击此处查看本环境基本用法.
Please click here for more detailed instructions.
更多推荐
所有评论(0)