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,复制粘贴即可。