香橙派Orange AI Pro / 华为昇腾310芯片 部署自己训练的yolov8模型进行中国象棋识别

香橙派Orange AI Pro / 华为昇腾310芯片 部署自己训练的yolov8模型进行中国象棋识别

  • 一、香橙派简介
    • 1.1、香橙派 AI Pro 硬件资源介绍
    • 1.2、华为昇腾310(Ascend310) 简介
    • 1.3、 昇腾310AI能力和CANN 简介
    • 昇腾310 NPU简介
  • 二、远程环境配置
    • 2.1、ssh
    • 2.2、vnc
  • 三、香橙派Orange AI Pro安装pytorch并运行yolov8
    • 使用conda安装虚拟环境
    • 环境配置
    • 代码下载
    • 推理图片
    • 推理usb摄像头
  • 四、香橙派Orange AI Pro使用昇腾310 npu和cann 部署加速yolov8
    • 4.1、增加swap 交换内存
    • 4.2、设置设备编译进程数CPU核数(可选)
    • 4.3、设置环境变量
    • 4.4、yolov8 pt 模型转onnx模型
    • 4.5、yolov8 onnx模型转换om模型
    • 4.6、使用华为昇腾 npu推理加速运行自己训练的yolov8模型——python代码
      • 代码
      • 安装依赖
      • 运行效果图
    • 4.7 使用华为昇腾npu运行自己训练的yolov8模型——C++部署
      • 下载ascend官方示例代码
      • 修改sampleYOLOV8.cpp后处理代码
      • 编译运行
        • 安装acllite
  • 五、其他开发环境安装
    • 5.1、香橙派Orange AI Pro / 华为昇腾310 使用源码方式安装opencv 4.9.0
  • 六、可能出现的错误
  • 七、昇腾芯片常用命令
    • 基础信息查看命令
    • 查看npu,AI core以及cpu的资源情况
    • 将远程文件复制到本地
    • AI CPU和Control CPU切换
  • 八、 使用总结
    • 香橙派Ai pro的优点
    • 香橙派Ai pro的不足
  • 参考文章

官方参考资料:

在香橙派官网可以下载到OrangePi AIpro的相关资料,其中包括用户手册,
1、官网地址:香橙派官网
2、昇腾论坛:香橙派AIpro学习资源一站式导航
3、orangepi 论坛:http://forum.orangepi.cn/
4、升腾官方 深度学习示例源码库:https://gitee.com/ascend/samples

一、香橙派简介

香橙派(Orange Pi)是深圳市迅龙软件有限公司旗下开源产品品牌,香橙派AIpro开发板采用昇腾AI技术路线,接口丰富且具有强大的可扩展性,提供8/20TOPS澎湃算力,可广泛使用于AI边缘计算、深度视觉学习及视频流AI分析、视频图像分析、自然语言处理等AI领域。通过昇腾CANN软件栈的AI编程接口,可满足大多数AI算法原型验证、推理应用开发的需求。该产品搭载的是华为昇腾310芯片。

而昇腾310主打高能效、灵活可编程,参数如下

  • 16TOPS@INT8, 8TOPS@FP16
  • 功耗8W
  • 华为自研达芬奇架构
  • 12nm FFC工艺

1.1、香橙派 AI Pro 硬件资源介绍

在这里插入图片描述

1.2、华为昇腾310(Ascend310) 简介

Ascend310 AI处理器逻辑架构昇腾AI处理器的主要架构组成:芯片系统控制CPU(Control CPU)AI计算引擎(包括AI Core和AI CPU)多层级的片上系统缓存(Cache)或缓冲区(Buffer)数字视觉预处理模块(Digital Vision Pre-Processing,DVPP)等AI Core:集成了2个AI Core。

Ascend310 AI处理器规格:
Ascend310 AI处理器规格

昇腾 310,高能效比推理型 AI 处理器,基于达芬奇架构,本质上是一块 SoC,集 成了多个运算单元,包括 CPU(8 个 a55)、AI Core、数字视觉预处理子系统等。除了 CPU 之外,该芯片真正的算力担当是采用了达芬奇架构的 AI Core。这些 AI Core 通过 特别设计的架构和电路实现了高通量、大算力和低功耗,特别适合处理深度学习中神经 网络必须的常用计算。目前该芯片能对整型数(INT8、INT4) 或对浮点数(FP16)提 供强大的算力。根据海思官网披露,该芯片 FP16 算力为 8TOPS,INT8 算力 16TOPS, 采用 12nm 工艺制造。

Ascend310 AI处理器逻辑架构:
在这里插入图片描述
昇腾AI处理器的主要架构组成:

  • 芯片系统控制CPU(Control CPU)

  • AI计算引擎(包括AI Core和AI CPU)

  • 多层级的片上系统缓存(Cache)或缓冲区(Buffer)

  • 数字视觉预处理模块(Digital Vision Pre-Processing,DVPP)等

  • AI Core:集成了2个AI Core。昇腾AI芯片的计算核心,主要负责执行矩阵、向量、标量计算密集的算子任务,采用达芬奇架构。

  • ARM CPU核心: 集成了8个A55。其中一部分部署为AI CPU,负责执行不适合跑在AI Core上的算子(承担非矩阵类复杂计算);一部分部署为专用于控制芯片整体运行的控制CPU。两类任务占用的CPU核数可由软件根据系统实际运行情况动态分配。此外,还部署了一个专用CPU作为任务调度器(Task Scheduler,TS),以实现计算任务在AI Core上的高效分配和调度;该CPU专门服务于AI Core和AI CPU,不承担任何其他的事务和工作。

  • DVPP:数字视觉预处理子系统,完成图像视频的编解码。用于将从网络或终端设备获得的视觉数据,进行预处理以实现格式和精度转换等要求,之后提供给AI计算引擎。

  • Cache & Buffer:SOC片内有层次化的memory结构,AI core内部有两级memory buffer,SOC片上还有8MB L2 buffer,专用于AI Core、AI CPU,提供高带宽、低延迟的memory访问。芯片还集成了LPDDR4x控制器,为芯片提供更大容量的DDR内存。

  • 对外接口:支持PCIE3.0、RGMII、USB3.0等高速接口、以及GPIO、UART、I2C、SPI等低速接口。

昇腾AI处理器特点:

  • 昇腾AI处理器集成了多个ARM公司的CPU核心,每个核心都有独立的L1和L2缓存,所有核心共享一个片上L3缓存。集成的CPU核心按照功能可以划分为专用于控制芯片整体运行的主控CPU 和专用于承担非矩阵类复杂计算的AI CPU。两类任务占用的CPU核数可由软件根据系统实际运行情况动态分配。

  • 除了CPU之外,该芯片真正的算力担当是采用了达芬奇架构的AI Core。这些AI Core通过特别设计的架构和电路实现了高通量、大算力和低功耗,特别适合处理深度学习中神经网络必须的常用计算如矩阵相乘等。目前该芯片能对整型数(INT8、INT4) 或对浮点数(FP16)提供强大的乘加计算力。由于采用了模块化的设计,可以很方便的通过叠加模块的方法提高后续芯片的计算力。

  • 针对深度神经网络参数量大、中间值多的特点,该芯片还特意为AI计算引擎配备了容量为8MB的片上缓冲区(On-Chip Buffer),提供高带宽、低延迟、高效率的数据交换和访问。能够快速访问到所需的数据对于提高神经网络算法的整体性能至关重要,同时将大量需要复用的中间数据缓存在片上对于降低系统整体功耗意义重大。为了能够实现计算任务在AI Core上的高效分配和调度,还特意配备了一个专用CPU作为任务调度器(Task Scheduler,TS)。该CPU专门服务于AI Core和AI CPU,而不承担任何其他的事务和工作。

  • 数字视觉预处理模块主要完成图像视频的编解码,支持4K分辨率,视频处理,对图像支持JPEG和PNG等格式的处理。来自主机端存储器或网络的视频和图像数据,在进入昇腾AI芯片的计算引擎处理之前,需要生成满足处理要求的输入格式、分辨率等,因此需要调用数字视觉预处理模块进行预处理以实现格式和精度转换等要求。数字视觉预处理模块主要实现视频解码(Video Decoder,VDEC),视频编码(Video Encoder,VENC),JPEG编解码(JPEG Decoder/Encoder,JPEGD/E),PNG解码(PNG Decoder,PNGD)和视觉预处理(Vision Pre-Processing Core,VPC)等功能。图像预处理可以完成对输入图像的上/下采样、裁剪、色调转换等多种功能。数字视觉预处理模块采用了专用定制电路的方式来实现高效率的图像处理功能,对应于每一种不同的功能都会设计一个相应的硬件电路模块来完成计算工作。在数字视觉预处理模块收到图像视频处理任务后,会读取需要处理的图像视频数据并分发到内部对应的处理模块进行处理,待处理完成后将数据写回到内存中。

1.3、 昇腾310AI能力和CANN 简介

一颗昇腾310芯片可以实现高达16T的现场算力,支持同时识别包括人、物体、交通标志、障碍物在内的两百个不同目标,一秒钟可处理上千张图片,无论在急速行驶的汽车上还是高速运转的生产线,无论是复杂的科学研究还是日常教育活动,昇腾310可以为各行各业提供触手可及的高效算力。

CANN(Compute Architecture for Neural Networks)异构计算架构,是以提升用户开发效率和释放昇腾AI处理器极致算力为目标,专门面向AI场景的异构计算架构。对上支持主流前端框架,向下对用户屏蔽系列化芯片的硬件差异,以全场景、低门槛、高性能的优势,满足用户全方位的人工智能诉求。CANN通过Plugin适配层,能轻松承接基于不同框架开发的AI模型,将不同框架定义的模型转换成标准化的Ascend IR(Intermediate Representation)表达的图格式,屏蔽框架差异。

算子在硬件上的加速计算构成了加速神经网络的基础和核心。目前CANN提供了1200+种深度优化的、硬件亲和的算子,正是如此丰富的高性能算子,筑起了澎湃的算力源泉,让你的神经网络「瞬时」加速。

  • NN(Neural Network)算子库:CANN覆盖了包括TensorFlow、Pytorch、MindSpore、ONNX框架在内的,常用深度学习算法的计算类型,在CANN所有的算子中占有最大比重,用户只需要关注算法细节的实现,大部分情况下不需要自己开发和调试算子。
  • BLAS(Basic Linear Algebra Subprograms)算子库:BLAS为基础线性代数程序集,是进行向量和矩阵等基本线性代数操作的数值库,CANN支持通用的矩阵乘和基础的Max、Min、Sum、乘加等运算。
  • DVPP(Digital Video Pre-Processor)算子库:提供高性能的视频编解码、图片编解码、图像裁剪缩放等预处理能力。
  • AIPP(AI Pre-Processing)算子库:主要实现改变图像尺寸、色域转换(转换图像格式)、减均值/乘系数(图像归一化),并与模型推理过程融合,以满足推理输入要求。
  • HCCL(Huawei Collective Communication Library)算子库:主要提供单机多卡以及多机多卡间的Broadcast,allreduce,reducescatter,allgather等集合通信功能,在分布式训练中提供高效的数据传输能力。

昇腾310 NPU简介

Ascend 310处理器,可以高效地在端侧部署典型的深度学习推理应用。以下是昇腾310的主要特点:

  • 高效能低功耗: 昇腾310采用7nm工艺制造,拥有高效的能耗比,能够在提供强大计算能力的同时保持较低的功耗,非常适合嵌入式和边缘计算应用。
  • 强大计算能力: 昇腾310能够提供多达16 TOPS(Tera Operations Per Second)的整数计算能力和8 TFLOPS(Tera Floating Point Operations Per Second)的浮点计算能力,能够高效处理复杂的深度学习模型。
  • 丰富的接口支持: 昇腾310支持多种接口,包括PCIe、I2C、UART等,方便与各种外设进行连接,适用于广泛的应用场景。
  • 全场景AI支持: 昇腾310支持包括图像处理、语音识别、自然语言处理等多种AI任务,提供灵活的AI推理能力。
  • 优秀的开发工具: 昇腾310配备了丰富的开发工具和软件生态,包括华为的MindSpore、TensorFlow、PyTorch等主流深度学习框架的支持,使开发者能够快速上手并进行模型训练和部署。

二、远程环境配置

我一般就直接

ssh HwHiAiUser@192.168.71.155

下面是更详细的步骤

2.1、ssh

获取香橙派ip地址

首先将显示器鼠标键盘接入香橙派,然后在终端输入ifconfig 查看ip地址。

ifconfig

然后在ubuntu主机使用Remmina远程香橙派,一般ubuntu自带 Remmina,如果没有 可以使用以下命令安装:

sudo apt install remmina remmina-plugin-rdp remmina-plugin-vnc

在这里插入图片描述
输入用户名和密码

默认用户名和密码如下

HwHiAiUser
Mind@123

在这里插入图片描述

成功进入
在这里插入图片描述

当然也可以之间在主机终端直接连接ssh

ssh HwHiAiUser@192.168.71.155
Mind@123

2.2、vnc

首先在香橙派上安装和设置vnc

sudo apt update
sudo apt install tightvncserver

配置密码

vncserver

配置开机启动

mv ~/.vnc/xstartup ~/.vnc/xstartup.bak
vim ~/.vnc/xstartup

然后输入

#!/bin/bash
xrdb $HOME/.Xresources
startxfce4 &

保存后给权限

sudo chmod +x ~/.vnc/xstartup

启动vnc

vncserver

关闭vnc

sudo systemctl stop vncserver@*

修改用户名和密码

sudo vim /etc/systemd/system/vncserver\@.service

在这里插入图片描述

然后在ubuntu主机打开Remmina的主界面中,点击“+”号图标来创建一个新的连接配置。配置如下:
注意端口号也要写,一般板子的第一个桌面连接是用5901端口。
在这里插入图片描述

然后连接,成功!
在这里插入图片描述

三、香橙派Orange AI Pro安装pytorch并运行yolov8

使用conda安装虚拟环境

环境配置

其中requirements.txt 中包含了必要的配置环境:
基本如下:

3.10>=Python>=3.7
torch>=1.7.0
torchvision>=0.8.1
#创建虚拟环境
conda create --name pytorch python=3.8conda activate pytorch#安装ultralytics,可以直接使用yolo
pip install ultralytics -i https://pypi.tuna.tsinghua.edu.cn/simple/

在这里插入图片描述

测试环境是否配置成功:

import torchprint(torch.__version__)
a = torch.Tensor(5,3)
print(a)

代码下载

git clone https://github.com/ultralytics/ultralytics  

推理图片

from ultralytics import YOLO# Load a pretrained YOLOv8n model
# model = YOLO("yolov8n.pt")model = YOLO('./weights/24_0506_6541_yolov8x_1280.pt')  # load a custom model# Define path to the image file
source ="./images/*.jpg"# Run inference on the source
results = model(source,show=True,save=True)  # list of Results objects

推理usb摄像头

插入usb相机,然后查看是否插入成功
在这里插入图片描述
使用pytorch cpu版本 yolov8x模型 推理usb摄像头,命令如下:

yolo predict model=./weights/24_0506_6541_yolov8x_1280.pt source=0 show

耗时达到了恐怖的50s。
yolov8s也需要2s多。但是精度还是不错的,不过毕竟 Orange AI Pro 的成本低,ai推理肯定是需要C++和npu加速来部署。
在这里插入图片描述

pytorch+cpu推理,虽然环境配置很方便,但是几乎没有实际使用的意义。ai推理还是需要用npu。

四、香橙派Orange AI Pro使用昇腾310 npu和cann 部署加速yolov8

4.1、增加swap 交换内存

通过free -h命令查看内存使用情况,如果内存总量小于4G,则需要挂载swap分区

free -h

申请一个8G的文件作为swap分区【推荐2.5G以上,请提前预留足够的空间】

sudo fallocate -l 8G /swapfile 

修改文件权限

sudo chmod 600 /swapfile

创建swap分区

sudo mkswap /swapfile

挂载swap分区

sudo swapon /swapfile

通过 free -h查看swap分区是否挂载成功

free -h

在这里插入图片描述

4.2、设置设备编译进程数CPU核数(可选)

转om模型时内存不足,开发板cpu核数较少,atc过程中使用的最大并行进程数默认是服务器的配置,可以使用环境变量减少atc过程中的进程数来减少内存消耗;当设备内存小于 8G 时,可设置如下两个环境变量减少atc模型转换过程中使用的进程数,减小内存占用。

  • 减小算子最大并行编译进程数
export TE_PARALLEL_COMPILER=1
  • 减少图编译时可用的CPU核数
export MAX_COMPILE_CORE_NUMBER=1

4.3、设置环境变量

# 配置程序编译依赖的头文件与库文件路径
export DDK_PATH=/usr/local/Ascend/ascend-toolkit/latest 
export NPU_HOST_LIB=$DDK_PATH/runtime/lib64/stub

4.4、yolov8 pt 模型转onnx模型

这一步也可在自己电脑上转换在这里插入图片描述
从输出信息中可以看出,我自己训练的这个中国象棋模型 yolov8x.pt原始模型的输出尺寸为 (1, 3, 1280, 1280),格式为 BCHW ,输出尺寸为 (1, 84, 8400) 。这个模型的更多信息,可以用 netron 工具进行可视化查看,在安装了netron后,可以执行如下命令打开yolov8x.onnx模型进行Web网络结构的查看:

在这里插入图片描述

4.5、yolov8 onnx模型转换om模型

转换命令

atc --framework=5 --model=yolov8x_24_0307_5381_1280.onnx  --input_format=NCHW  --input_shape="images:1,3,1280,1280" --output=yolov8x_24_0307_5381_1280_huawei --soc_version=Ascend310B4

atc命令中各参数的含义如下:
–framework:原始框架类型,5表示ONNX。
–model:ONNX模型文件存储路径。
–input_format:输入的格式定义
–output:离线om模型的路径以及文件名。
–soc_version:昇腾AI处理器的型号。
在服务器种执行npu-smi info命令进行查询,在查询到的“Name”前增加Ascend信息,例如“Name”对应取值为310B4,实际配置的–soc_version值为Ascend310B4。

在这里插入图片描述

转换成功标志
在这里插入图片描述

4.6、使用华为昇腾 npu推理加速运行自己训练的yolov8模型——python代码

代码

"""  "*******************************************************************************************
*文件名称 :.py
*文件功能 :华为晟腾    yolov8x.om python 推理代码 ——文件夹推理版本:1.0
内容:华为晟腾    yolov8x.om python 推理代码 ——文件夹推理
时间:2023.6.2
作者:狄云
********************************************************************************************"""import osprint(os.environ['LD_LIBRARY_PATH'])
import cv2
import numpy as np
from IPython.display import display, clear_output,Image
from time import time
from ais_bench.infer.interface import InferSession
from ultralytics.utils import ASSETS, yaml_load
from ultralytics.utils.checks import check_yaml#中国象棋类别
CLASSES =['red_shuai','red_shi','red_xiang','red_ma','red_che','red_pao','red_bing','black_jiang','black_shi','black_xiang','black_ma','black_che','black_pao','black_bing']colors = np.random.uniform(0, 255, size=(len(CLASSES), 3))model = InferSession(device_id=0, model_path="chess_yolov8x_24_0307_5381_1280.om")def draw_bounding_box(img, class_id, confidence, x, y, x_plus_w, y_plus_h):label = f'{CLASSES[class_id]} ({confidence:.2f})'color = colors[class_id]cv2.rectangle(img, (x, y), (x_plus_w, y_plus_h), color, 2)cv2.putText(img, label, (x - 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)def main(original_image):[height, width, _] = original_image.shapelength = max((height, width))image = np.zeros((length, length, 3), np.uint8)image[0:height, 0:width] = original_imagescale = length / 640blob = cv2.dnn.blobFromImage(image, scalefactor=1 / 255, size=(640, 640), swapRB=True)begin_time = time()outputs = model.infer(feeds=blob, mode="static")end_time = time()print("om infer time:", end_time - begin_time)outputs = np.array([cv2.transpose(outputs[0][0])])rows = outputs.shape[1]boxes = []scores = []class_ids = []for i in range(rows):classes_scores = outputs[0][i][4:](minScore, maxScore, minClassLoc, (x, maxClassIndex)) = cv2.minMaxLoc(classes_scores)if maxScore >= 0.25:box = [outputs[0][i][0] - (0.5 * outputs[0][i][2]), outputs[0][i][1] - (0.5 * outputs[0][i][3]),outputs[0][i][2], outputs[0][i][3]]boxes.append(box)scores.append(maxScore)class_ids.append(maxClassIndex)result_boxes = cv2.dnn.NMSBoxes(boxes, scores, 0.25, 0.45, 0.5)detections = []for i in range(len(result_boxes)):index = result_boxes[i]box = boxes[index]detection = {'class_id': class_ids[index],'class_name': CLASSES[class_ids[index]],'confidence': scores[index],'box': box,'scale': scale}detections.append(detection)draw_bounding_box(original_image, class_ids[index], scores[index], round(box[0] * scale), round(box[1] * scale),round((box[0] + box[2]) * scale), round((box[1] + box[3]) * scale))# 指定图像文件夹路径
input_image_folder = 'path_to_your_image_folder'  # 替换为你的图像文件夹路径
out_image_folder = 'output'
# 遍历文件夹中的所有图像文件
for filename in os.listdir(input_image_folder):if filename.endswith(".jpg") or filename.endswith(".png"):  # 根据你的图像格式调整image_path = os.path.join(input_image_folder, filename)image = cv2.imread(image_path)  # 读取图像if image is not None:start_time = time.time()  # 获取开始时间# 调用main函数进行处理main(image)end_time = time.time()  # 获取结束时间print(f" 函数耗时:{(end_time - start_time) * 1000:.2f} 毫秒")# 显示图像(可选)cv2.imshow('Image', image)cv2.waitKey(0)  # 按任意键查看下一张图像# 保存处理后的图像(可选)output_path = os.path.join(out_image_folder, filename)  # 替换为保存路径cv2.imwrite(output_path, image)# 释放资源
cv2.destroyAllWindows()

安装依赖

!pip install scikit_video
!pip install pip_packages/aclruntime-0.0.2-cp39-cp39-linux_aarch64.whl
!pip install pip_packages/ais_bench-0.0.2-py3-none-any.whl

参考:http://www.hzhcontrols.com/new-1997735.html

注意,aclruntime和ais_bench推理程序的whl包请 前往下载。
晟腾git 仓库 :https://gitee.com/ascend/tools/tree/master/ais-bench_workload/tool/ais_bench

在这里插入图片描述

运行效果图

在这里插入图片描述准确度不错
在这里插入图片描述
使用python 进行om推理,整体上速度较直接使用pytorch和pt模型快了很多,yolov8x ,1280*1280分辨率,速度是1s左右,但是还是不能达到实时的效果,还需要进行C++来部署。

4.7 使用华为昇腾npu运行自己训练的yolov8模型——C++部署

华为昇腾 CANN YOLOV8 推理示例 C++样例 , 可以基于Ascend CANN Samples官方示例中的sampleYOLOV7进行适配。一般来说,YOLOV7模型输出的数据大小为[1,25200,85],而YOLOV8模型输出的数据大小为[1,84,8400],因此,需要对sampleYOLOV7中的后处理部分进行修改,从而做到YOLOV8/YOLOV9模型的适配。(当然自己训练的模型这几个参数都会变化,主要和模型类别以及输入分辨率有关)

下载ascend官方示例代码

git clone https://gitee.com/ascend/samples

进入 inference/modelInference/sampleYOLOV7,将sampleYOLOV7文件夹复制一份,并命名为sampleYOLOV8

修改sampleYOLOV8.cpp后处理代码

注意修改类别和输入分辨率

   size_t classNum = 80;
    size_t modelOutputBoxNum = 8400; 

上面两个参数主要看你的onnx输入输出,改成自己的即可。

Result SampleYOLOV8::GetResult(std::vector<InferenceOutput> &inferOutputs,string imagePath, size_t imageIndex, bool release)
{uint32_t outputDataBufId = 0;float *classBuff = static_cast<float *>(inferOutputs[outputDataBufId].data.get());// confidence thresholdfloat confidenceThreshold = 0.35;// class numbersize_t classNum = 80;//// number of (x, y, width, hight)size_t offset = 4;// total number of boxs yolov8 [1,84,8400]size_t modelOutputBoxNum = 8400; // read source image from filecv::Mat srcImage = cv::imread(imagePath);int srcWidth = srcImage.cols;int srcHeight = srcImage.rows;// filter boxes by confidence thresholdvector<BoundBox> boxes;size_t yIndex = 1;size_t widthIndex = 2;size_t heightIndex = 3;// size_t all_num = 1 * 84 * 8400 ; // 705,600for (size_t i = 0; i < modelOutputBoxNum; ++i){float maxValue = 0;size_t maxIndex = 0;for (size_t j = 0; j < classNum; ++j){float value = classBuff[(offset + j) * modelOutputBoxNum + i];if (value > maxValue){// index of classmaxIndex = j;maxValue = value;}}if (maxValue > confidenceThreshold){BoundBox box;box.x = classBuff[i] * srcWidth / modelWidth_;box.y = classBuff[yIndex * modelOutputBoxNum + i] * srcHeight / modelHeight_;box.width = classBuff[widthIndex * modelOutputBoxNum + i] * srcWidth / modelWidth_;box.height = classBuff[heightIndex * modelOutputBoxNum + i] * srcHeight / modelHeight_;box.score = maxValue;box.classIndex = maxIndex;box.index = i;if (maxIndex < classNum){boxes.push_back(box);}}}ACLLITE_LOG_INFO("filter boxes by confidence threshold > %f success, boxes size is %ld", confidenceThreshold,boxes.size());// filter boxes by NMSvector<BoundBox> result;result.clear();float NMSThreshold = 0.45;int32_t maxLength = modelWidth_ > modelHeight_ ? modelWidth_ : modelHeight_;std::sort(boxes.begin(), boxes.end(), sortScore);BoundBox boxMax;BoundBox boxCompare;while (boxes.size() != 0){size_t index = 1;result.push_back(boxes[0]);while (boxes.size() > index){boxMax.score = boxes[0].score;boxMax.classIndex = boxes[0].classIndex;boxMax.index = boxes[0].index;// translate point by maxLength * boxes[0].classIndex to// avoid bumping into two boxes of different classesboxMax.x = boxes[0].x + maxLength * boxes[0].classIndex;boxMax.y = boxes[0].y + maxLength * boxes[0].classIndex;boxMax.width = boxes[0].width;boxMax.height = boxes[0].height;boxCompare.score = boxes[index].score;boxCompare.classIndex = boxes[index].classIndex;boxCompare.index = boxes[index].index;// translate point by maxLength * boxes[0].classIndex to// avoid bumping into two boxes of different classesboxCompare.x = boxes[index].x + boxes[index].classIndex * maxLength;boxCompare.y = boxes[index].y + boxes[index].classIndex * maxLength;boxCompare.width = boxes[index].width;boxCompare.height = boxes[index].height;// the overlapping part of the two boxesfloat xLeft = max(boxMax.x, boxCompare.x);float yTop = max(boxMax.y, boxCompare.y);float xRight = min(boxMax.x + boxMax.width, boxCompare.x + boxCompare.width);float yBottom = min(boxMax.y + boxMax.height, boxCompare.y + boxCompare.height);float width = max(0.0f, xRight - xLeft);float hight = max(0.0f, yBottom - yTop);float area = width * hight;float iou = area / (boxMax.width * boxMax.height + boxCompare.width * boxCompare.height - area);// filter boxes by NMS thresholdif (iou > NMSThreshold){boxes.erase(boxes.begin() + index);continue;}++index;}boxes.erase(boxes.begin());}ACLLITE_LOG_INFO("filter boxes by NMS threshold > %f success, result size is %ld", NMSThreshold,result.size());// opencv draw label paramsconst double fountScale = 0.5;const uint32_t lineSolid = 2;const uint32_t labelOffset = 11;const cv::Scalar fountColor(0, 0, 255); // BGRconst vector<cv::Scalar> colors{cv::Scalar(255, 0, 0), cv::Scalar(0, 255, 0),cv::Scalar(0, 0, 255)};int half = 2;for (size_t i = 0; i < result.size(); ++i){cv::Point leftUpPoint, rightBottomPoint;leftUpPoint.x = result[i].x - result[i].width / half;leftUpPoint.y = result[i].y - result[i].height / half;rightBottomPoint.x = result[i].x + result[i].width / half;rightBottomPoint.y = result[i].y + result[i].height / half;cv::rectangle(srcImage, leftUpPoint, rightBottomPoint, colors[i % colors.size()], lineSolid);string className = label[result[i].classIndex];string markString = to_string(result[i].score) + ":" + className;ACLLITE_LOG_INFO("object detect [%s] success", markString.c_str());cv::putText(srcImage, markString, cv::Point(leftUpPoint.x, leftUpPoint.y + labelOffset),cv::FONT_HERSHEY_COMPLEX, fountScale, fountColor);}string savePath = "out_" + to_string(imageIndex) + ".jpg";cv::imwrite(savePath, srcImage);if (release){free(classBuff);classBuff = nullptr;}return SUCCESS;
}

编译运行

安装acllite

设置环境变量,配置程序编译依赖的头文件,库文件路径。

 export DDK_PATH=/usr/local/Ascend/ascend-toolkit/latestexport NPU_HOST_LIB=$DDK_PATH/runtime/lib64/stubexport THIRDPART_PATH=${DDK_PATH}/thirdpartexport LD_LIBRARY_PATH=${THIRDPART_PATH}/lib:$LD_LIBRARY_PATH

执行以下命令安装acllite

cd /media/HwHiAiUser/T9/Ascend_310/work/samples/inference/acllite/cplus
make
make install

安装成功
在这里插入图片描述
在CMakeLists.txt里增加

find_package(OpenCV REQUIRED)

修改 sample_build.sh ,记得将 yolov7x.om 改成你自己转换成功的模型

然后执行:

cd $HOME/samples/inference/modelInference/sampleYOLOV8/scripts
bash sample_build.sh

这个步骤才是最终ai推理的整体流程。

五、其他开发环境安装

5.1、香橙派Orange AI Pro / 华为昇腾310 使用源码方式安装opencv 4.9.0

下载源码到香橙派
https://opencv.org/releases/

在这里插入图片描述
解压

unzip opencv-4.9.0.zip

进入解压后的文件

cd opencv-4.9.0

创建构建目录build

mkdir build

进入目录

cd build

使用cmake配置后续的构建环境

cmake -D CMAKE_BUILD_TYPE=RELEASE \-D CMAKE_INSTALL_PREFIX=/usr/local \-D OPENCV_GENERATE_PKGCONFIG=ON ..

命令解释

第一行是构建的版本:这里是发行版RELEASE
第二行是安装的目录
第三行是显式地通过添加 -D OPENCV_GENERATE_PKGCONFIG=ON 到 CMake 命令来确保OPENCV能够被pkg-config工具找到

然后使用make -j2或者make -j4来进行编译,这个编译时间比较长,j后面的数字可以修改成4,6,8,视你的机器的处理核心数来定,越高的话越快,我是make -j2,因为香橙派Orange AI Pro 总共四个核,如果全部占满,直接会卡死。

make -j2

这样子就可以了,接下来使用命令安装Opencv,这样会安装Opencv以及生成的pkg-config文件

sudo make install

最后更新动态链接器的缓存

sudo ldconfig

这样就完成了
验证是否安装成功,使用pkg-config来检查是否能够找到OpenCV

pkg-config --modversion opencv4

安装成功
在这里插入图片描述

六、可能出现的错误

6.1、转换模型出现BrokenPipeError: [Errno 32] Broken pipe

Traceback (most recent call last):File "/usr/local/miniconda3/lib/python3.9/multiprocessing/pool.py", line 131, in workerput((job, i, result))File "/usr/local/miniconda3/lib/python3.9/multiprocessing/queues.py", line 378, in putself._writer.send_bytes(obj)File "/usr/local/miniconda3/lib/python3.9/multiprocessing/connection.py", line 205, in send_bytesself._send_bytes(m[offset:offset + size])File "/usr/local/miniconda3/lib/python3.9/multiprocessing/connection.py", line 416, in _send_bytesself._send(header + buf)File "/usr/local/miniconda3/lib/python3.9/multiprocessing/connection.py", line 373, in _sendn = write(self._handle, buf)
BrokenPipeError: [Errno 32] Broken pipe

内存不足,需要添加交换空间
在这里插入图片描述

在昇腾论坛找到了解决方案https://www.hiascend.com/forum/thread-0239142592318174023-1-1.html,总结就是:

转om模型时内存不足,开发板cpu核数较少,atc过程中使用的最大并行进程数默认是服务器的配置,可以使用环境变量减少atc过程中的进程数来减少内存消耗。

·减小算子最大并行编译进程数

export TE_PARALLEL_COMPILER=1

·减少图编译时可用的CPU核数

export MAX_COMPILE_CORE_NUMBER=1

之后就可以成功转换om模型啦!

6.2、 晟腾 onnx转换到om模型报错 /usr/local/Ascend/ascend-toolkit/latest/bin/atc: line 17: 7998 Aborted (core dumped) P K G P A T H / b i n / a t c . b i n " {PKG_PATH}/bin/atc.bin " PKGPATH/bin/atc.bin"@"

atc --framework=5 --model=yolov8n.onnx  --input_format=NCHW  --input_shape="images:1,3,640,640" --output=yolov8n_huawei --soc_version=Ascend310B4
ATC start working now, please wait for a moment.
Exception in thread Thread-1:
Fatal Python error: _enter_buffered_busy: could not acquire lock for <_io.BufferedWriter name='<stderr>'> at interpreter shutdown, possibly due to daemon threads
Python runtime state: finalizing (tstate=0xaaaacb04b040)Current thread 0x0000e7fff9bab020 (most recent call first):
<no Python frame>
/usr/local/Ascend/ascend-toolkit/latest/bin/atc: line 17: 11752 Aborted                 (core dumped) ${PKG_PATH}/bin/atc.bin "$@"

同样是cpu和内存不够的问题,可以通过增加交换空间解决。

解决办法如下

通过free -h命令查看内存使用情况,如果内存总量小于4G,则需要挂载swap分区

free -h

申请一个8G的文件作为swap分区【推荐2.5G以上,请提前预留足够的空间】

sudo fallocate -l 8G /swapfile 

修改文件权限

sudo chmod 600 /swapfile

创建swap分区

sudo mkswap /swapfile

挂载swap分区

sudo swapon /swapfile

通过 free -h查看swap分区是否挂载成功

free -h

在这里插入图片描述

6.3、 python 推理 晟腾npu模型报错 ModuleNotFoundError: No module named ‘IPython’

ModuleNotFoundError: No module named ‘IPython’

pip install IPython  -i https://pypi.tuna.tsinghua.edu.cn/simple

6.4、 运行om模型报错: RuntimeError: [-1][ACL: general failure]

[INFO] create model description success
[ERROR] Check i:0 name:images in size:4915200 needsize:19660800 not match
[ERROR] Check InVector failed ret:-1
Traceback (most recent call last):File "ascend_yolov8_folder_infer.py", line 100, in <module>main(image)File "ascend_yolov8_folder_infer.py", line 47, in mainoutputs = model.infer(feeds=blob, mode="static")File "/home/HwHiAiUser/.conda/envs/pytorch/lib/python3.8/site-packages/ais_bench/infer/interface.py", line 510, in inferreturn self.run(inputs, out_array)File "/home/HwHiAiUser/.conda/envs/pytorch/lib/python3.8/site-packages/ais_bench/infer/interface.py", line 450, in runoutputs = self.session.run(self.outputs_names, inputs)
RuntimeError: [-1][ACL: general failure] 
[INFO] unload model success, model Id is 1

检查模型输入尺寸和图片输入尺寸。需要和你的onnx模型的输入输出对应。

6.5、 使用opencv 4.5 运行dnn 读取yolov8 onnx 模型,报错[ERROR:0] global

使用opencv 4.5 运行dnn 读取yolov8 onnx 模型,报错[ERROR:0] global ./modules/dnn/src/onnx/onnx_importer.cpp (718) handleNode DNN/ONNX: ERROR during processing node with 2 inputs and 1 outputs: [Add]:(/model.22/Add_output_0)
terminate called after throwing an instance of ‘cv::Exception’
what(): OpenCV(4.5.4) ./modules/dnn/src/onnx/onnx_importer.cpp:739: error: (-2:Unspecified error) in function ‘handleNode’
Node [Add]:(/model.22/Add_output_0) parse error: OpenCV(4.5.4) ./modules/dnn/src/onnx/onnx_importer.cpp:1067: error: (-215:Assertion failed) blob_0.size == blob_1.size in function ‘parseBias’

解决办法
将opencv 4.5 升级到4.9
https://opencv.org/releases/

安装方式:
https://blog.csdn.net/weixin_55189321/article/details/135994384

6.6、 fatal error: opencv2/opencv.hpp: No such file or directory

/media/HwHiAiUser/T9/Ascend_310/work/samples/inference/modelInference/sampleYOLOV8/src/sampleYOLOV8.cpp:2:10: fatal error: opencv2/opencv.hpp: No such file or directory2 | #include <opencv2/opencv.hpp>

在CMakeLists.txt里增加

find_package(OpenCV REQUIRED)

6.7、fatal error: AclLiteUtils.h: No such file or directory

/media/HwHiAiUser/T9/Ascend_310/work/samples/inference/modelInference/sampleYOLOV8/src/sampleYOLOV8.cpp:3:10: fatal error: AclLiteUtils.h: No such file or directory3 | #include "AclLiteUtils.h"

七、昇腾芯片常用命令

基础信息查看命令

# 查看Ubuntu发行版版本号
lsb_release -a# 查看当前系统的内核名称、主机名、内核发型版本、节点名
uname -a# 查询设备信息
npu-smi info# 查询设备0中编号为0(NPU)的芯片的详细信息
npu-smi info -t board -i 0 -c 0# 查看昇腾芯片的详细信息
ascend-dmi -i -dt

查看npu,AI core以及cpu的资源情况

由于Aipro带了四颗AI core,我们可以使用

npu-smi info watch

来查看npu,AI core以及cpu的资源情况。

将远程文件复制到本地

进入香橙派
示例命令

scp username@remote_host:/path/to/remote/file /path/to/local/directory

我的命令

scp diyun@192.168.71.150://home/diyun/work/python_project/23_0130_xiangqi_yolov5/yolov8_to_310.zip ./

AI CPU和Control CPU切换

昇腾310B独特的机制:AI CPU和Control CPU切换
npu-smi是昇腾AI处理器的系统管理工具,类似于NVIDIA GPU的 nvidia-smi,通过npu-smi info命令我们可以查看到AI处理器名称为310B4(8T算力版本)。

根据开发手册所说:OrangePi AiPro使用的昇腾SOC总共有4个CPU,这4个CPU既可以设置为control CPU,也可以设置为AICPU。默认情况下,control CPU和AI CPU的分配数量为 3:1。

# 查看control CPU和AI CPU的分配数量
(base) root@orangepiaipro:/home/HwHiAiUser# npu-smi info -t cpu-num-cfg -i 0 -c 0Current AI CPU number          : 1Current control CPU number     : 3Current data CPU number        : 0# 查询AI CPU占用率
(base) root@orangepiaipro:/home/HwHiAiUser# npu-smi info -t usages -i 0 -c 0Memory Capacity(MB)            : 7545Memory Usage Rate(%)           : 27Hugepages Total(page)          : 15Hugepages Usage Rate(%)        : 100Aicore Usage Rate(%)           : 0Aicpu Usage Rate(%)            : 0Ctrlcpu Usage Rate(%)          : 0Memory Bandwidth Usage Rate(%) : 1# 查询芯片的算力档位
(base) root@orangepiaipro:/home/HwHiAiUser# npu-smi info -t nve-level -i 0 -c 0nve level                      : 8T_1.0GHz# 设置AI CPU为0,最多可以设置3个AI CPU(3:1:0,最后的0为data CPU,固定配置为 0)        
sudo npu-smi set -t cpu-num-cfg -i 0 -c 0 -v 0:4:0

八、 使用总结

香橙派Ai pro的优点

1、既可以有ai 推理,npu加速的能力,也有控制能力。吊打树莓派这种鸡肋产品。
2、价格便宜,也支持大多数主流的算法,这个ai性能和价格可以说让jetson nano这种高价低性能的产品没有了生存空间。(jetson nano 1.5k,jetson orin 4k,Orange AI Pro应该1k以内)。
3、资料和示例代码较齐全。
4、自带wifi功能很方便

香橙派Ai pro的不足

1、图像界面不稳定,在重启后登陆系统的时候,经常出现登陆不进去的问题。
2、转晟腾npu模型的时候,内存严重不够用,如果不配置交换空间,系统直接会卡死。希望香橙派能够优化一下。
3、cpu能力较差,不过这个价位说实话已经不错了。
4、晟腾生态不如英伟达。华为的ai芯片种类很多,没有一个统一的技术架构,代码和模型不能通用,比如之前很不错的海思芯片,现在又出来个晟腾芯片,不知道过几年又会不会出新的,英伟达的cuda和tensorrt加速的c++代码,不光在最低阶的jetson nano上能用,可以不用改任何代码,也可以快速移植到xavier、orin,甚至4090等ubuntu台式机上。增加学习成本。

参考文章

1、香橙派OrangePi AIpro上手初体验
2、昇腾 CANN YOLOV8 和 YOLOV9 适配
3、昇腾AI处理器:Ascend310和CANN简介
4、解密昇腾AI处理器–Ascend310简介
5、模型转换:华为昇腾310B1平台深度学习算法模型转换
6、vnc可以参考:https://blog.csdn.net/qq_63913621/article/details/139252520?spm=1001.2014.3001.5502
7、yolov8_pose 全身姿态估计 pytorch转onnx转昇腾部署
8、华为昇腾芯片ai开发工具ATC使用教程
9、https://blog.csdn.net/Johnor/article/details/139234285
10、yolov5和yolov7的例程
11、多媒体开发:https://zhuanlan.zhihu.com/p/685708537

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

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

相关文章

springboot管理的各依赖版本查看

找一个springboot相关的依赖&#xff0c;比如这里我找mybatis 鼠标点击artifactId名称&#xff0c;图中蓝色字段&#xff0c;跳转到springboot依赖&#xff08;鼠标悬停在上面变成蓝色表示可点击跳转&#xff09;&#xff0c; 点击spring-boot-dependencites&#xff0c;跳转到…

list(二)和_stack_queue

嗨喽大家好&#xff0c;时隔许久阿鑫又给大家带来了新的博客&#xff0c;list的模拟实现&#xff08;二&#xff09;以及_stack_queue&#xff0c;下面让我们开始今天的学习吧&#xff01; list(二)和_stack_queue 1.list的构造函数 2.设计模式之适配器和迭代器 3.新容器de…

产品人生(9):从“波士顿矩阵”看“个人职业规划”

波士顿矩阵&#xff08;简称BCG矩阵&#xff09;是一种战略规划工具&#xff0c;由波士顿咨询公司的创始人布鲁斯亨德森&#xff08;Bruce Henderson&#xff09;于1970年代初提出的&#xff0c;它以两个关键指标作为分析维度&#xff1a;市场增长率和相对市场份额&#xff0c;…

k8s牛客面经篇

k8s的pod版块: k8s的网络版块: k8s的deployment版块: k8s的service版块: k8s的探针板块: k8s的控制调度板块: k8s的日志监控板块: k8s的流量转发板块: k8s的宏观版块:

【InternLM实战营第二期笔记】04:XTuner 微调 LLM:1.8B、多模态、Agent

文章目录 笔记微调基础知识Xtuner8G显存微调模型InternLM2 1.8B多模态实践环节数据微调过拟合WebUI 交互 多模态微调 作业 这回学乖了&#xff0c;打开本节课第一件事先不看教程而是装环境~ 笔记 微调基础知识 这里感慨一下&#xff0c;垂直领域的训练还是挺困难的&#xff0c;…

docker安装redis以及持久化

为了避免当虚拟机关机后redis数据丢失的情况&#xff0c;redis需要持久化。所以要挂载数据卷 创建数据和配置存放的目录 [root192 data]# pwd /root/data [root192 data]# mkdir -p /root/data/redis/conf && chmod 777 /root/data/redis/conf [root192 data]# mkdir …

php反序列化中的pop链

目录 一、什么是POP 二、成员属性赋值对象 例题&#xff1a; 方法一 方法二 三、魔术方法的触发规则 例题&#xff1a; 四、POC的编写 例题1&#xff1a; 例题2 [NISACTF 2022]babyserialize 今日总结&#xff1a; 一、什么是POP 在反序列化中&#xff0c;我们…

项目资源管理

目录 1.概述 2.六个过程 2.1. 规划资源管理 2.2. 估算活动资源 2.3. 获取资源 2.4. 建设团队 2.5. 管理团队 2.6. 控制资源 3.应用场景 3.1.十个应用场景 3.2.软件开发项目 3.2.1. 资源规划 3.2.2. 资源分配 3.2.3. 资源获取 3.2.4. 资源优化 3.2.5. 资源监控与…

【AI基础】第二步:安装AI运行环境

开局一张图&#xff1a; 接下来按照从下往上的顺序来安装部署。 规则1 注意每个层级的安装版本&#xff0c;上层的版本由下层版本决定 比如CUDA的版本&#xff0c;需要看显卡安装了什么版本的驱动&#xff0c;然后CUDA的版本不能高于这个驱动的版本。 这个比较好理解&#xff…

ES 生命周期管理

一 .概念 ILM定义了四个生命周期阶段&#xff1a;Hot&#xff1a;正在积极地更新和查询索引。Warm&#xff1a;不再更新索引&#xff0c;但仍在查询。cold&#xff1a;不再更新索引&#xff0c;很少查询。信息仍然需要可搜索&#xff0c;但是如果这些查询速度较慢也可以。Dele…

Java面试——中间件

OpenFeign 1、openFeign是一个HTTP客户端&#xff0c;它融合了springmvc的注解&#xff0c;使之可以用REST风格的映射来请求转发。 2、可以把openFegin理解为是controller层或是service层。可以取代springmvc控制层作为请求映射&#xff0c;亦或是作为service层处理逻辑&#…

C++ priority_queue简单源码剖析:priority_queue模拟实现

文章目录 1. priority_queue介绍2. priority_queue模拟实现3. 适配器与虚函数 大家好&#xff01;本文会用C模拟一个基本的priority_queue类&#xff0c;帮助我们更好的理解priority_queue的内置函数的实现与规则。 1. priority_queue介绍 priority_queue被叫做优先队列&#…

ESP使用巴法云远程OTA(VScode + Platform io)

ESP使用巴法云远程OTA&#xff08;Platform&#xff09; 什么是OTA&#xff1a; OTA&#xff08;Over-the-AirTechnology&#xff09;即空中下载技术&#xff0c;是通过移动通信的空中接口实现对移动终端设备及SIM卡数据进行远程管理的技术。OTA升级是物联网&#xff08;IOT&am…

【C++初阶学习】第十二弹——stack和queue的介绍和使用

C语言栈&#xff1a;数据结构——栈(C语言版)-CSDN博客 C语言队列&#xff1a;数据结构——队列&#xff08;C语言版&#xff09;-CSDN博客 前言&#xff1a; 在之前学习C语言的时候&#xff0c;我们已经学习过栈与队列&#xff0c;并学习过如何使用C语言来实现栈与队列&…

企业软件产品和服务 之 设计保证安全 七项承诺

1. 引言 公司如何保护自己免受数据泄露的影响&#xff1f;标准答案就是&#xff1a; “启用多因素身份验证”——MTA&#xff08;Enable multifactor authentication&#xff09;。 但是&#xff0c;目前很多公司仍然盲目地只使用密码作为唯一的身份来源。 网络安全的核心是…

深入了解 C 语言 Bug

目录 一、引言二、Bug的定义三、Bug的由来四、Bug的影响五、应对 Bug 的方法六、结论 一、引言 1、在 C 语言的编程世界中&#xff0c;Bug 是一个我们无法回避的话题。 2、Bug&#xff0c;简单来说&#xff0c;就是程序中存在的错误或缺陷。它可以表现为程序运行结果的异常、崩…

步进电机双闭环细分控制(matlab仿真)内含课设等参考文件

1.1 步进电机工作原理 步进电机是一种用电脉冲进行控制&#xff0c;将电脉冲信号转换成相位移的电机&#xff0c;其机械位移和转速分别与输入电机绕组的脉冲个数和脉冲频率成正比,每一个脉冲信号可使步进电机旋转一个固定的角度。脉冲的数量决定了旋转的总角度&#xff0c;脉…

英伟达开源新利器NV-Embed向量模型,基于双向注意力的LLM嵌入模型,MTEB 56项任务排名第一

前言 文本嵌入模型能够将文本信息转化为稠密的向量表示&#xff0c;并在信息检索、语义相似度计算、文本分类等众多自然语言处理任务中发挥着关键作用。近年来&#xff0c;基于解码器的大型语言模型 (LLM) 开始在通用文本嵌入任务中超越传统的 BERT 或 T5 嵌入模型&#xff0c…

企业打款验证API在Java、Python、PHP中的使用教程

随着企业银行账号数量的增加和银行间的连接方式不断丰富&#xff0c;企业在进行资金交易时需要确保所填写的收款方账户信息的准确性和合法性&#xff0c;以避免资金损失和风险。然而&#xff0c;由于银行数量众多、地域分布广泛&#xff0c;不同银行间的账户验证机制和信息交互…

网络编程(八)

网络编程&#xff08;八&#xff09; 数据库数据库的分类基于嵌入式的数据库什么是SQLite?为什么使用SQLite?sqlite3数据库的安装 sqlite3中的点命令.open 数据库文件名字.tables [数据库文件名].schema 表名.database.quit.head on.mode column SQLite数据库中的数据类型SQL…