飞桨图像分割训练营-图像增强实现
收藏
import cv2 as cv import numpy as np from PIL import Image import random import math import matplotlib.pyplot as plt import os class Compose(object): def __init__(self, transforms): self.transforms = transforms def __call__(self, image, label=None): for t in self.transforms: image, label = t(image, label) return image, label class Normalize(object): def __init__(self, mean_val, std_val, val_scale=1): # set val_scale = 1 if mean and std are in range (0,1) # set val_scale to other value, if mean and std are in range (0,255) self.mean = np.array(mean_val, dtype=np.float32) self.std = np.array(std_val, dtype=np.float32) self.val_scale = 1/255.0 if val_scale==1 else 1 def __call__(self, image, label=None): image = image.astype(np.float32) image = image * self.val_scale image = image - self.mean image = image * (1 / self.std) return image, label class ConvertDataType(object): def __call__(self, image, label=None): if label is not None: label = label.astype(np.int64) return image.astype(np.float32), label class Pad(object): def __init__(self, size, ignore_label=255, mean_val=0, val_scale=1): # set val_scale to 1 if mean_val is in range (0, 1) # set val_scale to 255 if mean_val is in range (0, 255) factor = 255 if val_scale == 1 else 1 self.size = size self.ignore_label = ignore_label self.mean_val=mean_val # from 0-1 to 0-255 if isinstance(self.mean_val, (tuple,list)): self.mean_val = [int(x* factor) for x in self.mean_val] else: self.mean_val = int(self.mean_val * factor) def __call__(self, image, label=None): h, w, c = image.shape pad_h = max(self.size - h, 0) pad_w = max(self.size - w, 0) pad_h_half = int(pad_h / 2) pad_w_half = int(pad_w / 2) if pad_h > 0 or pad_w > 0: image = cv.copyMakeBorder(image, top=pad_h_half, left=pad_w_half, bottom=pad_h - pad_h_half, right=pad_w - pad_w_half, borderType=cv.BORDER_CONSTANT, value=self.mean_val) if label is not None: label = cv.copyMakeBorder(label, top=pad_h_half, left=pad_w_half, bottom=pad_h - pad_h_half, right=pad_w - pad_w_half, borderType=cv.BORDER_CONSTANT, value=self.ignore_label) return image, label # TODO def center_crop(img_array, crop_size): rows = img_array.shape[0] cols = img_array.shape[1] assert crop_size>0,"crop size should be greater than zero" if crop_size>max(rows,cols): crop_size = min(rows, cols) row_s = max(int((rows-crop_size)/2), 0) row_e = min(row_s+crop_size, rows) col_s = max(int((cols-crop_size)/2), 0) col_e = min(col_s+crop_size, cols) img_crop = img_array[row_s:row_e, col_s:col_e, ] return img_crop class CenterCrop(object): def __init__(self,size): self.size=size def __call__(self,img,label): if self.size > max(img.shape[0],img.shape[1]): self.size = min(img.shape[0],img.shape[1]) img = center_crop(img, self.size) label = center_crop(label, self.size) return img,label # TODO class Resize(object): def __init__(self,size): self.size=size def __call__(self,img,label=None): out_img = cv.resize(img,(self.size,self.size),interpolation=cv.INTER_LINEAR) if label is not None: out_label = cv.resize(label,(self.size,self.size),interpolation=cv.INTER_LINEAR) return out_img,out_label class RandomFlip(object): """ filp: 1: Horizontally 0: Vertically -1: Horizontally and vertically """ def __init__(self,flip=1): assert flip in [-1,0,1] self.flip = flip def __call__(self,img,label=None): img = cv.flip(img,self.flip) if label is not None: label = cv.flip(label,self.flip) return img, label class RandomCrop(object): def __init__(self, size): self.size = size self.scale = [0.08, 1.0] self.ratio = [3. / 4., 4. / 3.] def __call__(self, img,label=None): size = self.size scale = self.scale ratio = self.ratio aspect_ratio = math.sqrt(random.uniform(*ratio)) w = 1. * aspect_ratio h = 1. / aspect_ratio img_h, img_w = img.shape[:2] bound = min((float(img_w) / img_h) / (w**2), (float(img_h) / img_w) / (h**2)) scale_max = min(scale[1], bound) scale_min = min(scale[0], bound) target_area = img_w * img_h * random.uniform(scale_min, scale_max) target_size = math.sqrt(target_area) w = int(target_size * w) h = int(target_size * h) i = random.randint(0, img_w - w) j = random.randint(0, img_h - h) img = img[j:j + h, i:i + w, :] img = cv.resize(img, (size,size),interpolation=cv.INTER_LINEAR) if label is not None: label = label[j:j + h, i:i + w] label = cv.resize(label, (size,size), interpolation=cv.INTER_NEAREST) return img,label class Scale(object): def __init__(self,size): self.size=size def _call__(self,img,label): assert img.shape == label.shape w,h, = img.shape[0],img.shape[1] if (w>=h and w == self.size) or (h>=w and h == self.size): return img,label if w > h: ow = self.size oh = int(self.size * h / w) img = cv.resize(img,(ow,oh),interpolation=cv.INTER_LINEAR) label = cv.resize(label,(ow,oh),interpolation=cv.INTER_LINEAR) return img,label # TODO class RandomScale(object): def __init__(self, base_size=320,p=0.2): self.base_size = base_size self.p = p def __call__(self, img,label=None): # random scale (short edge) if random.random() w: ow = short_size oh = int(1.0 * h * ow / w) else: oh = short_size ow = int(1.0 * w * oh / h) img = cv.resize(img,(ow, oh),cv.INTER_LINEAR) if label is not None: label = cv.resize(label,(img.shape[1],img.shape[0]),cv.INTER_NEAREST) return img,label def showimg(img,label): plt.figure() plt.subplot(1,2,1) plt.imshow(img) plt.subplot(1,2,2) plt.imshow(label) plt.show()
一些常见的数据增强的实现,如填充,resize, 随机翻转,中心裁剪, 随机裁剪,缩放。效果还行,代码有待优化。
image = cv.imread('./work/dummy_data/JPEGImages/2008_000064.jpg') label = cv.imread('./work/dummy_data/GroundTruth_trainval_png/2008_000064.png') print(image.shape,label.shape) i,j = Resize(256)(image,label) showimg(i,j)
i,j = Pad(600)(image,label) showimg(i,j)
i,j = CenterCrop(100)(image,label) showimg(i,j)
i,j = RandomFlip(-1)(image,label) showimg(i,j)
i,j = RandomCrop(200)(image,label) showimg(i,j)
i,j = RandomScale(base_size=1000,p=0.1)(image,label) showimg(i,j)
参考:https://aistudio.baidu.com/aistudio/course/introduce/1767
0
收藏
请登录后评论
看着很不错呀
我感觉cv上,图像增强很管用啊