You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GeoTIFF文件中地理空间数据混合数据类型的处理方案

多数据类型波段GeoTIFF保存方案

问题场景

处理2字节双波段GeoTIFF影像时,需要生成Float32格式的比值派生波段(第一波段/第二波段),但直接堆叠保存会导致所有波段被统一转换为Float32类型。要求在单个GeoTIFF文件中保留原双波段的2字节数据类型,同时新增Float32格式的第三波段,使用Python的GDAL和Rasterio库实现。

尝试代码(Rasterio)

with rasterio.open("image.tif") as src:
    data = src.read()
    profile = src.profile
    meta = src.meta.copy()
    band_count = src.count

third_band = (data[0].astype('float32'))/((data[1].astype('float32')) + 1e-6)

with rasterio.open("output_img.tif", "w", **meta) as dst:
  dst.write(data[0], 1)
  dst.write(data[1], 2)
  dst.write(third_band, 3)

解决方法

方法一:Rasterio逐波段指定数据类型

Rasterio默认元数据中的dtype是全局统一设置,需删除全局dtype配置,在写入每个波段时单独指定对应的数据类型:

import rasterio

with rasterio.open("image.tif") as src:
    # 单独读取原波段数据
    band1 = src.read(1)
    band2 = src.read(2)
    # 复制元数据并更新波段数
    meta = src.meta.copy()
    meta.update(count=3)
    # 删除全局dtype,允许逐波段设置类型
    del meta['dtype']

# 计算Float32格式的比值波段
third_band = (band1.astype('float32')) / (band2.astype('float32') + 1e-6)

with rasterio.open("output_img.tif", "w", **meta) as dst:
    # 写入原波段,指定原数据类型
    dst.write(band1, 1, dtype=src.dtypes[0])
    dst.write(band2, 2, dtype=src.dtypes[1])
    # 写入第三波段,指定Float32类型
    dst.write(third_band, 3, dtype='float32')

方法二:GDAL逐波段定义数据类型

GDAL支持在创建数据集时为每个波段单独指定数据类型,步骤如下:

from osgeo import gdal

# 打开原影像
src_ds = gdal.Open("image.tif")
if src_ds is None:
    raise Exception("无法打开目标影像文件")

# 获取原影像的地理参数
proj = src_ds.GetProjection()
geotrans = src_ds.GetGeoTransform()
width = src_ds.RasterXSize
height = src_ds.RasterYSize
# 获取原波段的原生数据类型
band1_dtype = src_ds.GetRasterBand(1).DataType
band2_dtype = src_ds.GetRasterBand(2).DataType

# 创建输出GeoTIFF数据集
driver = gdal.GetDriverByName("GTiff")
dst_ds = driver.Create("output_img.tif", width, height, 3, options=["COMPRESS=LZW"])
if dst_ds is None:
    raise Exception("无法创建输出影像文件")

# 设置投影和地理变换
dst_ds.SetProjection(proj)
dst_ds.SetGeoTransform(geotrans)

# 写入第一波段(保留原数据类型)
dst_band1 = dst_ds.GetRasterBand(1)
dst_band1.SetRasterDataType(band1_dtype)
dst_band1.WriteArray(src_ds.GetRasterBand(1).ReadAsArray())

# 写入第二波段(保留原数据类型)
dst_band2 = dst_ds.GetRasterBand(2)
dst_band2.SetRasterDataType(band2_dtype)
dst_band2.WriteArray(src_ds.GetRasterBand(2).ReadAsArray())

# 计算并写入第三波段(Float32类型)
band1_data = src_ds.GetRasterBand(1).ReadAsArray().astype('float32')
band2_data = src_ds.GetRasterBand(2).ReadAsArray().astype('float32')
third_band = band1_data / (band2_data + 1e-6)
dst_band3 = dst_ds.GetRasterBand(3)
dst_band3.SetRasterDataType(gdal.GDT_Float32)
dst_band3.WriteArray(third_band)

# 释放资源
src_ds = None
dst_ds = None

内容的提问来源于stack exchange,提问作者user31404131

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 10:16:18