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

使用C++调用PyTorch模型的弯弯绕绕,推荐LibTorch加载,C++处理

需求:使用C++调用Pytorch模型,对处理后的图像进行预测。
第一种,使用C++调用Python代码处理,使用pybind11源代码再末尾
缺点,导入Python包非常麻烦,执行的C++程序找不到cv2 torch包等等
本人解决了cv2 numpy等包,但是torch一致搞不定,大概率包不兼容导致的(pip下载的PyTorch官网,搞不懂)
明明Python’直接执行可以,但是C++调用Python执行就不行,非常奇怪
第二种,C++使用LibTorch将加载模型,进行处理源代码再末尾
这个会不用例会网络架构以及包的问题,只需将PyTorch模型保存为pt,然后使用C++加载即可,非常简单
需要重写图像处理的一些代码,保持和Python一致,输入模型进行预测。

第一种方法的经验之谈
在使用conda的环境中,conda和pip都可以下载包,两种方式最好不要混用,避免出现奇奇怪怪的错误
例如C:\ProgramData\anaconda3\DLLs_ctypes.pyd
PIL_imaging.cp311-win_amd64.pyd”。模块已生成,不包含符号。等等无法加载的错误
本人使用conda下载的,使用pip卸载后,重新使用pip装就解决了问题
cv 2,numpy,pillow等包都是如此,统一conda,或者统一使用pip,推荐使用pip
这样使用visual studio C++调用python import的包就不会出现加载不了的问题
务必注意!!!
pip install 包名==版本号

不要轻易使用conda 一键升级包,会导致部分版本太高不兼容
本人将python升级到3.11.9后,cv2版本对不上,也找不到对应版本的
冒险使用官网上最新的版本,竟然可以使用

expected np.ndarray (got numpy.ndarray)
在这里插入图片描述
这个问题也是numpy版本过高导致
pip install "numpy<1.26.4"就解决了
总之,版本太高就会出现各种奇奇怪怪的bug,修来修去非常浪费时间。

手动清除包缓存,可以使用以下命令:
pip cache purge
这个命令会清除所有缓存,包括已下载但未安装的软件包和已安装但未被使用的缓存。

只想清除特定软件包的缓存,可以使用以下命令:
pip cache remove package-name

第二种
在C++部署Pytorch(Libtorch)模型的方法总结(Win10+VS2017)
读取torchlib文件夹所有的lib文件的python代码

import osdef list_lib_files(directory):try:# 获取目录中的所有文件和文件夹files_and_dirs = os.listdir(directory)# 筛选出以“lib”结尾的文件lib_files = [f for f in files_and_dirs if f.endswith('.lib')]# 打印每个文件的全名for file_name in lib_files:print(file_name)except Exception as e:print(f"发生错误: {e}")
directory_path = r'C:\Users\TomSawyer\Downloads\Compressed\libtorch\lib'
list_lib_files(directory_path)
asmjit.lib
c10.lib
cpuinfo.lib
dnnl.lib
fbgemm.lib
fbjni.lib
fmt.lib
kineto.lib
libprotobuf-lite.lib
libprotobuf.lib
libprotoc.lib
pthreadpool.lib
pytorch_jni.lib
sleef.lib
torch.lib
torch_cpu.lib
XNNPACK.lib

VS 配置外部DLL的引用路径【可执行文件的环境路径】
右键项目,属性->配置属性->调试->环境,在这里写入可执行文件运行时的环境路径
在这里插入图片描述

本人莎莎的以为要重写PyTorch模型网络架构,于是使用C++的LibTorch和gpt重写了一下,结果一致卡在load不上,非常奇怪,于是检查两个网络的架构,其实非常类似,忘记截图载下来了,就下面一张图
检查python的Pytorch模型 与 使用C++创建的LibTorch模型是否一致,先看看VGG模型长啥样
在这里插入图片描述

其实可以直接加载模型,pt文件里面保存了网络的架构的,无需重写,具体代码找一找就有
我之前都注释了,代码没问题的,自行理解一下
将pth保存为pt,再加载pt模型
.pt文件保存的是模型的全部,在加载时可以直接赋值给新变量model = torch.load(“filename.pt”)。
.pth保存的是模型参数,通过字符字典进行保存,在加载该类文件时应该先实例化一个具体的模型,然后对新建立的空模型,进行参数赋予。

import os
import cv2
from PIL import Image
from torchvision import transforms as T
import torchload_model_path = "./checkpoints/Cnn.pth"
model = getattr(models, "Cnn")()
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model.to(device)
model.load(load_model_path)
model.eval()var=torch.ones((1,3,224,224))
traced_script_module = torch.jit.trace(model, var)
traced_script_module.save("./checkpoints/Cnn.pt")# 测试pt模型
model_pt = torch.load("./checkpoints/Cnn.pt")
model_pt.to(device)
model_pt.eval()

将Python保存的pth模型与pt模型进行对比,看看保存的两个模型是否有差异,没有任何差异
在这里插入图片描述
使用C++实现Python的图像处理部分,看看实现是否有差异,发现数值类似,略有差异在这里插入图片描述
猜测可能是摄像头保存一帧 与 C++读取图像的不同所引起的,于是使用Python读取图像试试
发现结果一致了,原来是保存为jpg格式带来的有损压缩导致的
统一保存为png格式即可,无损格式
在这里插入图片描述

全部代码
Python使用Pytorch加载模型,处理图像,模型预测结果(模型是错的,只是走个流程)

import os
import cv2
from PIL import Image
from torchvision import transforms as T
import models
import datetime
import torch# 创建保存图像的文件夹
if not os.path.exists('testModel'):os.makedirs('testModel')# 1  先使用摄像头读取一帧图像,保存
# 0,读取摄像头保存的图片
flag = 0
if flag==1:cap = cv2.VideoCapture(0)if not cap.isOpened():print("无法打开摄像头")else:# 读取一帧图像ret, frame = cap.read()if ret:# 保存原始图像original_image_path = 'testModel/test1_original_image.png'cv2.imwrite(original_image_path, frame)print(f"原始图像已保存到 {original_image_path}")# 释放摄像头资源cap.release()
else:##读取摄像头保存的一帧画面frame =cv2.imread('testModel/test1_original_image.png');"""此类主要提供模型调用方法,接受一个图片,同时返回一个力的结果
"""
model_list = os.listdir("./checkpoints/")
# load_model_path = "./checkpoints/"+ model_list[0]
load_model_path = "./checkpoints/Cnn.pth"
model = getattr(models, "Cnn")()
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model.to(device)
model.load(load_model_path)
model.eval()# 测试pt模型
model_pt = torch.load("./checkpoints/Cnn.pt")
model_pt.to(device)
model_pt.eval()# veision1 预定义图像处理模式,图像预处理设置,正态化数据来自于图片空间,因此需要Normalize.py获取,此处已指定
normalize = T.Normalize(mean=[0.684, 0.831, 0.83],std=[0.684, 0.831, 0.83])
transform = T.Compose([T.ToTensor(),# normalize]
)img = frame
cv2.imshow("  ", img)
cv2.waitKey(0)
img=cv2.resize(img,[640,360])
# 裁剪图像,保留从第170列到第530列的区域
img=img[::,170:530,::] #样品1
cv2.imshow("  ", img)
cv2.waitKey(0)
# 保存处理后的图像
processed_image_path = 'testModel/test1_processed_image.png'
cv2.imwrite(processed_image_path, img)
print(f"处理后的图像已保存到 {processed_image_path}")img = Image.fromarray(img)
img = transform(img)
img = img.view(1, img.shape[0], img.shape[1], img.shape[2])#改变张量的形状,但不会改变其数据 第一、第二、第三和第四维度大小。
train = img.to(device)
force= model(train)
force = force.squeeze().detach().cpu()
force_act = force.tolist()
# 时间格式为分钟:秒.微秒
force_act.append(datetime.datetime.now().strftime("%M:%S.%f"))
# force_act为输出力的列表格式【f(x),f(y),f(z),时间】
print('pth模型结果:',force_act)force_pt= model_pt(train)
force_pt = force_pt.squeeze().detach().cpu()
force_act_pt = force_pt.tolist()
# 时间格式为分钟:秒.微秒
force_act_pt.append(datetime.datetime.now().strftime("%M:%S.%f"))
# force_act为输出力的列表格式【f(x),f(y),f(z),时间】
print('pt模型结果:',force_act_pt)

C++加载torch script保存的pt模型,重新实现图像处理,给出结果

#include <torch/torch.h>
#include <torch/script.h>
#include <string>
#include <iostream>
#include <opencv2/opencv.hpp>// 假设你已经定义了transform函数
torch::Tensor transform(const cv::Mat &img) {// 这里需要根据你的transform逻辑来实现// 例如,假设你只是将图像转换为Tensortorch::Tensor tensor_image = torch::from_blob(img.data, { img.rows, img.cols, img.channels() }, torch::kFloat32);将OpenCV图像数据(存储在img.data中)转换为一个PyTorch张量,张量的形状为[img.rows, img.cols, img.channels()],数据类型为kFloat32tensor_image = tensor_image.permute({ 2, 0, 1 }).to(torch::kFloat); // 转换为CHW格式并转换为Float类型return tensor_image;
}int test_pt() {// 假设模型路径和加载方式torch::jit::script::Module module;try {module = torch::jit::load(R"(C:\Users\TomSawyer\source\repos\testPython\force_indentify\checkpoints\Cnn.pt)");} catch (const c10::Error &e) {std::cerr << "Error loading the model\n";return {};}// 检查CUDA是否可用bool is_cuda = torch::cuda::is_available();torch::Device device(is_cuda ? torch::kCUDA : torch::kCPU);std::cout << (is_cuda ? "CUDA is available. Using GPU." : "Using CPU.") << std::endl;module.to(device);module.eval();// 指定图像路径std::string imagePath = R"(C:\Users\TomSawyer\source\repos\testPython\force_indentify\testModel\test1_original_image.png)";while (1) {cv::Mat frame = cv::imread(imagePath, cv::IMREAD_COLOR);// 检查图像是否加载成功if (frame.empty()) {std::cerr << "无法加载图片,请检查路径: " << imagePath << std::endl;return -1;}// 显示图片cv::imshow("Loaded Image", frame);cv::waitKey(0);cv::resize(frame, frame, cv::Size(640, 360));cv::imshow("frame", frame);cv::waitKey(0);frame = frame(cv::Rect(170, 0, 360, 360)); // 裁剪图像170到360列cv::imshow("frame", frame);cv::waitKey(0);frame.convertTo(frame, CV_32FC3, 1.0 / 255.0);// 应用transformtorch::Tensor tensor_image = transform(frame);// 调整形状tensor_image = tensor_image.unsqueeze(0); // 增加batch维度tensor_image = tensor_image.to(device);// 模型预测std::vector<torch::jit::IValue> inputs;inputs.push_back(tensor_image);at::Tensor output = module.forward(inputs).toTensor();//bugoutput = output.squeeze().detach().cpu();std::vector<float> force_act = { output[0].item<float>(), output[1].item<float>(), output[2].item<float>() };std::cout << "pt_Force: " << force_act[0] << ", " << force_act[1] << ", " << force_act[2] << std::endl;}return {};
}int main() {test_pt(); //测试pt模型和python的pthreturn 0;
}

pybind11,运行一直没解决,cv2,numpy包解决了,Torch包一直搞不定

#include <pybind11/pybind11.h>
#include <pybind11/embed.h>
#include <iostream>
#include <cstdlib> // for _putenvnamespace py = pybind11;int main() {// 设置 Python 解释器的路径为 Conda 环境std::string pythonHome = R"(C:\ProgramData\anaconda3)";std::string pythonHomeEnv = "PYTHONHOME=" + pythonHome;_putenv(pythonHomeEnv.c_str());// 设置 Python 路径std::string pythonPath = R"(C:\ProgramData\anaconda3\Lib\site-packages;C:\Users\TomSawyer\source\repos\testPython\force_indentify;)";std::string pythonPathEnv = "PYTHONPATH=" + pythonPath;_putenv(pythonPathEnv.c_str());// 添加 PATH 环境变量std::string path = R"(C:\ProgramData\anaconda3\Library\bin;)";std::string pathEnv = "PATH=" + path + ";" + getenv("PATH");_putenv(pathEnv.c_str());//std::cout << "PythonHome: " << pythonHomeEnv << std::endl;//std::cout << "PythonPath: " << pythonPathEnv << std::endl;std::cout << "PATH: " << getenv("PATH")<< std::endl;// 初始化 Python 解释器py::scoped_interpreter guard{};//在使用 pybind11 导入 Python 模块时,路径的指定方式需要注意。通常情况下,Python 模块的导入路径应该是模块的名称,而不是文件的绝对路径// 添加模块路径到 sys.pathpy::module::import("sys").attr("path").attr("append")(R"(C:\Users\TomSawyer\source\repos\testPython\force_indentify;C:\Users\TomSawyer\source\repos\testPython\force_indentify\models)");//std::cout <<std::endl <<"PATH: " << getenv("PATH") << std::endl;// 导入 Python 模块py::module script = py::module::import("interface_single");// 调用 Python 函数并获取返回的列表py::object result = script.attr("inter")();py::list py_list = result.cast<py::list>();// 将 Python 列表转换为 C++ 向量std::vector<int> cpp_list;for (auto item : py_list) {cpp_list.push_back(item.cast<int>());}// 处理 C++ 向量for (int value : cpp_list) {std::cout << value << " ";}std::cout << std::endl;return 0;
}

相关文章:

使用C++调用PyTorch模型的弯弯绕绕,推荐LibTorch加载,C++处理

需求&#xff1a;使用C调用Pytorch模型&#xff0c;对处理后的图像进行预测。 第一种&#xff0c;使用C调用Python代码处理&#xff0c;使用pybind11源代码再末尾 缺点&#xff0c;导入Python包非常麻烦&#xff0c;执行的C程序找不到cv2 torch包等等 本人解决了cv2 numpy等包&…...

实现异形(拱形)轮播图

项目需要实现如上图所示的轮播图。 实现思路&#xff1a; 1.项目引入使用普通轮播图。 2.根据轮播图个数&#xff0c;动态给可视范围的第一个轮播图和最后一个轮播图添加样式。 代码实现&#xff1a; 经调研&#xff0c;使用slick轮播图&#xff08;官网地址 https://kenwheel…...

【软件测试】2024年职业院校技能大赛高职组“软件测试”赛项样题

目录 任务一&#xff1a;功能测试&#xff08;45 分&#xff09; 任务二&#xff1a;自动化测试&#xff08;15 分&#xff09; 任务三&#xff1a;性能测试&#xff08;15 分&#xff09; 任务四&#xff1a;单元测试&#xff08;10 分&#xff09; 任务五&#xff1a;接…...

python数组和队列

一、数组 如果一个列表只包含数值&#xff0c;那么使用array.array会更加高效&#xff0c;数组不仅支持所有可变序列操作&#xff08;.pop、.insert、.extent等&#xff09;&#xff0c;而且还支持快速加载项和保存项的方法&#xff08;.fromfile、.tofile等&#xff09; 创建…...

Vision Transformer(ViT)一种将Transformer架构应用于计算机视觉领域的模型

Vision Transformer&#xff08;ViT&#xff09;是一种将Transformer架构应用于计算机视觉领域的模型&#xff0c;它通过自注意力机制处理图像数据&#xff0c;与传统的卷积神经网络&#xff08;CNN&#xff09;相比&#xff0c;ViT能够更好地捕捉全局依赖关系。以下是对ViT的详…...

得到任务式 大模型应用开发学习方案

根据您提供的文档内容以及您制定的大模型应用开发学习方案&#xff0c;我们可以进一步细化任务式学习的计划方案。以下是具体的任务式学习方案&#xff1a; 任务设计 初级任务 大模型概述&#xff1a;阅读相关资料&#xff0c;总结大模型的概念、发展历程和应用领域。深度学…...

使用el-menu跳转时偶尔会出现路由已经变了,但是页面却显示空白的情况

刚开始我以为是我数据加载的问题&#xff0c;后来又看有人说是template里不能包多个div&#xff0c;但我去看我出错的组件&#xff0c;并没有出现两个div。 后来我就把每个都给改了&#xff0c;即使是elemen-ui的标签也全部改在一个div里&#xff0c;就发现没问题了。 我改的…...

C语言家教记录(七)

C语言家教记录&#xff08;七&#xff09; 导语字符串字面量变量读写字符串操作函数惯用法数组 结构联合枚举总结与复习 导语 本次授课的内容如下&#xff1a;字符串&#xff0c;结构体、联合体、枚举 辅助教材为 《C语言程序设计现代方法&#xff08;第2版&#xff09;》 字…...

【数据结构】——十大排序详解分析及对比

【数据结构】——十大排序详解分析及对比 文章目录 【数据结构】——十大排序详解分析及对比前言1. 排序的概念及其运用1.1 排序的概念1.2 排序的应用 2. 插入排序2.1 直接插入排序2.2 希尔排序 3. 选择排序3.1 选择排序3.2 堆排序 4 交换排序4.1 冒泡排序4.2 快速排序4.2.1 霍…...

散点图适用于什么数据 thinkcell散点图设置不同颜色

在数据可视化的众多工具和技巧中&#xff0c;散点图是一种极为有效的方式&#xff0c;能够揭示变量之间的关系&#xff0c;尤其是在探索数据集的相关性、分布趋势、集群现象时。而在众多助力于制作高质量散点图的工具中&#xff0c;think-cell插件以其高效的操作和丰富的功能&a…...

1. windows搭建Kafka教程

目录 1. 部署zookeeper 1.1 下载地址 1.3 修改zoo配置 1.4 启动zookeepe服务 02 部署kafka 2.1 下载组件包 2.2 解压安装包 2.3 修改配置 2.4 启动kafka服务端 1. 部署zookeeper 1.1 下载地址 下载地址: kafka/zookeeper 下载地址 (qq.com) 1.2 解压 &#xff08;…...

XSS复现

目录 XSS简单介绍 一、反射型 1、漏洞逻辑&#xff1a; 为什么有些标签可以触发&#xff0c;有些标签不能触发 可以触发的标签 不能触发的标签 为什么某些标签能触发而某些不能 二、DOM型 1、Ma Spaghet! 要求&#xff1a; 分析&#xff1a; 结果&#xff1a; 2、J…...

怎么利用XML发送视频彩信

传统的短信推广主要以文字为主&#xff0c;用户接收到的信息往往显得单调乏味。而视频彩信则不同&#xff0c;它结合了视频和音频的优势&#xff0c;通过生动的画面和悦耳的音乐&#xff0c;给用户带来强烈的视听冲击&#xff0c;从而极大地提高了用户的吸引力。 XML成功返回示…...

5G+工业互联网产教融合创新实训室解决方案

一、建设背景 随着第五代移动通信技术&#xff08;5G&#xff09;的快速普及和工业互联网的迅猛发展&#xff0c;全球制造业正面临着前所未有的深刻变革。5G技术凭借其超高的传输速率、极低的延迟以及大规模的连接能力&#xff0c;为工业自动化、智能制造等领域带来了革命性的…...

象棋布局笔记

文章目录 布局中炮(当头炮)当头炮的缺点如何应对平车压马平炮对车的理解中炮对屏风马急进中兵 中炮盘头马盘头马两翼突破 盖马三锤 反宫马克制反宫马 顺手炮 士角炮56炮破解56炮 小当头 屏风马7卒分支3卒分支屏风马红车二进六败招(黑未挺7卒前直接进车)马八进九变车三退一变马二…...

百度AI智能云依赖库OpenSSL库和Curl库及jsoncpp库安装

开发百度AI项目时&#xff0c;需要用到https协议&#xff0c;因此需要安装OpenSSl和curl库。 若只安装curl库&#xff0c;只支持http协议&#xff0c;不支持https协议。此外&#xff0c;还需要jsoncpp库&#xff0c;用以组包及解析与百度AI通信的json格式协议。 1.Ubuntu上安装…...

智慧空调离线语音控制方案:NRK3301芯片的深度解析与应用

随着AI技术的大爆发和智能家居的风潮&#xff0c;语音交互已成为智能家居产品的一项必备技能&#xff0c;在家电、音箱、穿戴设备乃至墙壁开关等贴近生活的产品中应用越来越广泛&#xff0c;智能语音识别是当前最热门的方案之一。 九芯智能顺应家居行业智能语音交互市场需求&a…...

基础第3关:LangGPT结构化提示词编写实践

提示词&#xff1a; # Role: 伟大的数学家 ## Profile - author: LangGPT - version: 1.0 - language: 中文 - description: 一个伟大的数学家&#xff0c;能够解决任何的数学难题 ## Goals: 根据关键词进行描述&#xff0c;避免与已有描述重复。 ## Background: 你正在被…...

Nginx系列-负载均衡

文章目录 Nginx系列-负载均衡1. 负载均衡基础1.1 负载均衡定义1.2 Nginx负载均衡原理 2. 负载均衡策略2.1 轮询&#xff08;Round Robin&#xff09;2.2 加权轮询&#xff08;Weighted Round Robin&#xff09;2.3 IP哈希&#xff08;IP Hash&#xff09;2.4 最少连接&#xff…...

中职物联网实训室

一、中职物联网实训室建设背景 在当今科技日新月异的浪潮中&#xff0c;物联网技术以其迅猛的发展势头&#xff0c;成为了撬动数字化转型的关键杠杆&#xff0c;深刻地重塑着经济社会的面貌。面对这一变革&#xff0c;社会对精通物联网技术的应用型人才需求激增。鉴于此&#x…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

爬虫基础学习day2

# 爬虫设计领域 工商&#xff1a;企查查、天眼查短视频&#xff1a;抖音、快手、西瓜 ---> 飞瓜电商&#xff1a;京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空&#xff1a;抓取所有航空公司价格 ---> 去哪儿自媒体&#xff1a;采集自媒体数据进…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...