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

使用Python爬虫构建LingBot-Depth-Pretrain-ViTL-14训练数据集

使用Python爬虫构建LingBot-Depth-Pretrain-ViTL-14训练数据集1. 项目背景与目标LingBot-Depth-Pretrain-ViTL-14是一个先进的深度估计模型能够将不完整和有噪声的深度传感器数据转换为高质量、精确度量的3D测量结果。要训练这样的模型需要大量高质量的RGB-D彩色图像深度图配对数据。传统的深度数据集往往存在规模有限、质量参差不齐的问题。通过Python爬虫技术我们可以从多个来源收集高质量的图像和深度数据构建一个大规模、多样化的训练数据集为模型训练提供充分的数据支持。本文将手把手教你如何使用Python爬虫技术构建适合LingBot-Depth-Pretrain-ViTL-14模型的训练数据集涵盖数据采集、清洗、标注的全流程。2. 环境准备与工具安装在开始之前我们需要准备相应的开发环境和工具库。以下是推荐的环境配置# 创建虚拟环境 conda create -n depth-data python3.9 conda activate depth-data # 安装核心依赖 pip install requests beautifulsoup4 selenium scrapy pip install opencv-python pillow numpy pandas pip install tqdm matplotlib # 可选用于处理3D数据 pip install open3d trimesh对于需要JavaScript渲染的网站我们还需要安装浏览器驱动# 安装Chrome驱动根据你的Chrome版本选择对应版本 # 或者使用webdriver-manager自动管理 pip install webdriver-manager3. 数据源分析与选择构建深度估计数据集时我们需要寻找包含RGB图像和对应深度图的数据源。以下是几个可靠的数据来源3.1 公开数据集网站NYU Depth V2数据集ScanNet数据集Matterport3D数据集Redwood 3D数据集3.2 学术资源平台大学实验室公开数据研究论文附带数据集开源项目提供的样本数据3.3 合成数据生成使用Blender、Unity等工具生成合成RGB-D数据虽然不如真实数据但可以作为补充。4. 爬虫实现详解下面我们实现一个针对多个数据源的爬虫系统能够自动下载RGB图像和对应的深度图。4.1 基础爬虫框架import requests from bs4 import BeautifulSoup import os import time from urllib.parse import urljoin import json class DepthDataCrawler: def __init__(self, base_url, output_dirdataset): self.base_url base_url self.output_dir output_dir self.session requests.Session() self.session.headers.update({ User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 }) # 创建输出目录 os.makedirs(os.path.join(output_dir, rgb), exist_okTrue) os.makedirs(os.path.join(output_dir, depth), exist_okTrue) os.makedirs(os.path.join(output_dir, metadata), exist_okTrue) def fetch_page(self, url): 获取页面内容 try: response self.session.get(url, timeout10) response.raise_for_status() return response.content except requests.RequestException as e: print(f请求失败: {e}) return None4.2 多数据源适配器不同的数据源有不同的结构我们需要为每个数据源编写特定的解析器def parse_nyu_dataset(self, content): 解析NYU Depth V2数据集页面 soup BeautifulSoup(content, html.parser) data_links [] # 查找数据下载链接示例逻辑实际需要根据网站结构调整 for link in soup.find_all(a, hrefTrue): href link[href] if any(ext in href for ext in [.png, .jpg, .jpeg, .npy, .mat]): full_url urljoin(self.base_url, href) data_links.append(full_url) return data_links def download_file(self, url, file_type): 下载文件并根据类型保存到相应目录 try: response self.session.get(url, streamTrue, timeout30) if response.status_code 200: # 根据URL确定文件名 filename os.path.basename(url) if file_type rgb: save_path os.path.join(self.output_dir, rgb, filename) elif file_type depth: save_path os.path.join(self.output_dir, depth, filename) else: save_path os.path.join(self.output_dir, metadata, filename) # 下载文件 with open(save_path, wb) as f: for chunk in response.iter_content(chunk_size8192): f.write(chunk) print(f成功下载: {filename}) return True except Exception as e: print(f下载失败 {url}: {e}) return False4.3 自动化批量下载def batch_download(self, data_list, file_type, delay1): 批量下载文件 success_count 0 for i, url in enumerate(data_list): print(f下载进度: {i1}/{len(data_list)}) if self.download_file(url, file_type): success_count 1 time.sleep(delay) # 礼貌性延迟避免被封IP print(f下载完成: {success_count}/{len(data_list)} 个文件) return success_count def crawl_website(self, max_pages10): 爬取网站的多页内容 all_rgb_links [] all_depth_links [] for page in range(1, max_pages 1): page_url f{self.base_url}?page{page} if page 1 else self.base_url print(f正在爬取第 {page} 页: {page_url}) content self.fetch_page(page_url) if content: # 根据网站类型调用不同的解析方法 if nyu in self.base_url: links self.parse_nyu_dataset(content) # 可以添加其他网站的解析器 # 分类RGB和深度链接 for link in links: if any(keyword in link for keyword in [rgb, color, image]): all_rgb_links.append(link) elif any(keyword in link for keyword in [depth, distance, 3d]): all_depth_links.append(link) time.sleep(2) # 页面间延迟 return all_rgb_links, all_depth_links5. 数据清洗与配对下载的数据往往需要清洗和配对确保RGB图像和深度图正确对应import cv2 import numpy as np from pathlib import Path class DataCleaner: def __init__(self, data_dir): self.data_dir Path(data_dir) self.rgb_dir self.data_dir / rgb self.depth_dir self.data_dir / depth def find_matching_pairs(self): 查找匹配的RGB和深度图像对 rgb_files list(self.rgb_dir.glob(*.*)) depth_files list(self.depth_dir.glob(*.*)) pairs [] for rgb_file in rgb_files: # 根据命名规则寻找对应的深度文件 depth_filename self.get_corresponding_depth_name(rgb_file.name) depth_file self.depth_dir / depth_filename if depth_file.exists(): pairs.append((rgb_file, depth_file)) return pairs def get_corresponding_depth_name(self, rgb_name): 根据RGB文件名生成对应的深度文件名 # 常见的命名约定转换规则 if rgb in rgb_name: return rgb_name.replace(rgb, depth) elif color in rgb_name: return rgb_name.replace(color, depth) elif img in rgb_name: return rgb_name.replace(img, depth) else: # 添加其他命名规则或使用相同的文件名 return rgb_name def validate_image_pair(self, rgb_path, depth_path): 验证图像对是否有效 try: rgb_img cv2.imread(str(rgb_path)) depth_data np.load(str(depth_path)) if depth_path.suffix .npy else cv2.imread(str(depth_path), cv2.IMREAD_UNCHANGED) if rgb_img is None or depth_data is None: return False # 检查图像尺寸是否匹配深度图可能是不同尺寸 # 可以根据需要调整此逻辑 return True except: return False def clean_invalid_pairs(self): 清理无效的图像对 pairs self.find_matching_pairs() valid_pairs [] for rgb_path, depth_path in pairs: if self.validate_image_pair(rgb_path, depth_path): valid_pairs.append((rgb_path, depth_path)) else: # 删除无效文件 rgb_path.unlink(missing_okTrue) depth_path.unlink(missing_okTrue) print(f有效图像对: {len(valid_pairs)}/{len(pairs)}) return valid_pairs6. 数据标注与增强为了提高数据集质量我们可能需要对数据进行标注和增强class DataAnnotator: def __init__(self, data_dir): self.data_dir Path(data_dir) def generate_metadata(self, pairs): 为每个图像对生成元数据 metadata_list [] for rgb_path, depth_path in pairs: rgb_img cv2.imread(str(rgb_path)) depth_data np.load(str(depth_path)) if depth_path.suffix .npy else cv2.imread(str(depth_path), cv2.IMREAD_UNCHANGED) metadata { rgb_filename: rgb_path.name, depth_filename: depth_path.name, image_size: { height: rgb_img.shape[0], width: rgb_img.shape[1], channels: rgb_img.shape[2] }, depth_range: { min: float(np.nanmin(depth_data)), max: float(np.nanmax(depth_data)), mean: float(np.nanmean(depth_data)) }, data_source: crawled, collection_date: time.strftime(%Y-%m-%d) } # 保存元数据 meta_filename rgb_path.stem _meta.json meta_path self.data_dir / metadata / meta_filename with open(meta_path, w) as f: json.dump(metadata, f, indent2) metadata_list.append(metadata) return metadata_list def augment_data(self, pairs, augmentations5): 数据增强创建额外的训练样本 augmented_dir self.data_dir / augmented os.makedirs(augmented_dir / rgb, exist_okTrue) os.makedirs(augmented_dir / depth, exist_okTrue) for i, (rgb_path, depth_path) in enumerate(pairs): print(f增强数据 {i1}/{len(pairs)}) rgb_img cv2.imread(str(rgb_path)) depth_data np.load(str(depth_path)) if depth_path.suffix .npy else cv2.imread(str(depth_path), cv2.IMREAD_UNCHANGED) for aug_idx in range(augmentations): # 应用不同的增强技术 aug_rgb, aug_depth self.apply_augmentation(rgb_img, depth_data, aug_idx) # 保存增强后的数据 aug_rgb_name f{rgb_path.stem}_aug{aug_idx}{rgb_path.suffix} aug_depth_name f{depth_path.stem}_aug{aug_idx}{depth_path.suffix} cv2.imwrite(str(augmented_dir / rgb / aug_rgb_name), aug_rgb) if depth_path.suffix .npy: np.save(str(augmented_dir / depth / aug_depth_name), aug_depth) else: cv2.imwrite(str(augmented_dir / depth / aug_depth_name), aug_depth) def apply_augmentation(self, rgb_img, depth_data, aug_type): 应用具体的数据增强技术 # 水平翻转 if aug_type 0: return cv2.flip(rgb_img, 1), cv2.flip(depth_data, 1) # 亮度调整 elif aug_type 1: hsv cv2.cvtColor(rgb_img, cv2.COLOR_BGR2HSV) hsv[:,:,2] hsv[:,:,2] * np.random.uniform(0.8, 1.2) return cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR), depth_data # 添加更多增强技术... return rgb_img, depth_data7. 完整流程整合现在我们将所有步骤整合成一个完整的流程def main(): # 配置参数 target_websites [ https://example.com/nyu-dataset, https://example.com/scannet-data ] output_directory lingbot_depth_dataset max_pages_to_crawl 5 # 创建数据集目录 os.makedirs(output_directory, exist_okTrue) all_rgb_files [] all_depth_files [] # 爬取多个网站 for website in target_websites: print(f开始爬取: {website}) crawler DepthDataCrawler(website, output_directory) rgb_links, depth_links crawler.crawl_website(max_pages_to_crawl) print(f找到 {len(rgb_links)} 个RGB链接和 {len(depth_links)} 个深度链接) # 下载RGB图像 crawler.batch_download(rgb_links, rgb) # 下载深度数据 crawler.batch_download(depth_links, depth) # 数据清洗和配对 cleaner DataCleaner(output_directory) valid_pairs cleaner.clean_invalid_pairs() print(f清洗后剩余 {len(valid_pairs)} 个有效图像对) # 数据标注 annotator DataAnnotator(output_directory) metadata annotator.generate_metadata(valid_pairs) # 数据增强可选 annotator.augment_data(valid_pairs, augmentations3) # 生成数据集统计信息 generate_dataset_report(output_directory, metadata) print(数据集构建完成) def generate_dataset_report(data_dir, metadata): 生成数据集的统计报告 stats { total_pairs: len(metadata), image_resolutions: {}, depth_ranges: [], data_sources: set() } for meta in metadata: res_key f{meta[image_size][width]}x{meta[image_size][height]} stats[image_resolutions][res_key] stats[image_resolutions].get(res_key, 0) 1 stats[depth_ranges].append(meta[depth_range]) stats[data_sources].add(meta.get(data_source, unknown)) # 保存统计报告 report_path os.path.join(data_dir, dataset_report.json) with open(report_path, w) as f: # 转换set为list以便JSON序列化 stats[data_sources] list(stats[data_sources]) json.dump(stats, f, indent2) print(f数据集统计报告已保存至: {report_path}) if __name__ __main__: main()8. 注意事项与最佳实践在构建LingBot-Depth训练数据集时需要注意以下几点遵守版权法规确保你有权使用爬取的数据遵守网站的robots.txt规则数据质量优先宁愿数据量少一些也要保证数据质量多样性很重要收集不同场景、光照条件、相机角度的数据合理的延迟设置在爬取时设置适当的延迟避免给目标网站造成负担错误处理机制实现完善的错误处理和重试机制数据备份定期备份已收集的数据防止意外丢失9. 总结通过本文介绍的Python爬虫技术你可以构建一个高质量、大规模的RGB-D数据集为LingBot-Depth-Pretrain-ViTL-14模型的训练提供充分的数据支持。整个过程涵盖了数据采集、清洗、标注和增强的全流程确保最终数据集的多样性和质量。实际应用中你可能需要根据具体的数据源调整爬虫策略并始终遵守相关的法律法规和道德准则。有了高质量的训练数据LingBot-Depth模型就能更好地学习深度估计任务在各种实际场景中表现出色。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。

相关文章:

使用Python爬虫构建LingBot-Depth-Pretrain-ViTL-14训练数据集

使用Python爬虫构建LingBot-Depth-Pretrain-ViTL-14训练数据集 1. 项目背景与目标 LingBot-Depth-Pretrain-ViTL-14是一个先进的深度估计模型,能够将不完整和有噪声的深度传感器数据转换为高质量、精确度量的3D测量结果。要训练这样的模型,需要大量高质…...

31.命名管道——共享内存

unlink是删除管道文件命名管道,写入方没有open,那么读取方就要阻塞,知道有人打开管道看fifo代码, system v通过共享区和物理内存那块4KB进行映射,这不加载动态库,只映射空间,所以进程A&#xff…...

Junit到Springboot单元测试

第一部分 junit与springboot的前世今生一、junit4与junit5及springboot中的使用在现代软件开发中,单元测试是确保代码质量的重要环节。Spring Boot框架通过整合JUnit,为开发者提供了便捷的单元测试支持。1.1 Spring Boot中JUnit版本的变化在Spring Boot …...

GOM引擎插件加载全解析:从X-FKGOM到X-GOMPJ,如何正确配置登录器与M2插件

GOM引擎插件深度配置指南:从授权管理到功能优化全流程 在传奇私服开发领域,GOM引擎凭借其出色的画面表现和丰富的功能扩展性,已成为众多开发者的首选方案。但真正让GOM引擎从同类产品中脱颖而出的,是其强大的插件系统——通过X-FK…...

新手必看:Qwen-Image-Edit-2511-Unblur-Upscale修复模糊人像全流程详解

新手必看:Qwen-Image-Edit-2511-Unblur-Upscale修复模糊人像全流程详解 1. 为什么你需要这个工具? 你是否遇到过这样的情况:翻看老照片时发现珍贵的人像照片变得模糊不清?或者手机拍摄的照片因为手抖而变得模糊?传统…...

Dify Rerank性能翻倍实录:从0.42到0.89 NDCG提升,我们只改了这4行配置

第一章:Dify Rerank性能翻倍实录:从0.42到0.89 NDCG提升,我们只改了这4行配置在真实生产环境中对 Dify v0.12.3 的 Rerank 模块进行基准测试时,原始配置下对 1,247 条 QA 对的排序结果 NDCG5 仅为 0.42。通过深入分析 reranker 调…...

我把 VS Code 里看依赖版本的插件,做了一个更快的版本

我把 VS Code 里看依赖版本的插件,做了一个更快的版本 平时写 Node.js 项目时,我经常会在 package.json 里看看依赖有没有更新。 之前我一直在用 Version Lens 这类插件,它的体验本身是不错的:打开 package.json,就能直…...

NE2A-SCPU01安全网络控制器

NE2A-SCPU01 安全网络控制器一、产品概述NE2A-SCPU01 是一款工业级安全网络控制器,用于监控和管理工业安全系统。该控制器可集成多个安全设备(如安全传感器、急停开关、安全继电器等),实现安全逻辑运算、故障检测和系统保护&#…...

RV1126准备-----编译和测试SDK自带的RKNN例程

一、SDK自带的RKNN例程介绍位置: SDK自带的RKNN例程位于SDK的external/rknpu/rknn/rknn_api/examples目录下内容: 包含多输入示例、目标检测、批量推理、透传模式、零拷贝等不同功能的示例代码3rdparty目录:CImg: 轻量级C图像处理库,只有一个CImg.h头文件&#xff0…...

Make构建系统原理与嵌入式工程实践

1. Make 构建系统原理与工程实践在嵌入式开发流程中,从源代码到可执行镜像的转化过程包含两个关键阶段:编译(compile)与构建(build)。编译关注单个源文件如何转换为目标文件(如.o)&a…...

(二)传统企业vs数字原生企业:差距到底在数据,还是思维?

传统企业vs数字原生企业:差距到底在数据,还是思维?在上一篇博客《别再误解数字化!企业转型的核心本质,从来不是买软件》里,我们戳破了企业数字化转型的最大误区:把工具采购当成转型核心&#xf…...

如何在Java中使用字符串拼接优化性能

在Java中进行字符串拼接时,选择合适的方式对性能影响很大。由于String对象是不可变的,每次使用拼接都会创建新的String对象,频繁操作会导致大量临时对象,增加GC压力。以下是几种优化字符串拼接性能的方法。1. 使用StringBuilder进…...

Python后台任务不中断:nohup与输出缓冲的实战技巧

1. 为什么需要后台运行Python脚本 我在第一次部署机器学习模型训练任务时,就遇到了一个典型问题:本地SSH连接到远程服务器启动训练后,只要网络波动导致连接断开,训练进程就会立刻终止。这种经历相信不少开发者都遇到过——辛辛苦苦…...

基于T型三电平逆变器的下垂控制:电压电流双闭环与LCL滤波、SPWM调制仿真研究

下垂控制-基于T型三电平逆变器的下垂控制,电压电流双闭环,采用LCL滤波,SPWM调制方式 1.提供simulink仿真源文件 2.提供下垂控制原理与下垂系数计算方法 3.中点平衡控制,电压电流双闭环控制 4.提供参考文献 在现代电力系统中&#…...

从零到部署:我用SeaTable私有云为团队搭建了一个轻量级项目管理系统(附docker-compose.yml配置)

从零构建企业级项目协同平台:基于SeaTable私有云的轻量化实践指南 当团队规模扩张到10人以上时,Excel共享表格开始频繁出现版本冲突,而Jira这类专业工具又显得过于笨重。我们技术团队在尝试了市面上17种协作工具后,最终选择用SeaT…...

三月第三周周报

标题Physics-informed machine learning with embedded sediment rating curve constraints for high-fidelity multi-lead-time forecast of suspended sediment concentration背景作者Yousef Hemmatzadeh , Sadra Shadkani期刊来源Journal of hydrologyDOI10.1016/j.jhydrol.…...

FPGA千兆网硬件设计避坑指南:RTL8211EG布局布线实战经验分享

FPGA千兆网硬件设计避坑指南:RTL8211EG布局布线实战经验分享 在高速数字电路设计中,千兆以太网接口的硬件实现一直是工程师面临的挑战之一。作为FPGA与物理层之间的关键桥梁,RTL8211EG PHY芯片的布局布线质量直接影响着网络通信的稳定性和性能…...

为什么嵌入式开发离不开C语言:底层执行模型与工程实践

1. 项目概述本项目并非硬件设计实体,而是一则面向嵌入式系统工程师与底层开发者的技术科普漫画文档。其核心价值在于以可视化、具象化的方式厘清编程语言演进脉络中C语言的不可替代性,并锚定其在嵌入式领域的真实技术坐标。不同于常规开源硬件项目提供原…...

MCP 2.0生产部署安全熵值评估模型(独家):用3个量化指标预判协议层侧信道泄露风险——仅限首批200位架构师获取

第一章:MCP 2.0生产部署安全熵值评估模型的演进逻辑与核心定位MCP 2.0(Mission-Critical Platform 2.0)在金融与能源等高保障场景中承担着实时决策、多源异构数据融合与自主策略执行的关键职能。其生产部署的安全熵值评估模型并非对传统风险评…...

Kubernetes 入门:从容器到集群管理的全面指南

一、前言在云原生时代,Kubernetes(简称 K8S)已经成为容器编排的事实标准。无论是初创公司还是大型企业,都在积极采用 K8S 来管理和部署他们的应用程序。本文将带你从零开始,系统了解 Kubernetes 的核心概念、架构原理和…...

华为HCIA(华为认证ICT工程师)大纲:从零基础到网络实战的完整指南

1. 华为HCIA认证概述:网络工程师的起点 华为HCIA(华为认证ICT工程师)是华为认证体系中面向初学者的入门级认证,相当于网络工程师行业的"驾照考试"。作为华为认证金字塔的基石,HCIA认证覆盖网络技术、云计算、…...

绩效流于形式?3款HR咨询方案实测对比

一、先上硬参数:三家咨询机构核心信息对比先声明啊,这表是我跟三家机构对接企业客户反馈整理的,没水分,都是实打实的信息:机构名称核心服务模式付费方式咨询师背景售后保障适配企业类型润行咨询结果式咨询陪伴落地按月…...

仓储空间智能基础设施构建路径研究: 融合动态建模与 Pixel-to-Space 的三维空间认知与决策体系(面向“十五五”的关键技术突破与工程应用)

仓储空间智能基础设施构建路径研究 —— 融合动态建模与 Pixel-to-Space 的三维空间认知与决策体系(面向“十五五”的关键技术突破与工程应用) 一、研究背景:迈向空间智能基础设施时代 随着数字经济、智能制造与新型基础设施建设的持续推进…...

SPM新手避坑指南:手把手教你完成fMRI数据预处理(从DICOM到平滑)

SPM新手避坑指南:手把手教你完成fMRI数据预处理(从DICOM到平滑) 当你第一次打开SPM软件准备处理fMRI数据时,是否感到无从下手?作为神经影像分析的基础工具,SPM在学术研究中广泛应用,但其复杂的参…...

FPGA实战:从PWM原理到《欢乐颂》音乐播放器的设计与实现

1. 蜂鸣器与PWM基础原理 第一次接触FPGA驱动蜂鸣器时,我被这个看似简单却充满技术细节的项目深深吸引了。无源蜂鸣器就像个"挑剔的歌手",不给它合适的节奏就绝不开口。这里的关键就在于PWM(脉冲宽度调制)技术&#xff0…...

R语言实战:如何用ggplot2绘制Structure分析的DeltaK折线图

R语言实战:用ggplot2绘制Structure分析的DeltaK折线图 群体遗传学研究中,Structure软件是分析群体结构的经典工具。但如何从多次运行结果中确定最佳K值,一直是研究者面临的挑战。DeltaK方法由Evanno提出,通过计算相邻K值似然值的变…...

STM32F103RCT6+MPU6050实战:手把手教你打造自平衡麦克纳姆轮小车(附PID调参秘籍)

STM32F103RCT6MPU6050实战:从零构建自平衡麦克纳姆轮机器人 当四个麦克纳姆轮在地面划出精确的八字轨迹,车身在倾斜瞬间自动调整转速恢复平衡——这种充满未来感的运动控制,其实用一块30元的STM32开发板就能实现。本文将彻底拆解自平衡麦克纳…...

Jetson Orin NX实战:从零部署YOLOv5的完整环境配置指南

1. Jetson Orin NX与YOLOv5的黄金组合 如果你正在寻找一款能在边缘设备上高效运行目标检测的解决方案,Jetson Orin NX搭配YOLOv5绝对是当前最热门的选择之一。作为NVIDIA最新推出的边缘计算平台,Jetson Orin NX凭借其强大的AI算力和能效比,已…...

基于springboot大数据爬虫二手车管理系统平台设计与开发(源码+精品论文+答辩PPT等资料)

博主介绍:CSDN毕设辅导第一人、靠谱第一人、全网粉丝50W,csdn特邀作者、博客专家、腾讯云社区合作讲师、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交…...

普中51单片机打地鼠游戏开发全流程:从仿真到代码实现(附完整流程图)

普中51单片机打地鼠游戏开发全流程:从仿真到代码实现 记得第一次用51单片机做游戏时,那种看到LED灯随按键亮起的兴奋感至今难忘。打地鼠游戏看似简单,却是学习嵌入式开发的绝佳练手项目——它涵盖了硬件连接、中断处理、随机数生成、状态机设…...