当前位置: 首页 > news >正文

Atlas800昇腾服务器(型号:3000)—YOLO全系列NPU推理【检测】(五)

服务器配置如下:

CPU/NPU:鲲鹏 CPU(ARM64)+A300I pro推理卡
系统:Kylin V10 SP1【下载链接】【安装链接】
驱动与固件版本版本
Ascend-hdk-310p-npu-driver_23.0.1_linux-aarch64.run【下载链接】
Ascend-hdk-310p-npu-firmware_7.1.0.4.220.run【下载链接】
MCU版本:Ascend-hdk-310p-mcu_23.2.3【下载链接】
CANN开发套件:版本7.0.1【Toolkit下载链接】【Kernels下载链接】

测试om模型环境如下:

Python:版本3.8.11
推理工具:ais_bench
测试YOLO系列:v5/6/7/8/9/10/11

专栏其他文章
Atlas800昇腾服务器(型号:3000)—驱动与固件安装(一)
Atlas800昇腾服务器(型号:3000)—CANN安装(二)
Atlas800昇腾服务器(型号:3000)—YOLO全系列om模型转换测试(三)
Atlas800昇腾服务器(型号:3000)—AIPP加速前处理(四)
Atlas800昇腾服务器(型号:3000)—YOLO全系列NPU推理【检测】(五)
Atlas800昇腾服务器(型号:3000)—YOLO全系列NPU推理【实例分割】(六)
Atlas800昇腾服务器(型号:3000)—YOLO全系列NPU推理【关键点】(七)
Atlas800昇腾服务器(型号:3000)—YOLO全系列NPU推理【跟踪】(八)

全部代码github:https://github.com/Bigtuo/NPU-ais_bench

1 基础环境安装

详情见第(三)章环境安装:https://blog.csdn.net/weixin_45679938/article/details/142966255

2 ais_bench编译安装

注意:目前ais_bench工具只支持单个input的带有动态AIPP配置的模型,只支持静态shape、动态batch、动态宽高三种场景,不支持动态shape场景。
参考链接:https://gitee.com/ascend/tools/tree/master/ais-bench_workload/tool/ais_bench

2.1 安装aclruntime包

在安装环境执行如下命令安装aclruntime包:
说明:若为覆盖安装,请增加“–force-reinstall”参数强制安装.

pip3 install -v 'git+https://gitee.com/ascend/tools.git#egg=aclruntime&subdirectory=ais-bench_workload/tool/ais_bench/backend' -i https://pypi.tuna.tsinghua.edu.cn/simple

在这里插入图片描述

2.2 安装ais_bench推理程序包

在安装环境执行如下命令安装ais_bench推理程序包:

 pip3 install -v 'git+https://gitee.com/ascend/tools.git#egg=ais_bench&subdirectory=ais-bench_workload/tool/ais_bench' -i https://pypi.tuna.tsinghua.edu.cn/simple

在这里插入图片描述
卸载和更新【忽略】:

# 卸载aclruntime
pip3 uninstall aclruntime
# 卸载ais_bench推理程序
pip3 uninstall ais_bench

3 裸代码推理测试

# 1.进入运行环境yolo【普通用户】
conda activate yolo
# 2.激活atc【atc --help测试是否可行】
source ~/bashrc

注意:ais_bench调用和使用方式与onnx-runtime几乎一致,因此可参考进行撰写脚本!

代码逻辑如下
下面代码整个处理过程主要包括:预处理—>推理—>后处理—>画图。
假设图像resize为640×640,
前处理输出结果维度:(1, 3, 640, 640);
YOLOv5/6/7推理输出结果维度:(1, 8400×3, 85),其中85表示4个box坐标信息+置信度分数+80个类别概率,8400×3表示(80×80+40×40+20×20)×3,不同于v8与v9采用类别里面最大的概率作为置信度score;
YOLOv8/9/11推理输出结果维度:(1, 84, 8400),其中84表示4个box坐标信息+80个类别概率,8400表示80×80+40×40+20×20;
YOLOv10推理输出结果维度:(1, 300, 6),其中300是默认输出数量,无nms操作,阈值过滤即可,6是4个box坐标信息+置信度分数+类别。
后处理输出结果维度:(5, 6),其中第一个5表示图bus.jpg检出5个目标,第二个维度6表示(x1, y1, x2, y2, conf, cls)。

完整代码如下
新建YOLO_ais_bench_det_aipp.py,内容如下:

import argparse
import time 
import cv2
import numpy as np
import osfrom ais_bench.infer.interface import InferSessionclass YOLO:"""YOLO object detection model class for handling inference"""def __init__(self, om_model, imgsz=(640, 640), device_id=0, model_ndtype=np.single, mode="static", postprocess_type="v8", aipp=False):"""Initialization.Args:om_model (str): Path to the om model."""# 构建ais_bench推理引擎self.session = InferSession(device_id=device_id, model_path=om_model)# Numpy dtype: support both FP32(np.single) and FP16(np.half) om modelself.ndtype = model_ndtypeself.mode = modeself.postprocess_type = postprocess_typeself.aipp = aipp  self.model_height, self.model_width = imgsz[0], imgsz[1]  # 图像resize大小def __call__(self, im0, conf_threshold=0.4, iou_threshold=0.45):"""The whole pipeline: pre-process -> inference -> post-process.Args:im0 (Numpy.ndarray): original input image.conf_threshold (float): confidence threshold for filtering predictions.iou_threshold (float): iou threshold for NMS.Returns:boxes (List): list of bounding boxes."""# 前处理Pre-processt1 = time.time()im, ratio, (pad_w, pad_h) = self.preprocess(im0)pre_time = round(time.time() - t1, 3)# 推理 inferencet2 = time.time()preds = self.session.infer([im], mode=self.mode)[0]  # mode有动态"dymshape"和静态"static"等det_time = round(time.time() - t2, 3)# 后处理Post-processt3 = time.time()if self.postprocess_type == "v5":boxes = self.postprocess_v5(preds,im0=im0,ratio=ratio,pad_w=pad_w,pad_h=pad_h,conf_threshold=conf_threshold,iou_threshold=iou_threshold,)elif self.postprocess_type == "v8":boxes = self.postprocess_v8(preds,im0=im0,ratio=ratio,pad_w=pad_w,pad_h=pad_h,conf_threshold=conf_threshold,iou_threshold=iou_threshold,)elif self.postprocess_type == "v10":boxes = self.postprocess_v10(preds,im0=im0,ratio=ratio,pad_w=pad_w,pad_h=pad_h,conf_threshold=conf_threshold)else:boxes = []post_time = round(time.time() - t3, 3)return boxes, (pre_time, det_time, post_time)# 前处理,包括:resize, pad, 其中HWC to CHW,BGR to RGB,归一化,增加维度CHW -> BCHW可选择是否开启AIPP加速处理def preprocess(self, img):"""Pre-processes the input image.Args:img (Numpy.ndarray): image about to be processed.Returns:img_process (Numpy.ndarray): image preprocessed for inference.ratio (tuple): width, height ratios in letterbox.pad_w (float): width padding in letterbox.pad_h (float): height padding in letterbox."""# Resize and pad input image using letterbox() (Borrowed from Ultralytics)shape = img.shape[:2]  # original image shapenew_shape = (self.model_height, self.model_width)r = min(new_shape[0] / shape[0], new_shape[1] / shape[1])ratio = r, rnew_unpad = int(round(shape[1] * r)), int(round(shape[0] * r))pad_w, pad_h = (new_shape[1] - new_unpad[0]) / 2, (new_shape[0] - new_unpad[1]) / 2  # wh paddingif shape[::-1] != new_unpad:  # resizeimg = cv2.resize(img, new_unpad, interpolation=cv2.INTER_LINEAR)top, bottom = int(round(pad_h - 0.1)), int(round(pad_h + 0.1))left, right = int(round(pad_w - 0.1)), int(round(pad_w + 0.1))img = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_CONSTANT, value=(114, 114, 114))  # 填充# 是否开启aipp加速预处理,需atc中完成if self.aipp:return img, ratio, (pad_w, pad_h)# Transforms: HWC to CHW -> BGR to RGB -> div(255) -> contiguous -> add axis(optional)img = np.ascontiguousarray(np.einsum('HWC->CHW', img)[::-1], dtype=self.ndtype) / 255.0img_process = img[None] if len(img.shape) == 3 else imgreturn img_process, ratio, (pad_w, pad_h)# YOLOv5/6/7通用后处理,包括:阈值过滤与NMSdef postprocess_v5(self, preds, im0, ratio, pad_w, pad_h, conf_threshold, iou_threshold):"""Post-process the prediction.Args:preds (Numpy.ndarray): predictions come from ort.session.run().im0 (Numpy.ndarray): [h, w, c] original input image.ratio (tuple): width, height ratios in letterbox.pad_w (float): width padding in letterbox.pad_h (float): height padding in letterbox.conf_threshold (float): conf threshold.iou_threshold (float): iou threshold.Returns:boxes (List): list of bounding boxes."""# (Batch_size, Num_anchors, xywh_score_conf_cls), v5和v6的[..., 4]是置信度分数,v8v9采用类别里面最大的概率作为置信度scorex = preds  # outputs: predictions (1, 8400*3, 85)# Predictions filtering by conf-thresholdx = x[x[..., 4] > conf_threshold]# Create a new matrix which merge these(box, score, cls) into one# For more details about `numpy.c_()`: https://numpy.org/doc/1.26/reference/generated/numpy.c_.htmlx = np.c_[x[..., :4], x[..., 4], np.argmax(x[..., 5:], axis=-1)]# NMS filtering# 经过NMS后的值, np.array([[x, y, w, h, conf, cls], ...]), shape=(-1, 4 + 1 + 1)x = x[cv2.dnn.NMSBoxes(x[:, :4], x[:, 4], conf_threshold, iou_threshold)]# 重新缩放边界框,为画图做准备if len(x) > 0:# Bounding boxes format change: cxcywh -> xyxyx[..., [0, 1]] -= x[..., [2, 3]] / 2x[..., [2, 3]] += x[..., [0, 1]]# Rescales bounding boxes from model shape(model_height, model_width) to the shape of original imagex[..., :4] -= [pad_w, pad_h, pad_w, pad_h]x[..., :4] /= min(ratio)# Bounding boxes boundary clampx[..., [0, 2]] = x[:, [0, 2]].clip(0, im0.shape[1])x[..., [1, 3]] = x[:, [1, 3]].clip(0, im0.shape[0])return x[..., :6]  # boxeselse:return []# YOLOv8/9/11通用后处理,包括:阈值过滤与NMSdef postprocess_v8(self, preds, im0, ratio, pad_w, pad_h, conf_threshold, iou_threshold):"""Post-process the prediction.Args:preds (Numpy.ndarray): predictions come from ort.session.run().im0 (Numpy.ndarray): [h, w, c] original input image.ratio (tuple): width, height ratios in letterbox.pad_w (float): width padding in letterbox.pad_h (float): height padding in letterbox.conf_threshold (float): conf threshold.iou_threshold (float): iou threshold.Returns:boxes (List): list of bounding boxes."""x = preds  # outputs: predictions (1, 84, 8400)# Transpose the first output: (Batch_size, xywh_conf_cls, Num_anchors) -> (Batch_size, Num_anchors, xywh_conf_cls)x = np.einsum('bcn->bnc', x)  # (1, 8400, 84)# Predictions filtering by conf-thresholdx = x[np.amax(x[..., 4:], axis=-1) > conf_threshold]# Create a new matrix which merge these(box, score, cls) into one# For more details about `numpy.c_()`: https://numpy.org/doc/1.26/reference/generated/numpy.c_.htmlx = np.c_[x[..., :4], np.amax(x[..., 4:], axis=-1), np.argmax(x[..., 4:], axis=-1)]# NMS filtering# 经过NMS后的值, np.array([[x, y, w, h, conf, cls], ...]), shape=(-1, 4 + 1 + 1)x = x[cv2.dnn.NMSBoxes(x[:, :4], x[:, 4], conf_threshold, iou_threshold)]# 重新缩放边界框,为画图做准备if len(x) > 0:# Bounding boxes format change: cxcywh -> xyxyx[..., [0, 1]] -= x[..., [2, 3]] / 2x[..., [2, 3]] += x[..., [0, 1]]# Rescales bounding boxes from model shape(model_height, model_width) to the shape of original imagex[..., :4] -= [pad_w, pad_h, pad_w, pad_h]x[..., :4] /= min(ratio)# Bounding boxes boundary clampx[..., [0, 2]] = x[:, [0, 2]].clip(0, im0.shape[1])x[..., [1, 3]] = x[:, [1, 3]].clip(0, im0.shape[0])return x[..., :6]  # boxeselse:return []# YOLOv10后处理,包括:阈值过滤-无NMSdef postprocess_v10(self, preds, im0, ratio, pad_w, pad_h, conf_threshold):x = preds  # outputs: predictions (1, 300, 6) -> (xyxy_conf_cls)# Predictions filtering by conf-thresholdx = x[x[..., 4] > conf_threshold]# 重新缩放边界框,为画图做准备if len(x) > 0:# Rescales bounding boxes from model shape(model_height, model_width) to the shape of original imagex[..., :4] -= [pad_w, pad_h, pad_w, pad_h]x[..., :4] /= min(ratio)# Bounding boxes boundary clampx[..., [0, 2]] = x[:, [0, 2]].clip(0, im0.shape[1])x[..., [1, 3]] = x[:, [1, 3]].clip(0, im0.shape[0])return x  # boxeselse:return []if __name__ == '__main__':# Create an argument parser to handle command-line argumentsparser = argparse.ArgumentParser()parser.add_argument('--det_model', type=str, default=r"yolov8s.om", help='Path to OM model')parser.add_argument('--source', type=str, default=r'images', help='Path to input image')parser.add_argument('--out_path', type=str, default=r'results', help='结果保存文件夹')parser.add_argument('--imgsz_det', type=tuple, default=(640, 640), help='Image input size')parser.add_argument('--classes', type=list, default=['person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus', 'train', 'truck', 'boat', 'traffic light','fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow','elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee','skis', 'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard', 'surfboard','tennis racket', 'bottle', 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple', 'sandwich','orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch', 'potted plant', 'bed','dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone', 'microwave', 'oven','toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors', 'teddy bear', 'hair drier', 'toothbrush'], help='类别')parser.add_argument('--conf', type=float, default=0.25, help='Confidence threshold')parser.add_argument('--iou', type=float, default=0.6, help='NMS IoU threshold')parser.add_argument('--device_id', type=int, default=0, help='device id')parser.add_argument('--mode', default='static', help='om是动态dymshape或静态static')parser.add_argument('--model_ndtype', default=np.single, help='om是fp32或fp16')parser.add_argument('--postprocess_type', type=str, default='v8', help='后处理方式, 对应v5/v8/v10三种后处理')parser.add_argument('--aipp', default=False, action='store_true', help='是否开启aipp加速YOLO预处理, 需atc中完成om集成')args = parser.parse_args()# 创建结果保存文件夹if not os.path.exists(args.out_path):os.mkdir(args.out_path)print('开始运行:')# Build modeldet_model = YOLO(args.det_model, args.imgsz_det, args.device_id, args.model_ndtype, args.mode, args.postprocess_type, args.aipp)color_palette = np.random.uniform(0, 255, size=(len(args.classes), 3))  # 为每个类别生成调色板for i, img_name in enumerate(os.listdir(args.source)):try:t1 = time.time()# Read image by OpenCVimg = cv2.imread(os.path.join(args.source, img_name))# 检测Inferenceboxes, (pre_time, det_time, post_time) = det_model(img, conf_threshold=args.conf, iou_threshold=args.iou)print('{}/{} ==>总耗时间: {:.3f}s, 其中, 预处理: {:.3f}s, 推理: {:.3f}s, 后处理: {:.3f}s, 识别{}个目标'.format(i+1, len(os.listdir(args.source)), time.time() - t1, pre_time, det_time, post_time, len(boxes)))# Draw rectanglesfor (*box, conf, cls_) in boxes:cv2.rectangle(img, (int(box[0]), int(box[1])), (int(box[2]), int(box[3])),color_palette[int(cls_)], 2, cv2.LINE_AA)cv2.putText(img, f'{args.classes[int(cls_)]}: {conf:.3f}', (int(box[0]), int(box[1] - 9)),cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2, cv2.LINE_AA)cv2.imwrite(os.path.join(args.out_path, img_name), img)except Exception as e:print(e)     

检测结果可视化如下,效果与GPU上推理几乎一致:
在这里插入图片描述

4 推理耗时

YOLO各系列推理耗时(640*640)如下:
YOLOv5s:8-9ms
YOLOv7-tiny:7-8ms
YOLOv7:14ms
YOLOv8s:6ms
YOLOv9s:12ms
YOLOv10s:6ms
YOLOv11s:8ms
预处理耗时(bus.jpg):12ms
后处理耗时:除YOLOv10几乎无耗时外,其余1-2ms。
注意,上述耗时未使用AIPP进行前处理加速,如YOLOv8s加速后前处理+推理大约6-7ms。

相关文章:

Atlas800昇腾服务器(型号:3000)—YOLO全系列NPU推理【检测】(五)

服务器配置如下: CPU/NPU:鲲鹏 CPU(ARM64)A300I pro推理卡 系统:Kylin V10 SP1【下载链接】【安装链接】 驱动与固件版本版本: Ascend-hdk-310p-npu-driver_23.0.1_linux-aarch64.run【下载链接】 Ascend-…...

1.2.3 TCP IP模型

TCP/IP模型(接网叔用) 网络接口层 网络层 传输层 应用层 理念:如果某些应用需要“数据格式转换”“会话管理功能”,就交给应用层的特定协议去实现 tip:数据 局部正确不等于全局正确 但是,数据的 全局正…...

选择、冒泡和插入排序及其优化版本课件

视频链接:是趣味编程的个人空间-是趣味编程个人主页-哔哩哔哩视频...

Matlab自学笔记三十九:日期时间型数据的算术运算:加减运算

1.说明 时间点和(日历)持续时间是可加的,结果是时间点;两个时间点是可减的,结果是持续时间,用时分秒表示;时间型和浮点数运算,结果是时间型,浮点数默认单位是天&#xf…...

Java-多线程2

什么是线程? 线程是 cpu调度和执行的单位。 多个线程共享进程的堆和方法区资源,但每个线程有自己的程序计数器、虚拟机栈和本地方法栈。 如何实现线程 继承Thread类 实现步骤: 创建自定义类,继承Thread类 重写run方法 创建自定…...

POWER_CONMETRICS的packet wakeup events触发条件的代码走读

摘要: adb shell dumpsys connmetrics 的packet wakeup events触发条件:首先App是无法控制packet wakeup events的事件日志打印,主要App联网过程中网络状态或配置发生变化时由系统netd自动触发的统计。 通俗理解:目前主要表示触…...

Bug:通过反射修改@Autowired注入Bean的字段,明确存在,报错 NoSuchFieldException

【BUG】通过Autowired注入了一个Bean SeqNo,测试的时候需要修改其中的字段。通过传统的反射,无论如何都拿不到信息,关键是一方面可以通过IDEA跳转,一方面debug也确实能看到这个字段。但是每次调用set方法报错:NoSuchFi…...

Vue项目兼容IE11

配置Vue项目兼容IE11详解 Vue 不支持 IE8 及以下版本,因为 Vue 使用了 IE8 无法模拟的 ECMAScript 5 特性。但对于 IE9,Vue 底层是支持。 由于开发过程中,我们经常会使用一些第三方插件或组件,对于这些组件,有时我们…...

可以帮助你快速禁用windows自带的防火墙程序defender control,有效解决占用内存大的问题,供大家学习研究参考

可以关闭windows自带的windows defender防火墙的工具,defender control官方版界面小巧,功能强大,当大家需要手动关闭或禁用windows defender时,就可以使用这款软件,以此来一键关闭或开启这个烦人的系统防火墙。操作起来也非常的简单便捷。 defender control怎么使用 下载…...

2024年9月电子学会Scratch图形化编程等级考试二级真题试卷

2024.09 Scratch图形化编程等级考试二级真题试卷 题目总数:37 总分数:100 一、选择题 第 1 题 Scratch小猫初始坐标是(50,50),小猫向下移动100步后的坐标是?( ) A.(150,50) B.(-50,50) C.(50,-50) D.(50,1…...

STL-vector+题目

vector-顺序表&#xff0c;可以存放任意类型的数据。 vector在[ ]和迭代器、范围for方面的使用差不多一样。 vector的迭代器有普通的还有const类型的迭代器。 vector使用下标[ ]好用。迭代器是容器通用的访问方式&#xff0c;使用方法基本相似。 #include <iostream> #i…...

微服务--Gateway网关--全局Token过滤器【重要】

全局过滤器 GlobalFilter&#xff0c; 注入到 IOC里面即可 概念&#xff1a; 全局过滤器&#xff1a; 所有的请求 都会在执行链里面执行这个过滤器 如添加日志、鉴权等 创建一个全局过滤器的基本步骤&#xff1a; 步骤1: 创建过滤器类 首先&#xff0c;创建一个实现了Globa…...

负载均衡在线判题系统【项目】

项目介绍 本项目是一个负载均衡的在线判题系统 (Online Judge, OJ) 的简易实现。该系统的核心功能是处理大量编程问题的提交&#xff0c;并通过负载均衡的机制&#xff0c;分配判题任务到多台服务器上&#xff0c;确保高效和可靠的评测。系统通过自动选择负载较低的服务器进行…...

重构复杂简单变量之用子类替换类型码

子类替换类型码 是一种用于将类型码替换为子类。当代码使用类型码&#xff08;通常是 int、string 或 enum&#xff09;来表示对象的不同类别&#xff0c;并且这些类别的行为有所不同时&#xff0c;使用子类可以更加清晰地表达这些差异并减少复杂的条件判断。 一、什么时候使用…...

【Nginx系列】Nginx配置超时时间

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

2024年龙信

挂载VC的密码&#xff1a;MjAyNOmmeS/oeadrw 手机取证 1. Android 设备在通过 ADB 连接时&#xff0c;通常会要求用户授权连接&#xff0c;会要求用户确认设备授权&#xff0c;并将该设备的公钥保存在 adb_keys文件中 寻找到data/misc/adb/adb_keys下面有中有两个&#xff0c;…...

PyCharm配置Flask开发环境

文章目录 一、步骤1.安装虚拟环境2.创建虚拟环境文件夹3.安装虚拟环境目录4.进入虚拟环境5.active命令 激活6.安装Flask7.在Pycharm中配置Flask环境 总结 一、步骤 1.安装虚拟环境 代码如下&#xff08;示例&#xff09;&#xff1a; pip install virtualenv 或者 pip insta…...

【人工智能-初级】第2章 机器学习入门:从线性回归开始

文章目录 一、什么是线性回归&#xff1f;二、线性回归的基本概念2.1 一元线性回归2.2 多元线性回归 三、如何进行线性回归建模&#xff1f;四、用Python实现线性回归4.1 导入必要的库4.2 创建虚拟数据集4.3 数据可视化4.4 拆分训练集和测试集4.5 训练线性回归模型4.6 查看模型…...

SPOOLing技术详解,结合实际场景让你了解什么是假脱机技术。

SPOOLing技术 ​ 在手工操作阶段&#xff0c;主机直接从I/O设备获取数据&#xff0c;但是由于设备速度很慢&#xff0c;主机速度很快。人机速度矛盾明显&#xff0c;主机需要浪费很多时间来等待设备。 什么是脱机技术&#xff0c;脱机技术可以解决什么问题&#xff1f; 所谓脱…...

基于SSM汽车零部件加工系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;员工管理&#xff0c;经理管理&#xff0c;零件材料管理&#xff0c;产品类型管理&#xff0c;产品信息管理&#xff0c;产品出库管理&#xff0c;产品入库管理 员工账号功能包括&#xff1a;系统首页…...

改进 JavaScript 条件语句,探索可以替代 if...else 的 7 种方式!

当优化 JavaScript 代码时&#xff0c;条件语句是一个经常需要思考和改进的关键部分。if...else 结构虽然是我们常用的条件语句之一&#xff0c;但当代码逻辑变得复杂&#xff0c;if...else 结构可能会导致代码冗长、难以维护和理解。因此&#xff0c;了解并掌握优化 if...else…...

全新子比主题7.9.2开心版 子比主题最新版源码

内容目录 一、详细介绍二、效果展示1.部分代码2.效果图展示 三、学习资料下载 一、详细介绍 wordpress zibll子比主题7.9.2开心版 修复评论弹授权 可做付费下载站 含wordpress搭建视频教程zibll子比主题安装视频教程支付配置视频教程&#xff0c;视频都是语音讲解&#xff0c;…...

Kafka之消费者组与消费者

消费者&#xff08;Consumer&#xff09;在Kafka的体系结构中是用来负责订阅Kafka中的主题&#xff08;Topic&#xff09;&#xff0c;并从订阅的主题中拉取消息后进行处理。 与其他消息中间件不同&#xff0c;Kafka引入一个逻辑概念——消费组&#xff08;Consumer Group&…...

Damn-Vulnerable-Drone:一款针对无人机安全研究与分析的靶机工具

关于Damn-Vulnerable-Drone Damn-Vulnerable-Drone是一款针对无人机安全研究与分析的靶机工具&#xff0c;广大研究人员可以利用该环境工具轻松学习、研究和分析针对无人机安全态势。 Damn Vulnerable Drone 基于流行的 ArduPilot/MAVLink 架构&#xff0c;其中故意留下了各种…...

项目模块三:Socket模块

一、模块设计 1、套接字编程常用头文件展示 #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <fcntl.h> 2、成员函数设计 &#xff08;1&#xf…...

Unity-Shader-语义

1、从程序传给顶点函数&#xff1a; POSITION&#xff1a;顶点坐标&#xff08;模型空间下&#xff09; NORMAL&#xff1a;法线向量&#xff08;模型空间下&#xff09; TANGENT&#xff1a;切线向量&#xff08;模型空间下&#xff09; TEXCOORD0~n&#xff1a;纹理坐标 …...

MFC工控项目实例二十四模拟量校正值输入

承接专栏《MFC工控项目实例二十三模拟量输入设置界面》 对模拟量输入的零点校正值及满量程对应的电压值进行输入。 1、在SenSet.h文件中添加代码 #include "BtnST.h" #include "ShadeButtonST.h"/ // SenSet dialogclass SenSet : public CDialog { // Co…...

analysis-ik分词器

analysis-ik分词器 1、安装离线在线 2、使用配置拓展词典 3、测试ik_smartik_max_word 1、安装 离线 使用离线安装下载地址https://release.infinilabs.com/analysis-ik/stable/找到对应es版本的ik分词器、下载zip后放到/elasticsearch/plugins/ik文件夹下。重启es即可生效 …...

开源的、基于内存的键值存储数据库redis详细介绍

目录 一、Redis的概述 1、概述 2、特点 &#xff08;1&#xff09;基本特性 &#xff08;2&#xff09;数据结构 &#xff08;3&#xff09;运行环境 二、Redis的重要作用 1、缓存 2、会话存储 3、消息队列 4、计数器 5、分布式锁 6、排行榜 7、实时数据处理 三、…...

三种容器 std::vector、std::map、std::unordered_set 的对比分析

目录 1.添加元素 1.1 std::vector 1.2 std::map 1.3 std::unordered_set 2. 查找元素 2.1 std::vector 2.2 std::map 2.3 std::unordered_set 3. 遍历容器 3.1 std::vector 使用范围基for循环(range-based for loop) 使用迭代器: 3.2 std::map 3.3 std::unord…...