使用Python对tif格式图片进行随机裁剪和数据增广
最近在做关于遥感图像的卷积神经网络课题,因为遥感图像一般都是很大而且有标注的数据不多,所以在训练网络的时候就会遇到数据不够的问题,这时候就需要对数据进行增广,一般的增广办法就是对图像进行旋转,反转,加噪等等。
而我的图像数据因为尺寸太大,需要先进行裁决才能投到网络中。我之前用的是python的OpenCV来做这一工作,但是我发现OpenCV对tif文件不是很友好。因为tif文件除了能存unit8的图像数据,还会有float32等数据类型,而OpenCV对于这样数据的处理不是很友好。然后我找到python另一个类库Pillow(PIL),这个类库不仅能很好的读取tif格式的数据,还封装好了许多很实用的函数,在对图像进行增广的时候直接调用函数就行,同时该类库也能很好的处理其他类型的tif数据。
下面开始上代码:
from PIL import Image,ImageFilter,ImageDraw
import random
import os
import numpy as np
from tqdm import tqdm
#要裁剪图像的大小
img_w = 256
img_h = 256
#读取路径下图片的名称
def file_name(file_dir):
L=[]
for root, dirs, files in os.walk(file_dir):
for file in files:
img_name = os.path.split(file)[1]
L.append(img_name)
return L
image_sets=file_name('./data/src');#图片存贮路径
#添加噪声
def add_noise(img):
drawObject=ImageDraw.Draw(img)
for i in range(250): #添加点噪声
temp_x = np.random.randint(0,img.size[0])
temp_y = np.random.randint(0,img.size[1])
drawObject.point((temp_x,temp_y),fill="white")#添加白色噪声点,噪声点颜色可变
return img
#色调增强
def random_color(img):
img = ImageEnhance.Color(img)
img = img.enhance(2)
return img
def data_augment(src_roi,label_roi):
#图像和标签同时进行90,180,270旋转
if np.random.random() < 0.25:
src_roi=src_roi.rotate(90)
label_roi=label_roi.rotate(90)
if np.random.random() < 0.25:
src_roi=src_roi.rotate(180)
label_roi=label_roi.rotate(180)
if np.random.random() < 0.25:
src_roi=src_roi.rotate(270)
label_roi=label_roi.rotate(270)
#图像和标签同时进行竖直旋转
if np.random.random() < 0.25:
src_roi=src_roi.transpose(Image.FLIP_LEFT_RIGHT)
label_roi=label_roi.transpose(Image.FLIP_LEFT_RIGHT)
#图像和标签同时进行水平旋转
if np.random.random() < 0.25:
src_roi=src_roi.transpose(Image.FLIP_TOP_BOTTOM)
label_roi=label_roi.transpose(Image.FLIP_TOP_BOTTOM)
#图像进行高斯模糊
if np.random.random() < 0.25:
src_roi=src_roi.filter(ImageFilter.GaussianBlur)
#图像进行色调增强
if np.random.random() < 0.25:
src_roi=random_color(src_roi)
#图像加入噪声
if np.random.random() < 0.2:
src_roi = add_noise(src_roi)
return src_roi,label_roi
# image_num:增广之后的图片数据
def creat_dataset(image_num = 100000, mode = 'original'):
print('creating dataset...')
image_each = image_num / len(image_sets)
g_count = 0
for i in tqdm(range(len(image_sets))):
count = 0
src_img = Image.open('./data/src/' + image_sets[i]) # 3 channels
label_img = Image.open('./data/label/' + image_sets[i]) # 3 channels
#对图像进行随机裁剪,这里大小为256*256
while count < image_each:
width1 = random.randint(0, src_img.size[0] - img_w )
height1 = random.randint(0, src_img.size[1] - img_h)
width2 = width1 + img_w
height2 = height1 + img_h
src_roi=src_img.crop((width1, height1, width2, height2))
label_roi=label_img.crop((width1, height1, width2, height2))
if mode == 'augment':
src_roi,label_roi = data_augment(src_roi,label_roi)
src_roi.save('./data/train_src/%d.tif' % g_count)
label_roi.save('./data/train_label/%d.tif' % g_count)
count += 1
g_count += 1
if __name__=='__main__':
creat_dataset(mode='augment')
  下面是对某张图像进行随机裁剪并做了增广操作的结果:
对应的图像标签:
PIL中对图像的其他过滤方法:
from PIL import Image, ImageFilter
im = Image.open(im_path)
# 高斯模糊
im.filter(ImageFilter.GaussianBlur).save(r'D:\test\GaussianBlur.jpg')
# 普通模糊
im.filter(ImageFilter.BLUR).save(r'D:\data\BLUR.jpg')
# 边缘增强
im.filter(ImageFilter.EDGE_ENHANCE).save(r'D:\test\EDGE_ENHANCE.jpg')
# 找到边缘
im.filter(ImageFilter.FIND_EDGES).save(r'D:\test\FIND_EDGES.jpg')
# 浮雕
im.filter(ImageFilter.EMBOSS).save(r'D:\test\EMBOSS.jpg')
# 轮廓
im.filter(ImageFilter.CONTOUR).save(r'D:\test\CONTOUR.jpg')
# 锐化
im.filter(ImageFilter.SHARPEN).save(r'D:\test\SHARPEN.jpg')
# 平滑
im.filter(ImageFilter.SMOOTH).save(r'D:\test\SMOOTH.jpg')
# 细节
im.filter(ImageFilter.DETAIL).save(r'D:\test\DETAIL.jpg')
PIL对图像的其他操作,建议参考:
https://www.cnblogs.com/Lival/p/6211602.htmlhttps://blog.csdn.net/gzlaiyonghao/article/details/1852726