【Python&RS】基于GDAL的遥感影像压缩

发布时间 2023-06-28 09:53:09作者: RS然

        最近在处理一些高空间分辨率的卫星数据,数据量非常大。一个图幅都几十个G,ENVI表示压力太大了根本跑不动。所以研究了一下影像压缩的方式,在ArcGIS导出的压缩方式有很多限制,而且压缩并不是很明显。

        所以我尝试使用GDAL库对影像进行压缩,速度还可以,至少不会向ArcGIS一样未响应。压缩之后效果跟ArcGIS差不多,但是也达不到十几个G,压缩成几百兆的效果。毕竟遥感影像最重要的就是像素值,别为了压缩牺牲了质量,这就得不偿失了。

一、安装三方库

import os
from osgeo import gdal

二、压缩函数

        这里使用到GDAL的CreateCopy函数,在这里面可以设置压缩的参数。网上有很多人说LZW的压缩效果比PACKBITS好,但我在实测中发现PACKBITS的效果更好一点,可能因影像而已吧。不过庆幸的是两者都是无损压缩,我对比了压缩前后的像素值,均为一致的。

def Image_Compress(path_image, path_out_image):
    """
    :param path_image: 输入需要压缩的影像路径
    :param path_out_image: 输出压缩后的影像路径
    :return: None
    """
    ds = gdal.Open(path_image)
    # 打开影像数据
    driver = gdal.GetDriverByName('GTiff')
    # 创建输出的数据驱动
    driver.CreateCopy(path_out_image, ds, strict=1, callback=Show_Progress,
                      options=["TILED=YES", "COMPRESS=PACKBITS", "BIGTIFF=YES"])
    # 设置压缩参数
    """
    PACKBITS:连续字节压缩,快速无损压缩
    LZW:所有信息全部保留(可逆),以某一数值代替字符串,快速无损压缩
    """
    del ds

三、回调函数(显示进度)

        这个可以没有,将第压缩函数中的callback参数删除即可。作用就是用来显示压缩进度的。

def Show_Progress(percent, msg, tag):
    """
    :param percent: 进度,0~1
    :param msg:
    :param tag:
    :return:
    """
    if 0 <= percent * 100 <= 1:
        print("进度:" + "%.2f" % (0 * 100) + "%")
    if 25 <= percent*100 <= 26:
        print("进度:" + "%.2f" % (percent*100) + "%")
    if 50 <= percent*100 <= 51:
        print("进度:" + "%.2f" % (percent*100) + "%")
    if 75 <= percent*100 <= 76:
        print("进度:" + "%.2f" % (percent*100) + "%")
    if 99 <= percent * 100 <= 100:
        print("进度:" + "%.2f" % (1 * 100) + "%")

四、压缩效果展示

        这里用到了os的getsize函数,用来直观的显示压缩前后的空间占用率,当然也可以不要。纯属为了水一水字数(手动滑稽)。

def Get_Size(path_file):
    """
    :param path_file: 需要压缩影像的路径
    :return: 返回占用多少M
    """
    size = os.path.getsize(path_file)
    size = size / float(1024 * 1024)
    return round(size, 2)

五、完整代码

# -*- coding: utf-8 -*-
"""
@Time : 2023/6/20 14:20
@Auth : RS迷途小书童
@File :Image Compression.py
@IDE :PyCharm
@Purpose :遥感影像压缩
"""
import os
from osgeo import gdal


def Show_Progress(percent, msg, tag):
    """
    :param percent: 进度,0~1
    :param msg:
    :param tag:
    :return:
    """
    if 0 <= percent * 100 <= 1:
        print("进度:" + "%.2f" % (0 * 100) + "%")
    if 25 <= percent*100 <= 26:
        print("进度:" + "%.2f" % (percent*100) + "%")
    if 50 <= percent*100 <= 51:
        print("进度:" + "%.2f" % (percent*100) + "%")
    if 75 <= percent*100 <= 76:
        print("进度:" + "%.2f" % (percent*100) + "%")
    if 99 <= percent * 100 <= 100:
        print("进度:" + "%.2f" % (1 * 100) + "%")


def Image_Compress(path_image, path_out_image):
    """
    :param path_image: 输入需要压缩的影像路径
    :param path_out_image: 输出压缩后的影像路径
    :return: None
    """
    ds = gdal.Open(path_image)
    # 打开影像数据
    driver = gdal.GetDriverByName('GTiff')
    # 创建输出的数据驱动
    driver.CreateCopy(path_out_image, ds, strict=1, callback=Show_Progress,
                      options=["TILED=YES", "COMPRESS=PACKBITS", "BIGTIFF=YES"])
    # 设置压缩参数
    """
    PACKBITS:连续字节压缩,快速无损压缩
    LZW:所有信息全部保留(可逆),以某一数值代替字符串,快速无损压缩
    """
    del ds


def Get_Size(path_file):
    """
    :param path_file: 需要压缩影像的路径
    :return: 返回占用多少M
    """
    size = os.path.getsize(path_file)
    size = size / float(1024 * 1024)
    return round(size, 2)


if __name__ == "__main__":
    path_input = "B:\sharpening1"
    path_output = "B:\sharpening1.tif"
    print("开始压缩......")
    Image_Compress(path_input, path_output)
    print("压缩已完成......")
    print("压缩前:%sMB" % Get_Size(path_input))
    print("压缩后:%sMB" % Get_Size(path_output))

 

        遥感影像的压缩其实还是非常重要的,当然重中之重肯定还是无损!压缩。同样,对于高光谱数据的降维其实也是为了提高工作效率,减少数据的冗余。所以多学多看吧,任重道远!

        如果大家在学习Python或者RS时有什么问题,可以随时留言交流!如果大家对批量处理有兴趣同样可以留言给博主,博主会分享相关代码以供学习!