基于atlas环境下YOLOV7的睡岗识别

做到这里,其实只是想探索下新的检测框架、探索下atlas下ACL的推理方式。整个过程持续了3-4周把,回顾一下,感觉还是需要一些技巧才能拿下,如果没有任何经验的是断难搞定此代码的。主要基于华为的官方例子,里面修改了原始代码中某些库不支持的问题、解决了模型转化过程中的一些问题,发现了ACL不支持多线程的问题。

路漫漫、吾上下,纵使困顿难行,亦当砥砺奋进。

数据集制作标注:

数据集为网上搜集的,共计1407张。实用labelimg进行标注,大概花了1个多星期。

本着取之于民用之于民的思想,也分享出来,(https://download.csdn.net/download/qq_14845119/89775339),需要自提。

数据集目录结构如下,

模型训练:

训练yolov7-tiny模型

python train.py --workers 8 --device 1 --batch-size 32 --data data/sleep.yaml --img 640 640 --cfg cfg/training/yolov7-tiny-sleep.yaml --weights ./yolov7.pt --name yolov7 --hyp data/hyp.scratch.tiny.yaml

训练结果,

可视化效果,

训练yolov7模型

python train.py --workers 8 --device 0 --batch-size 32 --data data/sleep.yaml --img 640 640 --cfg cfg/training/yolov7-sleep.yaml --weights ./yolov7.pt --name yolov7 --hyp data/hyp.scratch.p5.yaml

训练结果,

可视化效果,

这里对比的训练的yolov7、yolov7-tiny两个模型,从精度上的明显差距,最终选择了yolov7模型作为最终模型。

模型转化:

Pt模型转化onnx模型,

python export.py --weights runs/train/yolov73/weights/best.pt --grid --end2end --simplify --topk-all 100 --iou-thres 0.65 --conf-thres 0.35 --img-size 640 640 --max-wh 640

首先使用Netron工具查看模型最终输出的3个节点的名称,得到模型的3个输出节点名称。

cd model/
atc --model=yolov7.onnx --framework=5 --output=yolov7 --soc_version=Ascend310P3 --out_nodes="/model/model.105/m.0/Conv:0;/model/model.105/m.1/Conv:0;/model/model.105/m.2/Conv:0" --input_shape="images:1,3,640,640"

后处理转化:

cd src/
python3 postProcessOperator.py
cd model/
atc --model=postprocess.onnx --soc_version=Ascend310P3 --output=postprocess --framework=5 --input_shape='img_info:1,4'

后处理postProcessOperator.py代码如下,

import onnx
from onnx import helper
h, w = 640, 640
boxNum = 3
outNUm = 3
#classes = 80
classes = 1
coords = 4
f_h, f_w = h // 8, w // 8
# yolov7x anchor
anchor = [12.0, 16.0, 19.0, 36.0, 40.0, 28.0, 36.0, 75.0, 76.0, 55.0, 72.0, 146.0, 142.0, 110.0, 192.0, 243.0, 459.0, 401.0]
#input_shape_0 = [1, 255, 80, 80]
#input_shape_1 = [1, 255, 40, 40]
#input_shape_2 = [1, 255, 20, 20]input_shape_0 = [1, 18, 80, 80]
input_shape_1 = [1, 18, 40, 40]
input_shape_2 = [1, 18, 20, 20]img_info_num = 4
max_boxes_out = 6 * 1024
box_num = 8
pre_nms_topn = 1024
post_nms_topn = 1024
relative = 1
out_box_dim = 2
obj_threshold = 0.25
score_threshold = 0.25
iou_threshold = 0.45input_0 = helper.make_tensor_value_info("input_0", onnx.TensorProto.FLOAT, input_shape_0)
input_1 = helper.make_tensor_value_info("input_1", onnx.TensorProto.FLOAT, input_shape_1)
input_2 = helper.make_tensor_value_info("input_2", onnx.TensorProto.FLOAT, input_shape_2)crd_align_len = f_h * f_w
obj_align_len = boxNum * f_h * f_w
coord_data_0 = helper.make_tensor_value_info("yolo_coord_0", onnx.TensorProto.FLOAT, ['batch', boxNum * 4, crd_align_len])
obj_prob_0 = helper.make_tensor_value_info("yolo_obj_0", onnx.TensorProto.FLOAT, ['batch', obj_align_len])
classes_prob_0 = helper.make_tensor_value_info("yolo_classes_0", onnx.TensorProto.FLOAT,['batch', classes, obj_align_len])yolo_pre_node_0 = helper.make_node('YoloPreDetection',inputs = ["input_0"],outputs = ["yolo_coord_0", "yolo_obj_0", "yolo_classes_0"],boxes = boxNum,coords = coords,classes = classes,yolo_version ='V5',name = "yolo_pre_node_0")f_h, f_w = f_h // 2, f_w // 2
crd_align_len = f_h * f_w
obj_align_len = boxNum * f_h * f_w
coord_data_1 = helper.make_tensor_value_info("yolo_coord_1", onnx.TensorProto.FLOAT, ['batch', boxNum * 4, crd_align_len])
obj_prob_1 = helper.make_tensor_value_info("yolo_obj_1", onnx.TensorProto.FLOAT, ['batch', obj_align_len])
classes_prob_1 = helper.make_tensor_value_info("yolo_classes_1", onnx.TensorProto.FLOAT,['batch', classes, obj_align_len])yolo_pre_node_1 = helper.make_node('YoloPreDetection',inputs = ["input_1"],outputs = ["yolo_coord_1", "yolo_obj_1", "yolo_classes_1"],boxes = boxNum,coords = coords,classes = classes,yolo_version = 'V5',name = "yolo_pre_node_1")f_h, f_w = f_h // 2, f_w // 2
crd_align_len = f_h * f_w
obj_align_len = boxNum * f_h * f_w
coord_data_2 = helper.make_tensor_value_info("yolo_coord_2", onnx.TensorProto.FLOAT, ['batch', boxNum * 4, crd_align_len])
obj_prob_2 = helper.make_tensor_value_info("yolo_obj_2", onnx.TensorProto.FLOAT, ['batch', obj_align_len])
classes_prob_2 = helper.make_tensor_value_info("yolo_classes_2", onnx.TensorProto.FLOAT,['batch', coords, obj_align_len])yolo_pre_node_2 = helper.make_node('YoloPreDetection',inputs=["input_2"],outputs=["yolo_coord_2", "yolo_obj_2", "yolo_classes_2"],boxes=boxNum,coords = coords,classes = classes,yolo_version='V5',name="yolo_pre_node_2")# create yolo detection output layer
img_info = helper.make_tensor_value_info("img_info", onnx.TensorProto.FLOAT, ['batch', img_info_num])
box_out = helper.make_tensor_value_info("box_out", onnx.TensorProto.FLOAT, ['batch', max_boxes_out])
box_out_num = helper.make_tensor_value_info("box_out_num", onnx.TensorProto.INT32, ['batch', box_num])
yolo_detect_node = helper.make_node('YoloV5DetectionOutput',inputs = [f"yolo_coord_{i}" for i in range(outNUm)] +[f"yolo_obj_{i}" for i in range(outNUm)] +[f"yolo_classes_{i}" for i in range(outNUm)] +['img_info'],outputs = ['box_out', 'box_out_num'],boxes = boxNum,coords = coords,classes = classes,pre_nms_topn = pre_nms_topn,post_nms_topn = post_nms_topn,relative = relative,out_box_dim = out_box_dim,obj_threshold = obj_threshold,score_threshold = score_threshold,iou_threshold = iou_threshold,biases = anchor,name ='YoloV5DetectionOutput')
# make graph
graph = helper.make_graph(nodes = [yolo_pre_node_0, yolo_pre_node_1, yolo_pre_node_2, yolo_detect_node],name = "yolo",inputs = [input_0, input_1, input_2, img_info],outputs = [box_out, box_out_num]
)onnx_model = helper.make_model(graph, producer_name="onnx-parser")
onnx_model.opset_import[0].version = 12
onnx.save(onnx_model, "./models/postprocess.onnx")

注意这里要根据自己的实际训练参数,修改classes、anchor、input_shape_0、input_shape_1、input_shape_2等变量的数值。

推理代码编写:

import os
import cv2
import time
import numpy as np
from label import labelsimport sys
sys.path.append("./acllite/python/")from acllite_imageproc import AclLiteImage
from acllite_imageproc import AclLiteImageProc
from acllite_model import AclLiteModel
from acllite_resource import AclLiteResource
from acllite_logger import log_infoclass YOLOV7_NMS_ONNX(object):def __init__(self,):self.yolo_model_path = "./models/yolov7.om"    # stringself.yolo_model = Noneself.yolo_model_width = 640self.yolo_model_height = 640#self.yolo_result = Noneself.postprocess_model = Noneself.postprocess_model_path = "./models/postprocess.om"#self.postprocess_input = None#self.postprocess_result = Noneself.resource = None#self.image = None#self.resized_image = Noneself.init_resource()def init_resource(self):# init acl resourceself.resource = AclLiteResource()self.resource.init()# load yolo model from fileself.yolo_model = AclLiteModel(self.yolo_model_path)# load postprocess model from fileself.postprocess_model = AclLiteModel(self.postprocess_model_path)def yolo_process_input(self, image):image = image[:,:,::-1]resized = cv2.resize(image, (self.yolo_model_width, self.yolo_model_height))new_image = resized.astype(np.float32)new_image = new_image / 255.0resized_image = new_image.transpose(2, 0, 1).copy()#self.resized_image = new_image#self.image = imagereturn resized_imagedef postprocess_process_input(self, yolo_result):# construct image infoimage_info = np.array([self.yolo_model_width, self.yolo_model_height,self.yolo_model_width, self.yolo_model_height],dtype=np.float32)#yolo_result.reverse()# construct postprocess inputpostprocess_input = [*yolo_result, image_info]  return postprocess_inputdef yolo_inference(self, resized_image):# inferenceyolo_result = self.yolo_model.execute([resized_image])  return yolo_resultdef postprocess_inference(self, postprocess_input):postprocess_result = self.postprocess_model.execute(postprocess_input)return postprocess_resultdef postprocess_get_reslut(self, src_image, postprocess_result):box_num = postprocess_result[1][0, 0]box_info = postprocess_result[0].flatten()scale_x = src_image.shape[1] / self.yolo_model_widthscale_y = src_image.shape[0] / self.yolo_model_height# get scale factor#if scale_x > scale_y:#    max_scale = scale_x#else:#    max_scale = scale_yids = []scores = []boxes = []for n in range(int(box_num)):id = int(box_info[5 * int(box_num) + n])score = box_info[4 * int(box_num) + n]top_left_x = box_info[0 * int(box_num) + n] * scale_x#max_scaletop_left_y = box_info[1 * int(box_num) + n] * scale_y#max_scalebottom_right_x = box_info[2 * int(box_num) + n] * scale_x#max_scalebottom_right_y = box_info[3 * int(box_num) + n] * scale_y#max_scaleif id ==0:ids.append(id)scores.append(float(score))boxes.append([int(top_left_x), int(top_left_y), int(bottom_right_x), int(bottom_right_y)])return ids, scores, boxesdef release_resource(self):# release resource includes acl resource, data set and unload modelself.yolo_model.__del__()self.postprocess_model.__del__()self.resource.__del__()AclLiteResource.__del__ = lambda x: 0AclLiteModel.__del__ = lambda x: 0def process(self, image):resized_image = self.yolo_process_input(image)yolo_result = self.yolo_inference(resized_image)postprocess_input = self.postprocess_process_input(yolo_result)postprocess_result = self.postprocess_inference(postprocess_input)ids, scores, boxes = self.postprocess_get_reslut(image, postprocess_result)return ids, scores, boxesdef draw(self, image, ids, scores, boxes):colors = [0, 0, 255]# draw the boxes in original image for id, score, box in zip(ids, scores, boxes):label = labels[id] + ":" + str("%.2f" % score)cv2.rectangle(image, (box[0], box[1]), (box[2], box[3]), colors)p3 = (max(box[0], 15), max(box[1], 15))cv2.putText(image, label, p3, cv2.FONT_ITALIC, 0.6, colors, 2)return imagedef __del__(self):self.release_resource()def test_images():current_dir = os.path.dirname(os.path.abspath(__file__))images_path = os.path.join(current_dir, "./data")all_path = []for path in os.listdir(images_path):if path.split(".")[-1] != 'mp4':total_path = os.path.join(images_path, path)all_path.append(total_path)print(all_path)if len(all_path) == 0:raise Exception("the directory is empty, please download image")net = YOLOV7_NMS_ONNX()for images_path in all_path:image = cv2.imread(images_path)t1 = time.time()ids, scores, boxes = net.process(image)src_image = net.draw(image, ids, scores, boxes)t2 = time.time()print("time cost:", t2-t1)output_path = os.path.join("./out", os.path.basename(images_path))cv2.imwrite(output_path, src_image)log_info("success")def test_video():yolov7 =  YOLOV7_NMS_ONNX()# Open the video filevideo_path = "./data/sleep.mp4"cap = cv2.VideoCapture(video_path)fourcc = cv2.VideoWriter_fourcc('X', 'V', 'I', 'D') # 确定视频被保存后的编码格式output = cv2.VideoWriter("output.mp4", fourcc, 25, (852, 480)) # 创建VideoWriter类对象# Loop through the video frameswhile cap.isOpened():# Read a frame from the videosuccess, frame = cap.read()if success:# Run YOLOv8 tracking on the frame, persisting tracks between framest1 = time.time()ids, scores, boxes = yolov7.process(frame)t2 = time.time()annotated_frame = yolov7.draw(frame, ids, scores, boxes)t3 = time.time()print("time", t2-t1, t3-t2,t3-t1)output.write(annotated_frame)# Display the annotated frame# Break the loop if 'q' is pressedif cv2.waitKey(1) & 0xFF == ord("q"):breakelse:# Break the loop if the end of the video is reachedbreak# Release the video capture object and close the display windowcap.release()cv2.destroyAllWindows()if __name__ == "__main__":#test_images()test_video()

测试效果:

视频测试:

B站找一段睡觉的视频下载下来,这里实用you-get工具,

you-get 当 代 高 三 牲 睡 觉 图 鉴_哔哩哔哩_bilibili,实际效果如下,

其他问题记录:

本来自己是想做一个grpc的架构的,可是实际做的过程中发现华为的AclLiteModel实现的很差,对于进程、线程这些非常不友好,必须得是一个进程,同样的上下文才可以得到正确的推理结果。最终也没好的解决方法,重新修改了架构。

华为官方文档链接(aclmdlExecute-模型加载与执行-AscendCL API参考-应用开发(C++)-推理应用开发-CANN商用版6.0.1开发文档-昇腾社区)

参考链接:

https://github.com/WongKinYiu/yolov7

Ascend/modelzoo-GPL - Gitee.com

samples: CANN Samples - Gitee.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/144778.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

峟思科普:溢流坝是什么?溢流坝承载着哪些作用

水坝系统中的一项关键组成部分——溢洪结构,又常被称作溢洪道,其独特功能在于精准调控水库水位,确保水坝安全。当水库蓄水量超过预设阈值,该结构能够引导多余水流平稳穿越坝体,注入下游河床。此过程中,坝前…

Snapchat API 访问:Objective-C 实现示例

Snapchat 是一个流行的社交媒体平台,它允许用户发送和接收短暂存在的图片和视频。对于开发者来说,访问 Snapchat API 可以为应用程序添加独特的社交功能。本文将介绍如何在 Objective-C 中实现对 Snapchat API 的访问,并提供一个详细的代码示…

uni-app页面调用接口和路由(四)

文章目录 一、路由二、页面调用接口二、路由跳转1.uni.navigateTo(OBJECT)2.uni.redirectTo(OBJECT)3.uni.reLaunch(OBJECT)4.uni.switchTab(OBJECT)5.uni.navigateBack(OBJECT) 总结 一、路由 路由配置 uni-app页面路由为框架统一管理,开发者需要在pages.json里配…

yolo自动化项目实例解析(四)ui页面整理1 (1.85)

我们在上一章整理main.py 的if __name__ __main__: 内容还留下面这一段, from PyQt5.QtWidgets import *from lanrenauto.moni.moni import *from PyQt5.QtGui import *app QApplication(sys.argv) # 初始化Qt应用ratio screen_width / 2560 # 分辨率比例# 设…

centos 安装VNC,实现远程连接

centos 安装VNC,实现远程连接 VNC(Virtual Network Computing)是一种远程控制软件,可以实现通过网络远程连接计算机的图形界面。 服务器安装VNC服务 yum install -y tigervnc-server*启动VNC服务,过程中需要输入连接密码 vncserver :1查看…

全国网安众测招募计划启动啦,欢迎加入~

在数字化时代,网络安全已成为维护社会稳定、促进经济发展的基石。为了积极响应国家关于加强网络安全工作的号召,确保某区域关键信息系统的稳固运行,我们特此启动一项网络安全众测活动。该活动旨在通过汇聚业界有经验的网络安全攻防人才&#…

RetrievalAttention——提高 LLM 处理长上下文的效率

概述 论文地址:https://arxiv.org/abs/2409.10516 本文的研究背景主要是为了解决 "具有长语境的大型语言模型(LLM)"问题。基于变换器的 LLM 被广泛应用于各个领域,但在处理长上下文时,其计算成本非常高。特…

电脑USB端口禁止软件有哪些?什么软件能指定USB端口禁用?分享四款好用软件!

想象一下,你正准备在办公桌上插入U盘,打算快速拷贝文件,突然系统蹦出一个警告:“这个USB端口已被禁用!” 是不是感觉好像被一双隐形的手制止了? 其实,这双“隐形的手”就是专门为企业安全设计…

visionpro脚本

visionproToolBlock的脚本的优先级优于工具连线的优先级,一般是照着脚本的执行顺序进行执行对应的工具,最常用的是C#的高级脚本,C#的脚本如下分为5部分。 第一部分:主要是一些库的引用,对于有些类型不知道库的时候&…

vue2中字符串动态拼接字段给到接口

【设计初衷是用户可根据给定的字段进行准确描述】 实现功能: 1. 文本域内容串动态配置字段,以$ {英文}拼接格式给到接口。 (传参如:$ {heat_status_code}正常,$ {wdy_temp}也正常!) 2. 编辑时根…

Instagram全面升级“青少年账号”保护措施,除了信息分类过滤,还应从根源加强内容审核

在持续多年的监管和诉讼压力下,作为社交网站的巨头,Instagram落实了“最严格的青少年用户保护法”。 Instagram 上所有未满 18 岁的用户都将被归为“青少年用户”,默认把账号设置为私密状态,自动实施多项防护措施,很多…

Vue3实战:使用 errorHandler 捕获全局错误

你好同学,我是沐爸,欢迎点赞、收藏、评论和关注。 在 Vue3 中,app.config.errorHandler 是一个错误处理器,用于为应用内抛出的未捕获错误指定一个全局处理函数,它接收三个参数:错误对象、触发该错误的组件…

什么品牌超声波清洗机质量好?四大绝佳超声波清洗机品牌推荐!

在快节奏的现代生活中,个人物品的清洁卫生显得至关重要。眼镜、珠宝饰品、手表乃至日常餐厨用具,这些频繁接触的物品极易累积污渍与细菌。拿眼镜为例,缺乏定期清洁会让油渍与尘埃积累,进而成为细菌的温床,靠近眼睛使用…

人脸识别系统+电插锁安装配置过程

一、适用场景 1、各住宅小区内,一个单元涉及多户,一楼安装公共的人脸识别门禁进行身份的认证。 2、某企业的职工住宅区,企业统一安装人脸识别门禁认证身份。 3、自建楼栋,分多间出租给住户时,每个住户配备电子钥匙存在…

GEE使用require函数调用自己的Js库

新建了一个repository,名为Lib 把我的地形校正的函数放了进去 在自己的代码中调用就用到这个路径,主要Lib后面用冒号

观《中国数据库前世今生》有感:从历史到未来的技术变迁

观《中国数据库前世今生》有感:从历史到未来的技术变迁 在数字化浪潮中,数据库技术作为信息化建设的核心,承载了时代发展的脉搏。观看了纪录片《中国数据库前世今生》后,我深深感受到了中国数据库技术从无到有、从追赶到引领的艰…

深度残差网络ResNet简介

【图书推荐】《PyTorch深度学习与企业级项目实战》-CSDN博客 《PyTorch深度学习与企业级项目实战(人工智能技术丛书)》(宋立桓,宋立林)【摘要 书评 试读】- 京东图书 (jd.com) 卷积神经网络经典模型架构简介-CSDN博客 深度残差网络&#xf…

10分钟搞清楚为什么Transformer中使用LayerNorm而不是BatchNorm

1. Norm(Normalization) 首先,LayerNorm和BatchNorm的Norm是Normalization的缩写,不是Norm-范数。 Normalization在统计学中一般翻译为归一化,还有类似的是Standardization,一般翻译成标准化。这两个概念有什么区别呢? 归一化是…

vue2 + moment 实现日历,并带有上个月和下个月日期的日历

在 Vue 2 中使用 moment 库绘制一个带有上个月和下个月日期的日历,可以通过以下步骤实现。这个日历将显示当前月份的天数,以及前一个月和下一个月的部分日期(通常为了让日历对齐为6行,每行7天)。 主要步骤&#xff1a…

海睿思ABI——不只是BI,更多的是数据和智能

在当今这个数据洪流席卷各行各业的数字化时代,企业BI的建设已不再是可选项,而是驱动企业转型升级、实现精细化运营的必由之路。传统BI通过临时数据集直连业务系统,仅能展示预设报表和仪表盘,难以集成异构数据源,适应业…