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

对开源VLA sota π0的微调——如何基于各种开源数据集、以及你自己的私有数据集微调π0(含我司的微调实践)

前言

25年2.4日,几个月前推出π0的公司Physical Intelligence (π)宣布正式开源π0及π0-FAST,如之前所介绍的,他们对用超过 10,000 小时的机器人数据进行了预训练

该GitHub代码仓库「 π0及π0-FAST的GitHub地址:github.com/Physical-Intelligence/openpi」包括4个方面:简言之,就是π0本身的代码和权重、特定平台上特定任务的微调checkpoint、推理代码、微调代码

第一部分 如何基于各种开源数据集微调π0

1.1 π0及π0-FAST对外开源的具体内容

1.1.1 开源基础模型π0及π0-FAST,可自行微调

  1. π0基础模型的代码及权重
    可用于微调的扩散π0「标准的预训练π 0模型,该模型在 OXE 和他们的 7 个机器人平台上进行训练
    其对应的checkpoint路径为:s3://openpi-assets/checkpoints/pi0_base
  2. π0-FAST基础模型的代码及权重
    可用于微调的π0_FAST——基于FAST分词器的自回归模型
    该模型使用FAST tokenizer通过自回归离散化实现控制
    它提供了更好的语言跟踪性能,但推理成本更高(根据他们的经验,大约高出 4-5 倍),如果您更喜欢使用discretization而不是流匹配,这是一个不错的选择

    其对应的checkpoint路径为:s3://openpi-assets/checkpoints/pi0_fast_base

1.1.2 已经微调好的模型 可直接推理:π0 DROID/π0 ALOHA/π0 Libero

且他们还提供了专门为ALOHA和DROID平台上一些简单任务做了微调的checkpoint,相当于在ALOHA 和 DROID 收集的相对较小的数据集上进行了微调

即several checkpoints that are fine-tuned for a few simple tasks on a few widely available platforms such as ALOHA and DROID,当然,它们可能无法推广到您的特定设置

  1. π0 DROID:在DROID 数据集上微调过的扩散π0
    DROID数据集由 Franka 机械臂在不同环境中执行的不同任务组成的开源数据集,且他们通过视频展示了 openpi 在训练数据中从未见过的环境中运行,这些环境遍布世界各地,包括蒙特利尔大学、华盛顿大学、韩国科学技术研究院等

    其对应的checkpoint路径为:s3://openpi-assets/checkpoints/pi0_droid
    推理速度比π0-FAST-DROID快,但可能不遵循语言命令
  2. π0-FAST DROID:在DROID数据集微调过的π0-FAST
    可以在DROID机器人平台上的新场景中执行各种简单的零样本桌面操控任务,例如“从烤面包机中取出面包”任务

    其对应的checkpoint路径为:s3://openpi-assets/checkpoints/pi0_fast_droid
  3. π0 ALOHA
    根据 ALOHA(适合灵巧操作的低成本双臂系统) 数据进行了微调,可以在ALOHA机器人平台上进行毛巾折叠、食物舀取和其他任务,相当于提供了一套针对 ALOHA 平台上的任务进行微调的检查点「这些检查点可能对整体机器人设置非常敏感,但能够在完全未出现在训练数据中的全新 ALOHA 站点上运行它们

    不同任务对应的不同checkpoint路径分别为
    折叠毛巾:s3://openpi-assets/checkpoints/pi0_aloha_towel
    从容器中取出食物:s3://openpi-assets/checkpoints/pi0_aloha_tupperware
    打开笔帽:s3://openpi-assets/checkpoints/pi0_aloha_pen_uncap
  4. π0 Libero
    此检查点针对 Libero 基准进行了微调,并且可以在 Libero 任务上进行开箱即用的评估

1.1.3 模型推理与私有数据自行微调

他们还开源了在多个显示世界和仿真机器人平台上推理运行的示例代码(example code to run inference on several real-world and simulated robot platforms)

 以下是跑π0-FAST-DROID模型的预训练检查点

from openpi.training import config
from openpi.policies import policy_config
from openpi.shared import downloadconfig = config.get_config("pi0_fast_droid")
checkpoint_dir = download.maybe_download("s3://openpi-assets/checkpoints/pi0_fast_droid")# Create a trained policy.
policy = policy_config.create_trained_policy(config, checkpoint_dir)# Run inference on a dummy example.
example = {"observation/exterior_image_1_left": ...,"observation/wrist_image_left": ...,..."prompt": "pick up the fork"
}
action_chunk = policy.infer(example)["actions"]

且也可以在示例笔记本中测试这一点,他们还提供了在DROID和ALOHA机器人上运行预先训练的检查点的推理的详细分步示例

此外

  1. 远程推理:他们提供了示例和代码,用于远程运行模型推理,详见远程运行π0模型
    模型可以在不同的服务器上运行,并通过 websocket 连接将操作传输到机器人。这样可以轻松在机器人外使用更强大的 GPU,并将机器人和策略环境分开

    要启动远程策略服务器,您只需运行以下命令:
    uv run scripts/serve_policy.py --env=[DROID | ALOHA | LIBERO]
    其中,参数env指定哪个π0 checkpoint 应该被加载,比如是ALOHA还是LIBERO。在后台,这个脚本将执行如下命令,你可以使用它来启动策略服务器,例如用于你自己训练的检查点——这里是 DROID 环境的一个示例
    uv run scripts/serve_policy.py policy:checkpoint --policy.config=pi0_fast_droid --policy.dir=s3://openpi-assets/checkpoints/pi0_fast_droid
    其中,config这将启动一个策略服务器,该服务器将执行和参数指定的策略dir。该策略将在指定端口(默认值:8000)上执行
  2. 无需机器人即可测试推理:提供无需机器人即可测试推理的脚本。此脚本将生成随机观察并使用模型运行推理。有关更多详细信息,请参阅此处

1.2 基于自己的数据集微调π0基础模型

1.2.1 利用Libero数据集微调π0基础模型的三个步骤

此外,他们还提供了用于根据用户自身任务和平台微调π0的代码(code for fine-tuning the base π0 model for your own tasks and platforms),这个微调π0的代码 个人觉得很有价值且huggingface上有相应的pytorch接口

Physical Intelligence (π)认为,1 到 20 小时的数据足以微调各种任务,具体而言,如果想利用自己的数据上微调π0基础模型,只需以下三个步骤即可:

  1. 将Libero数据集转换为LeRobot数据集v2.0格式
    作者提供了一个脚本convert_libero_data_to_lerobot.py「下一小节,我会详细分析一下这个脚本」,用于将 Libero 数据转换为 LeRobot 数据集 v2.0 格式,且可以轻松修改它以转换您自己的数据

    比如从此处下载原始 Libero 数据集,然后使用以下命令运行脚本
    uv run examples/libero/convert_libero_data_to_lerobot.py --data_dir /path/to/your/libero/data
    且作为示例,已将 BiPlay 代码库中的 aloha_pen_uncap_diverse_raw 数据集转换,并将其上传至 HuggingFace Hub,地址为 physical-intelligence/aloha_pen_uncap_diverse
  2. 定义使用自定义数据集的训练配置,并运行训练
    提供pi0_aloha_pen_uncap 配置作为示例,您应该参考根README以了解如何使用新配置运行训练

    比如下面是 Libero 示例配置,可以根据自己的数据集进行修改:
    \rightarrow  LiberoInputs和LiberoOutputs:定义从 Libero 环境到模型的数据映射,反之亦然——将用于训练和推理
    \rightarrow  LeRobotLiberoDataConfig:定义了如何处理来自 LeRobot 数据集的原始 Libero 数据以用于训练
    \rightarrow  TrainConfig:定义微调超参数、数据配置和权重加载器
  3. 启动策略服务器并运行推理
    训练完成后,可以通过启动策略服务器,然后从 Libero 评估脚本中查询它来运行推理。启动模型服务器很容易(他们在此示例中使用迭代 20,000 的检查点,根据需要进行修改)
    uv run scripts/serve_policy.py policy:checkpoint --policy.config=pi0_fast_libero --policy.dir=checkpoints/pi0_fast_libero/my_experiment/20000

Libero数据集转换脚本convert_libero_data_to_lerobot.py的解析


​接下来,我们使用Libero数据集(存储在RLDS格式中)作为示例——将RLDS格式转换为LeRobot格式,如何修改以适应其他自定义格式的数据

首先,咱们明确下Libero数据集的层级结构

Libero数据集
├── libero_10_no_noops/
├── libero_goal_no_noops/
├── libero_object_no_noops/
└── libero_spatial_no_noops/
    └── train/
                └── episode
                            └── steps
                                      ├── observation
                                      │      ├── image (256x256x3)
                                      │      ├── wrist_image (256x256x3)
                                      │      └── state (8维向量)
                                      ├── action (7维向量)
                                      └── language_instruction (文本)

接下来,按如下步骤逐一执行

  1. 关键常量定义
    # 输出数据集名称,也用于Hugging Face Hub
    REPO_NAME = "your_hf_username/libero"  
    RAW_DATASET_NAMES = ["libero_10_no_noops","libero_goal_no_noops","libero_object_no_noops","libero_spatial_no_noops",
    ]  # 将多个Libero数据集合并为一个训练数据集
  2. 定义主函数结构
    def main(data_dir: str, *, push_to_hub: bool = False):
    主函数接受两个参数:
    data_dir: 原始数据目录路径
    push_to_hub: 是否推送到HuggingFace Hub的标志
  3. 清理现有数据
        output_path = LEROBOT_HOME / REPO_NAMEif output_path.exists():shutil.rmtree(output_path)
    确保输出目录干净,删除任何已存在的数据
  4. 创建LeRobot数据集:包含处理图像、状态和动作数据
        # 创建LeRobot数据集,定义要存储的特征# OpenPi假设本体感知数据存储在`state`中,动作存储在`action`中# LeRobot假设图像数据的dtype为`image`dataset = LeRobotDataset.create(repo_id=REPO_NAME,           # 数据集的仓库IDrobot_type="panda",          # 机器人类型fps=10,                      # 帧率features={                   # 特征定义"image": {                  # image数据"dtype": "image",                             # 数据类型"shape": (256, 256, 3),                       # 数据形状"names": ["height", "width", "channel"],      # 维度名称},"wrist_image": {            # 手腕image数据"dtype": "image", "shape": (256, 256, 3),  "names": ["height", "width", "channel"], },"state": {                  # 状态数据"dtype": "float32",  "shape": (8,), "names": ["state"],  },"actions": {                # 动作数据"dtype": "float32", "shape": (7,),  "names": ["actions"],  },},image_writer_threads=10,           # 图像写入线程数image_writer_processes=5,          # 图像写入进程数)
    定义数据集结构,包括:
    - 机器人类型:panda
    - 帧率:10fps
    - 特征定义:
      - 图像:256x256x3的RGB图像
      - 手腕图像:同样的格式
      - 状态:8维浮点数向量
      - 动作:7维浮点数向量
    - 多线程/进程配置用于图像处理
  5. 数据转换循环
        # 遍历原始Libero数据集并将episode写入LeRobot数据集# 你可以根据自己的数据格式修改此部分for raw_dataset_name in RAW_DATASET_NAMES:raw_dataset = tfds.load(raw_dataset_name, data_dir=data_dir, split="train")  # 加载原始数据集for episode in raw_dataset:  # 遍历每个episodefor step in episode["steps"].as_numpy_iterator():      # 遍历每个步骤dataset.add_frame({"image": step["observation"]["image"],      # 添加图像数据"wrist_image": step["observation"]["wrist_image"],  # 添加手腕图像数据"state": step["observation"]["state"],      # 添加状态数据"actions": step["action"],                  # 添加动作数据})dataset.save_episode(task=step["language_instruction"].decode())  # 保存episode并解码语言指令
    这部分实现了数据转换的核心逻辑:
    1. 遍历所有原始数据集
    2. 对每个数据集中的每个episode
    3. 处理episode中的每一步
    4. 保存frame数据和语言指令

    相当于
  6. 数据集的整合与发布
    最后的处理步骤:
    1. 整合数据集(不计算统计信息)
    2. 可选:推送到HuggingFace Hub,包括:
       - 添加标签
       - 设置为公开
       - 包含视频
       - 指定许可证

脚本可以通过以下命令运行:

uv run examples/libero/convert_libero_data_to_lerobot.py --data_dir /path/to/your/data

如果要推送到HuggingFace Hub:

uv run examples/libero/convert_libero_data_to_lerobot.py --data_dir /path/to/your/data --push_to_hub

总之,这个脚本展示了如何构建标准化的机器人学习数据集,为训练像Pi0这样的模型提供数据支持

1.2.2 在 UR5 数据集上微调 pi0

// 待更

1.3 安装与运行

1.3.1 如何安装本openpi开源库

要运行此存储库中的模型,需要至少具有以下规格的 NVIDIA GPU。这些估算假设单个 GPU,但您也可以通过fsdp_devices在训练配置中进行配置来使用具有模型并行性的多个 GPU,以减少每个 GPU 的内存要求。另请注意,当前的训练脚本尚不支持多节点训练

模式所需内存示例 GPU
推理> 8 GBRTX 4090
微调(LoRA)> 22.5 GBRTX 4090
微调(完整版)> 70 GBA100(80GB)/H100

PS,他们说该 repo 已在 Ubuntu 22.04 上测试过,其他操作系统可能不支持

以下是安装过程

  1. 克隆此 repo 时,请确保更新子模块:
    git clone --recurse-submodules git@github.com:Physical-Intelligence/openpi.git# Or if you already cloned the repo:
    git submodule update --init --recursive
  2. 使用uv来管理 Python 依赖项。可参阅uv 安装说明进行设置
    安装 uv 后,运行以下命令设置环境:
    GIT_LFS_SKIP_SMUDGE=1 uv sync
    注意:GIT_LFS_SKIP_SMUDGE=1需要将 LeRobot 作为依赖项
    Docker:作为 uv 安装的替代方案,他们还提供了使用 Docker 安装 openpi 的说明
    如果在系统设置中遇到问题,还可以考虑使用 Docker 来简化安装,详情请参阅Docker 设置

2.3.2 如何把该库的ALOHA sim环境跑起来

此外,该开源库还提供ALOHA SIM

  • 如使用docker
    export SERVER_ARGS="--env ALOHA_SIM"
    docker compose -f examples/aloha_sim/compose.yml up --build
  • 如没有docker
    \rightarrow  终端窗口1
    # Create virtual environment
    uv venv --python 3.10 examples/aloha_sim/.venv
    source examples/aloha_sim/.venv/bin/activate
    uv pip sync examples/aloha_sim/requirements.txt
    uv pip install -e packages/openpi-client# Run the simulation
    MUJOCO_GL=egl python examples/aloha_sim/main.py
    注意:如果您看到 EGL 错误,则可能需要安装以下依赖项
    sudo apt-get install -y libegl1-mesa-dev libgles2-mesa-dev
    \rightarrow  终端窗口2
    # Run the server
    uv run scripts/serve_policy.py --env ALOHA_SIM

第二部分 如何基于你自己的私有数据集微调π0:含我司的微调实践

// 待更

相关文章:

对开源VLA sota π0的微调——如何基于各种开源数据集、以及你自己的私有数据集微调π0(含我司的微调实践)

前言 25年2.4日,几个月前推出π0的公司Physical Intelligence (π)宣布正式开源π0及π0-FAST,如之前所介绍的,他们对用超过 10,000 小时的机器人数据进行了预训练 该GitHub代码仓库「 π0及π0-FAST的GitHub地址:github.com/Ph…...

[排序算法]直接插入排序

1.基本思想 直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列。 实际中我们玩扑克牌时,就用…...

四、云原生应用监控-Etcd

Etcd 是 Kubernetes 内部核心组件之一,作为分布式键值存储,天然支持 Prometheus 监控,自带 /metrics 端点,可直接被 Prometheus 抓取。 Etcd监控需要使用到证书。 一、检查云原生Etcd 检查节点上的Etcd [root@k8s-master01 manifests]#netstat -lnpt |grep etcd tcp …...

STM32-I2C通信外设

目录 一:I2C外设简介 二:I2C外设数据收发 三:I2C的复用端口 四:主机发送和接收 五:硬件I2C读写MPU6050 相关函数: 1.I2C_ GenerateSTART 2.I2C_ GenerateSTOP 3.I2C_ AcknowledgeConfig 4.I2C…...

CTA策略【量化理论】

CTA策略演变史 全称:Commodity Trading Advisor (商品交易顾问) CTA最开始是指通过为客户提供期权、期货方面的交易建议,或者直接通过受管理的期货账户参与实际交易,来获得收益的机构或个人。 随着市场的发展&#…...

基于AMD AU15P FPGA的SLVS-EC桥PCIe设计方案分享

作者:Hello,Panda 各位FPGAer周末愉快,今天熊猫君分享一个基于AMD AU15P FPGA的SLVS-EC桥PCIe设计方案。 一、方案背景 先说方案的应用背景:众所周知,较为上层的如基于AI的机器视觉应用,大多基于高端的专用SoC、AI专…...

②Modbus TCP转Modbus RTU/ASCII网关同步采集无需编程高速轻松组网

Modbus TCP转Modbus RTU/ASCII网关同步采集无需编程高速轻松组网https://item.taobao.com/item.htm?ftt&id784749793551 网关 MS-A1-5081 MS-A1-5081 网关通过 MODBUS TCP 协议与 Modbus RTU/ASCII 协议的相互转换,可以将 Modbus 串口设备接入 MODBUS TCP 网络…...

游戏引擎学习第145天

仓库:https://gitee.com/mrxiao_com/2d_game_3 今天的计划 目前,我们正在完成遗留的工作。当时我们已经将声音混合器(sound mixer)集成到了 SIMD 中,但由于一个小插曲,没有及时完成循环内部的部分。这个小插曲主要是…...

【Kotlin】Kotlin基础笔记

一、数据类型 1.1 变量声明与类型推导 变量声明 使用 val 声明不可变变量(相当于常量);使用 var 声明可变变量。 val a 10 // 类型自动推断为 Int,不可变 var b: Double 5.0 // 显示声明为 Double,可变变量…...

Jump( 2015-2016 ACM-ICPC Northeastern European Regional Contest (NEERC 15). )

Jump( 2015-2016 ACM-ICPC Northeastern European Regional Contest (NEERC 15). ) 题目大意: 在这个交互式问题中,你需要通过查询系统,逐步找出隐藏的位字符串 S。给定一个偶数 n,表示目标位字符串 S 的长度,你需要通…...

uniapp uniCloud引发的血案(switchTab: Missing required args: “url“)!!!!!!!!!!

此文章懒得排版了,为了找出这个bug, 星期六的晚上我从9点查到0点多,此时我心中一万个草泥马在崩腾,超级想骂人!!!!!!!!! uniCloud 不想…...

【Linux】冯诺依曼体系与操作系统理解

🌟🌟作者主页:ephemerals__ 🌟🌟所属专栏:Linux 目录 前言 一、冯诺依曼体系结构 二、操作系统 1. 操作系统的概念 2. 操作系统存在的意义 3. 操作系统的管理方式 4. 补充:理解系统调用…...

STM32之软件SPI

SPI传输更快,最大可达80MHz,而I2C最大只有3.4MHz。输入输出是分开的,可以同时输出输入。是同步全双工。仅支持一主多从。SS是从机选择线。每个从机一根。SPI无应答机制的设计。 注意:所有设备需要共地,时钟线主机输出&…...

Python零基础学习第三天:函数与数据结构

一、函数基础 函数是什么? 想象你每天都要重复做同一件事,比如泡咖啡。函数就像你写好的泡咖啡步骤说明书,每次需要时直接按步骤执行,不用重新想流程。 # 定义泡咖啡的函数 def make_coffee(sugar1): # 默认加1勺糖 print("…...

启动wsl里的Ubuntu24报错:当前计算机配置不支持 WSL2,HCS_E_HYPERV_NOT_INSTALLED

问题:启动wsl里的Ubuntu24报错 报错信息: 当前计算机配置不支持 WSL2。 请启用“虚拟机平台”可选组件,并确保在 BIOS 中启用虚拟化。 通过运行以下命令启用“虚拟机平台”: wsl.exe --install --no-distribution 有关信息,请访…...

顶点着色器和片段着色器

在Unity渲染中,**顶点着色器(Vertex Shader)和片段着色器(Fragment Shader)**是图形渲染管线中的两个核心阶段。我们可以通过一个比喻来理解它们的分工:想象你要画一幅由三角形组成的3D模型,顶点…...

std::optional详解

基础介绍 c17版本引入了std::optional特性&#xff0c;这一个类模板&#xff0c;基本的使用方法如下&#xff1a; std::optional<T> 这个新特性的含义是利用std::optional<T>创建的某个类型的对象&#xff0c;这个对象存储某个类型的值&#xff0c;这个值可能存在…...

Web三件套学习笔记

<!-- HTML --> HTML是超文本标记语言 1、html常用标签 块级标签 独占一行 可以设置宽度&#xff0c;高度&#xff0c;margin,padding 宽度默认所在容器的宽度 标签作用table定义表格h1 ~ h6定义标题hr定义一条水平线p定义段落li标签定义列表项目ul定义无序列表ol定…...

Scala 中trait的线性化规则(Linearization Rule)和 super 的调用行为

在 Scala 中&#xff0c;特质&#xff08;Trait&#xff09;是一种强大的工具&#xff0c;用于实现代码的复用和组合。当一个类混入&#xff08;with&#xff09;多个特质时&#xff0c;可能会出现方法冲突的情况。为了解决这种冲突&#xff0c;Scala 引入了最右优先原则&#…...

C++入门——引用

C入门——引用 一、引用的概念 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的变量共用同一块内存空间。这就好比《水浒传》中&#xff0c;一百零八位好汉都有自己的绰号。通过&…...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

ServerTrust 并非唯一

NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案

随着新能源汽车的快速普及&#xff0c;充电桩作为核心配套设施&#xff0c;其安全性与可靠性备受关注。然而&#xff0c;在高温、高负荷运行环境下&#xff0c;充电桩的散热问题与消防安全隐患日益凸显&#xff0c;成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上&#xff0c;所以报错&#xff0c;到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本&#xff0c;cu、torch、cp 的版本一定要对…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

OPENCV形态学基础之二腐蚀

一.腐蚀的原理 (图1) 数学表达式&#xff1a;dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一&#xff0c;腐蚀跟膨胀属于反向操作&#xff0c;膨胀是把图像图像变大&#xff0c;而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合

在汽车智能化的汹涌浪潮中&#xff0c;车辆不再仅仅是传统的交通工具&#xff0c;而是逐步演变为高度智能的移动终端。这一转变的核心支撑&#xff0c;来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒&#xff08;T-Box&#xff09;方案&#xff1a;NXP S32K146 与…...