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

news2024/11/13 13:01:48

做到这里,其实只是想探索下新的检测框架、探索下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.45

input_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 labels


import 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_info




class YOLOV7_NMS_ONNX(object):
    def __init__(self,):

        self.yolo_model_path = "./models/yolov7.om"    # string
        self.yolo_model = None
        self.yolo_model_width = 640
        self.yolo_model_height = 640
        #self.yolo_result = None
        self.postprocess_model = None
        self.postprocess_model_path = "./models/postprocess.om"
        #self.postprocess_input = None
        #self.postprocess_result = None
        self.resource = None
        #self.image = None
        #self.resized_image = None

        self.init_resource()

        

    def init_resource(self):
        # init acl resource
        self.resource = AclLiteResource()
        self.resource.init()

        # load yolo model from file
        self.yolo_model = AclLiteModel(self.yolo_model_path)
        
        # load postprocess model from file
        self.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.0

        resized_image = new_image.transpose(2, 0, 1).copy()

        #self.resized_image = new_image
        #self.image = image

        return resized_image

    def postprocess_process_input(self, yolo_result):
        # construct image info
        image_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 input
        postprocess_input = [*yolo_result, image_info]  
        return postprocess_input
        
    def yolo_inference(self, resized_image):
        # inference
        yolo_result = self.yolo_model.execute([resized_image])  
        return yolo_result
        
    def postprocess_inference(self, postprocess_input):
        postprocess_result = self.postprocess_model.execute(postprocess_input)
        return postprocess_result
    
    def 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_width
        scale_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_y

        ids = []
        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_scale
            top_left_y = box_info[1 * int(box_num) + n] * scale_y#max_scale
            bottom_right_x = box_info[2 * int(box_num) + n] * scale_x#max_scale
            bottom_right_y = box_info[3 * int(box_num) + n] * scale_y#max_scale

            if 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, boxes


  
    def release_resource(self):
        # release resource includes acl resource, data set and unload model
        self.yolo_model.__del__()
        self.postprocess_model.__del__()
        self.resource.__del__()
        AclLiteResource.__del__ = lambda x: 0
        AclLiteModel.__del__ = lambda x: 0


    def 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, boxes




    def 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 image


    def __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 file
    video_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 frames
    while cap.isOpened():
        # Read a frame from the video
        success, frame = cap.read()

        if success:
            # Run YOLOv8 tracking on the frame, persisting tracks between frames
            t1 = 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 pressed
            if cv2.waitKey(1) & 0xFF == ord("q"):
                break
        else:
            # Break the loop if the end of the video is reached
            break

    # Release the video capture object and close the display window
    cap.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.coloradmin.cn/o/2150113.html

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

相关文章

ApplicationEvent 事件泛型封装记录

一、一个事件的封装、发布以及监听 事件类封装 把需要的信息封装到一个事件类中 Data public class Person {private String name; }Data public class PersonEvent {private Person person;private String addOrUpdate;public PersonEvent(Person person, String addOrUpda…

【云安全】云服务安全攻防

一、云服务安全事件 1、CVE-2021-44228: AWS Log4Shell热补丁漏洞,用来进行容器逃逸和权限提升 2、CVE-2022-30137: Microsoft Azure Service Fabic权限提升漏洞,允许攻击者在容器内提升权限至主机节点root权限 FabricScape: Esca…

神奇的css动画:animation、transform、transition

前言 动画包括两个部分:描述动画的样式和用于指定动画开始、结束以及中间点样式的关键帧。 相比较于传统的脚本实现动画技术,使用css动画三个主要优点: 1.能够非常容易创建简单动画,甚至不需要了解JavaScript就能创建动画 2.动画运行效果…

Trainer API训练属于自己行业的本地大语言模型 医疗本地问答大模型示例

Trainer API 是 Hugging Face transformers 库中强大而灵活的工具,简化了深度学习模型的训练和评估过程。通过提供高层次的接口和多种功能,Trainer API 使研究人员和开发者能够更快地构建和优化自然语言处理模型 文章目录 前言一、Trainer API它能做什么…

Machine Learning Specialization 学习笔记(3)

文章目录 前言一、神经网络基本概念基本组成工作流程训练过程类型应用举例不同层次特征的学习 为什么从基础特征到复杂特征逐渐推进什么是感受野更简单的解释具体示例总结 二、TensorFlow实现简单神经网络安装及环境配置数据预处理标准化 Dense层Convolutional Layer训练DEBUG …

独立站技能树/工具箱1.0 总纲篇丨出海笔记

正所谓要把一件事做到90分很难,但做到60分基本上照着SOP做到位都没问题,如果我们能把每件事都做到60分,那绝对比至少60%的人都强,除非你的对手不讲武德——那就是他很可能看了我这篇文章,不但每方面都超过及格线&#…

MySQL高阶1853-转换日期格式

目录 题目 准备数据 分析数据 总结 题目 给定一个Days表,请你编写SQL查询语句,将Days表中的每一个日期转化为"day_name, month_name day, year"格式的字符串。 返回的结果表 不计顺序 。 准备数据 Create table If Not Exists Days (d…

Arthas 全攻略:让调试变得简单

文章目录 一、简介二、命令列表 一、简介 Arthas 是一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常&#xff…

排序---冒泡排序、堆排序

一、冒泡排序 相邻两个位置交换,假设排升序,就不断把最大的往后拿,所以这段序列从后往前变得有序。 //flag为0,即这个数组已经是有序的了,节省循环次数 二、堆排序(数组实现) 具体原理介绍看这…

jetcache-阿里多级缓存框架神器一定要掌握

文章目录 1. 简介2. springboot集成jetcache2.1 引入依赖2.2 配置文件2.3 高级API模式:通过CacheManager使用缓存,2.7 版本才可使用2.4 (推荐)AOP模式:通过Cached,CacheUpdate,CacheInvalidate注解 1. 简介 JetCache是…

局部整体(六)利用python绘制树状图

局部整体(六)利用python绘制树状图 树状图( Dendrogram)简介 由一个根节点组成,根节点产生多个通过分支连接的子节点。常用于表示层次结构或显示聚类算法的结果。树状图既可以看明白数据的层次结构,也能明…

兴业小知识|法拍房你不知道的省钱小技巧~划走可就亏大了

如果说二手房市场是买卖双方之间的博弈,那法拍房市场则是纯买方的心理游戏。 在法拍房竞拍过程中,有人稳如泰山,有人坐立不安,每一次的出价都是对相互底线的一番试探。 有激进竞拍,拍出天价的,有一举夺魁…

2024.9.20营养小题【2】(动态分配二维数组)

这道题里边涉及到了动态分配二维数组的知识点,不刷这道题我也不知道这个知识点,算是一个比较进阶一点的知识点了。 参考:C语言程序设计_动态分配二维数组_哔哩哔哩_bilibili【C/C 数据结构 】二维数组结构解析 - 知乎 (zhihu.com)

网络爬虫Request静态页面数据获取

在现代 Web 开发中,HTTP 请求(Request)是与服务器进行通信的核心操作。无论是在前端还是后端开发中,数据的获取、传递以及处理都离不开请求的应用。特别是在静态页面的数据获取中,使用请求可以将页面变得更加动态和互动,从而大大提升用户体验,使得页面内容更加丰富和灵活…

电风扇制造5G智能工厂物联数字孪生平台,推进制造业数字化转型

电风扇正悄然成为制造业数字化转型浪潮中的一颗璀璨新星。通过构建5G智能工厂物联数字孪生平台,电风扇制造业正以前所未有的速度和精度,推进着整个行业的智能化、网络化与个性化发展。5G技术的飞速发展,为制造业带来了前所未有的通信速度和低…

vue 入门一

参考&#xff1a;丁丁的哔哩哔哩 1.使用vue 1.1 使用CDN的方式使用Vue mount和<div id"counter">关联起来 1.2 vue中的createApp import { createApp } from "vue"; import App from "./App.vue"; createApp(App).mount("#app&qu…

【软件测试】如何设计测试用例? 设计测试用例常用的方法.

目录 一.什么是测试用例?二.总体设计测试用例的万能公式.2.1 功能性能界面兼容易用安全2.2 弱网测试2.3 安装卸载测试. 三. 常用设计具体测试用例的方法3.1 等价类3.2 边界值3.3 正交法3.3.1 正交表3.3.2 如何设计正交表,并根据正交表编写测试用例 3.4 判定表法3.4.1 根据判定…

红日药业携手实在智能,构建RPA数字员工平台满足业务一体化需求 | 实在RPA案例

近日&#xff0c;天津红日药业股份有限公司&#xff08;简称“红日药业”&#xff09;与实在智能达成合作&#xff0c;依托实在智能业内领先的AIRPA技术&#xff0c;红日药业着手构建企业数字员工平台&#xff0c;满足业务一体化需求&#xff0c;培育新质生产力&#xff0c;为企…

基于PHP的电脑线上销售系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于phpMySQL的电脑线上销售系…

小程序服务零工市场

零工市场小程序有着信息发布、岗位匹配、线上接单、零工人员保障险参保、技能培训、费用结算、完工确认、服务评价、纠纷调解等功能&#xff0c;为求职者和雇主搭建一座高效、便捷、精准的对接桥梁。 用工单位通过小程序的“雇主找人”&#xff0c;发布招聘信息&#xff0c;找到…