ROI裁剪--基于python

从一个大的 TIFF 图像文件中裁剪出一个小的区域,并将该区域保存为新的 TIFF 文件。这个过程通常被称为 “region of interest” (ROI) 裁剪。

在arcgis可以实现这个功能,但是如何使用代码去实现?

image-20240227151152418

代码

代码短,实现了ROI裁剪影像。

from osgeo import gdal
import os
import numpy as np
from tqdm import tqdm

def saveTif(data, cols, rows, band_num, driver, proj, geoTransform, filename):
    '''
    @todo 保存tif文件

    @param data: 数据
    @param cols: 列
    @param rows: 行
    @param driver: 驱动
    @param proj: 坐标系
    @param geoTransform: 坐标转换
    @param filename: 文件名
    @return:
    '''

    outDs = driver.Create(filename, cols, rows, band_num, gdal.GDT_UInt16)
    if band_num > 1:
        for i in range(band_num):
            outBand = outDs.GetRasterBand(i + 1)
            outBand.WriteArray(data[i], 0, 0)
            outBand.FlushCache()
            outBand.SetNoDataValue(0)
    else:

        outBand = outDs.GetRasterBand(1)
        outBand.WriteArray(data, 0, 0)
        outBand.FlushCache()
        outBand.SetNoDataValue(0)
    outDs.SetProjection(proj)
    outDs.SetGeoTransform(geoTransform)
    outBand = None
    outDs = None
class ClipTif:
    def __init__(self, tiffile):
        self.tiffile = tiffile
    def roi_clip(self, roi= None, outpath = None):
        ds = gdal.Open(self.tiffile, gdal.GA_ReadOnly)
        data = ds.ReadAsArray()
        transform = ds.GetGeoTransform()
        proj = ds.GetProjection()
        originX = transform[0]
        originY = transform[3]
        pixelWidth = transform[1]
        pixelHeight = transform[5]

        cols = ds.RasterXSize  # 列数
        rows = ds.RasterYSize  # 行数
        bandnum = ds.RasterCount
        # roi = [2000, 3000, 3000, 3000]  # x1,y1,dx,dy
        if bandnum ==1:
            temp_arr = data[roi[0]:roi[0] + roi[2], roi[1]:roi[1] + roi[3] ]
        else:
            temp_arr = data[:,roi[0]:roi[0] + roi[2], roi[1]:roi[1] + roi[3] ]

        new_transform = (originX + roi[1] * pixelWidth, transform[1], transform[2], originY + roi[0] * pixelHeight,
                         transform[4], transform[5])
        driver = gdal.GetDriverByName("GTiff")

        name = os.path.splitext(os.path.basename(self.tiffile))[0] + '_'+str(roi[0]) + '_' + str(roi[1]) + '_' + str(roi[2]) + '_' + str(roi[3]) + '.tif'
        if outpath:
            if os.path.exists(outpath) == False:
                os.makedirs(outpath)
        else:
            outpath = os.path.dirname(self.tiffile)

        outfile = os.path.join(outpath, name)

        # GDT_Byte = 1, GDT_UInt16 = 2, GDT_UInt32 = 4, GDT_Int32 = 5, GDT_Float32 = 6
        datatype = ds.GetRasterBand(1).DataType
        print("数据类型:", datatype)
        saveTif(temp_arr, roi[3], roi[2], bandnum, driver, proj, new_transform, outfile, datatype = datatype)

        a = 1

if __name__ == '__main__':

    tiffile = r'image.tif'  # 影像的全路径

    roi = [5000, 4000, 10000, 10000]
    ClipTif(tiffile).roi_clip(roi

以下是代码的详细解读:

  1. 首先,定义了一个名为 ClipTif 的类,它接收一个 TIFF 文件路径作为初始化参数。
  2. ClipTif 类中,定义了一个名为 roi_clip 的方法,它接收一个 ROI 列表和一个输出路径作为参数。ROI 列表定义了裁剪区域的起始行、起始列、行数和列数。如果没有提供输出路径,那么新的 TIFF 文件将会保存在原文件的同一目录下。
  3. roi_clip 方法首先使用 GDAL 库打开 TIFF 文件并读取其数据和元数据,包括地理变换参数和投影信息。
  4. 然后,它根据提供的 ROI 列表裁剪出一个小的区域。
  5. 接下来,它计算新的地理变换参数,这些参数将用于新的 TIFF 文件。
  6. 然后,它创建一个新的 TIFF 文件,并将裁剪的数据保存到其中。数据的类型(例如,字节、无符号短整数、浮点数等)与原始 TIFF 文件中的数据类型相同。
  7. 最后,如果你运行这个脚本(而不是导入它作为模块),那么它将会裁剪一个名为 “GF2.tif” 的 TIFF 文件中的一个区域,并将结果保存为新的 TIFF 文件。裁剪区域的参数通过 roi 列表提供。