基于高光谱数据集的创新点实现-高斯核函数卷积神经网络

一、高光谱数据集简介

1.1 数据集简介

数据集链接在这:高光谱数据集(.mat.csv)-科研学术
数据集包含下面三个文件:
在这里插入图片描述
文件中包含.mat与.csv,145x145x220,
其实主要使用avirissub.csv文件,在代码上只是将mat文件转成了csv文件。具体avirissub.csv如下:145x145x220,每行代表一个数据,每行前220列代表特征,最后一列代表标签值,共17类标签。
在这里插入图片描述

1.2.软件环境与配置:

安装TensorFlow2.12.0版本。指令如下:

 pip install tensorflow==2.12.0

这个版本最关键,其他库,以此安装即可。

二、基线模型实现:

该代码旨在通过构建和训练卷积神经网络(CNN)模型来进行分类任务。下面是代码的详细解释和网络模型结构的说明:

2.1. 环境设置和数据加载

import pandas as pd
from tensorflow import keras
from tensorflow.keras.layers import Dense, Dropout, Conv1D, MaxPooling1D, Flatten
from tensorflow.keras.models import Sequential
from tensorflow.keras import optimizers
from sklearn.model_selection import train_test_split
import numpy as np
import matplotlib.pyplot as plt
from tensorflow.keras.callbacks import ModelCheckpoint, ReduceLROnPlateau
from keras.utils import np_utils
import scipy.io as sio
import os

os.environ["CUDA_VISIBLE_DEVICES"] = "0"
np.random.seed(42)

num_epoch = []
result_mean = []
result_std_y = []
result_std_w = []
  • 引入所需库,包括Pandas、TensorFlow、Keras、Scipy等。
  • 设置环境变量以使用指定的GPU设备。
  • 设置随机种子以确保结果可重现。

2.2. 数据加载和预处理

data = sio.loadmat('D:/python_test/data/avirissub.mat')
data_L = sio.loadmat('D:/python_test/data/avirissub_gt.mat')

print(sio.whosmat('D:/python_test/data/avirissub.mat'))
print(sio.whosmat('D:/python_test/data/avirissub_gt.mat'))

data_D = data['x92AV3C']
data_L = data_L['x92AV3C_gt']

data_D_flat = data_D.reshape(-1, data_D.shape[-1])
print(data_D_flat.shape)

data_combined = pd.DataFrame(data_D_flat)
data_combined['label'] = data_L.flatten()
data_combined.to_csv('D:/python_test/data/avirissub.csv', index=False, header=False)

data = pd.read_csv('D:/python_test/data/avirissub.csv', header=None)
data = data.values
data_D = data[:, :-1]
data_L = data[:, -1]
print(data_D.shape)

data_D = data_D / np.max(np.max(data_D))
data_D_F = data_D / np.max(np.max(data_D))

data_train, data_test, label_train, label_test = train_test_split(data_D_F, data_L, test_size=0.8, random_state=42, stratify=data_L)

data_train = data_train.reshape(data_train.shape[0], data_train.shape[1], 1)
data_test = data_test.reshape(data_test.shape[0], data_test.shape[1], 1)

print(np.unique(label_train))

label_train = np_utils.to_categorical(label_train,  None)
label_test = np_utils.to_categorical(label_test,  None)
  • 加载数据和标签,查看文件中的键和形状。
  • 数据预处理:将多维数据展平成二维数组,合并数据和标签,保存为CSV文件,并从CSV文件中读取数据。
  • 对特征数据进行归一化。
  • 划分训练集和测试集,并调整数据形状以与Conv1D层兼容。
  • 对标签数据进行独热编码。

2.3. 定义卷积神经网络模型

def CNN(num):
    result = []
    num_epoch.append(num)
    for i in range(3):
        time_S = time.time()
        model = Sequential()
        model.add(Conv1D(filters=6, kernel_size=8, input_shape=inputShape, activation='relu', name='spec_conv1'))
        model.add(MaxPooling1D(pool_size=2, name='spec_pool1'))
        
        model.add(Conv1D(filters=12, kernel_size=7, activation='relu', name='spec_conv2'))
        model.add(MaxPooling1D(pool_size=2, name='spec_pool2'))
        
        model.add(Conv1D(filters=24, kernel_size=8, activation='relu', name='spec_conv3'))
        model.add(MaxPooling1D(pool_size=2, name='spec_pool3'))

        model.add(Flatten(name='spe_fla'))
        model.add(Dense(256, activation='relu', name='spe_De'))

        model.add(Dense(17, activation='softmax'))

        adam = optimizers.Adam(learning_rate=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-8)

        model.compile(loss='categorical_crossentropy', optimizer=adam, metrics=['accuracy'])
        filepath = "../model/model_spe(5%).h5"
        checkpointer = ModelCheckpoint(filepath, monitor='val_acc', save_weights_only=False, mode='max', save_best_only=True, verbose=0)
        callback = [checkpointer]
        reduce_lr = ReduceLROnPlateau(monitor='val_acc', factor=0.9, patience=10, verbose=0, mode='auto', epsilon=0.000001, cooldown=0, min_lr=0)

        history = model.fit(data_train, label_train, epochs=num, batch_size=5, shuffle=True, validation_split=0.1, verbose=0)
        scores = model.evaluate(data_test, label_test, verbose=0)
        print("\n%s: %.2f%%" % (model.metrics_names[1], scores[1] * 100))
        result.append(scores[1] * 100)
        time_E = time.time()
        print("costTime:", time_E - time_S, 's')
    print(result)
    result_mean.append(np.mean(result))
    print("均值是:%.4f" % np.mean(result))
    result_std_y.append(np.std(result))
    print("标准差(有偏)是:%.4f" % np.std(result))
    result_std_w.append(np.std(result, ddof=1))
    print("标准差(无偏)是:%.4f" % np.std(result, ddof=1))
  • 定义CNN函数,构建并训练卷积神经网络模型。
  • 网络模型结构包括:
    • Conv1D 层:一维卷积层,用于提取特征。共三个卷积层,每层有不同的过滤器数量和卷积核大小。
    • MaxPooling1D 层:最大池化层,用于下采样。每个卷积层后都有一个池化层。
    • Flatten 层:将多维特征图展平成一维。
    • Dense 层:全连接层,包含256个神经元,激活函数为ReLU。
    • 最后一层 Dense 层:输出层,包含17个神经元,对应17个类别,激活函数为Softmax。

2.4. 模型训练和评估

if __name__ == '__main__':
     CNN(5)
  • 调用CNN函数并设置迭代次数为5。

完整的基线模型版本代码如下

from __future__ import print_function
import pandas as pd
from tensorflow import keras
from tensorflow.keras.layers import Dense, Dropout, Conv1D, MaxPooling1D, Flatten
from tensorflow.keras.models import Sequential
from tensorflow.keras import optimizers
from sklearn.model_selection import train_test_split
import numpy as np
import matplotlib.pyplot as plt
from tensorflow.keras.callbacks import ModelCheckpoint, ReduceLROnPlateau
from keras.utils import np_utils
import scipy.io as sio
import os

# 设置环境变量,指定使用的 GPU 设备
os.environ["CUDA_VISIBLE_DEVICES"] = "0"

# 设置随机种子以便实验结果可重现
np.random.seed(42)

# 初始化存储结果的列表
num_epoch = []
result_mean = []
result_std_y = []
result_std_w = []

# 加载数据
data = sio.loadmat('D:/python_test/data/avirissub.mat')  # 加载数据
data_L = sio.loadmat('D:/python_test/data/avirissub_gt.mat')  # 加载标签

# 查看.mat文件中包含的键和它们的形状
print(sio.whosmat('D:/python_test/data/avirissub.mat'))
print(sio.whosmat('D:/python_test/data/avirissub_gt.mat'))

# 提取数据和标签
data_D = data['x92AV3C']
data_L = data_L['x92AV3C_gt']

# 将多维数据展平成二维数组
data_D_flat = data_D.reshape(-1, data_D.shape[-1])
print(data_D_flat.shape)
# 将数据和标签合并
data_combined = pd.DataFrame(data_D_flat)
data_combined['label'] = data_L.flatten()

# 保存为.csv文件
data_combined.to_csv('D:/python_test/data/avirissub.csv', index=False, header=False)

# 从 CSV 文件中读取数据
data = pd.read_csv('D:/python_test/data/avirissub.csv', header=None)  # 14 类可以用于分类
data = data.values
data_D = data[:, :-1]  # 提取特征 提取了 data 矩阵的所有行和除了最后一列之外的所有列,这就是特征数据。
data_L = data[:, -1]  # 提取标签 提取了 data 矩阵的所有行的最后一列,这就是标签数据
print(data_D.shape)  # 打印特征数据的形状

# 对特征数据进行归一化
data_D = data_D / np.max(np.max(data_D))
data_D_F = data_D / np.max(np.max(data_D))

# 将数据划分为训练集和测试集
data_train, data_test, label_train, label_test = train_test_split(data_D_F, data_L, test_size=0.8, random_state=42,
                                                                  stratify=data_L)
# 将数据重新调整为与 Conv1D 层兼容的形状
data_train = data_train.reshape(data_train.shape[0], data_train.shape[1], 1)
data_test = data_test.reshape(data_test.shape[0], data_test.shape[1], 1)


# 打印标签数据的唯一值,确保它们的范围是正确的
print(np.unique(label_train))

# 根据类来自动定义独热编码
label_train = np_utils.to_categorical(label_train,  None)
label_test = np_utils.to_categorical(label_test,  None)



inputShape = data_train[0].shape  # 输入形状

import time


def CNN(num):
    result = []
    num_epoch.append(num)
    # for i in range(50):
    for i in range(3):
        time_S = time.time()
        model = Sequential()
        # 定义模型结构
        model.add(Conv1D(filters=6, kernel_size=8, input_shape=inputShape, activation='relu', name='spec_conv1'))
        model.add(MaxPooling1D(pool_size=2, name='spec_pool1'))
        #
        model.add(Conv1D(filters=12, kernel_size=7, activation='relu', name='spec_conv2'))
        model.add(MaxPooling1D(pool_size=2, name='spec_pool2'))
        #
        model.add(Conv1D(filters=24, kernel_size=8, activation='relu', name='spec_conv3'))
        model.add(MaxPooling1D(pool_size=2, name='spec_pool3'))

        # model.add(Conv1D(filters=48, kernel_size=10, activation='relu', name='spec_conv4'))
        # model.add(MaxPooling1D(pool_size=2, name='spec_pool4'))

        model.add(Flatten(name='spe_fla'))
        model.add(Dense(256, activation='relu', name='spe_De'))

        # model.add(Dropout(0.5,name = 'drop'))

        model.add(Dense(17, activation='softmax'))

        # 设置优化器和损失函数,并编译模型
        adam = optimizers.Adam(learning_rate=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-8)

        model.compile(loss='categorical_crossentropy', optimizer=adam, metrics=['accuracy'])
        filepath = "../model/model_spe(5%).h5"
        checkpointer = ModelCheckpoint(filepath, monitor='val_acc', save_weights_only=False, mode='max',
                                       save_best_only=True, verbose=0)
        callback = [checkpointer]
        reduce_lr = ReduceLROnPlateau(monitor='val_acc', factor=0.9, patience=10, verbose=0, mode='auto',
                                      epsilon=0.000001,
                                      cooldown=0, min_lr=0)

        # 训练模型并计算评分
        history = model.fit(data_train, label_train, epochs=num, batch_size=5, shuffle=True, validation_split=0.1,
                            verbose=0)
        scores = model.evaluate(data_test, label_test, verbose=0)
        print("\n%s: %.2f%%" % (model.metrics_names[1], scores[1] * 100))
        # 保存模型
        result.append(scores[1] * 100)
        time_E = time.time()
        print("costTime:", time_E - time_S, 's')
    print(result)
    result_mean.append(np.mean(result))
    print("均值是:%.4f" % np.mean(result))
    result_std_y.append(np.std(result))
    print("标准差(有偏)是:%.4f" % np.std(result))
    result_std_w.append(np.std(result, ddof=1))
    print("标准差(无偏)是:%.4f" % np.std(result, ddof=1))


if __name__ == '__main__':
    # 调用 CNN 函数并设置迭代次数为 50
    # CNN(50)
     CNN(5)

三、创新点实现:

这段代码在原有基础上引入了一些创新点,主要包括自定义卷积层和自定义回调函数。下面是具体创新点的详细解释:

3.1. 高斯核函数和自定义卷积层

高斯核函数
def gaussian_kernel(x, y, sigma=1.0):
    return tf.exp(-tf.reduce_sum(tf.square(x - y), axis=-1) / (2 * sigma ** 2))
  • 定义高斯核函数,用于计算输入片段与卷积核之间的相似性。
自定义卷积层
class GaussianKernelConv1D(Layer):
    def __init__(self, filters, kernel_size, sigma=1.0, **kwargs):
        super(GaussianKernelConv1D, self).__init__(**kwargs)
        self.filters = filters
        self.kernel_size = kernel_size
        self.sigma = sigma

    def build(self, input_shape):
        self.kernel = self.add_weight(name='kernel',
                                      shape=(self.kernel_size, int(input_shape[-1]), self.filters),
                                      initializer='uniform',
                                      trainable=True)
        super(GaussianKernelConv1D, self).build(input_shape)

    def call(self, inputs):
        output = []
        for i in range(inputs.shape[1] - self.kernel_size + 1):
            slice = inputs[:, i:i+self.kernel_size, :]
            slice = tf.expand_dims(slice, -1)
            kernel = tf.expand_dims(self.kernel, 0)
            similarity = gaussian_kernel(slice, kernel, self.sigma)
            output.append(tf.reduce_sum(similarity, axis=2))
        return tf.stack(output, axis=1)
  • GaussianKernelConv1D 是一个自定义的一维卷积层,使用高斯核函数来计算相似性。
  • build 方法中定义了卷积核,并设置为可训练参数。
  • call 方法中实现了卷积操作,通过滑动窗口方式计算输入片段和卷积核之间的相似性,并累加这些相似性值。

3.2. 自定义回调函数

自定义回调函数用于在每个 epoch 结束时输出训练信息
class TrainingProgressCallback(Callback):
    def on_epoch_end(self, epoch, logs=None):
        logs = logs or {}
        print(f"Epoch {epoch + 1}/{self.params['epochs']}, Loss: {logs.get('loss')}, Accuracy: {logs.get('accuracy')}, "
              f"Val Loss: {logs.get('val_loss')}, Val Accuracy: {logs.get('val_accuracy')}")
  • TrainingProgressCallback 是一个自定义回调函数,用于在每个 epoch 结束时输出训练进度,包括损失和准确率。

3.3. 模型构建、训练和评估

CNN 函数
def CNN(num):
    result = []
    num_epoch.append(num)
    for i in range(3):
        time_S = time.time()
        model = Sequential()
        # 定义模型结构
        model.add(GaussianKernelConv1D(filters=6, kernel_size=8, input_shape=inputShape, name='spec_conv1'))
        model.add(MaxPooling1D(pool_size=2, name='spec_pool1'))
        
        model.add(GaussianKernelConv1D(filters=12, kernel_size=7, name='spec_conv2'))
        model.add(MaxPooling1D(pool_size=2, name='spec_pool2'))
        
        model.add(GaussianKernelConv1D(filters=24, kernel_size=8, name='spec_conv3'))
        model.add(MaxPooling1D(pool_size=2, name='spec_pool3'))

        model.add(Flatten(name='spe_fla'))
        model.add(Dense(256, activation='relu', name='spe_De'))
        model.add(Dense(17, activation='softmax'))

        # 设置优化器和损失函数,并编译模型
        adam = optimizers.Adam(learning_rate=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-8)

        model.compile(loss='categorical_crossentropy', optimizer=adam, metrics=['accuracy'])
        filepath = "../model/model_spe(5%).h5"
        checkpointer = ModelCheckpoint(filepath, monitor='val_accuracy', save_weights_only=False, mode='max',
                                       save_best_only=True, verbose=0)
        callback = [checkpointer, TrainingProgressCallback()]
        reduce_lr = ReduceLROnPlateau(monitor='val_accuracy', factor=0.9, patience=10, verbose=0, mode='auto',
                                      min_delta=0.000001,
                                      cooldown=0, min_lr=0)
        callback.append(reduce_lr)

        # 训练模型并计算评分
        history = model.fit(data_train, label_train, epochs=num, batch_size=5, shuffle=True, validation_split=0.1,
                            verbose=1, callbacks=callback)
        scores = model.evaluate(data_test, label_test, verbose=0)
        print("\n%s: %.2f%%" % (model.metrics_names[1], scores[1] * 100))
        result.append(scores[1] * 100)
        time_E = time.time()
        print("costTime:", time_E - time_S, 's')
    print(result)
    result_mean.append(np.mean(result))
    print("均值是:%.4f" % np.mean(result))
    result_std_y.append(np.std(result))
    print("标准差(有偏)是:%.4f" % np.std(result))
    result_std_w.append(np.std(result, ddof=1))
    print("标准差(无偏)是:%.4f" % np.std(result, ddof=1))
  • CNN 函数中,模型结构与之前类似,但卷积层替换为自定义的 GaussianKernelConv1D 层。
  • 使用 TrainingProgressCallback 在每个 epoch 结束时输出训练进度。
  • 训练模型并评估其性能。

四、总结

相对于原代码,新的代码主要创新点包括:

  1. 引入高斯核函数和自定义卷积层:使用高斯核函数来计算输入片段与卷积核之间的相似性,增加了模型的灵活性和非线性特征提取能力。
  2. 自定义回调函数:用于在每个 epoch 结束时输出训练进度,提供更详细的训练信息,便于实时监控和调整模型。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第二十四章多栏布局解决方案(什么是自适应?/)

什么是自适应? 指能使网页自适应显示在不同大小终端设备上新网页设计方式及技术.简单的来说自适应就是让同一个页面自动适应不同大小的设备,从而解决为不同设备提供不同版本的页面问题。 1.两列自适应 两列自适应布局是指左侧固定宽度,右…

小程序使用Canvas设置文字竖向排列

在需要使用的js页面引入js文件,传入对应参数即可 /** * 文本竖向排列 */ function drawTextVertical(context, text, x, y) {var arrText text.split();var arrWidth arrText.map(function (letter) {return 26;});var align context.textAlign;var baseline context.…

河北奥润顺达集团研究院PMO经理常江南受邀为第十三届中国PMO大会演讲嘉宾

全国PMO专业人士年度盛会 河北奥润顺达集团研究院PMO经理、研发部运营管理办负责人常江南先生受邀为PMO评论主办的2024第十三届中国PMO大会演讲嘉宾,演讲议题为“初建PMO的体系宣贯和人员培养实践总结”。大会将于6月29-30日在北京举办,敬请关注&#xf…

质量工具系列之Dependency-Track

项目开发中依赖了很多第三方开源工具,对于其版本,漏洞等因为时间或者是数量太多而无法关注到,Dependency-Track解决这些问题。 Dependency-Track 是一个开源组件分析平台,是开放网络应用安全项目(OWASP)的一…

【自动化运营】PlugLink 1.0开源版发布

什么是PlugLink? PlugLink,顾名思义,就是插件的链接。它旨在帮助个人和小微企业实现运营自动化,通过链接脚本、API、AI大模型等,实现全自动工作流程。你可以把PlugLink看作一个巨大的拼装积木,每一个插件都…

Java解析JSON并修改属性值:从JSON到JsonObject的逐层解析

哈喽,大家好,我是木头左! 在Java中,可以使用各种库来解析和操作JSON数据。其中,Gson和Jackson是两个非常流行且功能强大的库。在这篇文章中,将使用Gson库来解析给定的JSON字符串,修改operationB…

加氢站压缩液驱比例泵放大器

加氢站压缩液驱液压系统的要求是实现换向和速度控制,对液压动力机构而言,按原理可区分为开式(阀控)- 节流控制系统和闭式(泵控)- 容积控制系统: 阀控系统 – 节流调速系统:由BEUEC比…

Sui新共识协议刷新了区块链交易速度的标准

Sui是提供业界领先性能和无限水平扩展的创新Layer 1区块链,今日在官推上宣布其最新共识协议Mysticeti已成功部署到测试网。这一重大突破将Sui测试网的共识时间减少了80%,至390毫秒,同时保持协议的行业领先吞吐量。这一令人印象深刻的演示证明…

英国金融时报:波场TRON出席康奈尔大学区块链会议

近日,康奈尔区块链大会的白金赞助商波场TRON在罗斯福岛的康奈尔大学科技校区(Cornell Tech)举办多项活动,消息得到英国金融时报,费加罗报和Benzinga等权威外媒报道,这全面彰显了波场TRON的领导力。大会吸引了包括学生、学者和行业领袖等在内的 800 多名参与者,凸显了波场TRON致…

【教程】Linux部署Android安卓模拟器

转载请注明出处:小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你,欢迎[点赞、收藏、关注]哦~ 未完成, 先简单记录下指令。 docker-android https://github.com/budtmo/docker-android 检查系统是否支持: sudo apt instal…

【ARM+Codesys案例】树莓派+Codesys软PLC方案在包装行业灌装旋盖机的应用

ARM系列支持:全志T3、RK3568、树莓派 机型定义:双工位旋盖机 旋盖机主要适用于不同规格的材质及不同规格的盖、旋(轧)盖。适用螺旋盖、防盗盖、防撞盖、压入盖等。压力可方便调整,根据瓶盖大小设置取盖位。结构紧凑、…

【Springboot】注解@JsonIgnore、@TableField、@TableId

文章目录 1.JsonIgnore2.TableField(exist false)3.TableId 1.JsonIgnore 2.TableField(exist false) 新增一个字符串字段,并且这个字段是不用到数据库查询的 3.TableId Mybatis-plus 出现 WHERE null?,此时就要加这个注解。

全球十大体育赛事API服务

体育赛事API汇总: Broadage全球橄榄球赛事数据Broadage全球棒球赛事数据Broadage全球篮球实时数据Broadage全球冰球赛事数据Broadage全球排球实时数据TennisApi全球网球赛事讯息Broadage全球足球实时数据棒球数据【纳米数据】

AACR美国癌症研究学会文献及补充文献下载的途径

美国癌症研究学会American Association for Cancer Research(AACR)创建于1907年,是世界上成立最早、规模最大的致力于全面、创新和高水准癌症研究的科学组织。其出版物包括7种正式出版的期刊(其中五种经同行评议*)和其…

C++重点基础知识汇总大全

文章目录 一些基础知识点指针和引用 一些基础知识点 1、十进制的数字比较长的时候&#xff0c;可以加方便阅读到底是几位&#xff0c;输出的时候跟不加是一样的效果 // 十进制可以加 cout << 13890324 << endl; // 13890324 // 二进制前加0b cout << 0b111…

Web前端复习二

第一章测试 选项中加粗的为答案 1.图片的边框可以通过( )设定宽度。 A.width B.height C.border D.align 2.关于超链接&#xff0c;( )属性用于规定在何处打开链接文档。 A.href . B.target C.title D.onclick 3.( )是在新窗口打开网页文档。 A _blank B_self C_…

TQSDRPI开发板教程:DDR检测

项目资源分享 链接&#xff1a;https://pan.baidu.com/s/1IIrUL7Zczb6DwCAkihylRA 提取码&#xff1a;0z0z 打开vivado2019.1创建工程 下一步 设置工程名称与地址。勾选reate…选项&#xff0c;会创建一个新的文件夹&#xff0c;项目保存在其中&#xff0c;文件夹名称与工程名…

算法学习笔记(7.1)-贪心算法(分数背包问题)

##问题描述 给定 &#x1d45b; 个物品&#xff0c;第 &#x1d456; 个物品的重量为 &#x1d464;&#x1d454;&#x1d461;[&#x1d456;−1]、价值为 &#x1d463;&#x1d44e;&#x1d459;[&#x1d456;−1] &#xff0c;和一个容量为 &#x1d450;&#x1d44e;&…

Midjourney保姆级教程(五):Midjourney图生图

Midjourney生成图片的方式除了使用文字描述生成图片外&#xff0c;还有“图生图”的方式&#xff0c;可以让生成的图片更接近参考的图片。 今天我们来聊聊“图生图”的方式。 一、模仿获取propmt 很多时候&#xff0c;我们不知道画什么内容的图片&#xff0c;大家可以关注内…

28-ESP32-S3 lwIP 轻量级 TCP/IP 协议栈

ESP32-S3 lwIP 介绍 ESP32-S3 是一款集成了Wi-Fi 和蓝牙功能的微控制器。它的设计初衷是为了方便嵌入式系统的开发。不过你可能会好奇&#xff0c;ESP32-S3 怎么实现与外部网络的通信呢&#xff1f;这里就要提到一个开源的 TCP/IP 协议栈&#xff0c;它叫做lwIP&#xff08;轻…