基于华为atlas的重车(满载)空车(空载)识别

该教程主要是想摸索出华为atlas的基于ACL的推理模式。最终实现通过煤矿磅道上方的摄像头,识别出车辆的重车(满载)、空车(空载)情况。本质上是一个简单的检测问题。

但是整体探索过程比较坎坷,Tianxiaomo的代码可以基于原始yolov4模型进行推理,可以转化onnx,但是训练过程我感觉代码有问题,loss很大,也没检测框输出。同时输出的结果的维度和atlas教程的维度也不一样。对于这2个问题,第1个问题训练效果不对选择使用原始darknet网络解决,第2个问题输出维度和atlas不一样通过重新实现atlas后处理代码实现。

风雨兼程,终见彩虹;艰辛耕耘,方得硕果。

darknet数据集制作及配置文件修改:

(1)数据集采用labelimg工具标注为VOC格式,一共标注了1087张图片。

(2)数据集格式如下,

其中,VOC2025为我自己的数据集起的名字,你也可以起别的名字,Annotations存放XML文件,Main中存放,train.txt,val.txt,txt中只写图片的名字,一行一个。JPEGImages中存放图片。labels中存放由XML生成的txt文件。

(3)修改scripts下面的voc_label.py,将数据集的目录修改为自己的目录,

#开始几行
sets=[('2025', 'train'), ('2025', 'val')]
classes = ["full", "empty"]
#最后2行
os.system("cat 2025_train.txt 2025_val.txt > train.txt")
os.system("cat 2025_train.txt 2025_val.txt > train.all.txt")

然后执行

Python3 scripts/voc_label.py

就会生成labels文件夹,以及文件夹下面的txt标记,以及train.txt 和train.all.txt

其中,train.txt中存储路径+图片名,一行一个

/data/jxl/darknet/VOCdevkit/VOC2025/JPEGImages/3743_01467.jpg
/data/jxl/darknet/VOCdevkit/VOC2025/JPEGImages/3743_01468.jpg
/data/jxl/darknet/VOCdevkit/VOC2025/JPEGImages/3743_01469.jpg
/data/jxl/darknet/VOCdevkit/VOC2025/JPEGImages/3743_01559.jpg

Labels文件夹下每个图片对应一个txt文件,里面存储类别 框坐标的归一化值

0 0.6794407894736842 0.5394736842105263 0.5516447368421052 0.9195906432748537

(4)修改,cfg/fullempty.data

classes= 2
train  = ./VOCdevkit/VOC2025/ImageSets/Main/train.txt
valid  = ./VOCdevkit/VOC2025/ImageSets/Main/val.txt
names = ./data/fullempty.names
backup = ./pjreddie/backup/

class为训练的类别数

train为训练集train.txt

valid为验证集val.txt

names为fullempty.names,里面为自己训练的目标名称

backup为weights的存储位置

(5)修改cfg/yolov4-fullempty.cfg

修改每个classes=2

修改最后一个卷基层,filters和最后一个region的classes,num参数是因为yolov4有3个分支,每个分支3个anchor。

其中,filters=num×(classes + coords + 1)=3*(2+4+1)=21,这里我有2个类别。

(6)修改data/fullempty.names

full
empty

darknet模型训练:

./darknet detector train ./cfg/fullempty.data ./cfg/yolov4-fullempty.cfg  ./yolov4.weights -clear

darknet的.weights模型测试:

./darknet detect  ./cfg/yolov4-fullempty.cfg  ./pjreddie/backup/yolov4-fullempty_last.weights  ./VOCdevkit/VOC2025/JPEGImages/2793_00847.jpg

Pytorch代码配置文件修改:

#cfg.py,

Cfg.use_darknet_cfg = True
Cfg.cfgfile = os.path.join(_BASE_DIR, 'cfg', 'yolov4-custom.cfg')

#cfg/yolov4-custom.cfg,

Pytorch代码bug修改:

#train.py211行,

pred_ious = bboxes_iou(pred[b].view(-1, 4), truth_box, xyxy=False)修改为,
pred_ious = bboxes_iou(pred[b].contiguous().view(-1, 4), truth_box, xyxy=False)

# dataset.py, get_image_id函数,因为我的图片命名规则是Id_id.jpg,所以将2个id拼接起来作为最终的id。

parts = filename.split('.')[0].split('_')
id = int(parts[0]+ parts[1])
return id

基于pytorch代码的.weights模型测试:

python3 demo.py -cfgfile ./cfg/yolov4-custom.cfg -weightfile ./yolov4-fullempty_last.weights -imgfile ./full_empty_dataset/images/2793_00847.jpg -torch False

.weights模型转onnx模型:

python3 demo_darknet2onnx.py ./cfg/yolov4-custom.cfg ./data/full_empty.names ./yolov4-fullempty_last.weights ./full_empty_dataset/images/2793_00847.jpg 1

onnx模型转om模型:

atc --model=./yolov4_1_3_608_608_static.onnx --framework=5 --output=yolov4_bs1 --input_shape="input:1,3,608, 608"  --soc_version=Ascend310P3 --input_format=NCHW

atlas推理代码编写:

#yolov4.py

import sys
sys.path.append("./common/acllite")
import os
import numpy as np
import acl
import cv2
import time
from acllite_model import AclLiteModel
from acllite_resource import AclLiteResourcefrom utils import post_processing, plot_boxes_cv2MODEL_PATH = "./model/yolov4_bs1.om"#ACL resource initialization
acl_resource = AclLiteResource()
acl_resource.init()
#load model
model = AclLiteModel(MODEL_PATH)class YOLOV4(object):def __init__(self):self.MODEL_PATH = MODEL_PATHself.MODEL_WIDTH = 608self.MODEL_HEIGHT = 608self.class_names= ['full', 'empty']self.model = modeldef preprocess(self, bgr_img):sized = cv2.resize(bgr_img.copy(), (self.MODEL_WIDTH, self.MODEL_HEIGHT))sized = cv2.cvtColor(sized, cv2.COLOR_BGR2RGB)new_image = sized.astype(np.float32)new_image = new_image / 255.0new_image = new_image.transpose(2, 0, 1).copy()return new_imagedef process(self, bgr_img):height, width = bgr_img.shape[:2]#preprocessdata = self.preprocess(bgr_img)#(3, 608, 608)#Send into model inferenceresult_list = self.model.execute([data,])    #Process inference resultsconf_thresh, nms_thresh = 0.4, 0.6boxes = post_processing(conf_thresh, nms_thresh, result_list, height, width)return boxesdef draw(self, bgr_img, boxes):drawed_img = plot_boxes_cv2(bgr_img, boxes[0], class_names=self.class_names)return drawed_imgdef test_image():yolov4 = YOLOV4()img_name = "./data/3553_00173.jpg"#read imagebgr_img = cv2.imread(img_name)t1 = time.time()boxes = yolov4.process(bgr_img)t2 = time.time()drawed_img = yolov4.draw(bgr_img, boxes)t3 = time.time()print("result = ", len(boxes[0]), boxes, t2-t1, t3-t2)cv2.imwrite("out.jpg", drawed_img)if __name__ == '__main__':test_image()

#utils.py

import sys
import os
import time
import math
import numpy as npimport itertools
import struct  # get_image_size
import imghdr  # get_image_sizedef sigmoid(x):return 1.0 / (np.exp(-x) + 1.)def softmax(x):x = np.exp(x - np.expand_dims(np.max(x, axis=1), axis=1))x = x / np.expand_dims(x.sum(axis=1), axis=1)return xdef bbox_iou(box1, box2, x1y1x2y2=True):if x1y1x2y2:mx = min(box1[0], box2[0])Mx = max(box1[2], box2[2])my = min(box1[1], box2[1])My = max(box1[3], box2[3])w1 = box1[2] - box1[0]h1 = box1[3] - box1[1]w2 = box2[2] - box2[0]h2 = box2[3] - box2[1]else:w1 = box1[2]h1 = box1[3]w2 = box2[2]h2 = box2[3]mx = min(box1[0], box2[0])Mx = max(box1[0] + w1, box2[0] + w2)my = min(box1[1], box2[1])My = max(box1[1] + h1, box2[1] + h2)uw = Mx - mxuh = My - mycw = w1 + w2 - uwch = h1 + h2 - uhcarea = 0if cw <= 0 or ch <= 0:return 0.0area1 = w1 * h1area2 = w2 * h2carea = cw * chuarea = area1 + area2 - careareturn carea / uareadef nms_cpu(boxes, confs, nms_thresh=0.5, min_mode=False):x1 = boxes[:, 0]y1 = boxes[:, 1]x2 = boxes[:, 2]y2 = boxes[:, 3]areas = (x2 - x1) * (y2 - y1)order = confs.argsort()[::-1]keep = []while order.size > 0:idx_self = order[0]idx_other = order[1:]keep.append(idx_self)xx1 = np.maximum(x1[idx_self], x1[idx_other])yy1 = np.maximum(y1[idx_self], y1[idx_other])xx2 = np.minimum(x2[idx_self], x2[idx_other])yy2 = np.minimum(y2[idx_self], y2[idx_other])w = np.maximum(0.0, xx2 - xx1)h = np.maximum(0.0, yy2 - yy1)inter = w * hif min_mode:over = inter / np.minimum(areas[order[0]], areas[order[1:]])else:over = inter / (areas[order[0]] + areas[order[1:]] - inter)inds = np.where(over <= nms_thresh)[0]order = order[inds + 1]return np.array(keep)def plot_boxes_cv2(img, boxes, class_names=None, color=None):import cv2img = np.copy(img)colors = np.array([[1, 0, 1], [0, 0, 1], [0, 1, 1], [0, 1, 0], [1, 1, 0], [1, 0, 0]], dtype=np.float32)def get_color(c, x, max_val):ratio = float(x) / max_val * 5i = int(math.floor(ratio))j = int(math.ceil(ratio))ratio = ratio - ir = (1 - ratio) * colors[i][c] + ratio * colors[j][c]return int(r * 255)width = img.shape[1]height = img.shape[0]for i in range(len(boxes)):box = boxes[i]x1 = int(box[0])y1 = int(box[1])x2 = int(box[2])y2 = int(box[3])bbox_thick = int(0.6 * (height + width) / 600)if color:rgb = colorelse:rgb = (255, 0, 0)if len(box) >= 7 and class_names:cls_conf = box[5]cls_id = box[6]print('%s: %f' % (class_names[cls_id], cls_conf))classes = len(class_names)offset = cls_id * 123457 % classesred = get_color(2, offset, classes)green = get_color(1, offset, classes)blue = get_color(0, offset, classes)if color is None:rgb = (red, green, blue)msg = str(class_names[cls_id])+" "+str(round(cls_conf,3))t_size = cv2.getTextSize(msg, 0, 0.7, thickness=bbox_thick // 2)[0]c1, c2 = (x1,y1), (x2, y2)c3 = (c1[0] + t_size[0], c1[1] - t_size[1] - 3)cv2.rectangle(img, (x1,y1), (np.int32(c3[0]), np.int32(c3[1])), rgb, -1)img = cv2.putText(img, msg, (c1[0], np.int32(c1[1] - 2)), cv2.FONT_HERSHEY_SIMPLEX,0.7, (0,0,0), bbox_thick//2,lineType=cv2.LINE_AA)#cv2.rectangle(img, (x1,y1), (np.float32(c3[0]), np.float32(c3[1])), rgb, -1)#img = cv2.putText(img, msg, (c1[0], np.float32(c1[1] - 2)), cv2.FONT_HERSHEY_SIMPLEX,0.7, (0,0,0), bbox_thick//2,lineType=cv2.LINE_AA)img = cv2.rectangle(img, (x1, y1), (x2, y2), rgb, bbox_thick)return imgdef read_truths(lab_path):if not os.path.exists(lab_path):return np.array([])if os.path.getsize(lab_path):truths = np.loadtxt(lab_path)truths = truths.reshape(truths.size / 5, 5)  # to avoid single truth problemreturn truthselse:return np.array([])def load_class_names(namesfile):class_names = []with open(namesfile, 'r') as fp:lines = fp.readlines()for line in lines:line = line.rstrip()class_names.append(line)return class_namesdef post_processing(conf_thresh, nms_thresh, output, height, width):# anchors = [12, 16, 19, 36, 40, 28, 36, 75, 76, 55, 72, 146, 142, 110, 192, 243, 459, 401]# num_anchors = 9# anchor_masks = [[0, 1, 2], [3, 4, 5], [6, 7, 8]]# strides = [8, 16, 32]# anchor_step = len(anchors) // num_anchors# [batch, num, 1, 4]box_array = output[0]# [batch, num, num_classes]confs = output[1]t1 = time.time()if type(box_array).__name__ != 'ndarray':box_array = box_array.cpu().detach().numpy()confs = confs.cpu().detach().numpy()num_classes = confs.shape[2]# [batch, num, 4]box_array = box_array[:, :, 0]# [batch, num, num_classes] --> [batch, num]max_conf = np.max(confs, axis=2)max_id = np.argmax(confs, axis=2)t2 = time.time()bboxes_batch = []for i in range(box_array.shape[0]):argwhere = max_conf[i] > conf_threshl_box_array = box_array[i, argwhere, :]l_max_conf = max_conf[i, argwhere]l_max_id = max_id[i, argwhere]bboxes = []# nms for each classfor j in range(num_classes):cls_argwhere = l_max_id == jll_box_array = l_box_array[cls_argwhere, :]ll_max_conf = l_max_conf[cls_argwhere]ll_max_id = l_max_id[cls_argwhere]keep = nms_cpu(ll_box_array, ll_max_conf, nms_thresh)if (keep.size > 0):ll_box_array = ll_box_array[keep, :]ll_max_conf = ll_max_conf[keep]ll_max_id = ll_max_id[keep]for k in range(ll_box_array.shape[0]):bboxes.append([ll_box_array[k, 0]*width, ll_box_array[k, 1]*height, ll_box_array[k, 2]*width, ll_box_array[k, 3]*height, ll_max_conf[k], ll_max_conf[k], ll_max_id[k]])bboxes_batch.append(bboxes)t3 = time.time()return bboxes_batch

atlas推理代码测试:

python3 yolov4.py

视频测试:

参考链接:

https://github.com/AlexeyAB/darknet

https://github.com/Tianxiaomo/pytorch-YOLOv4

samples: CANN Samples - Gitee.com

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

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

相关文章

《零基础Go语言算法实战》【题目 2-25】goroutine 的执行权问题

《零基础Go语言算法实战》 【题目 2-25】goroutine 的执行权问题 请说明以下这段代码为什么会卡死。 package main import ( "fmt" "runtime" ) func main() { var i byte go func() { for i 0; i < 255; i { } }() fmt.Println("start&quo…

IntelliJ IDEA中Maven项目的配置、创建与导入全攻略

大家好&#xff0c;我是袁庭新。 IntelliJ IDEA是当前最流行的Java IDE&#xff08;集成开发环境&#xff09;之一&#xff0c;也是业界公认最好用的Java开发工具之一。IntelliJ IDEA支持Maven的全部功能&#xff0c;通过它我们可以很轻松地实现创建Maven项目、导入Maven项目、…

TypeScript语言的学习路线

TypeScript语言的学习路线 TypeScript&#xff08;TS&#xff09;是由Microsoft开发的一种开源编程语言&#xff0c;是JavaScript的超集&#xff0c;提供了严格的类型检查和基于类的面向对象编程特性。随着前端开发的不断进步&#xff0c;TypeScript逐渐成为了现代前端开发的主…

计算机网络之---静态路由与动态路由

静态路由 静态路由是由网络管理员手动配置并固定的路由方式。路由器通过静态配置的路由条目来转发数据包&#xff0c;而不会自动调整。它不依赖于任何路由协议。 特点&#xff1a; 手动配置&#xff1a;网络管理员需要手动在路由器中配置每条静态路由。不自动更新&#xff1a;…

【Rust】函数

目录 思维导图 1. 函数的基本概念 1.1 函数的定义 2. 参数的使用 2.1 单个参数的示例 2.2 多个参数的示例 3. 语句与表达式 3.1 语句与表达式的区别 3.2 示例 4. 带返回值的函数 4.1 返回值的示例 4.2 返回值与表达式 5. 错误处理 5.1 错误示例 思维导图 1. 函数…

Cython全教程2 多种定义方式

—— 本篇文章&#xff0c;主要讲述Cython中的四种定义关键字 全教程2 多种定义方式&#xff1a; 在Cython中&#xff0c;关于定义的关键字有四个&#xff0c;分别是&#xff1a; cdef、def、cpdef、DEF 一、cdef定义关键字 顾名思义&#xff0c;cdef关键字定义的是一个C函数…

Web开发(一)HTML5

Web开发&#xff08;一&#xff09;HTML5 写在前面 参考黑马程序员前端Web教程做的笔记&#xff0c;主要是想后面自己搭建网页玩。 这部分是前端HTML5CSS3移动web视频教程的HTML5部分。主要涉及到HTML的基础语法。 HTML基础 标签定义 HTML定义 HTML(HyperText Markup Lan…

MATLAB学习笔记目录

MATLAB学习笔记-生成纯音并保存-CSDN博客 MATLAB学习笔记-各种格式之间的转换 - 知乎 MATLAB学习笔记-胞组&#xff08;cell array&#xff09;转换为矩阵&#xff0c;cell2mat_matlab如何把元胞数组改为矩阵-CSDN博客MATLAB学习笔记-判断数组、结构体、数值、字符串是否相同…

Java-数据结构-栈与队列(常考面试题与单调栈)

在上一篇的学习中&#xff0c;我们学习了栈和队列的基本知识&#xff0c;以及它们对应都有哪些方法&#xff0c;在什么应用场景下如何使用&#xff0c;并且还对它们进行了模拟实现&#xff0c;而其实对于栈和队列的相关知识还远不止于此&#xff0c;而今天我们就对栈与队列进行…

JSON.stringify(res,null,2)的含义

JSON.stringify(res, null, 2) 是 JavaScript 中将对象转换为 JSON 字符串的方法&#xff0c;具体说明如下&#xff1a; 参数解释 res&#xff1a;要转换的对象。它可以是 JavaScript 中的任意类型&#xff0c;如对象、数组、字符串、数字等。例如&#xff0c;{name: "K…

Spring 项目 基于 Tomcat容器进行部署

文章目录 一、前置知识二、本地Idea运行Spring项目1. 将写好的 Spring 项目先打包成 war 包2. 查看项目工件&#xff08;Artifact&#xff09;是否存在3. 配置 Tomcat3.1 添加一个本地 Tomcat 容器3.2 将项目部署到 Tomcat 4. 运行项目 三、基于 Tomcat 部署及多实例部署1. Spr…

usbredir学习

文章目录 背景典型场景编译usbredirparserusbredirfilterusbredirparser/usbredirproto usbredirhostusbredirect/usbredirtestclient参考 背景 usbredir 是一种用于通过网络转发 USB 设备流量的网络协议。它也是一个软件包的名称&#xff0c;该软件包提供了一个解析库、一个 …

ESXI 安装教程(3) ---​vCenter Server 安装

不涉及复杂的操作此项可不安装 1.镜像加载到虚拟光盘 对应的网盘文件 2.打开文件路径 双击运行文件installer.exe 3.调整安装语言 4.点击安装 5. 6. 证书,有效问题导致此提示,非专业网络管理人员,不知道如何处理,此处点是即可 证书有效开始时间是安装时间8小时 证书有效结束…

【初识扫盲】逆概率加权

我们正在处理一个存在缺失数据的回归模型&#xff0c;并且希望采用一种非参数的逆概率加权方法来调整估计&#xff0c;以应对这种缺失数据的情况。 首先&#xff0c;我们需要明确问题的背景。我们有样本 { ( Y i , X i , r i ) : i 1 , … , n } \left\{\left(Y_i, \boldsym…

极客说|Azure AI Agent Service 结合 AutoGen/Semantic Kernel 构建多智能体解决⽅案

作者&#xff1a;卢建晖 - 微软高级云技术布道师 「极客说」 是一档专注 AI 时代开发者分享的专栏&#xff0c;我们邀请来自微软以及技术社区专家&#xff0c;带来最前沿的技术干货与实践经验。在这里&#xff0c;您将看到深度教程、最佳实践和创新解决方案。关注「极客说」&am…

【集成学习】Boosting算法详解

文章目录 1. 集成学习概述2. Boosting算法详解3. Gradient Boosting算法详解3.1 基本思想3.2 公式推导 4. Python实现 1. 集成学习概述 集成学习&#xff08;Ensemble Learning&#xff09;是一种通过结合多个模型的预测结果来提高整体预测性能的技术。相比于单个模型&#xf…

小米vela系统(基于开源nuttx内核)——如何使用信号量进行PV操作

如何使用信号量进行PV操作 前言信号量1. 信号量简介2. NuttX中信号量的创建与使用2.1 Nuttx信号量的初始化和销毁2.2 信号量的等待和发布 3. 信号量的实际应用&#xff1a;下载任务示例3.1 实际代码3.2 代码说明3.3 执行说明 4. 信号量的优势与应用场景5. 常见应用场景&#xf…

CMake学习笔记(2)

1. 嵌套的CMake 如果项目很大&#xff0c;或者项目中有很多的源码目录&#xff0c;在通过CMake管理项目的时候如果只使用一个CMakeLists.txt&#xff0c;那么这个文件相对会比较复杂&#xff0c;有一种化繁为简的方式就是给每个源码目录都添加一个CMakeLists.txt文件&#xff…

旅游网站设计与实现

文末附有完整项目代码 在当今数字化时代&#xff0c;旅游网站成为人们获取旅游信息的重要途径。本文将详细介绍旅游网站的设计与实现&#xff0c;让你轻松了解其中的技术奥秘&#xff01; 一、项目背景 随着社会经济的发展&#xff0c;人们对精神消费愈发重视&#xff0c;旅游…

【C++】size_t究竟是什么?全面解析与深入拓展

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;一、什么是size_t&#xff1f;为什么需要size_t&#xff1f; &#x1f4af;二、size_t的特性与用途1. size_t是无符号类型示例&#xff1a; 2. size_t的跨平台适应性示例对…