OrangePi AIpro 快速上手初体验——接口、样例和目标检测

一、 开发板简介

OrangePi AIpro开发板是香橙派联合华为精心打造的高性能 AI 开发板,其搭载了昇腾 AI 处理器,可提供 8TOPS INT8 的计算能力,内存提供了 8GB 和 16GB两种版本。可以实现图像、视频等多种数据分析与推理计算,可广泛用于教育、机器人、无人机等场景。

下面让我们来具体看看吧:

1.1 开发板全貌

首先看一眼产品的全貌:

img

img

(不得不说,颜值还是很nice的)

1.2 硬件规格

(1)昇腾AI处理器: 搭配华为昇腾310NPU,4核64位Arm处理器+AI处理器
(2)AI算力: 支持半精度(FP16):4 TFLOPS 和 整数精度(INT8):8 TOPS
(3)内存: 8GB 或 16GB
(4)存储: 板载32MB的SPI Flash,提供Micro SD卡插槽和eMMC插座
(5)接口: 接口配置丰富,包括USB3.0、USB Type-C 3.0、Micro USB、HDMI、CSI、DSI、以太网口、40pin扩展口等多种接口
(6)Wifi+蓝牙: 支持2.4G和5G双频WIFI、BT 4.2
(7)操作系统: 支持Ubuntu 22.04 和 openEuler 22.03
(8)外观规格: 107*68mm、82kg
输入npu-smi info 再看一下芯片信息:

img

1.3 接口和引脚图

接口:

img

引脚:

img

二、 开机和使用

2.1 开机准备

由于获得的Orange Pi AIpro 已经烧录了ubuntu的镜像到TF卡,因此选择使用TF卡的启动方式。
而开发板支持从 TF 卡、eMMC 和 SSD(支持 NVMe SSD 和 SATA SSD)启动,通过背面的两个拨码开关(BOOT1和BOOT2)控制

img

两个拨码开关都支持左右两种设置状态,共4种状态,目前开发板使用了其中的3种,不同状态的启动设备如下表所示:

拨码开关BOOT1拨码开关BOOT2对应的启动设备
未使用
SATA SSD和NVMe SSD
eMMC
TF卡

SATA SSD和NVMe SSD通过M2_TYPE引脚的电平自动区分。此外切换拨码开关需要重新插拔电源使启动设备选项生效,复位键不行。

2.2 开机

使用 HDMI0 连接屏幕,如图所示,上电等待一会儿后即自动开机,输入密码:Mind@123进入 ubuntu 系统

img

(注意:使用时天线不能贴到板子上,同时天线的导电布也不能挨着板子,否则可能会烧坏板子)

img

鼠标和键盘插到两个usb 3.0的接口中都可以正常使用!

2.3 SSH连接

直接用MobaXterm软件连接,下面VNC也是,填上ip地址,username可以填HwHiAiUser或者root,密码:Mind@123

img

登陆成功后显示:

img

2.4 VNC远程连接

由于我的屏幕有点拉闸,所以我选择vnc远程连接

输入ip和 端口,默认是5901,密码:Mind@123

img

说明:

打开终端后,请执行bash激活命令行。

在命令行开启远程桌面服务(执行以后重启,可使用VNC登录图形桌面。默认已开启,无需配置。)

sudo systemctl enable vncserver@1.service
reboot
在命令行关闭远程桌面服务(执行以后重启,不可使用VNC登录图形桌面,且系统会释放相应内存。)

sudo systemctl disable vncserver@1.service
reboot
在命令行修改VNC登录密码(修改密码之后,使用VNC登陆远程桌面需要重新输入密码。)

vncpasswd
成功连接后桌面:

img

若始终无法连接:

如果你不小心重新配置了vnc,导致始终无法连接的话,可以参考以下方法。

(1)输入 cd ~/.vnc进入 .vnc 文件夹

(2)输入 gedit xstartup修改 xstartup 文件

#!/bin/sh
unset SESSION_MANAGER
unset DBUS_SESSION_BUS_ADDRESS
exec startxfce4
(3)输入 chmod u+x ~/.vnc/xstartup 加上权限

(4)最后输入:

vncserver -localhost no
vncserver
即可启动vnc,此时再重新连接

三、 样例和接口测试

3.1 登录Jupyter Lab

(1)首先进入保存AI样例的目录:

cd samples/notebooks/
(2)执行 start_notebook.sh 启动Jupyter Lab

./start_notebook.sh
(3)进入Jupyter Lab的网址,直接用火狐浏览器打开即可

img

进入后,即可看到左侧有9个样例的文件夹

img

下面我就挑选几个样例进行测试一下!

3.2 yolov5目标检测

到 样例运行 部分,可以切换视频、图片和摄像头三种模式运行

infer_mode = 'video'
infer_mode = 'image'
infer_mode = 'camera'

img

img

img

def infer_frame_with_vis(image, model, labels_dict, cfg, bgr2rgb=True):# 数据预处理img, scale_ratio, pad_size = preprocess_image(image, cfg, bgr2rgb)# 模型推理output = model.infer([img])[0]output = torch.tensor(output)# 非极大值抑制boxout = nms(output, conf_thres=cfg["conf_thres"], iou_thres=cfg["iou_thres"])pred_all = boxout[0].numpy()# 预测坐标转换scale_coords(cfg['input_shape'], pred_all[:, :4], image.shape, ratio_pad=(scale_ratio, pad_size))# 图片预测结果可视化img_vis = draw_bbox(pred_all, image, (0, 255, 0), 2, labels_dict)return img_vis

从这里的推理框架来看,我们可以将我们训练好模型转换成om模型后直接使用,只要对数据的输入做好前处理,推理后,再做好后处理即可。

img

3.3 卡通图像生成

该样例使用 cartoonGAN 模型对输入图片进行卡通化处理。在样例中已经包含转换后的om模型和测试图片。

main 如下:

def main():MODEL_PATH = "cartoonization.om"MODEL_WIDTH = 256MODEL_HEIGHT = 256acl_resource = AclLiteResource()  # 初始化acl资源acl_resource.init()# instantiation Cartoonization objectcartoonization = Cartoonization(MODEL_PATH, MODEL_WIDTH, MODEL_HEIGHT)  # 构造模型对象# initret = cartoonization.init()  # 初始化模型类变量utils.check_ret("Cartoonization.init ", ret)  image_file = 'img.jpg'# read imageimage = AclLiteImage(image_file)  # 构造 AclLiteImage ,方便利用 dvpp 进行前处理print('===================')print(image)# preprocesscrop_and_paste_image = cartoonization.pre_process(image)  # 前处理# inferenceresult = cartoonization.inference([crop_and_paste_image, ])  # 推理# postprocesscartoonization.post_process(result, image_file, image)  # 后处理

从代码逻辑中可以看到,整套代码:

(1)首先初始化了acl资源,也就是对AscendCL进行初始化;
(2)创建了一个Cartoonization类,定义了前处理、推理和后处理函数;
(3)构造AclLiteImage类型数据,并转换图片格式为模型需要的yuv格式;
(4)进行推理;
(5)进行后处理。

img

img

3.4 人像分割与背景替换

该样例使用了PortraitNet模型进行人像分割。

main函数如下所示:

def main():"""推理主函数"""os.makedirs(OUTPUT_DIR, exist_ok=True)os.makedirs(MASK_DIR, exist_ok=True)acl_resource = AclLiteResource()acl_resource.init()seg = Seg(MODEL_PATH, MODEL_WIDTH, MODEL_HEIGHT)ret = seg.init()utils.check_ret("seg.init ", ret)images_list = [os.path.join(IMAGE_DIR, img)for img in os.listdir(IMAGE_DIR)if os.path.splitext(img)[1] in const.IMG_EXT]for image_file in images_list:image_name = os.path.basename(image_file)if image_name != 'background.jpg':print('====' + image_name + '====')# read imageimage = AclLiteImage(image_file)# Preprocess the pictureresized_image = seg.pre_process(image)# Inferenceresult = seg.inference([resized_image, ])# Post-processingmask = seg.post_process(result, image_name)# Fusion of segmented portrait and background imagebackground_replace(os.path.join(IMAGE_DIR, 'background.jpg'), \image_file, os.path.join(MASK_DIR, image_name))

可以看出代码逻辑都相似:
(1)首先初始化了acl资源;
(2)创建Seg类对象,定义前处理、推理和后处理函数;
(3)构造AclLiteImage类型图像数据并进行前处理;
(4)推理后得到分割结果进行后处理获得mask;
(5)进行背景替换

img

3.5 摄像头测试

上面开机时我们接了HDMI0的屏幕和USB的键盘、鼠标,都可以正常使用,下面我们试一下USB摄像头。

在昇腾论坛上,找到一位楼主部署了一个贪吃蛇的小游戏,我打算用这个案例来测试一下:
https://www.hiascend.com/forum/thread-0265146309613977027-1-1.html

首先接入摄像头,将代码下载到系统中,该套代码使用的Google的开源的MediaPipe手势识别库;
其次要安装相关的库:

pip install mediapipe
pip install cvzone

随后就可以直接运行代码:

python main.py

img

可见,效果还是不错的,但是有一点,用vnc连接时默认是虚拟桌面,虚拟桌面好像无法识别到摄像头,所以我还是用的hdmi屏幕。

3.6 串口通信测试

既然是开发板,那么有时候避免不了使用串口的吧,嘿嘿,所以这里对串口也进行了测试。
根据用户手册,可以找到uart设备节点和uart的对应关系:

img

也可以输入 ls /dev/ttyAMA* 来查看,需要注意的是,uart0默认设置为了调试串口功能

img

再看一下引脚图:

img

于是我用一个CH340 USB转TTL模块,选择使用uart7,也就是ttyAMA2TXGPIO7_07RXGPIO7_02

img

这里使用python的一个库:pyserial

输入:pip install pyserial 安装

import serial
import serial.tools.list_portsports_list = list(serial.tools.list_ports.comports())  # 获得所有串口设备实例
for port in ports_list:  # 输出所有串口号print(list(port)[0], list(port)[1])  #/dev/ttyAMA1、/dev/ttyAMA2ser = serial.Serial("/dev/ttyAMA2", 115200)  # 打开串口,设置波特率
if ser.isOpen():  # 判断是否打开print("open success")print(ser.name)  # 输出串口号
else:print("failed")
write_len = ser.write("OrangePi AIpro".encode('utf-8'))
ser.close()  # 关闭串口
if ser.isOpen():  # 判断是否关闭串口print("no closed")
else:print("closed")

运行: sudo python3 serial_test.py,串口ttyAMA2发送 “OrangePi AIpro”,pc端通过串口调试助手也接收到了发送过来的数据

img

img

四、AscendCL快速入门

下面我们具体来看一下AscendCL要如何应用?

AscendCL(Ascend Computing Language)是一套用于在昇腾平台上开发深度神经网络应用的C语言API库,提供运行资源管理、内存管理、模型加载与执行、算子加载与执行、媒体数据处理等API,能够实现利用昇腾硬件计算资源、在昇腾CANN平台上进行深度学习推理计算、图形图像预处理、单算子加速计算等能力。简单来说,就是统一的API框架,实现对所有资源的调用。

而AscendCL结构调用的基本流程可分下面几个步骤:
(1)AscendCL初始化
(2)运行管理资源申请
(3)模型推理/单算子调用/媒体数据处理
(4)运行管理资源释放
(5)AscendCL去初始化

下面我们通过一个简单的狗狗图像分类的应用快速了解AscendCL接口(C语言接口)开发应用的基本过程:

img

首先进入到昇腾开源仓库:Ascend: 昇腾万里,让智能无所不及

进入samples\cplusplus\level2_simple_inference\1_classification\resnet50_firstapp目录下:

(1)直接git整个仓库,或者下载zip,将resnet50_firstapp上传到ubuntu中

(2)下载测试需要的文件:

a)下载模型文件(*.prototxt):

https://obs-9be7.obs.cn-east-2.myhuaweicloud.com/003_Atc_Models/AE/ATC%20Model/resnet50/resnet50.prototxt

放到resnet50_firstapp/model目录下

b)下载权重文件(*.caffemodel):

https://obs-9be7.obs.cn-east-2.myhuaweicloud.com/003_Atc_Models/AE/ATC%20Model/resnet50/resnet50.caffemodel

放到resnet50_firstapp/model目录下

c)下载测试的输入图片:

https://obs-9be7.obs.cn-east-2.myhuaweicloud.com/models/aclsample/dog1_1024_683.jpg

放到resnet50_firstapp/data目录下

img

(3)使用ATC工具进行模型转换

执行:

atc --model=model/resnet50.prototxt --weight=model/resnet50.caffemodel --framework=0 --output=model/resnet50 --soc_version=Ascend310B4

将原始模型转换为昇腾AI处理器能识别的*.om模型文件

● --model: ResNet-50网络的模型文件(.prototxt)的路径。
● --weight: ResNet-50网络的预训练模型文件(
.caffemodel)的路径。
● --framework: 原始框架类型。0:Caffe; 1:MindSpore; 3:Tensorflow; 5:Onnx
● --output: resnet50.om模型文件的路径。请注意,记录保存该om模型文件的路径,后续开发应用时需要使用。
● --soc_version: 昇腾AI处理器的版本。进入“CANN软件安装目录/compiler/data/platform_config”目录,".ini"文件的文件名即为昇腾AI处理器的版本,请根据实际情况选择。实际目录可参考:
./usr/local/Ascend/ascend-toolkit/7.0.0/compiler/data/platform_config
(我这里是通过命令npu-smi info指令这里选择的版本)

img

成功后输出如下所示:

img

转模型有可能会遇到下述问题:

img

img

在昇腾论坛找到了解决方案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模型啦!

(4)对输入图片进行处理

由于我们下载的.jpg的输入图片,与模型要求的输入不同,模型要求输入图片是rgb的且大小为224*224,所以这里直接运行resnet50_firstapp/script/transferPic.py脚本进行数据处理

(5)执行编译脚本

给编译脚本执行权限:

chmod +x sample_build.sh

添加环境变量:

export APP_SOURCE_PATH=/home/HwHiAiUser/samples/test_samples/resnet50_firstapp
export DDK_PATH=/usr/local/Ascend/ascend-toolkit/latest
export NPU_HOST_LIB=${DDK_PATH}/runtime/lib64/stub

执行编译脚本:

./sample_build.sh

img

此时在out/main下生成了一个名为main的可执行文件

(6)执行运行脚本

给执行脚本执行权限:

chmod +x sample_run.sh

执行运行脚本:

./sampele_run.sh

img

因为模型使用imagenet数据集训练的,所以标签可以imagenet数据集处查看:https://blog.csdn.net/u013491950/article/details/83927968

img

五、YOLOv8移植测试

虽然官方提供了yolov5的样例,但还是想体验一把部署自己模型的感觉,恰恰又对yolo系列更为熟悉,所以就还是选择以yolov8为例啦

5.1 模型转换

首先我们git下yolov8的源码:https://github.com/ultralytics/ultralytics,下载一下模型,这里我选择下载yolov8s.pt

img

用简单的代码转换成onnx模型:

from ultralytics import YOLOmodel = YOLO('yolov8s.pt', 'detect')
model.export(format='onnx', opset=11, simplify=True)

输出如下:

img

注意这里的输出是三个尺度的。

将onnx模型放到ubuntu系统中后,转换成om模型:

export TE_PARALLEL_COMPILER=1
export MAX_COMPILE_CORE_NUMBER=1
atc --model=yolov8s.onnx --framework=5 --output=yolov8s --soc_version=Ascend310B4 --input_format=NCHW --input_shape="images:1,3,640,640" --output_type="FP32" --log=error

–framework: 选择5,即onnx模型
–output: 为输出的名称,会自动加上.om后缀
–input_format: 输入格式为NCHW
–input_shape: 设置模型输入的格式
–output_type: 输出格式,可以自己选择

img

我这里为了方便后处理直接使用一个转换好的onnx模型,输出为(1, 84, 8400),大家可以自取,免费下载:https://download.csdn.net/download/qq_47941078/89365245

5.2 推理

获得om模型后,就要自己写一下推理代码啦

import cv2
import torch
import numpy as np
import time
import random
from numpy import ndarray
from typing import List, Tuple
from ais_bench.infer.interface import InferSession# 类别名称
CLASS_NAMES = ('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')# 预处理
def preprocess_warpAffine(image, dst_width=640, dst_height=640):scale = min((dst_width / image.shape[1], dst_height / image.shape[0]))ox = (dst_width  - scale * image.shape[1]) / 2oy = (dst_height - scale * image.shape[0]) / 2M = np.array([[scale, 0, ox],[0, scale, oy]], dtype=np.float32)img_pre = cv2.warpAffine(image, M, (dst_width, dst_height), flags=cv2.INTER_LINEAR,borderMode=cv2.BORDER_CONSTANT, borderValue=(114, 114, 114))IM = cv2.invertAffineTransform(M)img_pre = (img_pre[...,::-1] / 255.0).astype(np.float32)img_pre = img_pre.transpose(2, 0, 1)[None]img_pre = torch.from_numpy(img_pre)return img_pre, IM# 计算iou
def iou(box1, box2):def area_box(box):return (box[2] - box[0]) * (box[3] - box[1])left   = max(box1[0], box2[0])top    = max(box1[1], box2[1])right  = min(box1[2], box2[2])bottom = min(box1[3], box2[3])cross  = max((right-left), 0) * max((bottom-top), 0)union  = area_box(box1) + area_box(box2) - crossif cross == 0 or union == 0:return 0return cross / union# nms非极大值抑制
def NMS(boxes, iou_thres):remove_flags = [False] * len(boxes)keep_boxes = []for i, ibox in enumerate(boxes):if remove_flags[i]:continuekeep_boxes.append(ibox)for j in range(i + 1, len(boxes)):if remove_flags[j]:continuejbox = boxes[j]if(ibox[5] != jbox[5]):continueif iou(ibox, jbox) > iou_thres:remove_flags[j] = Truereturn keep_boxes# 后处理
def postprocess(pred, IM=[], conf_thres=0.25, iou_thres=0.45):# 1,8400,84 [cx,cy,w,h,class*80]boxes = []for item in pred[0]:cx, cy, w, h = item[:4]label = item[4:].argmax()confidence = item[4 + label]if confidence < conf_thres:continueleft    = cx - w * 0.5top     = cy - h * 0.5right   = cx + w * 0.5bottom  = cy + h * 0.5boxes.append([left, top, right, bottom, confidence, label])boxes = np.array(boxes)lr = boxes[:,[0, 2]]tb = boxes[:,[1, 3]]boxes[:,[0,2]] = IM[0][0] * lr + IM[0][2]boxes[:,[1,3]] = IM[1][1] * tb + IM[1][2]boxes = sorted(boxes.tolist(), key=lambda x:x[4], reverse=True)return NMS(boxes, iou_thres)def hsv2bgr(h, s, v):h_i = int(h * 6)f = h * 6 - h_ip = v * (1 - s)q = v * (1 - f * s)t = v * (1 - (1 - f) * s)r, g, b = 0, 0, 0if h_i == 0:r, g, b = v, t, pelif h_i == 1:r, g, b = q, v, pelif h_i == 2:r, g, b = p, v, telif h_i == 3:r, g, b = p, q, velif h_i == 4:r, g, b = t, p, velif h_i == 5:r, g, b = v, p, qreturn int(b * 255), int(g * 255), int(r * 255)def random_color(id):h_plane = (((id << 2) ^ 0x937151) % 100) / 100.0s_plane = (((id << 3) ^ 0x315793) % 100) / 100.0return hsv2bgr(h_plane, s_plane, 1)if __name__ == "__main__":model_path = 'yolov8s2.om'img_path = 'bus.jpg'img = cv2.imread(img_path)img22 = cv2.imread(img_path)# img_pre = preprocess_letterbox(img)img_pre, IM = preprocess_warpAffine(img)# model  = AutoBackend(weights="yolov8s.pt")model = InferSession(0, model_path)# names  = model.namesnames = CLASS_NAMESimg = np.ascontiguousarray(img_pre, dtype=np.float32)start = time.perf_counter()result = model.infer([img])print(np.array(result).shape) # (1, 1, 84, 8400)result = np.array(result).transpose(0, 1, 3, 2).squeeze()[np.newaxis]print(np.array(result).shape) # (1, 8400, 84)result = list(result)end = time.perf_counter()print(f'Inference FPS: {1 / (end - start)}')boxes  = postprocess(result, IM)for obj in boxes:left, top, right, bottom = int(obj[0]), int(obj[1]), int(obj[2]), int(obj[3])confidence = obj[4]label = int(obj[5])color = random_color(label)cv2.rectangle(img22, (left, top), (right, bottom), color=color ,thickness=2, lineType=cv2.LINE_AA)caption = f"{names[label]} {confidence:.2f}"print("caption:", caption)w, h = cv2.getTextSize(caption, 0, 1, 2)[0]cv2.rectangle(img22, (left - 3, top - 33), (left + w + 10, top), color, -1)cv2.putText(img22, caption, (left, top - 5), 0, 1, (0, 0, 0), 2, 16)print("img22:", img22.shape)#img22 = img22.transpose(1, 2, 0)#print("img22:", img22.shape)cv2.imwrite("infer.jpg", img22)print("save done")

输出打印:

img

保存的推理图片为:

img

可以看到精度还是很高的,并没有什么损失!

六、 总结

OrangePi AIpro是一款非常优秀的AI开发板,结合了高性能处理器和专用的AI加速硬件,算力强大,完全满足正常的视频流推理的需求,又有着非常丰富的接口,给开发者提供了一个强大且灵活的平台来用于深度学习、目标检测等AI应用的开发和部署。

同时,关于OrangePi AIpro有着非常丰富详细的资料,用户手册完全可以帮助快速使用开发板;各种开源仓库也提供了多种测试样例;此外还有论坛,用户活跃,各种问题都可以相互讨论交流,比如我在模型转换时遇到了内存不足的问题便是在论坛上找到的解决方案;社区还提供了详细的开发指南,从文本教程到视频教程,对开发者都是非常有帮助的,本次体验非常愉快!

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

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

相关文章

猫狗分类识别模型建立②模型建立

一、导入依赖库 pip install opencv-python pip install numpy pip install tensorflow pip install keras 二、模型建立 pip install opencv-python pip install numpy pip install tensorflow pip install kerasimport os import xml.etree.ElementTree as ETimpor…

[双指针] --- 快乐数 盛最多水的容器

Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏&#xff1a; 算法Journey 本篇博客我们分享一下双指针算法中的快慢指针以及对撞双指针&#xff0c;下面我们开始今天的学习吧~ &#x1f3e0; 快乐数 &#x1f4d2; 题…

LabVIEW中实现Trio控制器的以太网通讯

在LabVIEW中实现与Trio控制器的以太网通讯&#xff0c;可以通过使用TCP/IP协议来完成。这种方法包括配置Trio控制器的网络设置、使用LabVIEW中的TCP/IP函数库进行数据传输和接收&#xff0c;以及处理通讯中的错误和数据解析。本文将详细说明实现步骤&#xff0c;包括配置、编程…

分享10个我常逛的技术社区

多逛社区&#xff0c;了解新鲜的事情和技术&#xff0c;或许会有意想不到的观点给你灵感&#xff01; 国外技术交流网站合集&#xff08;30个类别&#xff09;的github地址: https://github.com/sdmg15/Best-websites-a-programmer-should-visit 这里收集了超过200个程序员应该…

K8s 小白入门|从电影配乐谈起,聊聊容器编排和 K8s

来听听音乐 电影&#xff0c;是我们生活中的重要调味剂。 配乐&#xff0c;是电影中不可或缺的一部分。 有的时候&#xff0c;配乐可以跟剧情共振&#xff0c;让你按捺不住自己的情绪&#xff0c;或眼含热泪、或慷慨激昂、或人仰马翻、或怅然若失&#xff1b; 有的时候&…

美团拼好饭小程序mtgsig1.2分析(补环境分析)

声明 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01;wx a15018601872 本文章未…

【AI绘画Stable Diffusion】单人LoRA模型训练,打造你的专属模型,新手入门宝典请收藏!

大家好&#xff0c;我是灵魂画师向阳 本期我将教大家如何进行LoRA模型训练&#xff0c;打造你的专属模型&#xff0c;内容比较干&#xff0c;还请耐心看完&#xff01; 随着AIGC的发展&#xff0c;许多传统工作岗位正逐渐被AI取代。同时&#xff0c;AI变革也在创造前所未有的…

【C++】---二叉搜索树

【C】---二叉搜索树 一、二叉搜索树概念二、二叉搜索树操作&#xff08;非递归&#xff09;1.二叉搜索树的查找 &#xff08;非递归&#xff09;&#xff08;1&#xff09;查找&#xff08;2&#xff09;中序遍历 2.二叉搜索树的插入&#xff08;非递归&#xff09;3.二叉搜索树…

三十三、openlayers官网示例Drawing Features Style——在地图上绘制图形,并修改绘制过程中的颜色

这篇讲的是使用Draw绘制图形时根据绘制形状设置不同颜色。 根据下拉框中的值在styles对象中取对应的颜色对象&#xff0c;new Draw的时候将其设置为style参数。 const styles {Point: {"circle-radius": 5,"circle-fill-color": "red",},LineS…

P2341 受欢迎的牛

题目描述 每一头牛的愿望就是变成一头最受欢迎的牛。现在有 N 头牛&#xff0c;给你 M 对整数&#xff0c;表示牛 A 认为牛 B 受欢迎。这种关系是具有传递性的&#xff0c;如果 A 认为 B 受欢迎&#xff0c;B 认为 C 受欢迎&#xff0c;那么牛 A 也认为牛 C 受欢迎。你的任务是…

UVa11604 General Sultan

UVa11604 General Sultan 题目链接题意分析AC 代码 题目链接 UVA - 11604 General Sultan 题意 给出一些0和1组成的模式串&#xff0c;问是否存在一个串使得有多种方案将这个串分解成模式串。    给一个包含n&#xff08;n≤100&#xff09;个符号的二进制编码方式&#xff…

基础—SQL—DQL(数据查询语言)基础查询

一、引言 1、介绍&#xff1a; 分类全称描述DQL英文全称&#xff1a;Data Query Language(数据查询语言)主要是学习对数据库表中的记录进行查询的语句 2、讲解 日常的开发中或者对于一个正常的业务系统中&#xff0c;对于查询的操作次数是远远多于数据的增删改的频次。例如…

Ansible自动化运维中的Setup收集模块应用详解

作者主页&#xff1a;点击&#xff01; Ansible专栏&#xff1a;点击&#xff01; 创作时间&#xff1a;2024年5月22日13点14分 &#x1f4af;趣站推荐&#x1f4af; 前些天发现了一个巨牛的&#x1f916;人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xf…

ABB 控制柜

1&#xff0c;主计算机&#xff1a;相当于电脑的主机&#xff0c;用于存放系统和数据&#xff0c;需要24V直流电才能工作。执行用户编写的程序&#xff0c;控制机器人进行响应的动作。主计算机有很多接口&#xff0c;比如与编程PC连接的服务网口、用于连接示教器的网口、连接轴…

揭秘网络编程:同步与异步IO模型的实战演练

摘要 ​ 在网络编程领域&#xff0c;同步(Synchronous)、异步(Asynchronous)、阻塞(Blocking)与非阻塞(Non-blocking)IO模型是核心概念。尽管这些概念在多篇文章中被广泛讨论&#xff0c;它们的抽象性使得彻底理解并非易事。本文旨在通过具体的实验案例&#xff0c;将这些抽象…

深入解析Web前端三大主流框架:Angular、React和Vue

Web前端三大主流框架分别是Angular、React和Vue。下面我将为您详细介绍这三大框架的特点和使用指南。 Angular 核心概念: 组件(Components): 组件是Angular应用的构建块,每个组件由一个带有装饰器的类、一个HTML模板、一个CSS样式表组成。组件通过输入(@Input)和输出(…

【Python】解决Python报错:TypeError: %d format: a number is required, not str

&#x1f9d1; 博主简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…

.NET 直连SAP HANA数据库

前言 上个项目碰到的需求&#xff0c;IT部门要求直连SAP的HANA数据库&#xff0c;以只读的权限读取SAP部门开发的CDS视图&#xff0c;是个有点复杂的工程&#xff0c;需要从成品一直往前追溯到原材料的产地&#xff0c;和交货单、工单、采购订单有相当程度上的关联 IT部门要求…

会议管理系统(含源码+sql+视频导入教程)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 会议管理系统拥有两种角色 管理员&#xff1a;部门管理、员工管理、会议管理、会议室管理、预订会议、添加员工、注册员工审批等 用户&#xff1a;个人通知中心、预订会议、查看所有会议…

错误记录:从把项目从Tomcat8.5.37转到Tomcat10.1.7

错误信息&#xff1a;在本地Servlet项目里没有报错&#xff0c;但是浏览器跳转该servlet时报错 型 异常报告 消息 实例化Servlet类[com.wangdao.lx.MyServlet1]异常 描述 服务器遇到一个意外的情况&#xff0c;阻止它完成请求。 例外情况 jakarta.servlet.ServletExceptio…