Tiff图像裁剪

卫星影像一般一景影像规模较大,直接放到网络里面去训练不现实,所以又得将原图和对应的mask图,进行裁剪,做成合适大小的patch图,再放入网络训练会比较好,也能有效减少一次性训练的计算量。

但由于tif图多波段和单波段,他的数据shape不一样,多波段的data.shape有三个参数,但是单波段的只有两个参数(不含band了,print出来就是两个参数了),因此还不能一劳永逸。下面是多波段tif图的裁剪,为了方便批量处理,因此给每个图一个mark标记,方便统计和按顺序保存,和裁剪的工作无关。

# 裁剪多波段tif图像,mark为图像的序号
def cuttingTiff(src_path,des_path,mark):
    im_data, im_geotrans, im_proj = readTiff(src_path)
    # print(im_data.shape)
    im_bands, im_height, im_width = im_data.shape
    # print(im_width)  # 图像的宽度。图像的长。图像的横向像素个数。
    # print(im_height)  # 图像的高度。图像的宽。图像的纵向像素个数。
    # print(im_data.shape[0],im_data.shape[1],im_data.shape[2]) # 第一个值是波段数,第二个值是高度,第三个值是宽度。
    # band,height,width = im_data.shape
    # print(im_width//256)
    # print(im_height//256)
    patch_size = 256  # patch的尺度
    # 切割成256*256小图(有不足一个patch的地方未切割,宽度余32,高度余144)
    for i in range(im_width//patch_size):  # 0~27
        for j in range(im_height//patch_size):  # 0~25
            cur_image = im_data[:,j*patch_size:(j+1)*patch_size,i*patch_size:(i+1)*patch_size] # 波段,宽,长。
            # print(cur_image.shape)
            writeTiff(cur_image, im_geotrans, im_proj, des_path+"/"+"{}_{}_{}.tif".format(mark,j,i))  # 横向扫描保存
        # print(i)
    '''
    # 将右侧的补齐
    for j in range(im_height//patch_size):
        cur_image = im_data[:,j*patch_size:(j+1)*patch_size,6944:7200]
        writeTiff(cur_image, im_geotrans, im_proj, des_path+"/"+"{}_{}_28.tif".format(mark,j))
    # 将下侧的补齐
    for i in range(im_width//patch_size):
        cur_image = im_data[:,6544:6800,i*patch_size:(i+1)*patch_size]
        writeTiff(cur_image, im_geotrans, im_proj, des_path+"/"+"{}_26_{}.tif".format(mark,i))
    # 将最右下角的一块补齐
    cur_image =im_data[:,6544:6800,6944:7200]
    writeTiff(cur_image, im_geotrans, im_proj, des_path+"/"+"{}_26_28.tif".format(mark))
    # 统计下来一景tif图可以裁剪为783张256*256图。
    '''

本人测试的图像是7200*6800的GID数据集。如果只是做整数的裁剪,那么右侧,下侧区域肯定会丢失。对于数据集本身就不够多的情况,肯定是要完全的利用起来,并且丢失的边缘很可能会对学习有帮助。所以在注释部分,有将右侧和下侧,以及右下角那一块补齐的补充代码,如果数据量足够,或者这几个区域用处不大则可以不用。如果需要使用就要根据自身的图像大小,以及裁剪的大小,调整里面H和W的参数。

对于单通道的裁剪,即去掉image中的band那一维即可:

# 裁剪灰度tif图像,mark为图像的序号
def cuttingGrayTiff(src_path,des_path,mark):
    # 使用gdal,读取并保存tif图像
    # img3 = gdal.Open(path)  # 直接使用Open函数读取数据
    im_data, im_geotrans, im_proj = readTiff(src_path)
    # print(im_data.shape)
    im_height, im_width = im_data.shape  # 灰度图,二维,波段为1相当于只有一层
    # print(im_width)  # 图像的宽度。图像的长。图像的横向像素个数。
    # print(im_height)  # 图像的高度。图像的宽。图像的纵向像素个数。
    # writeTiff(im_data, im_width, im_height, im_bands, im_geotrans, im_proj, "E:/data_test/1.tif")  # 写入原图
    # print(im_data.shape[0],im_data.shape[1],im_data.shape[2]) # 第一个值是波段数,第二个值是高度,第三个值是宽度。
    # band,height,width = im_data.shape
    # print(im_width//256)
    # print(im_height//256)
    # 切割成256*256小图(有不足一个patch的地方未切割,宽度余32,高度余144)
    patch_size = 256  # patch的尺度
    for i in range(im_width//patch_size):  # 0~27
        for j in range(im_height//patch_size):  # 0~25
            cur_image = im_data[j*patch_size:(j+1)*patch_size,i*patch_size:(i+1)*patch_size] # 宽,长。
            # print(cur_image.shape)
            writeTiff(cur_image, im_geotrans, im_proj, des_path+"/"+"{}_{}_{}.tif".format(mark,j,i))  # 横向扫描保存
        # print(i)

最后将两种进行了一下整合:

# 裁剪数据集中所有tif图
def cuttingallTiff(src_path,des_path):
    dirs = os.listdir(src_path)  # 逐个读取文件名
    i = 0  # 从0开始循环读
    over_No = 134  # 需要裁剪的图像的总数,根据需要自行设置
    for file_path in dirs:
        file_path = src_path+"/"+file_path  # 当前img路径
        if(band_number(file_path) == 1):  # 判断波段数
            cuttingGrayTiff(file_path,des_path,i)  # 裁剪单通道(灰度二值图)
        else:
            cuttingTiff(file_path, des_path, i)  # 裁剪多通道
        # print(file_path)
        print(i)
        i=i+1
        if i==over_No:  # 终止条件
            break
    print("cutting over")

总的来说还是比较顺利的,注意在整合的时候,各个路径的字符串组合不要加着加着重复了,之前就是其他问题都没有,但是总是跑不出来。后来通过断点检查,发现是路径错误,重复了一段。所以对于路径这种问题,尽量送入函数之前多输出,看看实际效果,不要只是单纯通过脑子进行逻辑判断,很容易有误区,同时在命名的时候,避免使用一个名字,很容易出现重复,多用几个不同名字的参数去加,能有效避免路径错误。像这里就只有一个路径,就无所谓,所以写file_path = …+file_path。但是如果出现多个路径要在同一个循环里搞定,这么写肯定会导致file_path又作为循环的变量,又作为你定位的变量,导致字段重复,所以多起几个名字,有好处的。

读、写、波段判断参考1,2,复制粘贴即可。