習(xí)管線實(shí)踐)
簡(jiǎn)介面向遙感影像分析與深度學(xué)習(xí)入門者的智能分析工具包基于YOLO目標(biāo)檢測(cè)算法集成了模型推理、部署配置與說(shuō)明文檔可用于地表覆蓋分類、目標(biāo)檢測(cè)、變化監(jiān)測(cè)等場(chǎng)景也適合畢業(yè)設(shè)計(jì)、課程設(shè)計(jì)或機(jī)器學(xué)習(xí)實(shí)戰(zhàn)訓(xùn)練。壓縮包共26個(gè)文件以jpg/png影像及標(biāo)注結(jié)果、md說(shuō)明文檔、模型權(quán)重model__與__params為主另含infer.py推理腳本、deploy.yaml部署配置及requirements.txt依賴清單總大小94.97MB。已有51人學(xué)習(xí)下載。工具內(nèi)含README.md詳細(xì)說(shuō)明、freeze_model模型凍結(jié)腳本、docs文檔目錄以及PaddleSeg推理基準(zhǔn)測(cè)試與TensorRT編譯指南既能快速上手推理流程也能根據(jù)需求進(jìn)行二次開發(fā)。對(duì)初學(xué)者而言借助該工具可完整走通遙感影像從輸入到智能分析的流程理解YOLO在目標(biāo)檢測(cè)任務(wù)中的回歸思想同時(shí)為模型部署和性能優(yōu)化提供參考。1. 遙感影像智能分析難點(diǎn)不在模型而在管線遙感影像智能分析這幾年幾乎被深度學(xué)習(xí)重寫了一遍從建筑物提取到道路分割再到農(nóng)田地塊識(shí)別公開模型在基準(zhǔn)數(shù)據(jù)集上一個(gè)賽一個(gè)漂亮。真正讓工程團(tuán)隊(duì)卡住的是管線一個(gè)基于深度學(xué)習(xí)的遙感影像智能分析工具面對(duì)的往往是一幅幾百 MB 甚至幾個(gè) GB 的 GeoTIFF多波段、16 bit、帶著地理參考直接扔進(jìn)用三通道 JPEG 訓(xùn)練的模型里第一行代碼就會(huì)報(bào)錯(cuò)。這個(gè)工具包要解決的就是這條從原始柵格到預(yù)測(cè)矢量圖的完整鏈路而不是重新發(fā)明一個(gè)網(wǎng)絡(luò)結(jié)構(gòu)。適合剛接觸遙感加深度學(xué)習(xí)組合的算法工程師、GIS 開發(fā)者和研究生把數(shù)據(jù)讀取、預(yù)處理、推理、后處理四段重復(fù)勞動(dòng)串成一條可復(fù)制的流水線。下面按這條流水線逐層拆開講再落到最小可運(yùn)行命令和參數(shù)調(diào)優(yōu)上最后給一條省標(biāo)注的進(jìn)階路徑。2. 拆開工具包從原始 TIF 到預(yù)測(cè)矢量圖的四個(gè)功能層拿到名為“基于深度學(xué)習(xí)的遙感影像智能分析工具.zip”這類壓縮包解壓后第一件事不是找可執(zhí)行文件而是判斷它的功能邊界。常見做法是把整條鏈路拆成四層數(shù)據(jù)讀取、預(yù)處理、模型推理、后處理導(dǎo)出。每一層職責(zé)單一層間只傳 numpy 數(shù)組和配置字典這樣你換傳感器、換模型、換輸出格式都不必把流程推倒重來(lái)。先確認(rèn)壓縮包本身完整。命令行解壓時(shí)遇到invalid zip archive: could not find eocd這類報(bào)錯(cuò)多數(shù)是下載中斷導(dǎo)致壓縮包尾部缺失重新下載一次通常比折騰修復(fù)工具更快。解壓后看目錄結(jié)構(gòu)如果包含data_loader、preprocess、model、postprocess之類的分包目錄基本就是上面的分層設(shè)計(jì)若沒有按這個(gè)思路重新組織一遍也行后面所有參數(shù)調(diào)整才有落點(diǎn)。2.1 數(shù)據(jù)讀取層?xùn)鸥癫皇且粡埰胀ㄕ掌b感影像讀取和普通圖片讀取完全不同。普通圖片解碼后是 HWC 順序的 uint8 數(shù)組遙感影像則是一個(gè)帶地理坐標(biāo)的多波段數(shù)組。波段順序可能是 RGB也可能是 BGR、RGBNIR多光譜甚至十幾個(gè)波段dtype 常見 uint16寬高動(dòng)輒幾萬(wàn)乘幾萬(wàn)像素。拿 PIL 的open去打開 GeoTIFF多半讀不全波段或者直接解碼失敗。import rasterio with rasterio.open(scene.tif) as src: img src.read() # (C, H, W)第 0 維是波段 profile src.profile # transform, crs, height, width, count, dtype bounds src.bounds print(波段數(shù):, img.shape[0], 尺寸:, img.shape[2], x, img.shape[1]) print(CRS:, profile[crs], 仿射變換:, profile[transform])這段代碼的邏輯很直接read()一次讀入全部波段profile保存寫出結(jié)果時(shí)必需的地理參考。注意read()返回的順序是 (C, H, W)和 PyTorch 輸入一致但與 OpenCV 習(xí)慣的 HWC 順序不同轉(zhuǎn)換時(shí)別把維數(shù)順序?qū)懛?。uint16 影像轉(zhuǎn) float32 后內(nèi)存直接翻倍處理超大影像前先估算一下16 bit 的單波段兩萬(wàn)乘兩萬(wàn)影像轉(zhuǎn)成 float32 就要占約 1.6 GB。拿到影像后第一件事不是寫模型而是確認(rèn)波段順序和坐標(biāo)系。很多坑都出在這一步有的影像文件頭標(biāo)著 RGB實(shí)際波段順序是 BGR有的 transform 是舊版本記錄問(wèn)題投影到 WGS84 會(huì)有整像素偏移。把profile和bounds打印存檔是這條流水線成本最低的第一個(gè)好習(xí)慣。2.2 預(yù)處理層切片、歸一化和內(nèi)存規(guī)劃預(yù)處理層解決三件事把不同來(lái)源的影像統(tǒng)一到相近的數(shù)值范圍把超大影像切成模型能吃下的 patch給每個(gè) patch 帶上在原圖的位置方便推理后拼回整幅。這里最容易忽視的是內(nèi)存規(guī)劃滑窗看起來(lái)簡(jiǎn)單實(shí)際一次性把幾千個(gè) patch 都放進(jìn)列表內(nèi)存會(huì)先被吃光。def sliding_window(img, tile_size512, overlap64): h, w img.shape[1], img.shape[2] step tile_size - overlap patches [] for y in range(0, h - tile_size 1, step): for x in range(0, w - tile_size 1, step): patches.append((y, x, img[:, y:ytile_size, x:xtile_size])) return patches tiles sliding_window(img) print(切片數(shù)量:, len(tiles), 每塊:, tiles[0][2].shape)滑窗函數(shù)是全流程里最值得反復(fù)調(diào)的一塊。tile_size由模型輸入尺寸和顯存共同決定常見值 256、512、1024遙感分割模型大多在 512 附近表現(xiàn)最穩(wěn)。overlap用于抵消邊緣預(yù)測(cè)誤差一般取 tile_size 的四分之一到八分之一64 或 128 是安全區(qū)間。overlap 太小拼接縫明顯太大推理時(shí)間幾乎翻倍。歸一化要單獨(dú)強(qiáng)調(diào)。遙感影像的直方圖差異極大同一片地在不同季節(jié)、不同傳感器下 DN 值可以差好幾倍。常見做法是用訓(xùn)練時(shí)統(tǒng)計(jì)的均值方差做標(biāo)準(zhǔn)化而不是簡(jiǎn)單除以 255。如果訓(xùn)練數(shù)據(jù)是 8 bit、推理影像是 16 bit要先做分位數(shù)截?cái)嘣倏s放否則模型看到的數(shù)值分布和訓(xùn)練時(shí)完全不同預(yù)測(cè)結(jié)果就會(huì)一片黑或者一片灰。2.3 推理層框架選型和批量大小推理層的職責(zé)是拿切好的 patch 和訓(xùn)練好的權(quán)重輸出逐像素類別概率。選型上有講究直接用 PyTorch 原生權(quán)重推理最省事但上生產(chǎn)環(huán)境更多人會(huì)先導(dǎo)出 ONNX 再切換到推理引擎因?yàn)?ONNX 對(duì)動(dòng)態(tài)尺寸和 CPU 指令集的適配更好部署時(shí)不依賴完整訓(xùn)練框架。工具包里如果同時(shí)給了.pth和.onnx優(yōu)先用 ONNX 做批量推理常見情況下能快兩到三成。import onnxruntime as ort import numpy as np tile_size 512 session ort.InferenceSession(model.onnx, providers[CPUExecutionProvider]) input_name session.get_inputs()[0].name pred_mask np.zeros((len(tiles), tile_size, tile_size), dtypenp.uint8) for i, (y, x, patch) in enumerate(tiles): tensor patch[None, ...].astype(np.float32) # (1, C, H, W) probs session.run(None, {input_name: tensor})[0] # (1, num_classes, H, W) pred_mask[i] probs[0].argmax(axis0)這里的關(guān)鍵參數(shù)是providers。有 N 卡時(shí)把CPUExecutionProvider換成CUDAExecutionProvider并在正式預(yù)測(cè)前跑一次 warmup否則第一次推理會(huì)卡幾秒。顯存足夠時(shí)一次喂 4 到 8 個(gè) patch比外層循環(huán)逐張推理效率高不少CPU 上也可以靠 numpy 批量計(jì)算稍微壓榨吞吐。逐 patch 單次session.run是最慢的寫法能避免就避免。還要注意類別數(shù)量。二分類模型輸出 1 通道、走 sigmoid多分類模型輸出num_classes通道。如果影像里明明有水、植、建筑、道路四類但模型只輸出三類通常不是推理代碼的問(wèn)題而是權(quán)重文件的類別數(shù)和訓(xùn)練標(biāo)簽不一致。這種不一致不會(huì)報(bào)錯(cuò)只會(huì)靜靜地少一類。2.4 輸出層把掩膜寫回帶坐標(biāo)的 TIF推理得到的是大量 patch 的類別索引下一步要拼回整幅影像并帶上原圖的地理參考寫出去。沒有坐標(biāo)的預(yù)測(cè)結(jié)果對(duì) GIS 同事來(lái)說(shuō)等于白做。拼回時(shí)要處理 overlap 區(qū)域直接一塊蓋一塊會(huì)產(chǎn)生接縫常見做法是累計(jì)求和后除以重疊權(quán)重。full_mask np.zeros((img.shape[1], img.shape[2]), dtypenp.float32) weight np.zeros((img.shape[1], img.shape[2]), dtypenp.float32) for i, (y, x, patch) in enumerate(tiles): full_mask[y:ypatch.shape[1], x:xpatch.shape[2]] pred_mask[i] weight[y:ypatch.shape[1], x:xpatch.shape[2]] 1 full_mask full_mask / np.maximum(weight, 1) out_meta profile.copy() out_meta.update(dtypeuint8, count1, compresslzw) with rasterio.open(pred_mask.tif, w, **out_meta) as dst: dst.write(full_mask.astype(np.uint8), 1)寫回有兩個(gè)高頻錯(cuò)點(diǎn)。一是out_meta必須在打開原圖時(shí)保存寫入時(shí)只改 dtype 和 counttransform 與 crs 保持原樣否則在 QGIS 里疊不到原圖上。二是壓縮算法類別索引圖重復(fù)值多用 LZW 往往能把幾百 MB 壓到幾十 MB。如果還需要矢量輸出先用 GDAL 的 polygonize 轉(zhuǎn)矢量再做邊緣簡(jiǎn)化這一步在避坑章節(jié)里單說(shuō)。3. 跑通最小用例用公開數(shù)據(jù)做一次建筑物提取目標(biāo)定為一小時(shí)跑出第一張預(yù)測(cè)圖。環(huán)境用常見 CPU 方案數(shù)據(jù)用一張公開高分影像模型用現(xiàn)成的語(yǔ)義分割權(quán)重。以建筑物提取為例因?yàn)楣_數(shù)據(jù)多、驗(yàn)證直觀流程推通后換成農(nóng)田地塊識(shí)別只是換權(quán)重和類別數(shù)的事。下面分環(huán)境、推理、驗(yàn)證三步。3.1 環(huán)境準(zhǔn)備深度學(xué)習(xí)環(huán)境配置的幾個(gè)注意點(diǎn)建議配置Python 3.9 PyTorch CPU 版 rasterio onnxruntime。GPU 不是必需有 N 卡就把 torch 換成 CUDA 版推理時(shí)間能縮小一個(gè)數(shù)量級(jí)。嚴(yán)格做環(huán)境管理用 conda別給系統(tǒng) Python 添亂。想補(bǔ)理論基礎(chǔ)的翻翻“動(dòng)手學(xué)深度學(xué)習(xí)”里環(huán)境配置和圖像分類那幾章對(duì)照著改成遙感場(chǎng)景完全夠用。conda create -n rs_ai python3.9 -y conda activate rs_ai pip install torch --index-url https://download.pytorch.org/whl/cpu pip install rasterio onnxruntime opencv-python-headless numpy--index-url指定 CPU 版 torch文件小、不依賴 CUDA 驅(qū)動(dòng)opencv-python-headless是無(wú) GUI 依賴的服務(wù)器版遙感批量推理不需要彈窗預(yù)覽用它比opencv-python干凈。內(nèi)網(wǎng)離線環(huán)境就用pip download拉到本地后再內(nèi)網(wǎng)安裝比在目標(biāo)機(jī)上源碼編譯省太多時(shí)間。有云 GPU 平臺(tái)的話把 conda 環(huán)境打包傳上去省掉重復(fù)裝依賴的半個(gè)鐘。3.2 最小推理腳本切片、逐塊預(yù)測(cè)、拼接寫盤把上一章的四段邏輯串成完整腳本。數(shù)據(jù)用公開高分影像權(quán)重?fù)Q成你手里在建筑物數(shù)據(jù)上訓(xùn)練好的 ONNX。暫時(shí)沒有權(quán)重就先用一個(gè)建筑/非建筑二分類權(quán)重把流程跑通再談精度。import rasterio import numpy as np import onnxruntime as ort TILE_SIZE 512 OVERLAP 64 MEAN np.array([0.485, 0.456, 0.406], dtypenp.float32) STD np.array([0.229, 0.224, 0.225], dtypenp.float32) with rasterio.open(scene.tif) as src: img src.read()[:3].astype(np.float32) # 只取 RGB 三個(gè)波段 profile src.profile img (img - MEAN[:, None, None]) / STD[:, None, None] sess ort.InferenceSession(building_seg.onnx, providers[CPUExecutionProvider]) step TILE_SIZE - OVERLAP h, w img.shape[1], img.shape[2] mask np.zeros((h, w), dtypenp.uint8) for y in range(0, h - TILE_SIZE 1, step): for x in range(0, w - TILE_SIZE 1, step): tile img[:, y:yTILE_SIZE, x:xTILE_SIZE][None, ...] pred sess.run(None, {sess.get_inputs()[0].name: tile})[0] mask[y:yTILE_SIZE, x:xTILE_SIZE] pred[0].argmax(axis0).astype(np.uint8) out_meta profile.copy() out_meta.update(dtypeuint8, count1, compresslzw) with rasterio.open(pred.tif, w, **out_meta) as dst: dst.write(mask, 1) print(輸出 pred.tif類別數(shù):, mask.max() 1)邏輯不復(fù)雜讀 RGB 三波段用訓(xùn)練集均值方差做標(biāo)準(zhǔn)化再滑窗逐塊預(yù)測(cè)每塊取 argmax 寫回對(duì)應(yīng)位置。兩個(gè)必須注意的參數(shù)是MEAN和STD要用所屬權(quán)重訓(xùn)練時(shí)統(tǒng)計(jì)的值不能隨手填 ImageNet 默認(rèn)值否則預(yù)測(cè)結(jié)果整體偏移。TILE_SIZE應(yīng)該與模型輸入保持一致亂改會(huì)遭遇未經(jīng)驗(yàn)證的尺寸變化邊緣預(yù)測(cè)明顯變糊。腳本里 overlap 只有 64重疊區(qū)寫回時(shí)按最后一個(gè) patch 覆蓋所以拼接處會(huì)有輕度接縫這很正常下一章講怎么消。3.3 驗(yàn)證結(jié)果別只看一眼要和人工標(biāo)注對(duì)齊跑出pred.tif后先在 QGIS 里疊加到原圖上看邊界再抽一小塊區(qū)域和人工標(biāo)注算 IOU。肉眼判斷在建筑物這種輪廓清晰的類別上會(huì)騙人模型邊緣略圓潤(rùn)時(shí)只覺得“差不多”定量一算可能才 0.6。gdal_translate -srcwin 1000 1000 1000 1000 pred.tif pred_sample.tifgdal_translate的-srcwin按像素取子集適合快速抽樣參數(shù)依次是左上角行列號(hào)、窗口寬高。驗(yàn)證時(shí)注意預(yù)訓(xùn)練權(quán)重在它自己的數(shù)據(jù)集上 IOU 常超 0.8換到新影像掉到 0.5 以下很常見。先檢查影像的 GSD 是否與訓(xùn)練數(shù)據(jù)匹配再檢查歸一化參數(shù)有沒有傳對(duì)最后才懷疑模型本身。4. 參數(shù)調(diào)整影響結(jié)果精度的五個(gè)關(guān)鍵旋鈕模型結(jié)構(gòu)定了之后真正決定落地效果的是下面幾個(gè)參數(shù)。它們不改變網(wǎng)絡(luò)層數(shù)卻經(jīng)常能讓誤檢率掉一半。按影響從大到小排逐個(gè)講清楚為什么有效、怎么調(diào)。4.1 切片尺寸與重疊度顯存和拼接縫的平衡tile_size決定模型感受野大小。512 是大多數(shù)遙感分割模型的甜點(diǎn)值256 對(duì)小目標(biāo)敏感但上下文不足細(xì)長(zhǎng)道路容易斷1024 需要至少 8 GB 顯存CPU 推理慢得讓人失去耐心。選型時(shí)先看權(quán)重訓(xùn)練時(shí)用的 patch 尺寸訓(xùn)練 512 推理也 512別為了保邊緣改成 1024。overlap至少要覆蓋模型感受野的一半64 到 128 像素是安全區(qū)。切換數(shù)據(jù)集時(shí)這套參數(shù)要和訓(xùn)練設(shè)置保持一致否則模型看到的上下文分布變了邊界類會(huì)亂跳。4.2 歸一化方式線性拉伸還是均值方差標(biāo)準(zhǔn)化遙感影像直方圖差異大同一區(qū)域夏季和冬季的亮度能差數(shù)倍。線性拉伸適合目視解譯把 2% 到 98% 分位數(shù)映射到 0 到 255而基于均值方差的標(biāo)準(zhǔn)化才是給神經(jīng)網(wǎng)絡(luò)用的標(biāo)準(zhǔn)做法因?yàn)橛?xùn)練數(shù)據(jù)正是在同一分布上統(tǒng)計(jì)的。16 bit 影像有個(gè)很常見的坑直接除以 65535 通常會(huì)整體偏暗因?yàn)橄袼囟级言诘椭刀?。正確做法是先用 1% 到 99% 分位數(shù)截?cái)嘣僮鰳?biāo)準(zhǔn)化等于先抑掉椒鹽噪聲和高光飽和。4.3 推理閾值二分類和多分類的調(diào)法不一樣二分類模型的概率閾值默認(rèn) 0.5但在建筑物提取、道路提取場(chǎng)景0.45 和 0.55 的結(jié)果差異可能很大。閾值調(diào)低找回細(xì)碎目標(biāo)但虛警變多調(diào)高邊緣更干凈但漏檢更多。別拍腦袋定閾值在驗(yàn)證集上從 0.3 到 0.6 掃一遍畫 IOU 曲線選最高點(diǎn)。多分類模型用 argmax 取類別沒有閾值問(wèn)題但可以加最小置信度過(guò)濾例如概率低于 0.7 的像素置為背景。代價(jià)是陰影遮擋的真實(shí)目標(biāo)可能被濾掉適合背景不重要的場(chǎng)景。4.4 形態(tài)學(xué)后處理先補(bǔ)空洞再按連通域過(guò)濾預(yù)測(cè)掩膜里最典型的噪聲是小碎塊和內(nèi)部空洞。閉運(yùn)算能填掉建筑內(nèi)部漏檢的小洞按連通域面積過(guò)濾能刪掉道路旁零星噪聲。順序必須先把空洞補(bǔ)上再做面積過(guò)濾否則面積統(tǒng)計(jì)不穩(wěn)定。import cv2 import numpy as np mask (mask 0).astype(np.uint8) kernel cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5)) mask cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel) num, labels, stats, _ cv2.connectedComponentsWithStats(mask) area_thresh 20 keep np.where(stats[:, 4] area_thresh)[0] mask np.isin(labels, keep).astype(np.uint8)MORPH_CLOSE是用 5×5 結(jié)構(gòu)元先膨脹后腐蝕把細(xì)小孔洞填平connectedComponentsWithStats統(tǒng)計(jì)每個(gè)連通域面積小于area_thresh的置 0。核心參數(shù)是area_thresh它由影像地面分辨率決定0.5 米分辨率影像上一棟一百平米的房子約 400 像素2 米分辨率只有 25 像素按實(shí)際 GSD 換算別固定給 20。4.5 類別不均衡先看占比再?zèng)Q定改損失還是改采樣遙感影像類別天然不均衡水體、植被占地多房子、道路占地少。用交叉熵訓(xùn)練時(shí)小類別的梯度被大類淹沒結(jié)果就是小目標(biāo)類別輸出近乎全黑。判斷方法是數(shù)標(biāo)簽文件里各類別像素占比相差兩個(gè)數(shù)量級(jí)基本就是這個(gè)原因。解決辦法是過(guò)采樣加損失函數(shù)調(diào)整兩者一起用比只調(diào)一樣有效。比如滑窗時(shí)強(qiáng)制讓小類別像素出現(xiàn)在一定比例的窗口里訓(xùn)練損失換成帶 focal loss 的變體難樣本貢獻(xiàn)更大梯度。這個(gè)參數(shù)藏在訓(xùn)練腳本里不屬推理配置但它決定了你推理閾值怎么調(diào)。5. 遙感影像深度學(xué)習(xí)避坑實(shí)錄5 個(gè)必須排查的翻車場(chǎng)景把前面幾章放到真實(shí)項(xiàng)目里下面的坑幾乎人人都踩過(guò)。按現(xiàn)象、原因、解決三段寫照順序排查比盲目調(diào)參快。5.1 現(xiàn)象預(yù)測(cè)結(jié)果是一塊塊馬賽克每塊中央準(zhǔn)、邊緣錯(cuò)原因滑窗推理時(shí) overlap 太小邊緣預(yù)測(cè)被直接丟棄最后拼接又沒有做融合。模型在 patch 邊緣的表現(xiàn)天生比中央差這是卷積填充造成的邊界效應(yīng)不是過(guò)擬合。現(xiàn)象最典型的特點(diǎn)就是每塊中央輪廓清晰靠近塊邊界的線狀目標(biāo)連續(xù)斷開。解決overlap 提高到 tile_size 的四分之一并在拼接時(shí)做加權(quán)平均讓每塊中央的預(yù)測(cè)權(quán)重高于邊緣。簡(jiǎn)單實(shí)現(xiàn)是保存一張距離權(quán)重圖中央為 1邊緣線性衰減到 0.2重疊區(qū)按權(quán)重混合。邊緣不整除時(shí)常見做法是補(bǔ)零預(yù)測(cè)再按真實(shí)長(zhǎng)度裁回不要整塊丟棄否則窄條目標(biāo)直接消失。5.2 現(xiàn)象水域被當(dāng)成建筑物陰影里全是道路原因訓(xùn)練數(shù)據(jù)沒覆蓋這類光譜特征。水體在近紅外波段的表現(xiàn)和建筑物陰影在某些波段下很接近模型的決策邊界在訓(xùn)練數(shù)據(jù)分布內(nèi)是合理的一出分布就翻車。這是最典型的訓(xùn)練域偏移和玄學(xué)無(wú)關(guān)想清楚光譜分布就能定位。解決影像含近紅外波段時(shí)把它加入輸入通道模型可以用 NDVI 這類指數(shù)區(qū)分水體與植被減少誤分。把陰影單獨(dú)當(dāng)一個(gè)類別也是常見做法后處理階段再按幾何特征過(guò)濾掉細(xì)長(zhǎng)虛警。核心是給模型增加光譜維度的區(qū)分信息而不是簡(jiǎn)單堆訓(xùn)練數(shù)據(jù)。5.3 現(xiàn)象幾 GB 影像在 CPU 推理時(shí)內(nèi)存爆炸原因代碼里src.read()一次讀掉整幅影像加上 float32 轉(zhuǎn)換和幾千個(gè) patch 的列表內(nèi)存峰值能到原始文件的十倍。很多演示腳本默認(rèn)你有 32 GB 內(nèi)存實(shí)際跑的時(shí)候才發(fā)現(xiàn)不夠。解決改成窗口按需讀取用 rasterio 的Window一次只讀一個(gè) patch 需要的矩形patch 用完即丟。大圖也可以寫進(jìn)np.memmap讓操作系統(tǒng)管換頁(yè)滑窗與讀取同步進(jìn)行內(nèi)存能壓到 1 GB 以下。with rasterio.open(scene.tif) as src: for y in range(0, h - TILE_SIZE 1, step): for x in range(0, w - TILE_SIZE 1, step): window rasterio.windows.Window(x, y, TILE_SIZE, TILE_SIZE) tile src.read(windowwindow)[:3]注意Window參數(shù)順序是 x 在前、y 在后也就是先列后行容易和 numpy 里[y, x]的習(xí)慣搞混寫反了照樣能讀出數(shù)據(jù)只是位置完全錯(cuò)位且不報(bào)錯(cuò)。5.4 現(xiàn)象矢量化輸出的多邊形邊緣鋸齒明顯面積統(tǒng)計(jì)偏大原因預(yù)測(cè)掩膜逐像素邊界不平滑矢量化后自然鋸齒再摻進(jìn)零碎噪聲點(diǎn)面積會(huì)被放大。GIS 里直接用這種矢量統(tǒng)計(jì)面積誤差能超過(guò) 10%。解決矢量化前先做一次中值濾波或形態(tài)學(xué)開閉運(yùn)算再用 GDAL 的 Simplify 做頂點(diǎn)抽稀tolerance 取 1 到 3 個(gè)像素肉眼幾乎看不出損失文件體積小很多。統(tǒng)計(jì)面積時(shí)一定要轉(zhuǎn)投影坐標(biāo)系再計(jì)算直接拿經(jīng)緯度算面積結(jié)果沒有參考價(jià)值。5.5 現(xiàn)象訓(xùn)練損失一直在降但驗(yàn)證集的小目標(biāo)類別全黑原因類別分布失衡損失被多數(shù)類主導(dǎo)模型學(xué)到了“全預(yù)測(cè)成背景損失也不高”這條捷徑。這是遙感標(biāo)注數(shù)據(jù)里最常見的結(jié)構(gòu)性問(wèn)題目標(biāo)越細(xì)小越容易踩中。解決損失換成 Focal Loss 或 Lovász-Softmax讓模型更關(guān)注難樣本同時(shí)抽 patch 時(shí)提升包含小類別樣本的窗口比例相當(dāng)于過(guò)采樣。兩件事一起做效果最好把道路類像素覆蓋的 patch 比例從自然分布的 10% 提到 30%小類別 IOU 往往能翻一倍。驗(yàn)證時(shí)除了看整體 IOU還要分別看每個(gè)類別的 IOU整體分?jǐn)?shù)會(huì)掩蓋小類別的災(zāi)難。6. 進(jìn)階局部聚焦輔助標(biāo)注把人工標(biāo)注成本降下來(lái)推理流程穩(wěn)定后下一步通常是對(duì)新區(qū)域做標(biāo)注和增量訓(xùn)練。這時(shí)人工逐像素畫邊界成本會(huì)迅速超過(guò)工具本身的價(jià)值。常見做法是局部聚焦輔助標(biāo)注用已有模型先預(yù)測(cè)再讓標(biāo)注員只修正低置信度區(qū)域而不是從頭畫起。流程如下。先用現(xiàn)有模型對(duì)新影像預(yù)測(cè)并生成掩膜再把掩膜轉(zhuǎn)成半透明疊加層疊加在原圖上。然后把影像和掩膜同時(shí)切成小窗口按模型置信度排序標(biāo)注任務(wù)置信度高的窗口由軟件自動(dòng)確認(rèn)置信度低的碎塊、邊緣和誤檢區(qū)域才推給人工修正。每個(gè)標(biāo)注任務(wù)只放大顯示一個(gè)目標(biāo)及小范圍上下文人工框選或局部重畫即可。關(guān)鍵在設(shè)計(jì)低置信度窗口的篩選規(guī)則常見實(shí)現(xiàn)是統(tǒng)計(jì)每塊 patch 中低于概率閾值的像素占比超過(guò) 5% 就進(jìn)入人工隊(duì)列。這套流程省下的時(shí)間相當(dāng)可觀。一名熟練標(biāo)注員一天精標(biāo) 5 到 8 平方公里的建筑物用輔助標(biāo)注在建成區(qū)這類模型表現(xiàn)好的場(chǎng)景能做到 20 到 30 平方公里高密度城中村這類模型常翻車的場(chǎng)景也能省下一半工作量。省下來(lái)的人力要投到困難樣本收集上也就是模型低置信度或預(yù)測(cè)錯(cuò)誤的 patch這才是持續(xù)提升精度的增量來(lái)源。我的習(xí)慣是每輪輔助標(biāo)注后統(tǒng)計(jì)人工修正比例。低于 10%說(shuō)明模型在這個(gè)區(qū)域基本夠用可以擴(kuò)大覆蓋范圍高于 40%先回頭看訓(xùn)練數(shù)據(jù)分布和歸一化參數(shù)把模型底子修好再繼續(xù)。這個(gè)比例就是判斷值不值得繼續(xù)投入的標(biāo)尺。把帶坐標(biāo)的輔助標(biāo)注樣本喂回訓(xùn)練集重訓(xùn)一輪再用新模型跑新一輪預(yù)測(cè)循環(huán)往復(fù)。我自己在遙感影像智能分析這個(gè)方向上的經(jīng)驗(yàn)是真正卡住項(xiàng)目進(jìn)度的很少是網(wǎng)絡(luò)結(jié)構(gòu)而是數(shù)據(jù)、歸一化參數(shù)和后處理流程這些細(xì)節(jié)。希望這條基于深度學(xué)習(xí)的遙感影像智能分析落地路徑能幫到你。本文還有配套的精品資源點(diǎn)擊獲取