news 2026/9/16 5:39:39

零标注遥感分割保姆级教程:SAM 3与SegEarth-OV3实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
零标注遥感分割保姆级教程:SAM 3与SegEarth-OV3实战

搞遥感分割的朋友应该都体会过这个痛:标注一张高分影像的成本,基本可以劝退大多数个人开发者和中小团队。建筑物轮廓、农田地块、水体边界,这些都得有人拿着标注工具一点一点抠,一个几千像素的目标,抠下来半小时起步。正因如此,我一直很关注“不用标注怎么做分割”这个方向。

前阵子折腾完 SegEarth-OV3 和 SAM 3 这套组合之后,我最大的感受是:零标注做遥感分割这件事,真的已经从实验室概念变成了可以上手的操作流程。SAM 3 是分割基础模型的新版本,官方在语义分割和实例分割上表现又往前推了一截;SegEarth-OV3 则是一套专门针对遥感场景的开放性评估协议,把“能不能不打标签直接分割”这件事拆成了可量化的步骤。

这篇文章我不打算讲太多理论,就把我这两天完整跑通的流程整理成保姆级教程,从环境配置到数据准备,从提示词采样到后处理导出,每个环节的坑我都踩了一遍,顺手记录下来了。不管你是刚开始接触遥感分割,还是已经用过 SAM 系列想迁移到遥感场景,这篇应该都能帮你省下不少弯路。

1. 整体思路拆解:为什么零标注遥感分割能成立

先把这个事儿的底层逻辑说清楚,不然你照着步骤跑完也不知道自己在调什么。

1.1 传统遥感分割为何“贵”

以前做遥感影像分割,路径基本是:收集影像、人工标注、训练模型、推理预测。问题出在前两步,影像可以批量下载,标注却完全依赖人力。

遥感图像的标注和自然图像不一样,自然图里一个“人”就是一个框或一条边,遥感图里一栋房子、一块田地,边缘往往模糊,有阴影遮挡,有光谱混淆。标注一个类别,东一块西一块,质量还要经过二次审核。五个类别的标注数据集,投入两三个人力,做一个月是常有的事。这份成本摆在这里,大量细分场景根本凑不出像样的训练集。

这也是为什么我一直留意零样本分割方向。如果模型本身已经具备“什么东西都能分”的能力,我们为什么还要为每个新场景重新造一套标注数据?

1.2 SAM 3 做了什么升级

SAM 系列的核心思路是用海量掩膜数据预训练一个通用分割模型。输入一张图,再输入一些提示(点、框或者文本),模型输出对应目标的掩膜。SAM 3 在同一条路线上继续升级,模型的架构做了优化,提示的理解能力更强,对边界模糊的目标分割结果更干净。

放在遥感场景里,这意味着很多以前需要针对性训练的类别——建筑物、道路、裸地、林地——现在可以直接被 SAM 3 “一次到位”地区分出来。你不需要为它准备任何训练样本,它本身就已经是“训练好了的”通用分割器。

1.3 SegEarth-OV3 补上最后一块拼图

但通用分割模型有一个实际问题:它会分,但它不知道你想分什么。一张影像丢进去,模型能输出成千上万个潜在目标的掩膜,到底哪个是你要的房子,哪个是背景里的空地?如果靠人工在图上点来点去提示,在大范围遥感影像上效率还是太低。

SegEarth-OV3 解决的正是这个问题。它提供了一套在遥感场景下的提示采样、推理编排和结果评估流程。简单来说,就是让 SAM 3 在大幅遥感影像上自动生成候选分割掩膜,再用类别信息或者规则过滤,最终把“模型能力”转成“实际可用结果”。这套协议是从遥感影像和地物特性出发设计的,对大幅面的拼接处理、小目标密集地物的提示密度都做了适配。

所以这套组合的逻辑闭环是:SAM 3 负责通用分割能力,SegEarth-OV3 负责遥感场景编排,两边一接,标注成本归零。

2. 环境准备:硬件要求与依赖清单

先把环境搞定,跑模型最烦的就是环境问题。

2.1 显存和算力的实测参考

先泼一盆冷水:零标注不等于零算力。SAM 3 这类基础模型参数量在那里摆着,不可能像以前训练个小 Unet 一样随便找块显卡都能跑。

我这边的实测环境是一张 RTX 4090(24GB 显存),在 1024×1024 的影像块上推理,单块耗时约 1.5 到 2.5 秒,具体取决于目标数量。如果你手上是 16GB 显存的显卡,比如 4080、V100 16G,也能跑,但建议把影像切成 512×512 的块,防止显存溢出。8GB 显存也不是完全没戏,可以用 CPU 推理做兜底,但速度会让人比较着急,体验差很多。

如果你只是想在缺少显卡的机器上快速验证效果,可以先下载官方提供的小权重版本,占用的显存大约能降到 6GB 左右,适合跑通流程,正式处理再用完整权重。

2.2 依赖库安装与权重下载

我是在 Linux 服务器上跑的,Windows 下流程基本一致,只是路径写法注意区分。核心依赖如下:

# Python 3.10 以上版本 conda create -n sam3 python=3.10 -y conda activate sam3 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121 pip install opencv-python pillow numpy rasterio geopandas fiona shapely

rasterio 和 geopandas 这两个是为了读遥感影像和导出矢量结果,实际处理矢量导出时还要用到 fiona。如果安装 geopandas 遇到依赖冲突,建议用 conda 统一安装:

conda install -c conda-forge geopandas rasterio

SAM 3 的代码和权重需要从官方仓库获取。不同版本的名称略有差异,你只需要在仓库的 Release 页面里找到对应版本的权重文件下载即可。以我这次用的版本为例,模型权重文件名大致是 sam3_vit_h.pth,体积在 2.5GB 左右。下载后放在项目目录下的 weights 文件夹里,后边调用直接指定路径。

提示:下载权重时一定注意检查文件大小是否和页面标注一致。我之前遇到过下载到一半中断但系统没报错的情况,结果加载权重时报错“unexpected key in state_dict”,排查了很久才发现是文件不完整。

环境准备好之后,建议先跑一个最小测试:加载模型 + 推理一张普通照片,确认整个链路没问题,再进遥感数据。这一步能帮你区分后续报错是环境问题还是遥感数据处理的问题。

3. 保姆级实操:从影像到矢量结果的完整流程

这个环节我按完整的处理链路来说,每一步都附上代码和思路解释。整体链路是:读影像 → 切块 → 生成提示 → SAM 3 推理 → 掩膜清洗 → 拼接导出。

3.1 读取大幅遥感影像

遥感影像和普通照片的区别在于:尺寸大、通道多、带地理坐标。普通的 OpenCV 直接读,会丢掉地理信息,后边导出的时候坐标就对不上了。

我习惯用 rasterio 读影像,它能把像素坐标和地理坐标绑定在一起:

import rasterio from rasterio.windows import from_bounds src = rasterio.open("sample_area.tif") print(src.crs) # 坐标系信息,比如 EPSG:32650 print(src.transform) # 仿射变换参数 print(src.width, src.height) # 影像宽高 img = src.read([1, 2, 3]) # 取 RGB 三个波段 # 转成 HWC 顺序,并归一化到 0-255 img = img.transpose(1, 2, 0) img = img[:, :, ::-1] # BGR 转 RGB,根据你的源数据情况决定是否需要

如果你的影像是多光谱的,不要直接把所有波段喂给模型。SAM 3 预训练时用的是三通道自然图像,多出来的波段对模型来说反而是干扰。建议通过主成分分析或者直接选 R、G、B 三个波段合成真彩色图。

3.2 影像切块与重叠处理

SAM 3 虽然能处理大图,但遥感影像动辄上万像素宽,直接整张塞进去,显存必然爆掉。而且大图上的目标太小,模型容易漏检。我的做法是切块处理,同时设置重叠区域。

def split_image_into_tiles(img, tile_size=1024, overlap=128): h, w = img.shape[:2] tiles = [] step = tile_size - overlap for y in range(0, h, step): for x in range(0, w, step): y_end = min(y + tile_size, h) x_end = min(x + tile_size, w) tile = img[y:y_end, x:x_end] # 边缘块可能不足尺寸,用 padding 补足 pad_y = tile_size - tile.shape[0] pad_x = tile_size - tile.shape[1] if pad_y > 0 or pad_x > 0: tile = cv2.copyMakeBorder( tile, 0, pad_y, 0, pad_x, cv2.BORDER_CONSTANT, value=(0, 0, 0) ) tiles.append((x, y, tile)) return tiles

切块的时候重叠区域设置多大,我建议是 128 到 256 像素。重叠的意义在于:如果目标恰好跨在切块边界上,模型可能在两个块里各分割出一半,后边拼接就要做去重合并。没有重叠的话,跨边界的目标可能直接在接缝处断开,后期很难补。

3.3 自动提示采样:让模型知道该分谁

这是零标注流程里最核心的一步。提示采样的质量直接决定了最后分割结果的完整性。

最基本的思路是网格采样。在影像上均匀撒点,每个点都作为一个提示送入模型,SAM 3 会为每个点返回最有可能包含该点的目标掩膜。网格密度越高,小目标越不容易漏,但推理耗时会线性增加。我这边的经验值:

  • 中高分辨率影像(0.3m-1m),建筑物为主,网格间距 32-48 像素,效果比较稳。
  • 大范围低分辨率影像(10m 以上),地物以大块为主,网格间距可以放到 80-120 像素。
  • 目标密集的城区,建议 24-32 像素,宁多勿漏。
def build_grid_prompt(img_shape, step=32): h, w = img_shape[:2] points = [] # 从 step//2 开始,避免所有点都落在边缘 for y in range(step // 2, h, step): for x in range(step // 2, w, step): points.append([x, y]) labels = [1] * len(points) # 1 表示前景点,0 表示背景点 return points, labels

这里有一个我自己踩过的坑:网格点不能从 0 开始,而是从 step//2 开始。如果从 0 开始,每行每列的第一个点都贴在图块边缘,SAM 3 对边缘点的处理不太稳定,有时候会返回空的预测结果。用半偏移采样可以让点均匀分布在网格中心,采样覆盖更合理。

还有一种增强方式是把点都映射到梯度较大的位置,也就是影像变化剧烈的区域。用 OpenCV 的 Canny 边缘检测或 Sobel 梯度幅度做引导,选择在边缘附近的点作为提示。这样做的好处是提示集中在地物边界区域,掩膜边界质量更高。不过这种采样方式对参数敏感,实际操作时我建议先用均匀网格跑一版,发现问题再考虑梯度引导。

3.4 推理:批量调用模型

SAM 3 的推理接口接收图像、提示点和标签,输出目标掩膜及置信度。以我实现的流程为例:

from sam3 import Sam3 model = Sam3("weights/sam3_vit_h.pth") model.to("cuda") def predict_tile(model, tile, points, labels): masks, scores = model.predict( image=tile, point_coords=points, point_labels=labels, multimask_output=True ) return masks, scores

multimask_output 这个参数值得展开说一下。开启后,模型为每个提示点返回多个候选掩膜,比如一个完整的目标、一个只包含核心区域的目标,还有一个包含周边扩展区域的目标。三个候选里哪个是对的,模型会给出置信度分数。SegEarth-OV3 的默认策略是选择置信度最高的那个掩膜,如果后续做类别过滤,可以把三个都保留,让后续筛选自己选。

处理大幅面时,建议每跑完一类地物的提示后,立即把掩膜存成临时文件,不要把所有结果都堆在内存里。我处理一个 2 万乘 2 万的区域,光掩膜文件就占了好几 GB,不落地迟早把内存打满。

3.5 掩膜清洗与拼接

模型输出的原始掩膜是“像素级布尔数组”,是单块范围的。在拼接前,必须先做几步清洗:

  1. 去掉面积过小的连通域,这些大多是噪声。面积阈值根据地物类型设定,建筑物一般小于 20 个像素的可以直接干掉。
  2. 去掉置信度过低的掩膜。SegEarth-OV3 里一般把置信度阈值设在 0.8 左右,低于这个值的掩膜可靠性差。
  3. 对同一目标产生多个掩膜的情况,用 IoU 去重。两个掩膜的 IoU 大于 0.7,就认为它们指向同一个目标,保留置信度高的那个。

清洗完的掩膜,按切块时的坐标位置拼回整幅影像范围。重叠区域的掩膜通过取并集或者取置信度较高的结果,这里我建议用置信度加权融合,过渡更自然。

def merge_masks_tile(masks, scores, x_offset, y_offset, full_size, min_iou=0.7): # 先做连通域分析,提取每个掩膜中的独立目标 # 再按坐标偏移写入全图掩膜数组 pass

这一步的函数实现很简单,我就不贴完整代码了,说下几个容易出错的位置:坐标偏移算错、边界同步不一致、Mask 的尺寸和原图没对上。每次拼接完后,务必可视化叠加检查一遍。

3.6 导出矢量结果并配准坐标

最后一步是把掩膜转成矢量,并写入地理坐标系,这样 GIS 软件里才能直接用。

import geopandas as gpd from shapely.geometry import shape from rasterio.features import shapes as rio_shapes import numpy as np def mask_to_vector(mask, transform, crs): results = [] for geom, value in rio_shapes(mask.astype(np.uint8), mask=mask, transform=transform): if value == 1: results.append(shape(geom)) gdf = gpd.GeoDataFrame({"geometry": results}, crs=crs) return gdf gdf = mask_to_vector(binary_mask, src.transform, src.crs) gdf.to_file("output_water.shp")

这里必须强调 transform 和 crs 一定要用 rasterio 打开原始影像时获取的那份,不能自己推断。我见过不少人在这步直接给了默认坐标系,导出的 Shapefile 在 ArcGIS 里叠到卫星影像上全部错位,浪费了大半天排查。

4. 提示词设计与精度调优技巧

零标注分割看起来是“点一下就跑”,实际要得到好的效果,需要在提示和参数层面反复打磨。下面这几个点是影响遥感分割精度最直接的因素。

4.1 提示点密度:不是越多越好

提示点密度和分割精度的关系,并不完全是线性的。点太密,一是耗时成倍增长,二是相邻点会让模型产生大量重叠掩膜,去重阶段处理复杂度飙升。

我在农田地块分割场景测试过一组对比实验:在同一个测试区域使用 16 像素、32 像素、64 像素三种网格密度。16 像素网格耗时最高,但和多类别场景里的小地块分割相比,效果不一定优于 32 像素;64 像素网格虽然快,但小块田之间的窄边界经常被跳过,导致地块合并。最后我采取的是分块变密度策略:用边缘检测生成梯度图,梯度强的区域用 24 像素密度,梯度弱的区域用 64 像素密度。效果和均匀 24 像素基本接近,但推理时间缩短了约 40%。

这套思路很实用,你在自己的数据上也可以试一试。

4.2 置信度阈值调整策略

掩膜的置信度阈值直接影响输出结果的干净程度。阈值设高了,漏掉一部分目标;阈值设低了,会混入大量背景碎片。

SegEarth-OV3 里默认建议是 0.8,但实际应用中要根据地物类型灵活调整:

  • 建筑物轮廓清晰,与背景差异大,置信度通常很高,阈值 0.85 以上没压力。
  • 水体边缘过渡缓慢,模型给出的置信度偏低,可以把阈值降到 0.75。
  • 林地与草地边界模糊,阈值建议 0.7,宁可多保留,在后续矢量化阶段再人工筛选。

这里我建议先跑一个小候选区域,用不同阈值分别导出,在 GIS 里目视比较一遍,确定最佳值再全量跑,避免浪费算力。

4.3 提示框与文本提示的互补用法

虽然 SegEarth-OV3 主打的是点提示自动采样,但在实际使用中,有些场景确实需要手工干预。

比如一个区域内只想要某一类目标,自动网格采样会分出所有目标,这时候可以画一个框限定范围,把框坐标交给模型,只对框内做密集采样。又比如某些非常特殊的场景,比如识别某个特定形状的目标,可以用文本提示试试,SAM 3 的文本理解能力比前代更强,虽然不保证每个遥感类别都认识,但值得一试。

我用下来觉得最合理的策略是:先用网格点提示跑全图,得到所有候选掩膜;再用一个简单的分类器(或者人工抽样确认)筛选类别;最后对不确定的区域人工撒点补漏。有选择地干预,效率最高。

4.4 大幅面场景的内存调度

大幅面影像处理时,最怕的不是分割效果差,而是跑到一半内存溢出,进程被杀,前功尽弃。建议按以下方式控制资源:

  • 切块尺寸不要超过 1024×1024。
  • 每个批次处理 1-2 个块,不要一次性把所有块载入。
  • 用 numpy 数组保存临时结果,不要用 Python 列表存图片数据,内存占用差距巨大。
  • 每处理完几个块,主动调用 gc.collect() 释放内存。

5. 常见问题与排查技巧实录

这一节把我遇到的高频问题按“现象 - 原因 - 解法”整理成表格,你如果正好撞上了,直接对照着查。

5.1 问题速查表

现象可能原因解决办法
模型加载报“unexpected key”权重文件下载不完整或版本不匹配重新下载权重并核对文件大小
推理时显存溢出(CUDA out of memory)切块尺寸过大或批处理太多缩小切块到 512;一次只处理一个块
输出掩膜全是空的提示点全部落在无目标区域或采样步长过大检查采样点的分布情况,缩小 step
掩膜边缘锯齿严重后处理没有进行平滑在矢量化前用 scipy 的 gaussian_filter 或形态学闭运算做平滑
拼接处出现裂缝切块重叠区域设置过小增大 overlap 到 256,并对重叠区做置信度融合
导出的 Shapefile 与影像错位crs 或 transform 没有取对确保使用 rasterio 读取原始影像时的参数
大图跑几天没结果没有合理切块或内存泄漏检查脚本是否在循环中不断累积变量

5.2 踩坑实录:几个典型的排查故事

第一个坑是有一次大范围水体提取,跑出来的结果在水面中央出现大量孤立的小碎片。我一开始以为阈值设低了,调高后碎片更多,排查了很久才发现问题出在提示采样:水体区域的光谱特征非常均匀,梯度很低,模型对均匀区域容易生成破碎的候选掩膜。解决办法是把置信度阈值提高,同时在后处理里加了一个最小面积过滤,把小于 100 像素的连通域全部去掉,结果才干净。

第二个坑是拼接边界错位。我处理一个 2 万像素宽的影像时,顶部几行和底部几行的掩膜对不齐,中间出现明显的水平错位线。排查后发现是 padding 补边时没有对齐坐标,边缘块的实际内容偏移了,导致拼接时位置错了一半。这个问题的教训是:padding 的信息一定要跟着切块记录走,不能只用坐标算回原图位置,还得考虑 padding 带来的偏移。

第三个坑是显存优化。最开始我一次处理 4 个 1024 的块,结果经常跑到一半就 OOM。后来改成一次 1 个块,并用 torch.no_grad() 包裹推理过程,显存占用直接降了三分之二,速度反而因为不用频繁清理内存变得更快了。

5.3 效率优化经验

处理超大幅面时,有几个优化策略可以组合使用:

  1. 按地物类型分类处理。先提取所有候选掩膜,再根据掩膜的平均光谱值做快速聚类,同类目标一次性后处理,避免反复读全图。
  2. 用多进程并行处理不同切块。SAM 3 推理是典型的 CPU 预处理 + GPU 推理模式,多进程能有效利用多核 CPU 做数据读取和预处理。推荐进程数设为 CPU 核数一半左右,太高反而会有调度开销。
  3. 推理阶段关闭所有日志输出。一句话:控制台打印 I/O 在高频推理循环里会显著拖慢速度。

6. 个人经验与后续扩展建议

这次实测最直观的体会是:零标注遥感分割真正落地的时间节点已经到了。以前遇到一个新场景,先想能不能找到公开数据集,找不到就只能发动大家手工标注。现在用这套组合,第一天拿到影像,当天就能出第一版结果,对项目预研和方案验证的价值非常大。

当然也要说句公道话,零标注不代表在所有场景下都能直接超过有监督模型的效果。在类别高度雷同、边界极不清晰的场景里,有监督训练的算法仍然可能更优。但零标注流程可以作为一个快速预筛工具,把大量精力从标注中解放出来,集中处理模型解决不了的那部分难题。

后续值得折腾的方向,我列几个自己正在看的:一是把分割掩膜接一个小分类器,做成完整的“分割 + 分类”自动解译链路;二是针对自己的地物类别积累一套提示采样参数模板,覆盖不同分辨率和地物密度;三是把分割结果接进变化检测流程,用不同时期的影像对比,判断地物变化情况。

整个流程的核心就是提示设计,建议你拿到自己的数据后,先切几个代表性区域实验,把提示密度、阈值、后处理顺序跑通,再全量处理,这个习惯能帮你避免很多浪费。希望这篇教程能帮你跳过我已经踩过的坑,少一点头秃时刻。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 5:37:53

无盘启动报错“please reboot and try again”排查思路全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/16 5:36:55

以规划基准重塑AI驱动研发流程:从单点工具到全链路智能体编排

1. 认知升级:从“AI工具”到“AI驱动的流程再造”1.1 为什么“会用AI写代码”不等于“AI驱动研发”我见过太多团队盘点AI落地成果时,拿出来的东西千篇一律:谁谁谁用ChatGPT生成了接口代码、谁用Copilot补了几个单元测试、谁拿AI做了个需求文档…

作者头像 李华
网站建设 2026/9/16 5:36:39

基于Python机器学习的猫狗识别分类项目:从源码到模型全解析

简介:这是一份基于 Python 机器学习的猫狗识别分类项目源码包,面向计算机相关专业学生、毕业设计/课程设计选题者以及深度学习入门者。项目围绕图像二分类任务,提供完整可运行的训练、测试与可视化流程,覆盖 CNN、ResNet、Swin Tr…

作者头像 李华
网站建设 2026/9/16 5:34:27

大模型权重下载与管理全流程实践指南

1. 为什么需要关注大模型权重下载在自然语言处理领域,预训练模型权重的获取已成为研究与应用的基础环节。Hugging Face平台作为当前最活跃的模型共享社区,托管了超过10万种开源模型权重,包括GPT、BERT、T5等主流架构。但实际操作中&#xff0…

作者头像 李华
网站建设 2026/9/16 5:33:38

中国为中心的世界地图SHP:投影参数与ArcGIS/QGIS实操指南

简介:以中国为中心的世界地图shp数据包,是一份面向GIS制图人员、科研学者及‘一带一路’相关研究者的矢量底图资源,专为解决国内出版要求与世界地图投影方式不匹配这一痛点而整理。与常见的欧美中心世界地图不同,该数据采用以中国…

作者头像 李华
网站建设 2026/9/16 5:33:26

FCN配Cityscapes:语义分割实战全流程与避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华