有段时间我一直在跟遥感影像标注较劲。几百张高分影像等着打标签,每张图动辄上亿像素,房区、水体、耕地、道路一类的要素密密麻麻,标注团队的人换了一茬又一茬,进度还是慢得像蜗牛。后来我把Meta开源的SAM(Segment Anything Model)引入到工作流里,虽然它本身并不直接输出"类别标签",但配合合理的后处理链路,完整跑通了一条从原始影像到语义分割成果的路。这篇文章就把我全流程的实操经验、踩过的坑、工具选型和参数调优都梳理一遍,给想拿SAM做遥感图像语义分割的人一个可以直接参考的路线。
1. 先想明白:SAM在遥感语义分割里到底扮演什么角色
1.1 SAM的"分割"和遥感要的"语义分割"不是一回事
刚开始用SAM时,团队里不少人有个误解:既然SAM号称"分割一切",那直接把遥感影像丢进去,是不是就能拿到像DeepLabV3那样带类别标签的分割图了?这个预期是错误的,而且错得很关键,不纠正这个认知,后面所有流程都会跑偏。
SAM的完整架构由三部分组成:图像编码器(ViT,Vision Transformer)、提示编码器(Prompt Encoder)和掩码解码器(Mask Decoder)。给它一张图,你可以用点、框或者粗略的掩码去"提示"它,它会在这些提示的基础上生成一个或多个高质量的目标掩码。它的训练数据是超过10亿个掩码的大规模数据集,这让它具有很强的零样本分割能力——也就是说,一个没有在遥感影像上专门微调过的SAM,拿到航拍图或者卫星图,依然能把地物的轮廓抠得相当漂亮。
但注意,SAM输出的是"这是什么形状的物体",它回答不了"这是什么类别的物体"。这是一条泾渭分明的界线。常规语义分割模型是像素级分类器,把每个像素映射到预定义的类别集合,比如建筑、水体、植被、道路;SAM是像素级分组器,它把所有"看起来像一个独立物体"的像素聚成一团,但不知道这团东西叫房屋还是叫油罐。正因如此,拿SAM做遥感语义分割的正确姿势,不是"替代语义分割模型",而是"用SAM先生成高质量掩码,再叠加一个分类步骤把掩码映射成类别"。
1.2 遥感影像的三大特性决定了它不能照搬自然影像的玩法
我在把SAM迁移到遥感影像时,遇到的第一个壁垒就是输入数据的差异。自然影像和遥感影像是两种物种,主要在三个方面有显著区别。
第一,幅面巨大。一张常见的WorldView-3影像单景可能超过10亿像素,而SAM的推理通常要先把图像缩放到1024x1024的输入尺寸,直接整图塞进去既不现实也没必要。这就要求我们必须引入滑窗裁剪等工程化手段,把大影像拆成可控子图处理。
第二,自上而下的视角和极端尺度差异。遥感是从头顶往下看,地物不存在自然照片的前后遮挡关系,但同一个场景里可能出现几平方公里的农田、几十米长的厂房,以及几米宽的小汽车。这种尺度跨度给SAM的"提示"策略和参数设置带来很大影响,比如在密集小目标场景下,默认16x16的网格采样往往会漏掉大量小目标,后面我会专门讲参数怎么调。
第三,多光谱特征。遥感影像通常不止RGB三个波段,近红外、红边甚至短波红外都是常用波段。SAM的预训练模型是在自然影像上训练的,用RGB波段喂它是符合预期的;但如果你的场景里农作物长势、水体边界、植被健康程度是判别关键,单纯依赖RGB可能会漏掉近红外上才能看出来的特征。我自己的做法是:先把多光谱映射成视觉友好的RGB合成图给SAM做掩码生成,再在分类环节把近红外等波段作为特征补充进去。这个"分工"很重要。
1.3 和DeepLabV3这类传统语义分割模型比,价值在哪
很多人会问:既然要折腾这么多后处理,我干脆用DeepLabV3、U-Net这些成熟模型直接训一个语义分割网络不行吗?行,但前提是你有足够多的标注数据。我把两种路线的差异用一个表直观对比:
| 对比维度 | SAM + 后处理分类 | DeepLabV3 / U-Net语义分割 |
|---|---|---|
| 类别语义 | 无,需后处理赋予类别 | 直接输出像素级类别 |
| 边界质量 | 掩码边缘贴合度高,对轮廓敏感 | 边缘容易平滑化,细碎地物容易糊 |
| 训练数据需求 | 可零样本推理,少量标注即可 | 通常需要大量像素级标注 |
| 交互性 | 支持点/框提示,可人机协同修正 | 训练完是固定模型,无法交互 |
| 推理速度 | 较慢,特别是大图裁剪后逐块处理 | 相对快,单次前向即可 |
| 对长尾目标 | 泛化能力强,见过类似形态就能分割 | 依赖训练集覆盖度 |
我并不是要否定DeepLabV3这类模型,恰恰相反,在遥感语义分割领域,传统模型和SAM是可以形成互补的。最理想的生产链路是:用SAM快速生成大量伪标签或者辅助人工标注,快速获得一个验收过的标注集,然后交给DeepLabV3这类轻量级分割模型去全图高效推理。这样既利用了SAM"不用训练也能分割"的能力,又得到了传统模型的类别输出和推理速度,一举两得。
2. 环境准备与模型加载:这几件事没做对,后面全是坑
2.1 模型选择:vit_b、vit_l还是vit_h
SAM官方提供了三档ViT骨干模型,我一开始图省事直接用了vit_b,处理自然照片没问题,但一上遥感影像就被小目标分割质量打脸了。三个模型的区别主要在这几点:
| checkpoint | 权重大小 | 显存占用参考 | 推理速度 | 适合场景 |
|---|---|---|---|---|
| sam_vit_b | 约375MB | 约6-8GB | 快 | 大目标为主,对精度要求不极端的预览 |
| sam_vit_l | 约1.2GB | 约10-14GB | 中等 | 常规分割场景 |
| sam_vit_h | 约2.5GB | 约14-18GB | 慢 | 遥感复杂场景、小目标密集场景 |
我的实际体验是,vit_b在遥感影像上经常出现建筑物边缘破碎、小型地物漏检的情况,而vit_h的掩码完整性明显好一个档次。如果显存允许,直接上vit_h,不要犹豫。遥感影像的地物边界复杂度和自然影像不是一个量级,省资源不如保质量。
运行环境方面,建议Python 3.9以上,PyTorch 2.0以上,CUDA版本对了之后直接装segment-anything库即可。权重文件从官方仓库下载,注意校验名字里的哈希后缀,比如sam_vit_h_4b8939.pth,加载代码是这样的:
from segment_anything import sam_model_registry sam = sam_model_registry["vit_h"](checkpoint="sam_vit_h_4b8939.pth") sam.to(device="cuda")建议把所有需要频繁调用的模块都封装成类,因为遥感项目的处理单位不是"一张图",而是"一个文件夹上千张瓦片",复用性和稳定性是第一位的。
2.2 遥感影像喂给SAM之前的预处理
我在项目里踩过一个大坑:直接把16位深度的GeoTIFF喂给SAM,结果输出一片黑。原因是SAM的输入期望是0-255范围的8位RGB图像,而很多原始遥感影像是16位、甚至32位浮点存储的,像素值范围动辄上万,落在SAR图像上还可能带复数数据。不做转换,输入分布跟模型期望完全对不上。
正确做法分三步走。第一步,用rasterio把影像读进来;第二步,做归一化和拉伸,把像素值映射到0-255;第三步,如果原始数据是多光谱,挑出合适的波段做成RGB合成图。拉伸方式我建议用百分位截断而不是简单线性归一化,因为遥感影像经常有极少数高亮噪点,线性的会把整体拉暗。以下是我项目里常用的一段预处理代码:
import rasterio import numpy as np def tif_to_rgb(path, bands=(3, 2, 1), percentiles=(2, 98)): """ bands参数根据影像波段顺序调整,常见为(B,G,R,NIR)时选(3,2,1) """ with rasterio.open(path) as src: data = src.read() if data.ndim == 3 and data.shape[0] >= 3: rgb = np.stack([data[idx - 1] for idx in bands], axis=-1) else: rgb = data[0] if data.ndim == 2 else np.mean(data[:3], axis=0) rgb = rgb.astype(np.float32) p_low, p_high = np.percentile(rgb, percentiles) rgb = np.clip((rgb - p_low) / (p_high - p_low + 1e-6), 0, 1) rgb = (rgb * 255).astype(np.uint8) return rgb注意,如果你的任务是水体提取并且手上有近红外波段,我强烈建议把近红外波段纳入RGB合成的一个重要通道,或者至少用NDVI、NDWI这类指数辅助后续分类环节,不要让近红外信息白白浪费。
2.3 推理设备与速度预期
遥感项目和单张自然图的处理节奏完全不同。一张1024x1024的瓦片,vit_h在V100上单次推理大概要3-6秒,如果启用自动掩码生成的crop_n_layers多尺度推理,时间还要翻倍。一个20000x20000像素的完整影像,裁成patch之后可能需要跑上几百次推理,如果不是GPU集群,建议先做好时间预算。
我通常的做法是:先把影像预处理和滑窗切割离线做好,把瓦片存成分块目录,然后启动一个批量推理脚本逐块跑,用中间结果落盘的方式防止程序中断导致全盘重来。进度日志务必打上"当前块序号/总块数",否则跑到一半卡住很难定位问题。
显存管理也有技巧。SAM推理完一张图后,分批释放显存,切忌把这千把个patch的中间结果全部留在内存里。PyTorch的torch.cuda.empty_cache()在某些场景下有用,但更根本的手段是控制batch size并在循环里及时把大tensor置为None。我的经验是每处理完一个瓦片就把它对应的掩码结果立刻转成磁盘上的uint8格式,内存只保留当前批次的数据。
3. 三种提示策略在遥感场景的实战效果
3.1 自动掩码生成:全图分割的起点
把SAM投入到遥感影像上的第一步,我建议先用自动掩码生成器(SamAutomaticMaskGenerator)跑通流程,因为它不需要任何先验信息,可以完整观察SAM在我们自己的数据上表现如何。它的原理是在图像上均匀铺设网格点作为提示,每个点都尝试分割出一个对象,再通过IoU预测分数和稳定性分数筛选出可信的掩码。
实际使用中,我关注的核心参数有这么几个:
from segment_anything import SamAutomaticMaskGenerator mask_generator = SamAutomaticMaskGenerator( model=sam, points_per_side=32, # 网格点数,16适合中目标,32适合小目标 pred_iou_thresh=0.86, # 预测IoU阈值,默认0.88,遥感可适当放宽 stability_score_thresh=0.90, # 稳定性阈值,默认0.95 min_mask_region_area=80, # 忽略小于80像素的碎块 )输出结果是一个list,每个元素是一个dict,结构大致如下:
{ "segmentation": np.ndarray(dtype=bool, shape=(H, W)), "bbox": [x1, y1, x2, y2], "area": 12345, "predicted_iou": 0.94, "stability_score": 0.98, }我在前面1.2节提到的"16x16网格采样漏小目标"问题,这时的解法就是把points_per_side从16提高到32甚至48。这个参数的作用是设置图像网格上采样的提示点数量,点数越多,小目标被覆盖到的概率越大,但相应地推理耗时也会明显增加。我在一片包含密集自建房的城乡结合部影像上测试过,从16提升到32之后,小型建筑掩码召回率大概提高了20个百分点,效果非常显著。
自动掩码生成适合的任务是:快速摸底、生成伪标签、做实例级分割。缺点是它不知道类别,整片的掩码堆在GIS软件里看得眼花缭乱,需要后续分类才行。
3.2 点提示与框提示:交互式标注的正确打开方式
真正的自动化工作流里我离不开SamPredictor,因为它支持点提示和框提示,这是辅助标注场景的关键能力。比如我拿到一张新影像时,可以先跑一个快速目标检测器或者人工粗略框选,把候选框交给SAM细化边界;也可以用几个前景点加背景点告诉SAM"这里是要分割的建筑物,那边是背景",让SAM像一个"智能套索"一样把轮廓抠出来。
核心代码逻辑如下,框提示和点提示可以单独用,也可以结合起来:
from segment_anything import SamPredictor predictor = SamPredictor(sam) predictor.set_image(rgb_patch) # 必须提前设置好图像 # 框提示:格式为 [x1, y1, x2, y2] input_box = np.array([100, 150, 400, 380]) # 点提示:坐标+标签,1是前景,0是背景 input_points = np.array([[250, 260]]) input_labels = np.array([1]) masks, scores, logits = predictor.predict( point_coords=input_points, point_labels=input_labels, box=input_box, multimask_output=True, )注意predict里的multimask_output参数。当设置为True时,SAM会返回3个候选掩码,分别对应整体、局部和更精细三种分割结果,scores数组给出每个候选的质量评分。做交互标注时这非常有用——同一个框可能对应"整栋楼"和"楼顶附属物"两种语义,用户可以从3个候选中选一个最贴合自己意图的。
实际标注时,我常常让标注员只点一个中心点做提示,SAM生成候选掩码后人工确认或微调,这个模式比传统的逐像素勾画效率高太多了。我们在一个地块项目里做过粗略统计,标注速度大约是纯手工的5到8倍。这个"遥感图像标注"方向我觉得是SAM当前对行业最立竿见影的贡献。
3.3 现实项目中的策略组合
单一的提示策略在实际项目中往往不够用。我现在的推荐组合是:自动掩码生成做"粗分割",把所有可能有意义的地物掩码全部找出来;然后用一组轻量规则或者聚类模型给掩码初步分类;最后对不确定的区域采用框提示或点提示进行人工确认。这个"自动+交互"的混合流程兼顾了效率和质量。
还有一种很实用的玩法:先用自动掩码生成得到一批掩码,再把这批掩码对应的中心点作为点提示重新送进SamPredictor,在更高分辨率下精修掩码边界。说白了就是分两遍,第一遍找目标,第二遍修细节。在分辨率为2米和0.5米的混合影像上,这个做法能明显改善边界锯齿和细小地物的断裂问题。
4. 从掩码到语义标签:后处理链路的设计
4.1 不做训练的轻量方案
如果项目周期紧,不想训练任何额外模型,也有办法把SAM掩码变成语义分割结果。核心思路是"过分割+合并归类":SAM把影像切成一大堆掩码片段,我们再用遥感领域已有的特征或规则把这些片段合并到语义类别里。
最典型的例子是水体提取。只要有近红外波段,NDWI(归一化差异水体指数)就能把水体和背景分得很干净:
def ndwi(green_band, nir_band): return (green_band.astype(float) - nir_band.astype(float)) / \ (green_band.astype(float) + nir_band.astype(float) + 1e-6)对于每个SAM掩码,计算掩码内部NDWI中位数,大于某个阈值(比如0.2)就判定为水体,否则归为其他类别。这种"指数+统计聚合"的方式稳定、可解释、零训练成本。植被、裸土、建筑等类别也可以用NDVI、亮度、纹理特征做类似处理。
另一种更通用的做法是对RGB特征做聚类。把每个掩码内的像素特征取平均,然后跑一个简单的k-means或者GMM聚类,聚出来的簇再由人工给类别命名。它的好处是适应性强,但簇数和类别的对应关系需要人工介入。在0.8m分辨率的卫星影像上,我用这个方法把建筑、道路、裸地、树木分得还可以,精度上线不高但足够用来做早期解译和变化监测的粗筛。
4.2 接分类头的微调方案
轻量方案能解的问题比较有限,一旦类别边界在光谱上重叠严重,就必须上"分类头"了。这个方案的核心思想是:SAM的图像编码器经过数十亿掩码的预训练,已经学会了非常强的通用视觉特征,我们完全可以在它提取的特征之上接一个轻量级分类器来输出语义类别,整体流程类似一个冻结backbone的迁移学习。
具体做法是:把SAM的image encoder当作特征提取器,对每个掩码区域提取对应的特征向量,然后接一个全连接层或者1x1卷积作为分类头,输出的就是类别概率分布。这个分类头非常轻,就算只用几千个标注样本也能训练到不错的水平,因为真正耗时费力的特征学习已经被SAM做完了。
在工程实现上,我会把分类头和掩码解码器做"双头"设计:同一套图像特征,一条路走SAM的掩码解码器生成边界,一条路走分类头判定类别。训练时用人工标注的小样本集来监督分类头,掩码分支可以保持完全冻结。我在一个项目里用300多张标注图像微调了这个分类头,在验证集上取得的效果已经接近用5000张图端到端训练的传统分割模型。想更深入地做语义分割模型的训练,还可以把SAM产生的掩码作为伪标签,结合自训练方式迭代扩充训练集,然后用DeepLabV3这类高效模型在全图上做最终部署。这就是我在1.3节说的互补链路的完整形态。
4.3 成果输出与地理坐标保留
分割完成后还有一个容易被新手忽略的环节:遥感影像里每个像素都有地理坐标,如果你输出的是一个普通PNG掩码图,那它跟一张白纸差不多,无法落到GIS里。正确的输出方式是把掩码结果写回带地理参考的GeoTIFF。
这个环节我的建议是全程围绕rasterio的transform来操作。在读取原始影像时把transform对象保存下来,掩码结果用同样的transform写入新数据源即可:
import rasterio from rasterio.transform import Affine with rasterio.open( "segmentation_result.tif", "w", driver="GTiff", height=H, width=W, count=1, dtype="uint8", crs=src.crs, transform=src.transform, ) as dst: dst.write(class_map, 1)如果需要输出矢量格式,可以用rasterio.features.shapes把掩码转成GeoJSON几何,再用geopandas写出去。注意做掩码到矢量的转换之前,先做一次小连通域过滤和形态学处理,不然矢量文件里会充满细碎多边形的噪声。
5. 大影像的裁剪-推理-拼接工程化流程
5.1 滑窗裁剪的参数设计
处理一块大影像,最忌讳的事情就是"一口气吞"。我在第2.2节提过用瓦片化的方式解决输入尺寸问题,这里详细讲讲裁剪参数怎么定。patch size我通常取512或1024,具体取决于你的显存大小和分割粒度要求。patch太大,SAM推理变慢且可能在喂入模型时被迫缩放,丢失小目标细节;patch太小,则会引入严重的上下文缺失问题——一个独立房屋在一张小patch里可能被切了一半,SAM就会把半个房顶当成"某种物体",导致掩码完整性变差。
我的经验是patch size取1024,配合50到128像素的重叠区。重叠区的作用是缓解边界处目标被切断的问题。裁剪时要记录每个patch在原图中的起始行列号,这个索引在后面拼接时是定位用的关键信息。裁剪和推理脚本尽量做成可断点续跑的,因为大项目跑到一半中断是常态,没有断点续跑功能会让人崩溃。
5.2 重叠区处理与拼接伪影消除
拼接是裁剪的镜像操作,但核心难点在于重叠区怎么处理。如果不做任何特殊处理,直接取第一个patch的结果覆盖重叠区,会在图像上留下明显的"马赛克接缝"——同一栋建筑在左右两个patch里可能被SAM分割成不同的掩码编号,接缝两侧的类别也可能不一致。
我的做法是:对每个patch的预测结果,不直接写出"硬类别标签",而是写出每个类别的概率值或者置信度分值,拼接时对重叠区做距离加权融合。具体来说,重叠区靠近哪个patch中心,就更多地采信哪个patch的预测概率,权重从中心向边缘线性递减:
def blend_prob(prob_left, prob_right, overlap_start, overlap_end, cur_col): # 线性权重:越接近左边patch中心,左权重越大 alpha = (overlap_end - cur_col) / (overlap_end - overlap_start) return alpha * prob_left + (1 - alpha) * prob_right拼接完概率图之后,最后一步再取argmax得到类别标签图。这个流程比直接拼标签图更平滑,能明显减少条带效应。如果做的是二值分割(比如水体),也可以用形态学闭运算把重叠区周围的细小断裂补上。
5.3 工程脚本的核心代码
这里给一个简化版的裁剪-推理-拼接主循环核心结构,方便大家搭建自己的工程管道:
def process_tile(tile_img, mask_generator, classifier=None): masks = mask_generator.generate(tile_img) prob_map = np.zeros((tile_img.shape[0], tile_img.shape[1], num_classes), dtype=np.float32) for m in masks: feat = extract_feature_from_mask(tile_img, m["segmentation"]) cls_prob = classifier.predict_proba(feat) if classifier else rule_based_classify(feat) prob_map[..., cls] += cls_prob * m["segmentation"] return prob_map主体流程就三件事:遍历patch、对每个patch做掩码生成和分类、按位置融合概率。实际项目里还会加上数据校验逻辑,比如判断patch是否全为无数据区域、掩码数量是否异常过少、GPU显存是否够用等防御性检查。工程化的本质不是算法多复杂,而是异常出现时能不能快速定位并恢复。
6. 我用SAM跑遥感影像踩过的坑(附调参经验)
6.1 线状地物断裂问题
道路、河流、防护林这类线状地物,在SAM分割结果里经常被切成好几段,严重的时候看起来像一串断线的珠子。这个现象的根本原因是SAM倾向于把"独立闭合对象"当成一个物体,而线状要素在局部patch里往往不构成闭合轮廓,容易被拆成多个边界片段。
我的应对方案分三层。第一层是在裁剪参数上增加重叠区,让线状地物至少完整出现在某一个patch里;第二层是在后处理里对目标类别(道路等)做形态学闭运算,用小半径的核把小的断裂缝隙桥接起来;第三层是利用道路的几何特征,比如对分割结果做骨架提取后按角度连续性连接。前两层基本能解决大部分断裂问题,第三层通常只在做路网提取时才需要。
6.2 大片农田过分割与阴影误检
另一个常见问题是过分割。一片几公顷的连片农田,在自然影像里属于"一个物体",但在遥感影像里因为田垄、灌溉痕迹、或者同一地块内作物长势不均,SAM会把一个田块切成几十个小碎片。这不是SAM不行,而是语义分割和实例分割的目标本来就不一样——语义上的"耕地"允许内部存在纹理差异,但SAM的实例分割逻辑不允许。
解决思路有两个方向。一个是在后处理合并时设定约束:如果多个掩码类别相同、边界相邻、光谱特征相似,就把它们合并成一个大的语义区域。另一个是调整自动掩码生成的参数,把points_per_side适当降低,减少提示点数,让SAM更倾向生成大而完整的掩码。两个方向结合效果最好。
阴影导致的误检也很常见。高层建筑旁边的阴影区域经常被SAM识别成一个独立的深色物体,后续分类时很容易错分。这个问题的根源在于我们的分类环节使用了颜色特征做判断,阴影区和高架桥底部的光谱特征确实容易跟水体或某些深色地物混淆。我通常会在特征上加入纹理和上下文特征,或者显式地把阴影区域作为一个类别让模型去学。
6.3 关键参数调试清单
我把几个直接影响遥感分割效果的参数整理成一张表,方便大家根据任务类型做初始值设置:
| 参数 | 默认值 | 遥感场景建议 | 调参意图 |
|---|---|---|---|
| points_per_side | 16 | 小目标多时调到32-48 | 增加提示点密集度,提高小目标召回率 |
| pred_iou_thresh | 0.88 | 0.82-0.88 | 阈值太高会漏检,太低会混入质量差的掩码 |
| stability_score_thresh | 0.95 | 0.85-0.92 | 过高的稳定性要求会让边缘模糊的掩码被丢弃 |
| min_mask_region_area | 0 | 80-300 | 过滤掉过小的碎块,控制掩码数量 |
| crop_n_layers | 0 | 1-2 | 对原图做多尺度裁剪推理,改善小目标召回 |
| multimask_output | True | True | 让模型返回多个候选掩码,方便挑选/合并 |
这些参数之间不是独立的。调高points_per_side后掩码数量会爆炸式增长,因此pred_iou_thresh和min_mask_region_area也要同步收紧,否则后处理阶段会面临几万个掩码的灾难。调参没有万能公式,关键是理解每个参数控制的环节——采样密度决定"能找到多少目标",IoU和稳定性阈值决定"保留下来的目标有多可信",最小面积决定"多小的目标值得保留"。
6.4 标注场景:SAM当前最有价值的落点
如果让我评价SAM在遥感语义分割里的最大价值,我不会说是"直接分割",而是"对标注生产力的解放"。遥感语义分割项目最大的成本从来不是GPU、不是算法调优,而是像素级标注。数据标注的瓶颈已经卡死了无数团队的项目进度。
我目前的主流工作流是:SAM自动生成候选掩码,标注员在界面上做"审核+分类+修正",而不是从零开始描绘边界。即使标注员只做审核和点选,效率也比纯手工提升数倍。这些经过人工确认的标注数据不浪费,它们会被攒成训练集,最终喂给DeepLabV3或者轻量级分割模型做全图推理。用我自己项目里的数据说话,过去做一个城区地块的标注需要两周,用SAM辅助之后三天左右就能完成验收。
最后分享一个小技巧:可以先用SAM自动生成掩码做一个粗糙的全图分割,然后把不同尺寸的掩码按大小分成几个层级,分别做类别判定。比如大面积的连续矩形块大概率是农田或裸地,细长条状是道路或河流,小而密集的矩形块可能是建筑。这种层级规则跟人工解译的思路很像,能极大减少后续人工审核的工作量。
我这个流程跑了大半年,期间不断踩坑、调参、迭代,目前的版本已经相对稳定。如果你们团队也在做遥感影像分割或者标注任务,不妨按照这篇文章的路径搭一版试试,从最小的patch开始跑通,再逐步扩展到大影像和更多类别,我相信SAM会给你的工作流带来明显的变化。