遙感圖像實例分割是指在遙感影像中,不僅要識別出不同類別的目標(如建筑物、車輛、道路等),還要區分同一類別中的不同個體(如建筑物1、建筑物2),并為每個實例生成精確的像素級掩碼。
一、遙感圖像實例分割的基本流程
- 數據準備:收集遙感影像數據,進行標注(需標注類別和每個實例的掩碼),劃分訓練集、驗證集和測試集。
- 預處理:包括圖像裁剪(適應模型輸入尺寸)、歸一化、輻射校正、去噪等。
- 模型選擇與訓練:選擇或改進實例分割模型(如Mask R-CNN),利用標注數據訓練模型。
- 推理與后處理:用訓練好的模型對新圖像進行預測,通過非極大值抑制(NMS)等方法優化結果。
- 評估:使用AP(Average Precision)、mIoU等指標評估分割效果。
二、遙感圖像實例分割的難點
- 尺度變化極大:同一類目標大小差異顯著(如小型房屋與大型廠房),且遙感圖像分辨率跨度大(從米級到亞米級)。
- 目標形態特殊:遙感圖像為俯視視角,目標形態與自然圖像(如街景)差異大(如建筑物呈多邊形、車輛呈鳥瞰形態)。
- 背景復雜且干擾多:存在云層、陰影、植被覆蓋、地形起伏等干擾,易與目標混淆。
- 樣本標注成本高:高分辨率遙感圖像像素密集,人工標注實例掩碼耗時耗力,導致高質量數據集稀缺。
- 目標密集與重疊:如城市區域密集的建筑物、停車場密集的車輛,易導致實例重疊和邊界模糊。
- 類別不平衡:部分目標(如特殊設施)出現頻率低,模型難以學習其特征。
三、解決方案
-
數據增強適配遙感特性:
- 多尺度訓練:隨機縮放圖像(如0.5~2倍),讓模型適應不同大小的目標。
- 旋轉與翻轉:模擬遙感圖像的任意拍攝角度(如90°、180°旋轉)。
- 輻射增強:調整亮度、對比度,模擬不同光照和大氣條件。
-
模型改進:
- 多尺度特征融合:使用特征金字塔網絡(FPN)融合不同層級的特征,增強對小目標的識別。
- 注意力機制:加入空間注意力模塊(如CBAM),讓模型聚焦于目標區域,抑制背景干擾。
- 自適應錨點設計:根據遙感目標的尺度分布調整錨點大小和比例(如增大錨點尺寸覆蓋大型建筑物)。
-
減少標注依賴:
- 半監督/弱監督學習:利用少量標注數據和大量未標注數據訓練(如偽標簽技術)。
- 遷移學習:基于自然圖像預訓練的模型(如Mask R-CNN),在遙感數據集上微調,加速收斂。
-
后處理優化:
- 改進NMS:針對密集目標,使用Soft-NMS或DIoU-NMS減少漏檢。
- 形態學操作:對預測掩碼進行腐蝕/膨脹,去除噪聲并平滑邊界。
四、Python代碼實現(基于Detectron2)
Detectron2是Facebook推出的實例分割框架,支持Mask R-CNN等模型,且易于擴展。以下代碼以建筑物實例分割為例,展示遙感圖像實例分割的實現流程。
1. 環境準備
# 安裝依賴
pip install torch torchvision torchaudio
pip install detectron2 -f https://dl.fbaipublicfiles.com/detectron2/wheels/cu118/torch2.0/index.html
pip install opencv-python pillow matplotlib
2. 代碼實現
import os
import cv2
import json
import matplotlib.pyplot as plt
from detectron2.structures import BoxMode
from detectron2.data import DatasetCatalog, MetadataCatalog
from detectron2.engine import DefaultTrainer, DefaultPredictor
from detectron2.config import get_cfg
from detectron2 import model_zoo
from detectron2.evaluation import COCOEvaluator, inference_on_dataset
from detectron2.data import build_detection_test_loader# ----------------------------
# 1. 數據準備:注冊遙感數據集
# ----------------------------
def get_remote_sensing_dicts(img_dir, ann_file):"""加載遙感數據集(COCO格式標注)img_dir: 圖像文件夾路徑ann_file: 標注文件路徑(JSON格式)"""with open(ann_file, 'r') as f:imgs_anns = json.load(f)dataset_dicts = []for idx, v in enumerate(imgs_anns['images']):record = {}filename = os.path.join(img_dir, v["file_name"])record["file_name"] = filenamerecord["image_id"] = v["id"]record["height"] = v["height"]record["width"] = v["width"]# 提取該圖像對應的標注annos = [anno for anno in imgs_anns['annotations'] if anno['image_id'] == v["id"]]objs = []for anno in annos:obj = {"bbox": anno["bbox"], # [xmin, ymin, width, height]"bbox_mode": BoxMode.XYWH_ABS, # COCO格式默認此模式"segmentation": anno["segmentation"], # 實例掩碼(多邊形坐標)"category_id": anno["category_id"], # 類別ID(如建筑物為0)"iscrowd": anno["iscrowd"] # 是否為密集目標(0表示否)}objs.append(obj)record["annotations"] = objsdataset_dicts.append(record)return dataset_dicts# 注冊訓練集和驗證集
dataset_name = "remote_sensing_buildings"
train_img_dir = "path/to/train/images" # 訓練圖像路徑
train_ann_file = "path/to/train/annotations.json" # 訓練標注文件
val_img_dir = "path/to/val/images" # 驗證圖像路徑
val_ann_file = "path/to/val/annotations.json" # 驗證標注文件DatasetCatalog.register(f"{dataset_name}_train", lambda: get_remote_sensing_dicts(train_img_dir, train_ann_file))
DatasetCatalog.register(f"{dataset_name}_val", lambda: get_remote_sensing_dicts(val_img_dir, val_ann_file))# 定義類別(此處僅示例建筑物一類)
MetadataCatalog.get(f"{dataset_name}_train").set(thing_classes=["building"])
MetadataCatalog.get(f"{dataset_name}_val").set(thing_classes=["building"])
metadata = MetadataCatalog.get(f"{dataset_name}_train")# ----------------------------
# 2. 模型配置:基于Mask R-CNN改進
# ----------------------------
def setup_cfg(output_dir):cfg = get_cfg()# 加載預訓練的Mask R-CNN模型(基于COCO數據集)cfg.merge_from_file(model_zoo.get_config_file("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml"))cfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml")# 配置數據集cfg.DATASETS.TRAIN = (f"{dataset_name}_train",)cfg.DATASETS.TEST = (f"{dataset_name}_val",)cfg.DATALOADER.NUM_WORKERS = 2 # 數據加載線程數# 訓練參數cfg.SOLVER.IMS_PER_BATCH = 2 # 批次大小(根據GPU內存調整)cfg.SOLVER.BASE_LR = 0.00025 # 學習率cfg.SOLVER.MAX_ITER = 3000 # 訓練迭代次數cfg.SOLVER.STEPS = [] # 學習率衰減步驟(空表示不衰減)# 模型參數(適配遙感目標)cfg.MODEL.ROI_HEADS.BATCH_SIZE_PER_IMAGE = 128 # 每個圖像的ROI采樣數cfg.MODEL.ROI_HEADS.NUM_CLASSES = 1 # 類別數(僅建筑物)# 調整錨點尺度(遙感建筑物可能更大)cfg.MODEL.RETINANET.ANCHOR_SCALES = (8, 16, 32, 64, 128) # 增大錨點尺寸# 輸出目錄cfg.OUTPUT_DIR = output_diros.makedirs(cfg.OUTPUT_DIR, exist_ok=True)return cfg# ----------------------------
# 3. 模型訓練
# ----------------------------
def train_model():output_dir = "./output_remote_sensing"cfg = setup_cfg(output_dir)# 初始化訓練器trainer = DefaultTrainer(cfg)trainer.resume_or_load(resume=False) # 從預訓練模型開始訓練trainer.train() # 啟動訓練# ----------------------------
# 4. 模型評估
# ----------------------------
def evaluate_model():output_dir = "./output_remote_sensing"cfg = setup_cfg(output_dir)cfg.MODEL.WEIGHTS = os.path.join(cfg.OUTPUT_DIR, "model_final.pth") # 加載訓練好的模型cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.5 # 測試時的置信度閾值# 構建評估器evaluator = COCOEvaluator(f"{dataset_name}_val", output_dir=output_dir)val_loader = build_detection_test_loader(cfg, f"{dataset_name}_val")# 評估并打印結果predictor = DefaultPredictor(cfg)print(inference_on_dataset(predictor.model, val_loader, evaluator))# ----------------------------
# 5. 推理測試(可視化結果)
# ----------------------------
def inference_demo(image_path):output_dir = "./output_remote_sensing"cfg = setup_cfg(output_dir)cfg.MODEL.WEIGHTS = os.path.join(cfg.OUTPUT_DIR, "model_final.pth")cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.5predictor = DefaultPredictor(cfg)# 加載圖像并預測im = cv2.imread(image_path)outputs = predictor(im)# 可視化結果from detectron2.utils.visualizer import Visualizerv = Visualizer(im[:, :, ::-1], metadata=metadata, scale=0.8)out = v.draw_instance_predictions(outputs["instances"].to("cpu"))plt.figure(figsize=(10, 10))plt.imshow(out.get_image()[:, :, ::-1])plt.axis("off")plt.show()# ----------------------------
# 主函數:執行訓練、評估或推理
# ----------------------------
if __name__ == "__main__":# 訓練模型(首次運行時執行)# train_model()# 評估模型(訓練完成后執行)# evaluate_model()# 推理測試(替換為實際圖像路徑)test_image_path = "path/to/test_image.jpg"inference_demo(test_image_path)
五、代碼解釋
- 數據注冊:
get_remote_sensing_dicts
函數將COCO格式的遙感標注數據轉換為Detectron2可識別的格式,支持實例的掩碼和邊界框信息。 - 模型配置:
setup_cfg
函數基于Mask R-CNN進行調整,包括:- 增大錨點尺度(
ANCHOR_SCALES
)以適應遙感中大型建筑物。 - 調整批次大小和學習率,適配遙感數據集規模。
- 增大錨點尺度(
- 訓練與評估:使用
DefaultTrainer
訓練模型,COCOEvaluator
評估AP等指標,反映實例分割精度。 - 推理可視化:
inference_demo
函數加載訓練好的模型,對新圖像進行預測,并通過Visualizer
顯示實例掩碼和類別。
六、測試用例
- 數據集準備:使用公開遙感數據集如Inria Aerial Image Labeling Dataset(含建筑物標注),按COCO格式整理數據。
- 訓練:運行
train_model()
,模型會在./output_remote_sensing
保存權重。 - 評估:訓練完成后運行
evaluate_model()
,輸出AP50、AP75等指標(如建筑物分割AP50可達0.7+)。 - 推理:替換
test_image_path
為測試圖像路徑,運行inference_demo()
,可視化結果應能準確分割出不同建筑物實例。
總結
遙感圖像實例分割需針對其尺度變化大、背景復雜等特點進行適配。基于Detectron2的Mask R-CNN改進方案,通過數據增強、模型調整和后處理優化,可有效提升分割效果。實際應用中需結合具體場景(如目標類型、分辨率)進一步調優。