客服/北京做的好的seo公司

客服,北京做的好的seo公司,网站做接口,免费个人网站空间申请背景 maskrcnn用作实例分割时,可以较为精准的定位目标物体,相较于yolo只能定位物体的矩形框而言,优势更大。虽然yolo的计算速度更快。 直接开始从0到1使用maskrCNN训练自己的模型并并导出给C部署(亲测可用) 数据标注…

背景

maskrcnn用作实例分割时,可以较为精准的定位目标物体,相较于yolo只能定位物体的矩形框而言,优势更大。虽然yolo的计算速度更快。
直接开始从0到1使用maskrCNN训练自己的模型并并导出给C++部署(亲测可用)

数据标注

使用labelme标注

在这里插入图片描述
标注完生成后,包含标注的jeson文件,以及.jpg图片文件
模型训练
我这里的环境
PyTorch版本: 2.6.0+cu126
torchvision版本: 0.21.0+cu126

import os
import json
import numpy as np
import torchvision
from PIL import Image, ImageDraw
import torch
from torch.utils.data import Dataset, DataLoader
from torchvision.models.detection import maskrcnn_resnet50_fpn
import torchvision.transforms.functional as F
from tqdm import tqdm# ===================== 数据集类 =====================
from torchvision import transforms
class LabelMeDataset(Dataset):def __init__(self, image_dir, annotation_dir, transforms=None):self.image_dir = image_dirself.annotation_dir = annotation_dirself.transforms = transforms or self.default_transforms()# 获取所有 JSON 文件路径self.json_files = [os.path.join(annotation_dir, f) for f in os.listdir(annotation_dir) if f.endswith(".json")]@staticmethoddef default_transforms():"""默认的图像转换"""return transforms.Compose([transforms.ToTensor()  # 将 PIL.Image 转换为张量 (C, H, W),并归一化到 [0, 1]])def __len__(self):"""返回数据集的长度"""return len(self.json_files)def _get_image_path(self, image_path):"""根据 JSON 文件中的 imagePath 构造图像的完整路径。:param image_path: JSON 文件中的 imagePath 字段:return: 规范化的完整图像路径"""# 拼接路径full_path = os.path.join(self.image_dir, image_path)# 规范化路径return os.path.normpath(full_path)def __getitem__(self, idx):# 加载 JSON 文件with open(self.json_files[idx], "r") as f:data = json.load(f)# 获取图像路径img_path = self._get_image_path(data["imagePath"])if not os.path.exists(img_path):raise FileNotFoundError(f"Image file not found: {img_path}")img = Image.open(img_path).convert("RGB")# 解析标注信息(省略部分代码)boxes = []labels = []masks = []for shape in data["shapes"]:label = shape["label"]points = shape["points"]# 验证 points 格式if not isinstance(points, list) or len(points) < 3:print(f"Invalid points for label '{label}': {points}")continue# 确保每个点是二维坐标try:points = [(float(p[0]), float(p[1])) for p in points]except (TypeError, IndexError, ValueError) as e:print(f"Error parsing points for label '{label}': {e}")continue# 转换多边形为掩码mask_img = Image.new("L", (data["imageWidth"], data["imageHeight"]), 0)ImageDraw.Draw(mask_img).polygon(points, outline=1, fill=1)mask = np.array(mask_img)# 计算边界框pos = np.where(mask)if len(pos[0]) == 0 or len(pos[1]) == 0:print(f"No valid mask for label '{label}'")continuexmin = np.min(pos[1])xmax = np.max(pos[1])ymin = np.min(pos[0])ymax = np.max(pos[0])boxes.append([xmin, ymin, xmax, ymax])labels.append(label)masks.append(mask)# 将标签转换为整数label_map = {"background": 0, "cat": 1, "dog": 2}  # 自定义类别映射labels = [label_map.get(label, 0) for label in labels]  # 如果标签不存在,默认为背景# 转换为张量boxes = torch.as_tensor(boxes, dtype=torch.float32)labels = torch.as_tensor(labels, dtype=torch.int64)masks = torch.as_tensor(masks, dtype=torch.uint8)target = {"boxes": boxes,"labels": labels,"masks": masks,"image_id": torch.tensor([idx]),"area": (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 2] - boxes[:, 0]),"iscrowd": torch.zeros((len(boxes),), dtype=torch.int64)}# 应用图像转换if self.transforms is not None:img = self.transforms(img)return img, target# ===================== 训练函数 =====================
def train_model(model, train_loader, optimizer, device, num_epochs=10):model.to(device)model.train()for epoch in range(num_epochs):total_loss = 0for images, targets in tqdm(train_loader):# 将图像移动到 GPUimages = [img.to(device) for img in images]# 将目标中的张量移动到 GPUtargets = [{k: v.to(device) for k, v in t.items()} for t in targets]# 前向传播loss_dict = model(images, targets)losses = sum(loss for loss in loss_dict.values())# 反向传播和优化optimizer.zero_grad()losses.backward()optimizer.step()total_loss += losses.item()print(f"Epoch {epoch+1}/{num_epochs}, Loss: {total_loss/len(train_loader)}")# ===================== 主程序 =====================
if __name__ == "__main__":# 定义路径image_dir = "C:/workspace/dog_cat_dataset/label"annotation_dir = "C:/workspace/dog_cat_dataset/label"# 创建数据集和 DataLoaderdataset = LabelMeDataset(image_dir=image_dir, annotation_dir=annotation_dir)train_loader = DataLoader(dataset,batch_size=2,shuffle=True,collate_fn=lambda batch: tuple(zip(*batch)))# 定义模型num_classes = 3  # 背景 + 猫 + 狗model = maskrcnn_resnet50_fpn(pretrained=True)# 修改分类头以适应你的类别数in_features = model.roi_heads.box_predictor.cls_score.in_featuresmodel.roi_heads.box_predictor = torchvision.models.detection.faster_rcnn.FastRCNNPredictor(in_features, num_classes)# 修改掩码头in_features_mask = model.roi_heads.mask_predictor.conv5_mask.in_channelshidden_layer = 256model.roi_heads.mask_predictor = torchvision.models.detection.mask_rcnn.MaskRCNNPredictor(in_features_mask, hidden_layer, num_classes)# 定义优化器optimizer = torch.optim.SGD(model.parameters(), lr=0.005, momentum=0.9, weight_decay=0.0005)# 设备配置device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")# 开始训练train_model(model, train_loader, optimizer, device, num_epochs=10)# 保存模型torch.save(model.state_dict(), "maskrcnn_model.pth")

模型推理

import torch
import torchvision
from PIL import Image, ImageDraw
import torchvision.transforms as T
import matplotlib.pyplot as plt
from torchvision.models.detection import maskrcnn_resnet50_fpn# ===================== 加载模型 =====================
def load_model(model_path, num_classes=3):# 定义模型model = maskrcnn_resnet50_fpn(pretrained=False)# 修改分类头以适应你的类别数in_features = model.roi_heads.box_predictor.cls_score.in_featuresmodel.roi_heads.box_predictor = torchvision.models.detection.faster_rcnn.FastRCNNPredictor(in_features, num_classes)# 修改掩码头in_features_mask = model.roi_heads.mask_predictor.conv5_mask.in_channelshidden_layer = 256model.roi_heads.mask_predictor = torchvision.models.detection.mask_rcnn.MaskRCNNPredictor(in_features_mask, hidden_layer, num_classes)# 加载权重model.load_state_dict(torch.load(model_path))model.eval()  # 设置为评估模式return model# ===================== 预处理输入数据 =====================
def preprocess_image(image_path):# 定义与训练时一致的预处理步骤transform = T.Compose([T.ToTensor()  # 转换为 Tensor 并归一化到 [0, 1]])# 加载并预处理输入图像image = Image.open(image_path).convert("RGB")input_tensor = transform(image).unsqueeze(0)  # 添加 batch 维度return image, input_tensor# ===================== 后处理输出结果 =====================
def visualize_predictions(image, predictions, threshold=0.5):"""可视化 Mask R-CNN 的预测结果。:param image: PIL.Image 对象:param predictions: 模型的输出:param threshold: 置信度阈值"""# 获取预测结果masks = predictions[0]['masks'].cpu().detach().numpy()boxes = predictions[0]['boxes'].cpu().detach().numpy()labels = predictions[0]['labels'].cpu().detach().numpy()scores = predictions[0]['scores'].cpu().detach().numpy()# 创建绘图对象draw = ImageDraw.Draw(image)for i in range(len(scores)):if scores[i] > threshold:# 绘制边界框box = boxes[i]draw.rectangle(box, outline="red", width=2)# 绘制标签label = "cat" if labels[i] == 1 else "dog"draw.text((box[0], box[1]), f"{label} ({scores[i]:.2f})", fill="red")# 绘制掩码mask = (masks[i][0] > 0.5).astype(float) * 255mask = Image.fromarray(mask).convert("L")image.paste(Image.new("RGB", image.size, (255, 0, 0)), mask=mask)# 显示图像plt.imshow(image)plt.axis("off")plt.show()# ===================== 主程序 =====================
if __name__ == "__main__":# 加载模型model_path = "maskrcnn_model.pth"model = load_model(model_path)device = torch.device("cuda" if torch.cuda.is_available() else "cpu")model.to(device)# 输入图像路径image_path = "C:/workspace/dog_cat_dataset/test/cattest1.jpg"# 预处理输入数据image, input_tensor = preprocess_image(image_path)input_tensor = input_tensor.to(device)# 进行推理with torch.no_grad():predictions = model(input_tensor)# 后处理输出结果visualize_predictions(image, predictions)

模型导出

ONXX版本:
Name: onnx
Version: 1.17.0

import torch
import torchvision
import onnxruntime as ort
import numpy as np
# 定义模型
num_classes = 3  # 背景 ++ 狗
model = torchvision.models.detection.maskrcnn_resnet50_fpn(pretrained=False)# 修改分类头以适应你的类别数
in_features = model.roi_heads.box_predictor.cls_score.in_features
model.roi_heads.box_predictor = torchvision.models.detection.faster_rcnn.FastRCNNPredictor(in_features, num_classes)# 修改掩码头
in_features_mask = model.roi_heads.mask_predictor.conv5_mask.in_channels
hidden_layer = 256
model.roi_heads.mask_predictor = torchvision.models.detection.mask_rcnn.MaskRCNNPredictor(in_features_mask, hidden_layer, num_classes
)# 加载模型权重
model.load_state_dict(torch.load("C:/workspace/maskrcnn_model.pth"))# 设置为评估模式
model.eval()
# 假设输入图像大小为 (800, 800),通道数为 3
dummy_input = torch.randn(1, 3, 800, 800)  # Batch size = 1, Channels = 3, Height = 800, Width = 800# 导出为 ONNX 格式
torch.onnx.export(model,dummy_input,"maskrcnn_model.onnx",  # 输出文件名opset_version=12,       # ONNX 版本号,建议使用最新稳定版input_names=["input"],  # 输入名称output_names=["boxes", "labels", "scores", "masks"],  # 输出名称dynamic_axes={"input": {0: "batch_size"},  # 动态 batch size"boxes": {0: "batch_size"},"labels": {0: "batch_size"},"scores": {0: "batch_size"},"masks": {0: "batch_size"},}
)print("Model has been exported to ONNX format.")# 加载 ONNX 模型
session = ort.InferenceSession("maskrcnn_model.onnx")# 准备输入数据
dummy_input = np.random.randn(1, 3, 800, 800).astype(np.float32)  # 匹配导出时的输入形状# 获取输入输出名称
input_name = session.get_inputs()[0].name
output_names = [output.name for output in session.get_outputs()]# 推理
outputs = session.run(output_names, {input_name: dummy_input})# 打印输出
for name, output in zip(output_names, outputs):print(f"{name}: {output.shape}")

C++推理

onnxruntime版本
onnxruntime-win-x64-gpu-1.20.0

//onxx推理
#include <onnxruntime_cxx_api.h>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
#include <string>
#include <Windows.h>  // 使用 WinAPI 进行字符转换
using namespace std;
using namespace cv;
// 图像预处理函数
std::vector<float> preprocess_image(const cv::Mat& image, int target_height, int target_width) {cv::Mat resized_image;cv::resize(image, resized_image, cv::Size(target_width, target_height));// 归一化到 [0, 1] 并转换为浮点数resized_image.convertTo(resized_image, CV_32F, 1.0 / 255.0);// 转换为 CHW 格式 (C=3, H=height, W=width)std::vector<float> input_data(3 * target_height * target_width);for (int c = 0; c < 3; ++c) {for (int h = 0; h < target_height; ++h) {for (int w = 0; w < target_width; ++w) {input_data[c * target_height * target_width + h * target_width + w] =resized_image.at<cv::Vec3f>(h, w)[c];}}}return input_data;
}
// 将 std::string 转换为 std::wstring
std::wstring string_to_wstring(const std::string& str) {if (str.empty()) return L"";int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);std::wstring wstr(size_needed, 0);MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstr[0], size_needed);return wstr;
}
// 将 std::wstring 转换为 std::string
std::string wstring_to_string(const std::wstring& wstr) {if (wstr.empty()) return "";int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);std::string str(size_needed, 0);WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &str[0], size_needed, NULL, NULL);return str;
}int main() {// 初始化 ONNX Runtime 环境Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "MaskRCNNExample");Ort::SessionOptions session_options;// 加载 ONNX 模型//const char* model_path = "C:/workspace/yolov5/yolov5-master/yolov5-master/maskrcnn_model.onnx";//Ort::Session session(env, model_path, session_options);// 加载 ONNX 模型std::string model_path = "C:/workspace/yolov5/yolov5-master/yolov5-master/maskrcnn_model.onnx";std::wstring w_model_path = string_to_wstring(model_path);  // Windows 平台需要宽字符Ort::Session session(env, w_model_path.c_str(), session_options);// 获取模型输入信息Ort::AllocatorWithDefaultOptions allocator;size_t num_input_nodes = session.GetInputCount();Ort::AllocatedStringPtr input_name = session.GetInputNameAllocated(0, allocator);const char* input_names[] = { input_name.get() };std::vector<int64_t> input_dims = { 1, 3, 800, 800 };  // 假设输入尺寸为 (1, 3, 800, 800)// 加载并预处理输入图像cv::Mat image = cv::imread("C:/workspace/dog_cat_dataset/test/cattest1.jpg");if (image.empty()) {std::cerr << "Error: Could not load image!" << std::endl;return -1;}std::vector<float> input_data = preprocess_image(image, 800, 800);// 创建输入张量Ort::MemoryInfo memory_info = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault);Ort::Value input_tensor = Ort::Value::CreateTensor<float>(memory_info, input_data.data(), input_data.size(), input_dims.data(), input_dims.size());// 推理std::vector<const char*> output_names = { "boxes", "labels", "scores", "masks" };auto output_tensors = session.Run(Ort::RunOptions{ nullptr }, input_names, &input_tensor, 1, output_names.data(), output_names.size());// 处理输出
// 处理输出float* boxes = output_tensors[0].GetTensorMutableData<float>();int64_t* labels = output_tensors[1].GetTensorMutableData<int64_t>();float* scores = output_tensors[2].GetTensorMutableData<float>();float* masks = output_tensors[3].GetTensorMutableData<float>();auto mask_shape = output_tensors[3].GetTensorTypeAndShapeInfo().GetShape();int num_masks = mask_shape[0];    // 掩码数量int mask_height = mask_shape[2];  // 掩码高度int mask_width = mask_shape[3];   // 掩码宽度// 缩放比例float scale_x = static_cast<float>(image.cols) / 800.0f;float scale_y = static_cast<float>(image.rows) / 800.0f;cout << "image.cols , image.rows" << image.cols << image.rows<<endl;// 绘制检测框和掩码for (size_t i = 0; i < num_masks && scores[i] > 0.5; ++i) {// 获取当前实例的边界框cout << boxes[i * 4 + 0] << " " << boxes[i * 4 + 1] << " " << boxes[i * 4 + 2] << " " << boxes[i * 4 + 3];float x1 = boxes[i * 4 + 0] * scale_x;float y1 = boxes[i * 4 + 1] * scale_y;float x2 = boxes[i * 4 + 2] * scale_x;float y2 = boxes[i * 4 + 3] * scale_y;cv::Rect box_rect(x1, y1, x2 - x1, y2 - y1);cv::rectangle(image, box_rect, cv::Scalar(0, 255, 0), 2);std::string label = "Class " + std::to_string(labels[i]) + " (" + std::to_string(scores[i]).substr(0, 4) + ")";cv::putText(image, label, cv::Point(x1, y1 - 10), cv::FONT_HERSHEY_SIMPLEX, 0.9, cv::Scalar(0, 255, 0), 2);// 获取当前掩码cv::Mat mask(mask_height, mask_width, CV_32F, masks + i * mask_height * mask_width);// 调整掩码尺寸以匹配原始图像cv::Mat resized_mask;cv::resize(mask, resized_mask, cv::Size(image.cols, image.rows));cv::imshow("mask", resized_mask); 将掩码转换为二值图像//cv::Mat binary_mask;//cv::threshold(resized_mask, binary_mask, 0.5, 1, cv::THRESH_BINARY); 创建一个彩色掩码用于叠加//cv::Mat color_mask = cv::Mat::zeros(image.size(), CV_8UC3);//cv::randu(color_mask, cv::Scalar(0, 0, 0), cv::Scalar(255, 255, 255)); // 随机颜色//cv::cvtColor(color_mask, color_mask, cv::COLOR_BGR2RGB); 将掩码应用到图像上//cv::Mat masked_image;//image.copyTo(masked_image, binary_mask);//cv::addWeighted(masked_image, 0.5, image, 0.5, 0, image);}// 显示结果cv::imshow("Image with Masks", image);cv::waitKey(0);return 0;
}

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

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

相关文章

PCL配置

1、下载 打开GitHub网站&#xff0c;搜索pcl&#xff0c;选择第一个结果打开&#xff0c;按照下图步骤操作 下载PCL预编译安装程序PCL-1.13.1-AllInOne-msvc2022-win64.exe 和要安装的PCL组件&#xff08;例如pcl-1.13.1-pdb-msvc2022-win64.zip&#xff09; 2、安装 双击 P…

VectorBT:使用PyTorch+LSTM训练和回测股票模型 进阶一

VectorBT&#xff1a;使用PyTorchLSTM训练和回测股票模型 进阶一 本文介绍了如何使用PyTorch和LSTM模型进行股票数据的训练和回测。涵盖了数据预处理、特征选择、LSTM模型构建、模型训练与验证、动态阈值策略生成交易信号以及使用VectorBT进行回测和绩效分析。 文中内容仅限技术…

MantisBT在Windows10上安装部署详细步骤

MantisBT 是一款基于 Web 的开源缺陷跟踪系统&#xff0c;以下是在 Windows 10 上安装部署 MantisBT 的详细步骤&#xff1a; 1. 安装必要的环境 MantisBT 是一个基于 PHP 的 Web 应用程序&#xff0c;因此需要安装 Web 服务器&#xff08;如 Apache&#xff09;、PHP 和数据…

深入理解K8s与Docker的关系:容器化技术的双雄

友情提示&#xff1a;本文内容由银河易创&#xff08;https://ai.eaigx.com&#xff09;AI创作平台gpt-4-turbo模型生成&#xff0c;仅供参考。 在现代云计算及微服务架构的发展中&#xff0c;Docker与Kubernetes&#xff08;K8s&#xff09;作为两大核心技术&#xff0c;被广泛…

蓝桥与力扣刷题(蓝桥 蓝桥骑士)

题目&#xff1a;小明是蓝桥王国的骑士&#xff0c;他喜欢不断突破自我。 这天蓝桥国王给他安排了 N 个对手&#xff0c;他们的战力值分别为 a1,a2,...,an&#xff0c;且按顺序阻挡在小明的前方。对于这些对手小明可以选择挑战&#xff0c;也可以选择避战。 身为高傲的骑士&a…

如何查看window电脑的GPU信息

GPU&#xff08;图形处理器&#xff0c;Graphics Processing Unit&#xff09;和显卡是两个密切相关但不同的概念 概念 1. ‌基本概念‌ ‌GPU‌&#xff1a;是专门用于处理图像和视频信息的微处理器&#xff0c;拥有强大的并行计算能力&#xff0c;主要负责图形渲染、数值分…

26考研——查找_树形查找_二叉排序树(BST)(7)

408答疑 文章目录 三、树形查找二叉排序树&#xff08;BST&#xff09;二叉排序树中结点值之间的关系二叉树形查找二叉排序树的查找过程示例 向二叉排序树中插入结点插入过程示例 构造二叉排序树的过程构造示例 二叉排序树中删除结点的操作情况一&#xff1a;被删除结点是叶结点…

如何在 Postman 中导入和导出 cURL 命令?

cURL 是一款广受欢迎的命令行工具&#xff0c;专门用于执行 HTTP 请求。它在 Web 应用或 API 测试中极为实用&#xff0c;让用户得以借助在 API 开发者社区广为流行的成熟语法&#xff0c;直接通过命令行与 API 进行交互。若你需要在多个环境下运行众多 cURL 命令&#xff0c;可…

用python制作一个贪吃蛇小游戏

文章目录 效果图python源码使用说明效果图 只需要一百多行python代码,就能制作一个贪吃蛇小游戏。效果如下: 操作说明: 你可以使用上下左右箭头键来控制蛇的移动方向。蛇吃到食物后会变长,当蛇撞到墙壁或自己的身体时游戏结束。游戏结束后,你可以按 Q 退出游戏,或按 C…

react 15-16-17-18各版本的核心区别、底层原理及演进逻辑的深度解析

一、React 15&#xff08;2016&#xff09; 核心架构&#xff1a;Stack Reconciler&#xff08;栈协调器&#xff09; 工作原理&#xff1a; 同步递归渲染&#xff1a;采用深度优先遍历方式递归处理 Virtual DOM&#xff0c;形成不可中断的调用栈渲染流程&#xff1a;1. 触发 …

微信小程序pdf预览

1.示例图 2.代码 fileId&#xff1a;要预览的pdf文件的id viewsFiles(fileId) {wx.showLoading({title: 加载中...});var params {url: "/common/getFile/" fileId ,//后端提供的接口method: "GET",responseType: "arraybuffer",callBack: …

把手搭建vue前后端管理系统-TAB标签通过pinia来进行管理(二十六)

目标&#xff1a;通过pinia的store来进行组件状态的统一管理&#xff0c;这样大家都可以共用到这个组件的状态信息&#xff0c;就可以实现组件的联动 一、添加侧边栏菜单的点击事件&#xff1a; 1、CommonAside.vue里面添加click的事件 <el-menu-itemv-for"item in …

计算机网络——数据链路层的功能

目录 物理链路 逻辑链路 封装成帧&#xff08;组帧&#xff09; 帧定界 透明传输 SDU 差错控制 可靠传输 流量控制 介质访问控制 主机需要实现第一层到第五层的功能&#xff0c;而路由器这种节点只需要实现第一层到第三层的这些功能 假设左边用户需要给右边用户发送…

数据抓取的缓存策略:减少重复请求与资源消耗

在数据采集领域&#xff0c;爬虫效率是决定项目成败的关键因素之一。传统的爬虫架构往往因请求频繁、资源消耗较大以及重复抓取等问题&#xff0c;导致效率低下。这些问题不仅拖慢了数据获取的速度&#xff0c;还可能引发目标服务器的过载风险&#xff0c;甚至导致爬虫被限制。…

k8s部署argocd

前言 ArgoCD是一个基于Kubernetes的GitOps持续交付工具&#xff0c;应用的部署和更新都可以在Git仓库上同步实现&#xff0c;并自带一个可视化界面。本文介绍如何使用GitHelmArgocd方式来实现在k8s中部署和更新应用服务&#xff1b; 安装Argocd 准备一个k8s集群&#xff0c;然…

【Linux】MAC帧

目录 一、MAC帧 &#xff08;一&#xff09;IP地址和MAC地址 &#xff08;二&#xff09;MAC帧格式 &#xff08;三&#xff09;MTU对IP协议的影响、 &#xff08;四&#xff09;MTU对UDP协议的影响 &#xff08;五&#xff09;MTU对TCP协议的影响 二、以太网协议 &…

【Unity3D】摄像机适配场景以及Canvas适配

目录 宽度不变策略 高度不变策略 宽度不变策略 开发分辨率 750*1334 (宽高比:0.56) 真机分辨率 1170*2532 (宽高比:0.46) 真机宽高比<开发宽高比&#xff0c;采用宽度不变策略 理由&#xff1a;小于代表真机高度比开发高度更大&#xff0c;因此不需要担心高度上…

二叉树的前,中,后序遍历

我们来了解一下二叉树的遍历&#xff0c;话不多说 二叉树的遍历的概念&#xff1a; 二叉树有四种遍历方式&#xff0c;分别为前序遍历&#xff0c;中序遍历&#xff0c;后序遍历和层序遍历&#xff0c;但我们今天谈谈前三种&#xff0c;并实现它 前序遍历&#xff1a; 按照根…

golang Error的一些坑

golang Error的一些坑 golang error的设计可能是被人吐槽最多的golang设计了。 最经典的err!nil只影响代码风格设计&#xff0c;而有一些坑会导致我们的程序发生一些与我们预期不符的问题&#xff0c;开发过程中需要注意。 ​​ errors.Is​判断error是否Wrap不符合预期 ​…

逼用户升级Win11,微软开始给Win10限速

随着Windows10的支持时间越来越短&#xff0c;微软也加大了对Win10用户的驱赶力度。 最近&#xff0c;微软官宣了将要在今年6月份降低OneNote for Windows 10的同步速度。软件也将和Windows10在今年的10月14日一同停止支持和维护。 这将影响实时协作和多设备访问。 对OneNote…