處理步驟
1.從顏色分類的 RGB 影像中取得所有像素
2. 過濾白色背景區域
3. 使用 K-Means RGB Centroid 進行色彩匹配
4. 將像素映射為指定的 數值分類值
5. 產生可用於 QGIS、ArcGIS、Python 的 GeoTIFF 數值影像
6. 完整設定 NoData、座標系、像元大小
import numpy as np
from osgeo import gdal, gdalconst
# ---------------------------------------------------
# 1. 路徑設定
# ---------------------------------------------------
input_path = r"D:\download\87ad4ea7-158c-4f27-9911-57fa9c1ebb472_modified.tif"
output_path = r"D:\download\value.tif"
# ---------------------------------------------------
# 2. 讀取 RGB 影像
# ---------------------------------------------------
ds = gdal.Open(input_path, gdalconst.GA_ReadOnly)
if ds is None:
raise Exception("❌ 無法開啟輸入 TIFF")
R = ds.GetRasterBand(1).ReadAsArray().astype(np.float32)
G = ds.GetRasterBand(2).ReadAsArray().astype(np.float32)
B = ds.GetRasterBand(3).ReadAsArray().astype(np.float32)
rows, cols = R.shape
pixels = np.stack([R.flatten(), G.flatten(), B.flatten()], axis=1)
# ---------------------------------------------------
# 3. 白色背景過濾(非常重要)
# ---------------------------------------------------
# 白底 = RGB 皆 > 225
bg_mask = (pixels[:,0] > 225) & (pixels[:,1] > 225) & (pixels[:,2] > 225)
# 非背景像素
non_bg_pixels = pixels[~bg_mask]
print("原始像素:", len(pixels))
print("非背景像素(有效區域):", len(non_bg_pixels))
# ---------------------------------------------------
# 4. 使用 K-Means 得到的 RGB centroid
# ---------------------------------------------------
centroids = np.array([
[117, 249, 20], # 群 0 → 32.5
[237, 28, 64], # 群 1 → 45
[148, 202, 235], # 群 2 → 10
[231, 224, 30], # 群 3 → 37.5
[ 19, 24, 20], # 群 4 → NoData
[ 56, 245, 161], # 群 5 → 27.5
[102, 97, 227], # 群 6 → 22.5
], dtype=np.float32)
mapping = {
0: 32.5,
1: 45,
2: 10,
3: 37.5,
4: -9999,
5: 27.5,
6: 22.5
}
# ---------------------------------------------------
# 5. 計算 pixel → 最近 centroid
# ---------------------------------------------------
dist = ((pixels[:, None, :] - centroids[None, :, :]) ** 2).sum(axis=2)
cluster_idx = np.argmin(dist, axis=1)
# ---------------------------------------------------
# 6. 對背景像素直接指定為 -9999
# ---------------------------------------------------
value_arr = np.vectorize(mapping.get)(cluster_idx)
value_arr[bg_mask] = -9999
value_arr = value_arr.reshape(rows, cols).astype(np.float32)
# ---------------------------------------------------
# 7. 輸出 GeoTIFF
# ---------------------------------------------------
driver = gdal.GetDriverByName("GTiff")
out_ds = driver.Create(output_path, cols, rows, 1, gdalconst.GDT_Float32)
out_ds.SetGeoTransform(ds.GetGeoTransform())
out_ds.SetProjection(ds.GetProjection())
band = out_ds.GetRasterBand(1)
band.WriteArray(value_arr)
band.SetNoDataValue(-9999)
band.FlushCache()
del out_ds
print("🎉 已完成:輸出數值影像 →", output_path)
沒有留言:
張貼留言