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

yolo11s rknn无法detect的bugfix - step by step

1.缘起

上周四下班时,发现在宿主机环境工作良好的既有的pytorch模型,在通过.pt->.onnx->.rknn的转换后无法正常工作。周五下班时,怀疑疑点在两处:

  1. 版本匹配问题
  2. 通道和参数传递问题。

周六,周日,周末时间,我将各个环境的pytorch版本修改为渐趋一致,并且参照了rknn2.3中的版本要求,对齐到同一个版本,并且怀疑training部分的版本与pt->rknn的环境不一致,我把两个环境融合到一个docker了。

training env:

torch                        2.4.0+cpu
torchaudio                   2.4.0+cpu
torchvision                  0.19.0+cpu

ultralytics                  8.3.68      /ultralytics
ultralytics-thop             2.0.14

rknn env:

torch                    2.4.0+cpu
torchaudio               2.4.0+cpu
torchvision              0.19.0+cpu 

 在周日最后一次detect测试时,结果仍然是目标对象无法检出。下面针对这个问题,开展分析,尝试解决。

2.尝试1:增加模型精度yolov11n->yolov11s

周日最后,我启动了针对yolov11s.pt的训练,训练的数据集是一个测试数据集moonpie.这一次,我把pt->onnx->rknn的docker处理成了唯一的一个,epoch增大到250(batch=16, imgsz=640)

model=YOLO('yolo11.yaml').load('yolo11s.pt')

result = model.train(data=r'./moonpie.yaml', epochs=250, batch=16, imgsz=640, device='cpu')

最终的训练结果:

results_dict: {'metrics/precision(B)': 0.8658830071855359, 'metrics/recall(B)': 0.770949720670391, 'metrics/mAP50(B)': 0.8821807607242769, 'metrics/mAP50-95(B)': 0.6566184427590052, 'fitness': 0.6791746745555324}
save_dir: PosixPath('/app/rk3588_build/yolo_sdk/ultralytics/runs/detect/train4')
speed: {'preprocess': 0.9470678144885648, 'inference': 83.09212807686097, 'loss': 0.00011536382859753024, 'postprocess': 1.3212234743179814}
task: 'detect'

突然发现一件事,因为我周四开始的测试,是把新物体放到了第81个slot返回。难道是class_id detected的时候忘记处理它的大小了?要是的话,这个错误就太低级了。

2.1 直接做模拟环境的最终测试 

 step1. pt2onnx

from ultralytics import YOLO# Load a model
model = YOLO("/app/rk3588_build/last_moonpie_yolov11s.pt")  # load an official model
#model = YOLO(r"./best.pt")  # load a custom trained model
# Export the model
model.export(format="onnx")

Ultralytics 8.3.68 🚀 Python-3.8.10 torch-2.4.0+cpu CPU (unknown)
YOLO11 summary (fused): 238 layers, 2,617,701 parameters, 0 gradients, 6.5 GFLOPs

PyTorch: starting from '/app/rk3588_build/last_moonpie_yolov11s.pt' with input shape (1, 3, 640, 640) BCHW and output shape(s) (1, 85, 8400) (5.3 MB)

ONNX: starting export with onnx 1.17.0 opset 19...
ONNX: slimming with onnxslim 0.1.48...
ONNX: export success ✅ 0.6s, saved as '/app/rk3588_build/last_moonpie_yolov11s.onnx' (10.2 MB)

Export complete (0.9s)
Results saved to /app/rk3588_build
Predict:         yolo predict task=detect model=/app/rk3588_build/last_moonpie_yolov11s.onnx imgsz=640  
Validate:        yolo val task=detect model=/app/rk3588_build/last_moonpie_yolov11s.onnx imgsz=640 data=./moonpie.yaml  
Visualize:       https://netron.app

step2. test rknn detect:

>>>>>>>>>>>>>>>original model: /app/rk3588_build/last_moonpie_yolov11s.onnx
--> Running model
I GraphPreparing : 100%|███████████████████████████████████████| 238/238 [00:00<00:00, 19028.68it/s]
I SessionPreparing : 100%|██████████████████████████████████████| 238/238 [00:00<00:00, 5188.41it/s]
target pic has no object concerned.

这一次我觉得我得把注意力集中到detect.py的语法上。

3.detect的语法:

    # Set inputsimg = cv2.imread(IMG_PATH)# img, ratio, (dw, dh) = letterbox(img, new_shape=(IMG_SIZE, IMG_SIZE))img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)img = cv2.resize(img, (IMG_SIZE, IMG_SIZE))print(f'>>>>>>>>>>>>>>>original model: {MODEL1}')# Inferenceprint('--> Running model')img2 = np.expand_dims(img, 0)outputs = rknn.inference(inputs=[img2], data_format=['nhwc'])

 这里的BGR2RGB有些可疑,第二个疑点是data_format=nhwc 

3.1 回顾训练时的通道设置:

yolo11.yaml发现一个重大疑点:

# Parameters

nc: 80 # number of classes

scales: # model compound scaling constants, i.e. 'model=yolo11n.yaml' will call yolo11.yaml with scale 'n'

  # [depth, width, max_channels]

  n: [0.50, 0.25, 1024] # summary: 319 layers, 2624080 parameters, 2624064 gradients, 6.6 GFLOPs

  s: [0.50, 0.50, 1024] # summary: 319 layers, 9458752 parameters, 9458736 gradients, 21.7 GFLOPs

  m: [0.50, 1.00, 512] # summary: 409 layers, 20114688 parameters, 20114672 gradients, 68.5 GFLOPs

  l: [1.00, 1.00, 512] # summary: 631 layers, 25372160 parameters, 25372144 gradients, 87.6 GFLOPs

  x: [1.00, 1.50, 512] # summary: 631 layers, 56966176 parameters, 56966160 gradients, 196.0 GFLOPs

# YOLO11n backbone

backbone:

  # [from, repeats, module, args]

  - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2

nc的配置始终是80!然后里面只有Yolo11n的配置。再查。

Detect - Ultralytics YOLO Docs

在Yolo转换到onnx时,额外的参数如下:

 3.1 Question1 onnx有没有对传入的颜色通道有限制?

 这个似乎取决于训练过程中,读取imge的颜色通道,据说:使用 Python 的 OpenCV 库读取图像默认是 BGR 顺序,而 Pillow 库读取图像是 RGB 顺序。

yolov11- patches.py

# OpenCV Multilanguage-friendly functions ------------------------------------------------------------------------------
_imshow = cv2.imshow  # copy to avoid recursion errorsdef imread(filename: str, flags: int = cv2.IMREAD_COLOR):"""Read an image from a file.Args:filename (str): Path to the file to read.flags (int, optional): Flag that can take values of cv2.IMREAD_*. Defaults to cv2.IMREAD_COLOR.Returns:(np.ndarray): The read image."""return cv2.imdecode(np.fromfile(filename, np.uint8), flags)

然后,pillow在:

./ultralytics/data/loaders.py:                    # Load HEIC image using Pillow with pillow-heif
./ultralytics/data/loaders.py:                    check_requirements("pillow-heif")
./ultralytics/data/loaders.py:                    from pillow_heif import register_heif_opener 

./ultralytics/cfg/datasets/ImageNet.yaml:  721: pillow
./ultralytics/cfg/datasets/ImageNet.yaml:  n03938244: pillow
./ultralytics/cfg/datasets/lvis.yaml:  803: pillow 

./pyproject.toml:    "pillow>=7.1.2", 

 在loaders.py中有:

                    register_heif_opener()  # Register HEIF opener with Pillowwith Image.open(path) as img:im0 = cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)  # convert image to BGR nparray

然后在yolov8的cv2.imread中有:

    def preprocess(self):"""Preprocesses the input image before performing inference.Returns:image_data: Preprocessed image data ready for inference."""# Read the input image using OpenCVself.img = cv2.imread(self.input_image)# Get the height and width of the input imageself.img_height, self.img_width = self.img.shape[:2]# Convert the image color space from BGR to RGBimg = cv2.cvtColor(self.img, cv2.COLOR_BGR2RGB)# Resize the image to match the input shapeimg = cv2.resize(img, (self.input_width, self.input_height))# Normalize the image data by dividing it by 255.0image_data = np.array(img) / 255.0# Transpose the image to have the channel dimension as the first dimensionimage_data = np.transpose(image_data, (2, 0, 1))  # Channel first# Expand the dimensions of the image data to match the expected input shapeimage_data = np.expand_dims(image_data, axis=0).astype(np.float32)# Return the preprocessed image datareturn image_data

结论:基本可以确定:最终的送入onnx的颜色通道是RGB。所以detect.py的颜色通道的处理没有错。

3.2 更详细的解释:

1. 颜色空间转换
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
这行代码将图像从 BGR(蓝、绿、红)颜色空间转换为 RGB(红、绿、蓝)颜色空间。此时,图像数据是一个三维数组,形状为 (H, W, C),其中 H 是图像高度,W 是图像宽度,C 是通道数(这里 C = 3,因为是 RGB 图像)。2. 图像尺寸调整
img = cv2.resize(img, (IMG_SIZE, IMG_SIZE))
这行代码将图像调整为指定的大小 (IMG_SIZE, IMG_SIZE)。调整后的图像仍然是三维数组,形状为 (IMG_SIZE, IMG_SIZE, 3),依旧保持 HWC 的格式。3. 增加批量维度
img2 = np.expand_dims(img, 0)
np.expand_dims 函数用于在指定的轴上增加一个维度。这里在轴 0 上增加了一个维度,使得原本形状为 (IMG_SIZE, IMG_SIZE, 3) 的三维数组变成了形状为 (1, IMG_SIZE, IMG_SIZE, 3) 的四维数组。此时,新增加的第一个维度表示批量大小(N = 1),所以现在图像数据的格式变为 NHWC。4. 推理时指定格式
outputs = rknn.inference(inputs=[img2], data_format=['nhwc'])
这行代码调用 rknn 的推理函数,明确指定输入数据 img2 的格式为 NHWC。综上所述,经过上述一系列操作后,最终输入到 rknn.inference 函数中的数据 img2 是 NHWC 格式。

4.成功的案例

最终参照:

https://blog.csdn.net/zhangqian_1/article/details/142722526https://blog.csdn.net/zhangqian_1/article/details/142722526走通了。原理大概是yolov11,从.onnx的模型输出参数,到inference的输出参数,都与rknn-toolkit2.3版的那个yolo的detect不同。这些代码我需要弄清楚原理,文件里的修改并不完美,也没有附带说明。修改的项点如下:

4.1 最终的侦测识别代码

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import argparse
import os
import sys
import os.path as osp
import cv2
import torch
import numpy as np
import onnxruntime as ort
from math import expROOT = os.getcwd()
if str(ROOT) not in sys.path:sys.path.append(str(ROOT))#ONNX_MODEL = r'/app/rk3588_build/yolo_sdk/ultralytics/yolo11s.onnx'
ONNX_MODEL = r'/app/rk3588_build/yolo11_selfgen.onnx'
#ONNX_MODEL = 'yolov5s_relu.onnx'
#ONNX_MODEL= '/app/rk3588_build/last_moonpie.onnx'
#ONNX_MODEL= '/app/rk3588_build/last_moonpie_yolov11s.onnx'
#ONNX_MODEL= '/app/rk3588_build/best.onnx'
#PYTORCH_MODEL=r"/app/rk3588_build/yolo_sdk/ultralytics/best.pt" #driller model 走不通,版本太严格
RKNN_MODEL = r'/app/rk3588_build/rknn_models/sim_moonpie-640-640_rk3588.rknn'
#IMG_PATH = './frame_2266.png'
DATASET = './dataset.txt'
#IMG_PATH = './bus.jpg'
IMG_PATH = '/app/rk3588_build/cake26.jpg'
QUANTIZE_ON = FalseCLASSES = ['moonpie', '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']meshgrid = []class_num = len(CLASSES)
headNum = 3
strides = [8, 16, 32]
mapSize = [[80, 80], [40, 40], [20, 20]]
nmsThresh = 0.45
objectThresh = 0.5input_imgH = 640
input_imgW = 640class DetectBox:def __init__(self, classId, score, xmin, ymin, xmax, ymax):self.classId = classIdself.score = scoreself.xmin = xminself.ymin = yminself.xmax = xmaxself.ymax = ymaxdef GenerateMeshgrid():for index in range(headNum):for i in range(mapSize[index][0]):for j in range(mapSize[index][1]):meshgrid.append(j + 0.5)meshgrid.append(i + 0.5)def IOU(xmin1, ymin1, xmax1, ymax1, xmin2, ymin2, xmax2, ymax2):xmin = max(xmin1, xmin2)ymin = max(ymin1, ymin2)xmax = min(xmax1, xmax2)ymax = min(ymax1, ymax2)innerWidth = xmax - xmininnerHeight = ymax - ymininnerWidth = innerWidth if innerWidth > 0 else 0innerHeight = innerHeight if innerHeight > 0 else 0innerArea = innerWidth * innerHeightarea1 = (xmax1 - xmin1) * (ymax1 - ymin1)area2 = (xmax2 - xmin2) * (ymax2 - ymin2)total = area1 + area2 - innerAreareturn innerArea / totaldef NMS(detectResult):predBoxs = []sort_detectboxs = sorted(detectResult, key=lambda x: x.score, reverse=True)for i in range(len(sort_detectboxs)):xmin1 = sort_detectboxs[i].xminymin1 = sort_detectboxs[i].yminxmax1 = sort_detectboxs[i].xmaxymax1 = sort_detectboxs[i].ymaxclassId = sort_detectboxs[i].classIdif sort_detectboxs[i].classId != -1:predBoxs.append(sort_detectboxs[i])for j in range(i + 1, len(sort_detectboxs), 1):if classId == sort_detectboxs[j].classId:xmin2 = sort_detectboxs[j].xminymin2 = sort_detectboxs[j].yminxmax2 = sort_detectboxs[j].xmaxymax2 = sort_detectboxs[j].ymaxiou = IOU(xmin1, ymin1, xmax1, ymax1, xmin2, ymin2, xmax2, ymax2)if iou > nmsThresh:sort_detectboxs[j].classId = -1return predBoxsdef sigmoid(x):return 1 / (1 + exp(-x))def postprocess(out, img_h, img_w):print('postprocess ... ')detectResult = []output = []for i in range(len(out)):print(out[i].shape)output.append(out[i].reshape((-1)))scale_h = img_h / input_imgHscale_w = img_w / input_imgWgridIndex = -2cls_index = 0cls_max = 0for index in range(headNum):reg = output[index * 2 + 0]cls = output[index * 2 + 1]for h in range(mapSize[index][0]):for w in range(mapSize[index][1]):gridIndex += 2if 1 == class_num:cls_max = sigmoid(cls[0 * mapSize[index][0] * mapSize[index][1] + h * mapSize[index][1] + w])cls_index = 0else:for cl in range(class_num):cls_val = cls[cl * mapSize[index][0] * mapSize[index][1] + h * mapSize[index][1] + w]if 0 == cl:cls_max = cls_valcls_index = clelse:if cls_val > cls_max:cls_max = cls_valcls_index = clcls_max = sigmoid(cls_max)if cls_max > objectThresh:regdfl = []for lc in range(4):sfsum = 0locval = 0for df in range(16):temp = exp(reg[((lc * 16) + df) * mapSize[index][0] * mapSize[index][1] + h * mapSize[index][1] + w])reg[((lc * 16) + df) * mapSize[index][0] * mapSize[index][1] + h * mapSize[index][1] + w] = tempsfsum += tempfor df in range(16):sfval = reg[((lc * 16) + df) * mapSize[index][0] * mapSize[index][1] + h * mapSize[index][1] + w] / sfsumlocval += sfval * dfregdfl.append(locval)x1 = (meshgrid[gridIndex + 0] - regdfl[0]) * strides[index]y1 = (meshgrid[gridIndex + 1] - regdfl[1]) * strides[index]x2 = (meshgrid[gridIndex + 0] + regdfl[2]) * strides[index]y2 = (meshgrid[gridIndex + 1] + regdfl[3]) * strides[index]xmin = x1 * scale_wymin = y1 * scale_hxmax = x2 * scale_wymax = y2 * scale_hxmin = xmin if xmin > 0 else 0ymin = ymin if ymin > 0 else 0xmax = xmax if xmax < img_w else img_wymax = ymax if ymax < img_h else img_hbox = DetectBox(cls_index, cls_max, xmin, ymin, xmax, ymax)detectResult.append(box)# NMSprint('detectResult:', len(detectResult))predBox = NMS(detectResult)return predBoxdef precess_image(img_src, resize_w, resize_h):image = cv2.resize(img_src, (resize_w, resize_h), interpolation=cv2.INTER_LINEAR)image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)image = image.astype(np.float32)image /= 255.0return imagedef detect(img_path):orig = cv2.imread(img_path)img_h, img_w = orig.shape[:2]image = precess_image(orig, input_imgW, input_imgH)image = image.transpose((2, 0, 1))image = np.expand_dims(image, axis=0)# image = np.ones((1, 3, 384, 640), dtype=np.float32)# print(image.shape)ort_session = ort.InferenceSession(ONNX_MODEL)pred_results = (ort_session.run(None, {'data': image}))out = []for i in range(len(pred_results)):out.append(pred_results[i])predbox = postprocess(out, img_h, img_w)print('obj num is :', len(predbox))for i in range(len(predbox)):xmin = int(predbox[i].xmin)ymin = int(predbox[i].ymin)xmax = int(predbox[i].xmax)ymax = int(predbox[i].ymax)classId = predbox[i].classIdscore = predbox[i].scorecv2.rectangle(orig, (xmin, ymin), (xmax, ymax), (0, 255, 0), 2)ptext = (xmin, ymin)title = CLASSES[classId] + "%.2f" % scorecv2.putText(orig, title, ptext, cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2, cv2.LINE_AA)cv2.imwrite('./test_onnx_result.jpg', orig)if __name__ == '__main__':print('This is main ....')GenerateMeshgrid()img_path = IMG_PATHdetect(img_path)

4.2 .pt2onnx的代码

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 获取当前脚本文件所在目录的父目录,并构建相对路径
import os
import sys
current_dir = os.path.dirname(os.path.abspath(__file__))
project_path = os.path.join(current_dir, '..')
sys.path.append(project_path)
sys.path.append(current_dir)
#based: https://docs.ultralytics.com/modes/export/#key-features-of-export-mode
from ultralytics import YOLO# Load a model
model = YOLO("/app/rk3588_build/last_moonpie_yolov11s.pt")  # load an official model
#model = YOLO("./best_moonpie.pt")  # load an official model
results = model(task='detect', source='../../cake26.jpg', save=True)  # predict on an image

4.1.1 关联修改1,修改yolov11-ultralytics源码: ./nn/head.py, 替换掉Detect.forward的代码

    def forward(self, x):#fengxh modified here. at Feb17,2025y = [] for i in range(self.nl):t1 = self.cv2[i](x[i])t2 = self.cv3[i](x[i])y.append(t1)y.append(t2)return y

4.1.2  关联修改2.修改onnx模型加载部分:./engine/model.py, 它重定义了.onnx输出模型参数:

      print("===================onnx====================")import torchdummy_input = torch.randn(1,3,640,640)input_names=['data']output_names=['reg1', 'cls1','reg2', 'cls2','reg3', 'cls3']torch.onnx.export(self.model, dummy_input, '/app/rk3588_build/yolo11_selfgen.onnx', verbose=False, input_names=input_names, output_names=output_names, opset_version=11)print("==================onnx self gened==========")

4.3 识别结果

我的数据集不会识别馅儿:

附录A 额外提示

为了转换成功,pytorch的版本不能超过2.4,我用的版本是2.4.0严格对齐到rknn-toolkits2.3的约定。

相关文章:

yolo11s rknn无法detect的bugfix - step by step

1.缘起 上周四下班时&#xff0c;发现在宿主机环境工作良好的既有的pytorch模型&#xff0c;在通过.pt->.onnx->.rknn的转换后无法正常工作。周五下班时&#xff0c;怀疑疑点在两处&#xff1a; 版本匹配问题通道和参数传递问题。 周六&#xff0c;周日&#xff0c;周…...

把 CSV 文件摄入到 Elasticsearch 中 - CSVES

在我们之前的很多文章里&#xff0c;我有讲到这个话题。在今天的文章中&#xff0c;我们就提重谈。我们使用一种新的方法来实现。这是一个基于 golang 的开源项目。项目的源码在 https://github.com/githubesson/csves/。由于这个原始的代码并不支持 basic security 及带有安全…...

尚硅谷爬虫note008

一、handler处理器 定制更高级的请求头 # _*_ coding : utf-8 _*_ # Time : 2025/2/17 08:55 # Author : 20250206-里奥 # File : demo01_urllib_handler处理器的基本使用 # Project : PythonPro17-21# 导入 import urllib.request from cgitb import handler# 需求&#xff…...

MongoDB数据导出工具mongoexport

个人博客地址&#xff1a;MongoDB数据导出工具mongoexport | 一张假钞的真实世界 导出示例&#xff1a; $ mongoexport --host 192.168.72.60 --db realtime_statistic_backup --collection all_play_stats_summary --fields "_id.timestamp,total_uv" --type csv …...

机器学习数学基础:29.t检验

t检验学习笔记 一、t检验的定义和用途 t检验是统计学中常用的假设检验方法&#xff0c;主要用于判断样本均值与总体均值间&#xff0c;或两个样本均值间是否存在显著差异。 在实际中应用广泛&#xff0c;例如在医学领域可用于比较两种药物的疗效&#xff1b;在教育领域&…...

Lineageos 22.1(Android 15) 编译隐藏API的 android.jar

一、前言 有时候会我们开发系统应用需要一些系统的方法或者属性之类的,但是被隐藏导致无法正常显示,因为SDK提供的android.jar被隐藏了,所以只能看到sourcecode,实际上编译是会报错的,比如: 一般这种无法是两种,直接添加一个类,同包名同类名,或者依赖framework.jar,可以骗过…...

floodfill算法系列一>扫雷游戏

目录 题目思路&#xff1a;代码设计&#xff1a;代码呈现&#xff1a; 题目思路&#xff1a; 代码设计&#xff1a; 代码呈现&#xff1a; class Solution {int m,n;int[] dx {0,0,-1,1,-1,-1,1,1};int[] dy {-1,1,0,0,-1,1,-1,1};public char[][] updateBoard(char[][] boa…...

2011年下半年软件设计师考试上午题真题的详细知识点分类整理(附真题及答案解析)

以下是针对2011年下半年软件设计师考试上午题真题的详细知识点分类整理&#xff0c;涵盖所有题目涉及的核心知识点&#xff0c;供考生背诵记忆&#xff1a; 1. 数据结构与算法 树与图&#xff1a; 树的性质&#xff1a;树的节点数、深度、叶子节点数之间的关系。二叉树遍历&am…...

算法基础 -- Fenwick树的实现原理

线段树与Fenwick树详解及C语言实现 线段树简介 线段树&#xff08;Segment Tree&#xff09;是一种二叉树结构&#xff0c;主要用于在数组修改的同时&#xff0c;快速进行区间查询。常见应用包括区间求和、区间最小值、区间最大值等。 线段树的特点 时间复杂度&#xff1a;…...

萌新学 Python 之集合 set

集合 set&#xff1a;使用一对大括号&#xff0c;元素写在大括号之间&#xff0c;使用逗号分隔 集合中的元素只能是不可变的数据类型&#xff0c;不能是列表、字典和集合 set1 {1, 2, 3} set2 {1, a, (1, 2, 3)} print(type(set1), type(set2)) # <class set> <c…...

(4)ENVI-guide的设置

1 General Settings 打开ENVI-guide&#xff0c;设置你的模拟时间&#xff0c;模拟名称以及输出文件所在位置 注意&#xff0c;选择多核心和单核运行的方式是 1&#xff09;如果只有一个模拟&#xff0c;并且需要尽快输出&#xff0c;并且运行文件的电脑可以暂时不需要进行其他…...

Golang学习笔记_32——适配器模式

Golang学习笔记_29——抽象工厂模式 Golang学习笔记_30——建造者模式 Golang学习笔记_31——原型模式 文章目录 一、核心概念二、模式结构三、模式特点四、实现方式对比五、适用场景六、与其他模式的对比1. 与装饰器模式2. 与外观模式3. 与创建型模式&#xff08;工厂/原型&am…...

python知识和项目经验

一些功能的实现 从.py文件中获取函数对象和参数 的字典 在给定的Python脚本中&#xff0c;通过模块导入和反射机制&#xff0c;如何动态获取包含模型函数的模块中的函数及其默认参数&#xff0c;并构建一个字典以便后续使用&#xff1f; 解决方案 test.py # test.py impor…...

【自学笔记】版本控制与持续集成基础知识点总览-持续更新

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 版本控制与持续集成基础知识点总览版本控制&#xff08;Version Control&#xff09;1. 版本控制简介2. 常用版本控制系统3. Git基础4. Git进阶 持续集成&#xff0…...

云平台结合DeepSeek的AI模型优化实践:技术突破与应用革新

目录 前言 一、技术架构&#xff1a;算力与算法的协同基石 1. 蓝耘平台的核心优势 2. DeepSeek的模型创新 二、应用场景&#xff1a;垂直领域的智能化落地 1. 商业领域&#xff1a;智能推荐与客服 2. 工业领域&#xff1a;质检与流程优化 3. 智慧城市与医…...

DockerFile优化镜像体积

title: DockerFile优化镜像体积 date: 2025-02-15 15:22:40 tags: DockerFile优化镜像体积DockerFile优化镜像体积 DockerFile优化镜像体积前文回顾:一、细数优化镜像体积的思路与方式二、优化Dockfile文件编辑 Dockerfile2文件三、构建镜像四、运行镜像五、查看运行效果原文 …...

WeMos D1+PIR+Android 的小场景制作

最近在做一个有趣的小场景功能&#xff0c;其实已经有成熟产品&#xff0c;但是考虑到没法实现场景扩展&#xff0c;所以自己开始动手做。 场景描述&#xff1a;玄关人体感应&#xff0c;有人进门&#xff0c;致欢迎词&#xff0c;有人离开&#xff0c;致欢送词。 硬件设备&a…...

实现pytorch注意力机制-one demo

主要组成部分&#xff1a; 1. 定义注意力层&#xff1a; 定义一个Attention_Layer类&#xff0c;接受两个参数&#xff1a;hidden_dim&#xff08;隐藏层维度&#xff09;和is_bi_rnn&#xff08;是否是双向RNN&#xff09;。 2. 定义前向传播&#xff1a; 定义了注意力层的…...

使用循环队列来接收串口信息--以stm32f103为例

一、引言 在stm32中&#xff0c;一般采用的是通过数组来接收串口信息&#xff0c;但是由于受到数组大小的限制&#xff0c;易出现数据覆盖或者数据溢出问题。针对上述问题&#xff0c;采用循环队列的方式来接收串口信息&#xff0c;循环队列可以动态管理缓冲区并且当队列满时&a…...

代码随想录D50-51 图论 Python

理论基础 理论基础部分依然沿用代码随想录教程中的介绍&#xff1a; 图的种类 度 连通性 连通性用于表示图中节点的连通情况。 如果有节点不能到达其他节点&#xff0c;则为非连通图&#xff0c;想象将多个水分子表示为图&#xff0c;不考虑非键作用&#xff0c;这张图就不是…...

大幂计算和大阶乘计算【C语言】

大幂计算&#xff1a; #include<stdio.h> long long int c[1000000]{0}; int main() {long long a,b,x1;c[0]1;printf("请输入底数&#xff1a;");scanf("%lld",&a);printf("请输入指数&#xff1a;");scanf("%lld",&b…...

段错误 (核心已转储)

struct Addressbooks {struct Person personArray[MAX];int m_Size; // 当前已用大小 };void addPerson(Addressbooks *abs) {// 开始添加操作string name;cout << "输入姓名&#xff1a;";cin >> name;// 下面这句话执行后就报&#xff1a;段错误 (核心…...

Leetcode 227-基本计算器 II

题解 本题不包含括号&#xff0c;比较简单 双栈法&#xff08;运算符栈数字栈&#xff09; 对于「任何表达式」而言&#xff0c;可以都使用两个栈 nums 和 ops&#xff08;本题只用到了nums&#xff09;&#xff1a; nums &#xff1a; 存放所有的数字 ops &#xff1a;存放…...

springcloudalibaba组件gateway

Spring Cloud Alibaba 组件中的 Gateway 是一个基于 Spring Cloud Gateway 实现的 API 网关&#xff0c;它专为微服务架构提供简单且有效的 API 路由管理方式。以下是对 Spring Cloud Alibaba Gateway 的详细介绍&#xff1a; 一、基本概念 API 网关&#xff1a;作为系统的统…...

MongoDB副本集

副本集架构 对于mongodb来说&#xff0c;数据库高可用是通过副本集架构实现的&#xff0c;一个副本集由一个主节点和若干个从节点所组成。 客户端通过数据库主节点写入数据后&#xff0c;由从节点进行复制同步&#xff0c;这样所有从节点都会拥有这些业务数据的副本&#xff0…...

LeetCode-680. 验证回文串 II

1、题目描述&#xff1a; 给你一个字符串 s&#xff0c;最多 可以从中删除一个字符。 请你判断 s 是否能成为回文字符串&#xff1a;如果能&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#xff1a; 输入&#xff1a;s "aba" 输出&a…...

国产编辑器EverEdit - “切换文件类型”的使用场景

1 “切换文件类型”的使用场景 1.1 应用背景 一般的编辑器都是通过扩展名映射到对应的语法高亮规则的&#xff0c;比如&#xff1a;文件test.xml中的扩展名“xml"对应XML的语法高亮&#xff0c;在编辑器中打开test.xml就会给不同标识符显示不同的颜色。 但有时一些应用程…...

AIP-146 泛化域

编号146原文链接AIP-146: Generic fields状态批准创建日期2019-05-28更新日期2019-05-28 API中的大多数域&#xff0c;无论是在请求、资源还是自定义应答中&#xff0c;都有具体的类型或模式。这个模式是约定的一部分&#xff0c;开发者依此约定进行编码。 然而&#xff0c;偶…...

C++11 thread

文章目录 C11 线程库线程对象的构造方式无参的构造函数调用带参的构造函数调用移动构造函数thread常用成员函数 this_thread命名空间join && detachmutex C11 线程库 线程对象的构造方式 无参的构造函数 1、调用无参的构造函数,调用无参的构造函数创建出来的线程对象…...

重生之我在异世界学编程之C语言:深入预处理篇(上)

大家好&#xff0c;这里是小编的博客频道 小编的博客&#xff1a;就爱学编程 很高兴在CSDN这个大家庭与大家相识&#xff0c;希望能在这里与大家共同进步&#xff0c;共同收获更好的自己&#xff01;&#xff01;&#xff01; 本文目录 引言正文一、预处理的作用与流程&#xf…...

Java并发编程5--Java内存模型的基础

1.并发编程模型的两个关键问题 在并发编程中&#xff0c;需要处理两个关键问题&#xff1a;线程之间如何通信及线程之间如何同步&#xff08;这里的线程是指并发执行的活动实体&#xff09;。 通信是指线程之间以何种机制来交换信息。 在命令式编程中&#xff0c;线程之间的通…...

国密算法SM1、SM2、SM3和SM4 具体的使用和区别

国密算法是中国自主研发的密码算法&#xff0c;包括SM1、SM2、SM3和SM4&#xff0c;分别用于不同场景。以下是它们的具体使用和区别&#xff1a; SM1 对称加密算法 类型: 对称加密 密钥长度: 128位 使用场景: 用于数据加密和解密&#xff0c;适用于金融、政务等领域。 特点: …...

package.json的全面详解

在 Node.js 的世界里&#xff0c;package.json 文件占据着举足轻重的地位。它就像项目的“大脑”&#xff0c;掌控着项目的各种信息和依赖管理。下面&#xff0c;我们就深入剖析 package.json 文件&#xff0c;让你全面了解它的奥秘。 一、创建 package.json 在正式开始使用 …...

Linux、Docker与Redis核心知识点与常用命令速查手册

Linux、Docker与Redis核心知识点与常用命令速查手册 一、Linux基础核心 1. 核心概念 文件系统&#xff1a;采用树形结构&#xff0c;根目录为/权限机制&#xff1a;rwx&#xff08;读/写/执行&#xff09;权限&#xff0c;用户分为owner/group/others软件包管理&#xff1a; …...

通过TDE工业通讯网关解决设备通讯问题

设备通讯现状 在现代工业环境中&#xff0c;设备的通讯已成为提高生产效率和实现智能化管理的关键。随着工业4.0时代的到来&#xff0c;越来越多的智能设备被投入到生产运营中&#xff0c;这些设备通过集成特定的通信模块&#xff0c;形成了各自独立的自组网子系统。然而&…...

CI/CD(二)docker-compose安装Jenkins

1、docker-compose.yml version: 3.8services:jenkins:image: jenkins/jenkins:lts # 使用官方的 Jenkins LTS 镜像container_name: jenkinsuser: root # 如果需要以 root 用户运行ports:- "8080:8080" # Jenkins Web 界面端口- "50000:50000" # 用于 Jen…...

Linux操作系统3-文件与IO操作5(动态库与静态库的建立与加载)

上篇文章&#xff1a;Linux操作系统3-文件与IO操作4(软硬链接的建立与使用, 文件的三种时间)-CSDN博客 本篇代码Gitee仓库&#xff1a;myLerningCode/l21 橘子真甜/Linux操作系统与网络编程学习 - 码云 - 开源中国 (gitee.com) 本篇重点&#xff1a;动态库与静态库 目录 一. 静…...

同步异步日志系统-日志器的实现

该模块是针对于前几个模块的整合&#xff0c;也是直接面向客户所使用的&#xff0c;对于该模块的实现&#xff0c;我们基于:继承建造者设计模式来实现; 因此我们需要抽象出一个日志器抽象基类&#xff1b; 该基类提供的接口如下: 1、 debug();//站在用户的角度来说就是我只需要…...

webpack 项目优化(一)

一、构建速度优化 缩小文件处理范围 module: {rules: [{test: /\.js$/,exclude: /node_modules/, // 排除第三方库include: path.resolve(__dirname, src), // 限定处理范围use: babel-loader}] }利用缓存 Webpack 5 内置持久化缓存&#xff08;直接配置&#xff09;&#xff1…...

【撰写技巧】基金项目撰写跟踪交流会

基金申请书撰写完成后&#xff0c;提交前的审查是一个非常关键的步骤&#xff0c;这决定了你提交的材料是否符合要求&#xff0c;是否具备足够的说服力&#xff0c;以及是否能够通过专家评审。审查主要可以分为自我审查和团队审查两个层面。以下是基金申请书审查的主要内容和注…...

vue学习笔记

结合目录&#xff0c;点击阅读 文章目录 案例1&#xff1a;第一行vue代码App.vue引入Person.vue案例&#xff1a;改变变量的值案例&#xff1a;改变对象属性值案例&#xff1a;toRefs进行解包案例&#xff1a;给名字首字母大写案例&#xff1a;监视变量值的变化案例&#xff1…...

前端构建工具——Webpack和Vite的主要区别

目录 1. 设计理念2. 性能表现3. 使用场景4. 配置复杂度5. 生态系统6. 性能对比总结7. 选择建议 1. 设计理念 Webpack 设计理念&#xff1a;Webpack是一个通用的模块打包工具&#xff0c;它将项目中的各种资源&#xff08;如JavaScript、CSS、图片等&#xff09;视为模块&…...

Letsencrypt+certbot为域名免费配置ssl

1、基础概念 Let’s Encrypt 是一个提供免费 SSL/TLS 证书的认证机构&#xff0c;它的目标是让互联网上的通信更加安全&#xff0c;特别是普及 HTTPS。通过 Let’s Encrypt 提供的证书&#xff0c;网站可以使用加密连接&#xff0c;保护用户的数据传输。 Certbot 是一个由电子…...

达梦数据库针对慢SQL,收集统计信息清除执行计划缓存

前言&#xff1a;若遇到以下场景&#xff0c;大概率是SQL走错了执行计划&#xff1a; 1、一条SQL在页面上查询特别慢&#xff0c;但拿到数据库终端执行特别快 2、一条SQL在某种检索条件下查询特别慢&#xff0c;但拿到数据库终端执行特别快 此时&#xff0c;可以尝试按照下述步…...

IDEA通过Contince接入Deepseek

Deepseek 的出色表现&#xff0c;上期【Deepseek得两种访问方式与本地部署】 安装Continue插件 第一步、下载插件 在编辑栏【File】->设置【Settiings】或快捷键【CtrlAltS】,弹窗的左侧导航树&#xff0c;选择【plugins】,在marketplace 搜索【Continue】&#xff0c;点…...

Windows 10 ARM工控主板CAN总线实时性能测试

在常规的Windows系统中支持CAN总线应用&#xff0c;需要外接CAN总线适配器&#xff0c;通常为USB转CAN模块或PCI接口CAN卡。实时性本身是CAN总线的显著特性之一&#xff0c;但由于Windows并非实时操作系统&#xff0c;应用程序容易受到系统CPU负载影响&#xff0c;导致调度周期…...

深入理解无锁队列与C++原子操作

文章目录 深入理解无锁队列与C原子操作引言原子操作基础什么是原子操作&#xff1f;内存顺序&#xff08;Memory Order&#xff09; 无锁队列实现环形缓冲区队列&#xff08;单生产者/单消费者&#xff09;链表式无锁队列&#xff08;多生产者/多消费者&#xff09; 关键问题与…...

OpenGL: QOpenGLShaderProgram

一、QOpenGLShaderProgram 编译过程的封装 1、bool addShaderFromSourceCode(QGLShader::ShaderType type, const char * source); 2、bool addShaderFromSourceFile(QGLShader::ShaderType type, const QString & fileName); 3、virtual bool link(); 4、bool bind(); 5、…...

【网络编程】之数据链路层

【网络编程】之数据链路层 数据链路层基本介绍基本功能常见协议 以太网什么是以太网以太网协议帧格式数据链路层的以太网帧报文如何封装/解封装以及分用以太网通信原理传统的以太网与集线器现代以太网与交换机碰撞域的概念 Mac地址基本概念为什么要使用Mac地址而不是使用IP地址…...

HTTP 和 TCP/IP-傻傻分不清

HTTP 和 TCP/IP 是计算机网络中不同层次的协议&#xff0c;它们的核心区别在于功能和所属的网络层次。以下是详细对比&#xff1a; 1. 所属网络层次 TCP/IP 定位&#xff1a;TCP/IP 是一个协议族&#xff08;包含多个协议&#xff09;&#xff0c;涵盖网络通信的传输层和网络层…...