高分二号遥感影像语义分割数据集制作全流程:从预处理到PyTorch加载
1. 项目缘起为什么从零开始制作遥感数据集如果你正在研究遥感图像的语义分割无论是做土地覆盖分类、建筑物提取还是灾害评估大概率会遇到一个共同的瓶颈没有现成的、完全符合你研究需求的标注数据集。公开数据集如ISPRS Vaihingen、Potsdam或者国内的WHU Building Dataset虽然质量很高但它们覆盖的区域、地物类别、影像分辨率往往与你的具体项目目标存在差异。比如你想研究中国北方城市的高分辨率建筑物阴影对分割的影响但公开数据集中可能没有“阴影”这个类别或者影像的时相、季节与你关心的不符。这就是为什么“从原始图像开始制作自己的数据集”成为了许多遥感从业者必须掌握的硬核技能。它不再是可有可无的加分项而是将想法落地为模型、将模型应用于实际场景的关键第一步。这个过程本质上是在为你的AI模型“编写教材”。教材的质量直接决定了学生模型能学到多深、多准。本次我选择以国产的“高分二号”GF-2卫星影像为例。原因有三其一GF-2数据在我国科研和行业中应用广泛具有亚米级的全色和4米级的多光谱分辨率非常适合精细地物提取其二其数据格式和处理流程具有代表性掌握了它再处理其他卫星或航空影像如Sentinel-2、无人机影像也能触类旁通其三从原始“*.tiff”文件到可供模型训练的“图片-标签对”中间涉及遥感特有的预处理和标注技巧这正是新手最容易踩坑的地方。网上有很多教程教你怎么用Labelme标注但很少告诉你一张原始的GF-2影像在导入Labelme之前需要经过哪些必不可少的处理。直接对原始16位数据或拼接异常的图像进行标注后期训练时轻则精度上不去重则直接报错。接下来我将完整复盘一次从GF-2原始数据到Pytorch可读数据集的实战流程重点分享那些在官方文档里找不到的“坑”与“技巧”。2. 高分二号数据解码与预处理从原始包到标准图像拿到GF-2的原始数据包通常是一堆包含PAN.tiff和MUL.tiff的文件夹第一步不是急着打开标注软件而是进行规范的预处理。这一步的目标是得到视觉清晰、数值范围合理、且已经完成几何校正的RGB真彩色图像。2.1 理解GF-2数据源结构一个标准的GF-2数据产品通常包含全色波段文件后缀如*_PAN.tiff空间分辨率约0.8米但只有一个灰度波段包含丰富的纹理和细节信息。多光谱波段文件后缀如*_MUL.tiff包含蓝、绿、红、近红外四个波段分辨率约3.2米。我们的目标通常是生成一份融合后的、具有高空间分辨率和真彩色信息的数据。但请注意对于语义分割初期的标注工作我强烈建议先使用多光谱波段合成的真彩色图像进行标注。原因在于全色与多光谱融合如Pansharpening虽然能提升视觉效果但会引入光谱畸变对于需要严格依赖光谱特征进行分类的模型尤其是初期实验可能不利。先用分辨率稍低但光谱保真度高的图像确定地物边界和类别是更稳妥的做法。2.2 关键预处理步骤与实操代码使用Python的rasterio和numpy库可以高效完成预处理。假设我们有一个多光谱文件GF2_MUL.tiff。import rasterio import numpy as np from matplotlib import pyplot as plt # 步骤1读取多光谱数据 with rasterio.open(GF2_MUL.tiff) as src: # 读取蓝、绿、红三个波段索引通常是1,2,3但务必以实际情况为准 blue src.read(1) green src.read(2) red src.read(3) profile src.profile # 保存元数据如坐标系、变换参数等 # 步骤2数据拉伸与增强显示 # GF-2的原始DN值范围可能很大如0-10000直接显示是一片黑。 # 我们需要将其线性拉伸到0-255的8位范围以便于肉眼观察和标注。 def stretch_band(band, lower_percent2, upper_percent98): # 去除极端值按百分比截断 lower np.percentile(band[band0], lower_percent) # 忽略0值可能是背景 upper np.percentile(band[band0], upper_percent) band_stretched np.clip(band, lower, upper) # 截断 # 线性归一化到0-255 band_stretched ((band_stretched - lower) / (upper - lower) * 255).astype(np.uint8) return band_stretched red_8bit stretch_band(red) green_8bit stretch_band(green) blue_8bit stretch_band(blue) # 步骤3合成RGB图像并保存 rgb_image np.stack([red_8bit, green_8bit, blue_8bit], axis-1) # 使用matplotlib保存或使用rasterio保存为GeoTIFF保留地理信息 plt.imsave(GF2_RGB_visual.jpg, rgb_image) # 如果需要保留地理信息用于后续GIS分析用rasterio保存 profile.update({ driver: GTiff, count: 3, # 波段数改为3 dtype: uint8 }) with rasterio.open(GF2_RGB_geo.tiff, w, **profile) as dst: dst.write(red_8bit, 1) dst.write(green_8bit, 2) dst.write(blue_8bit, 3)注意这里有一个至关重要的细节。np.percentile计算时我加入了[band0]的条件。这是因为许多遥感图像边缘或无效区域填充值为0如果把这些0值纳入统计会严重拉低有效像素的统计值导致拉伸后图像整体发白、对比度不足。这个处理能显著提升图像的视觉可用性。预处理后的GF2_RGB_visual.jpg就是我们标注工作的底图。确保它在图像查看器中打开时地物清晰、色彩自然没有大片的黑色或白色异常区域。3. 使用Labelme进行语义分割标注策略与效率提升有了清晰的底图就可以开始标注了。Labelme是一款非常灵活的工具但用于遥感语义分割需要一些特定的设置和技巧。3.1 Labelme的安装与初始配置安装很简单pip install labelme即可。但安装后我建议先进行两项配置创建预定义的标签列表在项目根目录创建一个labels.txt文件按行写入你的类别例如__ignore__ _background_ 水体 植被 建筑物 道路 裸土__ignore__和_background_是Labelme的保留标签分别表示忽略区域和背景。启动Labelme时通过--labels参数指定该文件labelme --labels labels.txt。这能避免手动输入标签时的拼写错误保证类别一致性。调整标注习惯遥感图像通常很大而Labelme默认视图可能不便于浏览。多用鼠标滚轮缩放用空格键拖拽画布。对于大范围连续地物如大片农田用“多边形”工具勾勒边界比用“矩形”或“圆形”更精确。3.2 针对遥感场景的标注实战技巧技巧一分级标注与“空洞”处理标注建筑物时如果中间有庭院不要画一个包含庭院的多边形。正确做法是先沿建筑物外轮廓画一个多边形标签为“建筑物”然后在庭院区域再画一个多边形标签选择“ignore”或“其他类别”。这样在生成掩膜时庭院部分会被正确处理为“非建筑物”而不是被外轮廓填充成建筑物。技巧二利用低分辨率先标再细化对于非常大的影像可以先降低分辨率进行快速、粗略的标注划定大致的区域和类别。然后再放大到原图分辨率对边界进行精细修正。这比一开始就追求像素级精度效率高得多。技巧三边界模糊地物的处理对于植被与裸土、水体与湿地的过渡带边界往往是渐变的。我的经验是根据你的应用定义明确的边界规则。例如规定“当植被覆盖度低于30%时视为裸土”。在标注时就在你认为符合这个规则的位置画线。保持同一类别标注标准的一致性比追求绝对“正确”的边界更重要。标注完成后每个图像会生成一个同名的.json文件。这个文件包含了所有多边形顶点的坐标和对应的标签。3.3 从Labelme JSON到语义分割掩膜Labelme本身提供了将JSON转换为分割掩膜的脚本但我们需要一个更适合深度学习训练的版本。以下脚本将每个类别的多边形转换为一个单通道的灰度图其中像素值等于类别ID。import json import numpy as np import cv2 import os from PIL import Image def json_to_mask(json_file, label_list, output_dir): 将Labelme的json文件转换为语义分割掩膜图像。 :param json_file: Labelme生成的json文件路径 :param label_list: 标签列表如[_background_, 水体, 植被, 建筑物, 道路, 裸土] :param output_dir: 掩膜输出目录 with open(json_file, r) as f: data json.load(f) image_height data[imageHeight] image_width data[imageWidth] # 创建全零掩膜背景默认为0 mask np.zeros((image_height, image_width), dtypenp.uint8) for shape in data[shapes]: label_name shape[label] # 查找标签对应的ID try: label_id label_list.index(label_name) except ValueError: print(f警告在label_list中未找到标签 {label_name}已跳过。) continue # 将多边形点列表转换为OpenCV格式 points np.array(shape[points], dtypenp.int32) # 使用cv2.fillPoly填充多边形填充值为label_id cv2.fillPoly(mask, [points], colorlabel_id) # 保存掩膜 mask_filename os.path.basename(json_file).replace(.json, _mask.png) mask_path os.path.join(output_dir, mask_filename) Image.fromarray(mask).save(mask_path) print(f掩膜已保存至{mask_path}) # 使用示例 label_list [_background_, 水体, 植被, 建筑物, 道路, 裸土] json_file GF2_RGB_visual.json output_dir ./masks os.makedirs(output_dir, exist_okTrue) json_to_mask(json_file, label_list, output_dir)关键提示保存掩膜时务必使用PNG等无损格式绝对不要用JPEG。JPEG的有损压缩会在掩膜边缘产生噪声和模糊导致类别标签错误对训练是灾难性的。另外掩膜是单通道的灰度图每个像素的值就是其类别索引这与PASCAL VOC等标准数据集的格式一致。4. 构建PyTorch数据集类与数据增强策略现在我们有了images文件夹存放GF2_RGB_visual.jpg和masks文件夹存放对应的_mask.png。下一步是创建一个PyTorch的Dataset类来加载它们并实施针对遥感数据的数据增强。4.1 自定义数据集类遥感图像通常很大例如5000x5000像素无法直接送入网络。我们需要将其裁剪成固定大小的小块如256x256或512x512。import torch from torch.utils.data import Dataset, DataLoader from PIL import Image import os import random class RemoteSensingDataset(Dataset): def __init__(self, images_dir, masks_dir, crop_size256, transformNone): self.images_dir images_dir self.masks_dir masks_dir self.crop_size crop_size self.transform transform # 获取所有图像文件名假设图像和掩膜文件名一一对应 self.image_filenames [f for f in os.listdir(images_dir) if f.endswith((.jpg, .png, .tiff))] # 预计算对于每张大图可以生成多少个裁剪块 self.samples [] # 每个元素是 (图像路径, 掩膜路径, 裁剪起始点y, x) for img_name in self.image_filenames: img_path os.path.join(images_dir, img_name) mask_name img_name.replace(.jpg, _mask.png) # 根据你的命名规则调整 mask_path os.path.join(masks_dir, mask_name) if not os.path.exists(mask_path): continue with Image.open(img_path) as img: width, height img.size # 以固定步长滑动窗口例如步长为crop_size/2实现重叠裁剪增加数据量 stride self.crop_size // 2 for y in range(0, height - self.crop_size 1, stride): for x in range(0, width - self.crop_size 1, stride): self.samples.append((img_path, mask_path, y, x)) # 如果希望随机裁剪可以在这里打乱self.samples random.shuffle(self.samples) def __len__(self): return len(self.samples) def __getitem__(self, idx): img_path, mask_path, y_start, x_start self.samples[idx] # 打开图像和掩膜并裁剪 with Image.open(img_path) as img, Image.open(mask_path) as mask: box (x_start, y_start, x_start self.crop_size, y_start self.crop_size) image_crop img.crop(box) mask_crop mask.crop(box) # 确保图像为RGB掩膜为L灰度 image_crop image_crop.convert(RGB) mask_crop mask_crop.convert(L) # 转换为numpy数组/Tensor image np.array(image_crop, dtypenp.float32) / 255.0 # 归一化到[0,1] mask np.array(mask_crop, dtypenp.int64) # 标签保持整数 # 应用额外的变换如数据增强 if self.transform: augmented self.transform(imageimage, maskmask) image augmented[image] mask augmented[mask] # 转换维度图像从 HWC 转为 CHW image torch.from_numpy(image).permute(2, 0, 1).float() mask torch.from_numpy(mask).long() return image, mask # 使用albumentations库进行数据增强 import albumentations as A from albumentations.pytorch import ToTensorV2 # 定义训练和验证阶段的变换 train_transform A.Compose([ A.HorizontalFlip(p0.5), A.VerticalFlip(p0.5), A.RandomRotate90(p0.5), A.RandomBrightnessContrast(brightness_limit0.1, contrast_limit0.1, p0.3), # 对于遥感数据谨慎使用色彩抖动可能破坏光谱特征 # A.HueSaturationValue(hue_shift_limit10, sat_shift_limit15, val_shift_limit10, p0.3), A.Normalize(mean(0.485, 0.456, 0.406), std(0.229, 0.224, 0.225)), # ImageNet统计量常用 ToTensorV2(), ]) val_transform A.Compose([ A.Normalize(mean(0.485, 0.456, 0.406), std(0.229, 0.224, 0.225)), ToTensorV2(), ]) # 创建数据集和数据加载器 train_dataset RemoteSensingDataset(./images/train, ./masks/train, crop_size256, transformtrain_transform) val_dataset RemoteSensingDataset(./images/val, ./masks/val, crop_size256, transformval_transform) train_loader DataLoader(train_dataset, batch_size8, shuffleTrue, num_workers4, pin_memoryTrue) val_loader DataLoader(val_dataset, batch_size8, shuffleFalse, num_workers4, pin_memoryTrue)4.2 遥感数据增强的特别考量与自然图像不同遥感数据增强需要更小心几何增强是安全的水平/垂直翻转、90度旋转、小角度随机旋转对于大多数地物除具有方向性的如阴影都是有效的不会改变语义。光谱/色彩增强需谨慎亮度、对比度调整可以模拟不同光照条件但调整幅度不宜过大。色相/饱和度调整HueSaturationValue我通常不建议使用因为遥感地物的光谱反射特征是关键的分类依据随意改变色相可能将植被变成非植被导致模型学习到错误特征。归一化参数示例中使用了ImageNet的均值和标准差。这对于使用在ImageNet上预训练的骨干网络如ResNet是常见的。如果你的数据分布与自然图像差异极大可以计算自己数据集的统计量进行替换。5. 类别不平衡处理与数据集划分验证制作数据集最后也是至关重要的一步是检查数据质量并处理类别不平衡问题。5.1 分析类别分布在投入训练前运行一个脚本统计所有掩膜中各类别的像素比例。from collections import Counter import numpy as np from tqdm import tqdm def analyze_class_distribution(masks_dir, label_list): pixel_counter Counter() total_pixels 0 mask_files [f for f in os.listdir(masks_dir) if f.endswith(.png)] for mask_file in tqdm(mask_files, desc分析类别分布): mask_path os.path.join(masks_dir, mask_file) mask np.array(Image.open(mask_path)) pixels mask.flatten() pixel_counter.update(pixels) total_pixels len(pixels) print(\n 类别像素分布统计 ) for label_id, label_name in enumerate(label_list): count pixel_counter.get(label_id, 0) percentage (count / total_pixels) * 100 print(f{label_name} (ID:{label_id}): {count:,} 像素, 占比 {percentage:.2f}%) return pixel_counter label_list [_background_, 水体, 植被, 建筑物, 道路, 裸土] pixel_stats analyze_class_distribution(./masks/train, label_list)如果发现“建筑物”占比5%“背景”占比80%这就是严重的类别不平衡。直接训练会导致模型倾向于预测背景对小类别物体视而不见。5.2 应对类别不平衡的策略损失函数层面使用加权交叉熵损失Weighted Cross-Entropy Loss或Focal Loss。根据类别频率的倒数或中位数频率平衡法为每个类别分配权重。# 计算类别权重中位数频率平衡 class_freq np.array([pixel_stats[i] for i in range(len(label_list))]) median_freq np.median(class_freq[class_freq 0]) # 忽略频率为0的类 class_weights median_freq / class_freq class_weights[class_freq 0] 0 # 频率为0的类权重设为0 class_weights torch.tensor(class_weights, dtypetorch.float32) criterion nn.CrossEntropyLoss(weightclass_weights)数据采样层面在RemoteSensingDataset的__getitem__中不是均匀地滑动窗口裁剪而是设计一个“智能裁剪”策略。例如优先选择包含稀有类别如建筑物中心的图像块。这需要预先计算每个可能裁剪块中各类别的像素比例构建一个采样权重图。数据增强层面对稀有类别进行针对性的增强如对建筑物区域使用更强的随机裁剪、旋转确保仍在图像内以增加其样本的多样性。5.3 数据集划分的陷阱千万不要简单地按文件顺序划分训练集和验证集如果原始影像是连续的一大片区域按顺序划分会导致验证集和训练集来自空间上相邻的区域其地物特征、光照条件高度相似这会使验证集分数虚高无法代表模型在全新区域上的泛化能力。正确做法空间分离如果有多景不连续的影像直接以“景”为单位划分。区块划分如果只有一景大图先将其切割成多个不重叠的大区块如1024x1024然后随机将这些大区块分配给训练集和验证集。确保训练和验证的样本在空间上是隔离的。最后在开始训练之前务必人工抽查一些(image_crop, mask_crop)样本对用可视化工具如matplotlib叠在一起查看确保图像和掩膜对齐无误标签ID正确映射。这个简单的检查能避免因预处理脚本bug导致的数天无效训练。从一颗卫星的原始数据包到一份规整的、可供深度学习模型消费的数据集这个过程充满了琐碎的细节。但每一步的严谨都直接关系到最终模型性能的上限。亲手制作数据集虽然耗时但它让你对数据的每一个像素都了如指掌在模型调优和错误分析时这种掌控感是无价的。当你看到模型在你亲手标注的数据上准确识别出每一栋建筑、每一片水体时你会觉得这一切的繁琐都是值得的。

相关新闻

Java大厂面试技巧:从基础到源码的深度解析

Java大厂面试技巧:从基础到源码的深度解析

1. 项目背景与核心价值最近在技术社区看到一个很有意思的Java面试模拟项目——"严肃面试官x搞笑水货谢飞机"的角色扮演式面试实录。这个项目通过戏剧化的方式还原了Java大厂真实的三轮技术面试场景,既有严谨的技术追问,又有轻松幽默的互动&…

2026/8/23 20:51:55 阅读更多 →
整数规划与非线性规划:数学建模核心工具的原理与应用实战

整数规划与非线性规划:数学建模核心工具的原理与应用实战

1. 项目概述:从“规划”到“建模”的思维跃迁很多刚接触数学建模的朋友,一看到“整数规划”、“非线性规划”这些词,第一反应可能就是翻开教材,去记那些复杂的数学符号和定理。这其实是一个误区。在我十多年的建模和指导经历中&am…

2026/8/23 20:51:55 阅读更多 →
X3D:高效视频动作识别的多维扩展架构解析

X3D:高效视频动作识别的多维扩展架构解析

1. 引言:从2D到3D,视频理解效率的永恒挑战在计算机视觉领域,动作识别或者说视频理解,一直是个让人又爱又恨的难题。爱的是,它能让机器看懂我们生活的动态世界,从安防监控到内容审核,从人机交互到…

2026/8/23 20:51:55 阅读更多 →

最新新闻

AI如何读取网页链接:从curl到Playwright的技术原理与实战验证

AI如何读取网页链接:从curl到Playwright的技术原理与实战验证

1. 引言:一个看似简单却暗藏玄机的问题“给Claude一个链接,它真的读了原文吗?” 这个问题乍一看,像是刚接触AI助手的新手会提出的疑问,带着一丝好奇和试探。但作为一名和各类大模型打了多年交道的从业者,我…

2026/8/23 21:33:27 阅读更多 →
Linux循环设备busy错误排查:losetup命令原理与解决方案详解

Linux循环设备busy错误排查:losetup命令原理与解决方案详解

1. 问题引入:当循环设备“忙”起来在Linux系统管理或者日常开发运维中,处理磁盘镜像、创建加密卷、或者挂载ISO文件时,losetup命令是我们的得力助手。它就像一个“虚拟光驱”的管理员,能将一个普通的文件(比如一个.img…

2026/8/23 21:33:27 阅读更多 →
前端面试实战:从八股文到场景化解决方案

前端面试实战:从八股文到场景化解决方案

1. 前端面试新趋势:从八股文到实战场景春节假期结束,金三银四的招聘季悄然拉开序幕。作为一名经历过多次招聘季的前端工程师,我明显感受到今年面试风向的变化——那些曾经被我们反复背诵的闭包、原型链、事件循环等八股文知识点,如…

2026/8/23 21:33:27 阅读更多 →
DeepSeek Harness:可组合插件运行时如何重塑AI应用架构

DeepSeek Harness:可组合插件运行时如何重塑AI应用架构

1. 项目概述:从“单体巨人”到“积木世界”的范式转移最近在AI工程化领域,一个名为“DeepSeek Harness”的项目引起了我的注意。乍一看标题“可组合的插件运行时”,可能觉得又是一个技术概念包装,但当你真正深入其设计哲学&#x…

2026/8/23 21:33:27 阅读更多 →
大模型Agent面试攻略:技术栈与实战解析

大模型Agent面试攻略:技术栈与实战解析

1. 项目概述:大模型Agent面试攻略的价值解析最近半年,大模型Agent岗位的招聘热度持续攀升。据我观察,阿里这类头部科技公司的大模型相关岗位,平均每个职位能收到300份简历,但真正能通过技术面试的候选人不足10%。这份面…

2026/8/23 21:33:27 阅读更多 →
嵌入式名企全解析:从芯片原厂到终端巨头的职业地图

嵌入式名企全解析:从芯片原厂到终端巨头的职业地图

1. 从“嵌入式名企”这个问题的背后说起最近在几个技术社区和社群里,经常看到有朋友在问:“嵌入式名企有哪些?” 这个问题看似简单,背后却藏着很多刚入行或者准备转行嵌入式的朋友最真实的困惑和焦虑。他们可能刚学完C语言和单片机…

2026/8/23 21:32:25 阅读更多 →

日新闻

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/23 0:00:50 阅读更多 →
SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/23 0:00:50 阅读更多 →
Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/23 0:00:50 阅读更多 →

周新闻

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/23 0:00:50 阅读更多 →
SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/23 0:00:50 阅读更多 →
Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/23 0:00:50 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/23 18:47:06 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/23 12:10:44 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/22 3:22:48 阅读更多 →