本文正在参加『In AidLux,To AIoT』AI应用案例征集活动
0.前言
本人一直做的是深度学习服务器端部署,没有过移动端的部署经验。一直对移动端的部署非常感兴趣,奈何涉及到的开发部署技术门槛较高,一直想学习,又感觉无从下手。直到阅读到江大白老师的文章,《万字长文手把手教你Yolov5制作家庭安防告警系统》,了解到AidLux平台,用户无需花费大量的精力于繁琐且问题频发的开发和部署环境配置,即可将基于其它平台开发的AI应用轻松迁移部署至AidLux上运行。于是只额外利用一部手机,便开启了自己的第一个移动端AI项目落地之旅。
1. AidLux简介
AidLux是一个构建在ARM硬件上,基于创新性跨Android/鸿蒙 + Linux融合系统环境的智能物联网 (AIoT) 应用开发和部署平台。也就是说不需要有Android基础,也可实现Android上AI应用的部署!
利用Android部署深度学习模型,需要C++,Java,Python,Linux等多技术栈工程师相互配合,开发周期长,成本高,同时学些的门槛也高。然而利用AidLux,仅需要会python,即可实现AI应用的部署。所以对于没有Android开发部署经验的小白,只要有深度学习基础,仅利用一部手机,就可轻松实现使自己的AI应用落地。
同时,AidLux官网有详细的学习文档,以及包含图像分类,物体检测,语义分割,关键点检测,ocr识别,风格迁移等丰富的AI应用示例。
每个应用示例都开放源码,可供下载学习。对于小白来说,简直不要太友好,能够不用花费大量的信息检索和筛选时间,就能学习到不同的AI应用范例。
2.场景介绍
小区保安大爷每天执勤时,需要给来访车辆手动开启升降杆。由于视野受限,为了能够及时放行车辆,保安大爷的活动范围基本上受限于保安岗亭。然而小区的车流量并不大,导致保安大爷每天大部分时间是在岗亭内无聊且无效度过。那有没有一种办法,让保安大爷可以扩大活动范围,去岗亭周边巡逻,散步的同时,通过手机就能够及时检测到门口是否有车辆到访呢?
基于AidLux平台,同时使用七牛云和喵提醒工具,即可使该AI项目轻松落地。
手机端检测效果如下:
https://www.bilibili.com/video/BV1iP4y1f7P7?share_source=copy_web
3. 项目结构
本项目使用yolov5算法来检测小区来访车辆,通过AidLux实现PC端到手机端的模型转换。为防止对过往车辆的误判,通过判断车辆在摄像设备(这里使用的是手机)的停留时间和进入镜头的比例过滤掉来往车辆。之后将报警图片上传到七牛云服务器,获取图片的url链接,再通过喵提醒将图片的url链接,推送到喵提醒的微信公众号中,这样就可以及时查看到来访车辆的信息。从而即使门卫大爷不在岗亭值守,只要在降栏杆遥控器的发射范围内(一般为300m),就可以实现车辆放行。
4. 项目实现
整个项目实现借鉴江大白老师的文章《万字长文手把手教你Yolov5制作家庭安防告警系统》,真正手把手教学,对小白格外友好,强烈推荐关注江大白老师公众号,学习更多深度学习知识。
4.1 七牛云注册及代码使用方法
(1) 登录七牛云官网https://www.qiniu.com/,按照大白老师的教程,注册账号,并且创建一个自己的存储空间,获取相关个人信息。
(2) 代码实现上传本地图片到七牛云以及获取图片的外链,需要替换的是个人信息access_key ,ecret_key ,bucket_name,bucket_url ,以及本地图片名称image_up_name。这样就可以将本地girl.jpg上传到七牛云中,重命名为girl_2022.jpg
``` from qiniu import Auth, put_file from qiniu import CdnManager # 配置七牛云信息 access_key = "Z1vp5NmGNB4Q6ba4loylI6xsjLKezRNC0gQ-" secret_key = "zI1-eyCuSTd3dCPrZqdDtuPiDMdjiyASbVnEsCzx" bucket_name = "testxxy" bucket_url = "rh3p5kuhj.hn-bkt.clouddn.com" q = Auth(access_key, secret_key) cdn_manager = CdnManager(q)将本地图片上传到七牛云中
def upload_img(bucket_name, file_name, file_path):
# generate token
token = q.upload_token(bucket_name, file_name)
put_file(token, file_name, file_path)
获得七牛云服务器上file_name的图片外链
def get_img_url(bucket_url, file_name):
img_url = ‘http://%s/%s’ % (bucket_url, file_name)
return img_url
需要上传到七牛云上面的图片的路径
image_up_name = “data/images/girl.jpg”
上传到七牛云后,保存成的图片名称
image_qiniu_name = “girl_2022.jpg”
将图片上传到七牛云,并保存成image_qiniu_name的名称
upload_img(bucket_name, image_qiniu_name, image_up_name)
取出和image_qiniu_name一样名称图片的url
url_receive = get_img_url(bucket_url, image_qiniu_name)
print(url_receive)
需要刷新的文件链接,由于不同时间段上传的图片有缓存,因此需要CDN清除缓存,
urls = [url_receive]
URL刷新缓存链接,一天有500次的刷新缓存机会
refresh_url_result = cdn_manager.refresh_urls(urls)
<h2>4.2 喵提醒注册及代码使用方法</h2>
<p>(1) 关注喵提醒微信公众号,注册账号,并且新建提醒,获取喵吗,激活账号。</p>
<p><img src="https://aidlux.oss-cn-beijing.aliyuncs.com/imgs/1661867647366428149.png" alt="" /></p>
<p>(2) 代码实现,将图片外链推送到喵提醒公众号,实现来车报警。需要修改的是喵吗以及图片外链。</p>
import time
import requests
填写对应的喵码
id = ‘tOarz9S’
填写喵提醒中,发送的消息,这里放上前面提到的图片外链
text = “告警图片:” + “http://rh3p5kuhj.hn-bkt.clouddn.com/girl_2022.jpg”
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)
print(result)
<h2>4.3 利用AidLux部署yolov5模型到手机上</h2>
<p>AidLux预编译集成全球主流AI框架 (TensorFlow、Pytorch、NCNN、TNN、PanddlePanddle、MNN、MindSpore等) 和相关科学计算依赖库,开箱即用。但是此种方法使用的是cpu算力,速度较慢。同时AidLux提供统一封装AI框架的 AidLite API,自适应模型框架。AidLux还提供CPU和GPU两种加速模式,内置aidlite_gpu模块,能够充分释放设备GPU性能,此外还支持CPU+GPU同时加速!本文通过AidLite实现AI模型的加载与推理。</p>
<h3>4.3.1 安装AidLux</h3>
<p>手机通过应用商城搜索AidLux,即可找到AidLux软件,下载安装即可。AidLux支持将手机端AidLux桌面通过cloud_id投影到电脑端,这样方便将电脑上的代码传输到手机上。</p>
<p><img src="https://aidlux.oss-cn-beijing.aliyuncs.com/imgs/1661868050105703199.png" alt="" /></p>
<h3>4.3.2 部署yolov5模型到AidLux</h3>
<p>相对于江大白老师的代码,主要修改和增加的代码部分如下:</p>
<p>(1) 修改保留类别=2(car)的检测框。 认为检测到的车辆外矩形框面积与整个画面的面积比值>0.15的车辆是要进小区的车辆。</p>
utils.py
def draw_detect_res(img, all_boxes,car,frame_id, frame_ratio):
‘’’
检测结果绘制
‘’’
img = img.astype(np.uint8)
color_step = int(255/len(all_boxes))
for bi in range(len(all_boxes)):
if len(all_boxes[bi]) == 0:
continue
for box in all_boxes[bi]:
x, y, w, h = [int(t) for t in box[:4]]
‘’’
由于汽车在coco数据集中的类别是2,所以通过bi == 2来保留只是汽车的检测框。
‘’’
if bi != 2:
continue
if bi == 2:
car = 1
‘’’
认为检测到的车辆外接矩形面积与整个画面的面积比值>0.15的车辆是要进小区的车辆
‘’’
car_area = wh
car_ratio = car_area / (img.shape[0] * img.shape[1])
print(“car_ratio”, car_ratio)
if car_ratio > 0.15:
frame_ratio[frame_id] = car_ratio
cv2.putText(img, f’{coco_class[bi]}', (x, y), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)
cv2.rectangle(img, (x,y), (x+w, y+h),(0, bicolor_step, 255-bi*color_step),thickness = 2)
return img,car,frame_ratio
<p>(2) 为了避免过往车辆误识别为要进小区的车辆,通过判断一定帧数内识别到的目标帧数所占比例,过滤掉来往车辆。</p>
aidlux相关
from cvs import *
import aidlite_gpu
from utils import detect_postprocess, preprocess_img, draw_detect_res
七牛云相关
from qiniu import Auth, put_file
from qiniu import CdnManager
import time
import requests
import cv2
配置七牛云信息
access_key = “Z1vp5NmGNB4Q6ba4loylI6xsjLKezRNC0gQ-”
secret_key = “zI1-eyCuSTd3dCPrZqdDtuPiDMdjiyASbVnEsCzx”
bucket_name = “testxxy”
bucket_url = “rh3p5kuhj.hn-bkt.clouddn.com”
q = Auth(access_key, secret_key)
cdn_manager = CdnManager(q)
将本地图片上传到七牛云中
def upload_img(bucket_name, file_name, file_path):
# generate token
token = q.upload_token(bucket_name, file_name)
put_file(token, file_name, file_path)
获得七牛云服务器上file_name的图片外链
def get_img_url(bucket_url, file_name):
img_url = ‘http://%s/%s’ % (bucket_url, file_name)
return img_url
加载模型
model_path = ‘yolov5s-fp16.tflite’
定义输入输出shape
in_shape = [1 * 640 * 640 * 3 * 4]
out_shape = [1 * 25200 * 85 * 4, 1 * 3 * 80 * 80 * 85 * 4, 1 * 3 * 40 * 40 * 85 * 4, 1 * 3 * 20 * 20 * 85 * 4]
载入模型
aidlite = aidlite_gpu.aidlite()
载入yolov5检测模型
aidlite.ANNModel(model_path, in_shape, out_shape, 4, 0)
cap = cvs.VideoCapture(0)
car = 0
frame_id = 0
‘’’
frame_ratio用来计时,记录识别到目标的帧数
‘’’
frame_ratio = {}
starttime = time.time()
while True:
frame = cap.read()
if frame is None:
continue
frame_id += 1
print("frame_id", frame_id)
# if frame_id == 100:
# endtime = time.time()
# print("time", endtime-starttime)
# 预处理
img = preprocess_img(frame, target_shape=(640, 640), div_num=255, means=None, stds=None)
aidlite.setInput_Float32(img, 640, 640)
# 推理
aidlite.invoke()
pred = aidlite.getOutput_Float32(0)
pred = pred.reshape(1, 25200, 85)[0]
pred = detect_postprocess(pred, frame.shape, [640, 640, 3], conf_thres=0.5, iou_thres=0.45)
print("frame_ratio", frame_ratio)
res_img, car, frame_ratio= draw_detect_res(frame, pred, car, frame_id, frame_ratio)
aumulative_times = list(frame_ratio.keys())
print("aumulative_times", aumulative_times)
'''
为了避免过往车辆误识别为要进小区的车辆,通过判断一定帧数内识别到的目标帧数所占比例,过滤掉来往车辆。
'''
if len(frame_ratio) > 10:
print("len(frame_ratio) / (aumulative_times[-1] - aumulative_times[0])", len(frame_ratio) / (aumulative_times[-1] - aumulative_times[0]))
if len(frame_ratio) / (aumulative_times[-1] - aumulative_times[0]) > 0.5:
cv2.imwrite("detect_image.jpg", res_img)
car = 0
# 需要上传到七牛云上面的图片的路径
image_up_name = "detect_image.jpg"
# 上传到七牛云后,保存成的图片名称
image_qiniu_name = "detect_image_2023.jpg"
# 将图片上传到七牛云,并保存成image_qiniu_name的名称
upload_img(bucket_name, image_qiniu_name, image_up_name)
# 取出和image_qiniu_name一样名称图片的url
url_receive = get_img_url(bucket_url, image_qiniu_name)
print(url_receive)
# 需要刷新的文件链接,由于不同时间段上传的图片有缓存,因此需要CDN清除缓存,
urls = [url_receive]
# URL刷新缓存链接,一天有500次的刷新缓存机会
refresh_url_result = cdn_manager.refresh_urls(urls)
# 填写对应的喵码
id = 'tOarz9S'
# 填写喵提醒中,发送的消息,这里放上前面提到的图片外链
text = "告警图片:" + url_receive
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)
'''
frame_ratio清空,重新计时(帧)
'''
frame_ratio = {}
cvs.imshow(res_img)
<p>(3) 通过Aidlux的PC端桌面将整个项目上传到/home/yolov5-master/aidlux中,手机端在Aidlux软件中找到相同同目录,打开主程序py文件,点击右上角build,成功后点击左上角run now即可启动手机摄像头,执行检测模型。如果检测到来访车辆,喵提醒微信公账号就会收到来访车辆实时画面。</p>
<p><img src="https://aidlux.oss-cn-beijing.aliyuncs.com/imgs/1661868557699068111.png" alt="" /></p>
<h1>5. 总结</h1>
<p>开始构思项目场景的时候,是想要把车牌定位和识别加到整个项目当中。但是由于手机性能问题,加载2个以上模型的时候,相机无法正常启动。尝试通过将量化降低到int8,但是模型的精度也跟着下降。最终由于时间问题,只能舍弃,没有对此问题根据官网的应用示例和<a href="https://docs.aidlux.com/#/intro/ai/ai-turbo?id=ai%e6%99%ba%e8%83%bd%e5%8a%a0%e9%80%9f">AI智能加速</a>办法进行深入研究。但是总体来说,Aidlux降低了Android部署深度学习模型的门槛,小白也能轻松落地移动端AI项目。Aidlux官网丰富的AI应用示例,也想让人一探究竟。没有尝试过的同学,赶快用起来吧。</p>