【Python&RS】栅格数据/图片位深度(bit)转换

发布时间 2024-01-05 19:34:19作者: RS迷途小书童

        关于栅格数据/图片的位深度(eg.8bit、16bit、32bit)转换之前我就发过一篇文章,【Python&RS】基于GDAL栅格数据/图片位深度(bit)转换。但是最近在使用的时候发现好像效果不行,有时候转换不成功,所以自己又研究了一下原理重新写了一份代码。今天就和大家分享一下如何使用Python对图片的位深度进行转换。

1 读取图片位深度信息

        通过这个函数可以帮助我们在进行位深数转换之前了解图片的基本信息。

def Read_Bit(image_path):
    ds = gdal.Open(image_path)
    # 获取第一个波段
    data_type = gdal.GetDataTypeName(ds.GetRasterBand(1).DataType).lower()
    # 获取位深度信息
    print("图像的位深度为:", data_type)

2 Python代码

        原理呢其实就是将图片的数组除以当前位深数再乘以目标位深数范围即可,就和归一化的原理差不多。

# -*- coding: utf-8 -*-
"""
@Time : 2024/1/4 10:19
@Auth : RS迷途小书童
@File :Raster Data Bit Converse.py
@IDE :PyCharm
@Purpose:多波段栅格数据位深数转换
@Web:博客地址:https://blog.csdn.net/m0_56729804
"""
import os
import numpy as np
from osgeo import gdal


def Repair_Bit(filepath, out_path):
    print("-------------------------------------Bit转换-------------------------------------")
    ds = gdal.Open(filepath)  # 打开数据集dataset
    ds_width = ds.RasterXSize  # 获取数据宽度
    ds_height = ds.RasterYSize  # 获取数据高度
    ds_geo = ds.GetGeoTransform()  # 获取仿射地理变换参数
    ds_prj = ds.GetProjection()  # 获取投影信息
    driver = gdal.GetDriverByName('GTiff')  # 载入数据驱动,用于存储内存中的数组
    ds_result = driver.Create(out_path, ds_width, ds_height, bands=ds.RasterCount, eType=gdal.GDT_Int16)
    print("正在遍历影像所有波段......")
    for i in range(1, ds.RasterCount):  # 遍历所有波段
        array_band = ds.GetRasterBand(i).ReadAsArray(0, 0, ds_width, ds_height).astype(np.float32)
        array_result = array_band/4294967295.0*65535.0  # 32位转16位
        # int8  [-128, 127]
        # int16 [-32768, 32767]
        # int32 [-2147483648, 2147483647]
        # int64 [-9223372036854775808, 9223372036854775807]
        # uint8  [0, 255]
        # uint16 [0, 65535]
        # uint32 [0, 4294967295]
        # uint64 [0, 18446744073709551615]
        ds_result.GetRasterBand(i).WriteArray(array_result)  # 将结果写入数组
        array_result = None
        del array_result
    ds_result.SetGeoTransform(ds_geo)  # 导入仿射地理变换参数
    ds_result.SetProjection(ds_prj)  # 导入投影信息
    ds_result.GetRasterBand(1).SetNoDataValue(0)  # 将无效值设为0
    del ds_result
    # 删除内存中的结果,否则结果不会写入图像中
    print("当前影像位深数转换已完成......")


if __name__ == "__main__":
    print("\n")
    gdal.PushErrorHandler('CPLQuietErrorHandler')
    image_path1 = r"彭俊喜/1/"
    out_path1 = r"彭俊喜/2/"
    path = os.listdir(image_path1)
    for image in path:
        if image.endswith(".tif"):
            print("正在处理", image)
            Repair_Bit(image_path1+image, out_path1+image)
    print("--------------------------------------程序结束--------------------------------------")

3 总结

        这个方法呢我用的还可以,但是要注意输入数据的格式是否满足对应位深数。比如有的数据是16位的,但它的像素值却不是0-65535,这个时候可能就需要现在数据还原成16位的范围才可以转换成功。