详解Python实现图像分割增强的两种方法
方法一
import random import numpy as np from PIL import Image, ImageOps, ImageFilter from skimage.filters import gaussian import torch import math import numbers import random class RandomVerticalFlip(object): def __call__(self, img): if random.random() < 0.5: return img.transpose(Image.FLIP_TOP_BOTTOM) return img class DeNormalize(object): def __init__(self, mean, std): self.mean = mean self.std = std def __call__(self, tensor): for t, m, s in zip(tensor, self.mean, self.std): t.mul_(s).add_(m) return tensor class MaskToTensor(object): def __call__(self, img): return torch.from_numpy(np.array(img, dtype=np.int32)).long() class FreeScale(object): def __init__(self, size, interpolation=Image.BILINEAR): self.size = tuple(reversed(size)) # size: (h, w) self.interpolation = interpolation def __call__(self, img): return img.resize(self.size, self.interpolation) class FlipChannels(object): def __call__(self, img): img = np.array(img)[:, :, ::-1] return Image.fromarray(img.astype(np.uint8)) class RandomGaussianBlur(object): def __call__(self, img): sigma = 0.15 + random.random() * 1.15 blurred_img = gaussian(np.array(img), sigma=sigma, multichannel=True) blurred_img *= 255 return Image.fromarray(blurred_img.astype(np.uint8)) # 组合 class Compose(object): def __init__(self, transforms): self.transforms = transforms def __call__(self, img, mask): assert img.size == mask.size for t in self.transforms: img, mask = t(img, mask) return img, mask # 随机裁剪 class RandomCrop(object): def __init__(self, size, padding=0): if isinstance(size, numbers.Number): self.size = (int(size), int(size)) else: self.size = size self.padding = padding def __call__(self, img, mask): if self.padding > 0: img = ImageOps.expand(img, border=self.padding, fill=0) mask = ImageOps.expand(mask, border=self.padding, fill=0) assert img.size == mask.size w, h = img.size th, tw = self.size if w == tw and h == th: return img, mask if w < tw or h < th: return img.resize((tw, th), Image.BILINEAR), mask.resize((tw, th), Image.NEAREST) x1 = random.randint(0, w - tw) y1 = random.randint(0, h - th) return img.crop((x1, y1, x1 + tw, y1 + th)), mask.crop((x1, y1, x1 + tw, y1 + th)) # 中心裁剪 class CenterCrop(object): def __init__(self, size): if isinstance(size, numbers.Number): self.size = (int(size), int(size)) else: self.size = size def __call__(self, img, mask): assert img.size == mask.size w, h = img.size th, tw = self.size x1 = int(round((w - tw) / 2.)) y1 = int(round((h - th) / 2.)) return img.crop((x1, y1, x1 + tw, y1 + th)), mask.crop((x1, y1, x1 + tw, y1 + th)) class RandomHorizontallyFlip(object): def __call__(self, img, mask): if random.random() < 0.5: return img.transpose(Image.FLIP_LEFT_RIGHT), mask.transpose(Image.FLIP_LEFT_RIGHT) return img, mask class Scale(object): def __init__(self, size): self.size = size def __call__(self, img, mask): assert img.size == mask.size w, h = img.size if (w >= h and w == self.size) or (h >= w and h == self.size): return img, mask if w > h: ow = self.size oh = int(self.size * h / w) return img.resize((ow, oh), Image.BILINEAR), mask.resize((ow, oh), Image.NEAREST) else: oh = self.size ow = int(self.size * w / h) return img.resize((ow, oh), Image.BILINEAR), mask.resize((ow, oh), Image.NEAREST) class RandomSizedCrop(object): def __init__(self, size): self.size = size def __call__(self, img, mask): assert img.size == mask.size for attempt in range(10): area = img.size[0] * img.size[1] target_area = random.uniform(0.45, 1.0) * area aspect_ratio = random.uniform(0.5, 2) w = int(round(math.sqrt(target_area * aspect_ratio))) h = int(round(math.sqrt(target_area / aspect_ratio))) if random.random() < 0.5: w, h = h, w if w <= img.size[0] and h <= img.size[1]: x1 = random.randint(0, img.size[0] - w) y1 = random.randint(0, img.size[1] - h) img = img.crop((x1, y1, x1 + w, y1 + h)) mask = mask.crop((x1, y1, x1 + w, y1 + h)) assert (img.size == (w, h)) return img.resize((self.size, self.size), Image.BILINEAR), mask.resize((self.size, self.size), Image.NEAREST) # Fallback scale = Scale(self.size) crop = CenterCrop(self.size) return crop(*scale(img, mask)) class RandomRotate(object): def __init__(self, degree): self.degree = degree def __call__(self, img, mask): rotate_degree = random.random() * 2 * self.degree - self.degree return img.rotate(rotate_degree, Image.BILINEAR), mask.rotate(rotate_degree, Image.NEAREST) class RandomSized(object): def __init__(self, size): self.size = size self.scale = Scale(self.size) self.crop = RandomCrop(self.size) def __call__(self, img, mask): assert img.size == mask.size w = int(random.uniform(0.5, 2) * img.size[0]) h = int(random.uniform(0.5, 2) * img.size[1]) img, mask = img.resize((w, h), Image.BILINEAR), mask.resize((w, h), Image.NEAREST) return self.crop(*self.scale(img, mask)) class SlidingCropOld(object): def __init__(self, crop_size, stride_rate, ignore_label): self.crop_size = crop_size self.stride_rate = stride_rate self.ignore_label = ignore_label def _pad(self, img, mask): h, w = img.shape[: 2] pad_h = max(self.crop_size - h, 0) pad_w = max(self.crop_size - w, 0) img = np.pad(img, ((0, pad_h), (0, pad_w), (0, 0)), 'constant') mask = np.pad(mask, ((0, pad_h), (0, pad_w)), 'constant', constant_values=self.ignore_label) return img, mask def __call__(self, img, mask): assert img.size == mask.size w, h = img.size long_size = max(h, w) img = np.array(img) mask = np.array(mask) if long_size > self.crop_size: stride = int(math.ceil(self.crop_size * self.stride_rate)) h_step_num = int(math.ceil((h - self.crop_size) / float(stride))) + 1 w_step_num = int(math.ceil((w - self.crop_size) / float(stride))) + 1 img_sublist, mask_sublist = [], [] for yy in range(h_step_num): for xx in range(w_step_num): sy, sx = yy * stride, xx * stride ey, ex = sy + self.crop_size, sx + self.crop_size img_sub = img[sy: ey, sx: ex, :] mask_sub = mask[sy: ey, sx: ex] img_sub, mask_sub = self._pad(img_sub, mask_sub) img_sublist.append(Image.fromarray(img_sub.astype(np.uint8)).convert('RGB')) mask_sublist.append(Image.fromarray(mask_sub.astype(np.uint8)).convert('P')) return img_sublist, mask_sublist else: img, mask = self._pad(img, mask) img = Image.fromarray(img.astype(np.uint8)).convert('RGB') mask = Image.fromarray(mask.astype(np.uint8)).convert('P') return img, mask class SlidingCrop(object): def __init__(self, crop_size, stride_rate, ignore_label): self.crop_size = crop_size self.stride_rate = stride_rate self.ignore_label = ignore_label def _pad(self, img, mask): h, w = img.shape[: 2] pad_h = max(self.crop_size - h, 0) pad_w = max(self.crop_size - w, 0) img = np.pad(img, ((0, pad_h), (0, pad_w), (0, 0)), 'constant') mask = np.pad(mask, ((0, pad_h), (0, pad_w)), 'constant', constant_values=self.ignore_label) return img, mask, h, w def __call__(self, img, mask): assert img.size == mask.size w, h = img.size long_size = max(h, w) img = np.array(img) mask = np.array(mask) if long_size > self.crop_size: stride = int(math.ceil(self.crop_size * self.stride_rate)) h_step_num = int(math.ceil((h - self.crop_size) / float(stride))) + 1 w_step_num = int(math.ceil((w - self.crop_size) / float(stride))) + 1 img_slices, mask_slices, slices_info = [], [], [] for yy in range(h_step_num): for xx in range(w_step_num): sy, sx = yy * stride, xx * stride ey, ex = sy + self.crop_size, sx + self.crop_size img_sub = img[sy: ey, sx: ex, :] mask_sub = mask[sy: ey, sx: ex] img_sub, mask_sub, sub_h, sub_w = self._pad(img_sub, mask_sub) img_slices.append(Image.fromarray(img_sub.astype(np.uint8)).convert('RGB')) mask_slices.append(Image.fromarray(mask_sub.astype(np.uint8)).convert('P')) slices_info.append([sy, ey, sx, ex, sub_h, sub_w]) return img_slices, mask_slices, slices_info else: img, mask, sub_h, sub_w = self._pad(img, mask) img = Image.fromarray(img.astype(np.uint8)).convert('RGB') mask = Image.fromarray(mask.astype(np.uint8)).convert('P') return [img], [mask], [[0, sub_h, 0, sub_w, sub_h, sub_w]]
方法二
import numpy as np import random import torch from torchvision import transforms as T from torchvision.transforms import functional as F def pad_if_smaller(img, size, fill=0): # 如果图像最小边长小于给定size,则用数值fill进行padding min_size = min(img.size) if min_size < size: ow, oh = img.size padh = size - oh if oh < size else 0 padw = size - ow if ow < size else 0 img = F.pad(img, (0, 0, padw, padh), fill=fill) return img class Compose(object): def __init__(self, transforms): self.transforms = transforms def __call__(self, image, target): for t in self.transforms: image, target = t(image, target) return image, target class RandomResize(object): def __init__(self, min_size, max_size=None): self.min_size = min_size if max_size is None: max_size = min_size self.max_size = max_size def __call__(self, image, target): size = random.randint(self.min_size, self.max_size) # 这里size传入的是int类型,所以是将图像的最小边长缩放到size大小 image = F.resize(image, size) # 这里的interpolation注意下,在torchvision(0.9.0)以后才有InterpolationMode.NEAREST # 如果是之前的版本需要使用PIL.Image.NEAREST target = F.resize(target, size, interpolation=T.InterpolationMode.NEAREST) return image, target class RandomHorizontalFlip(object): def __init__(self, flip_prob): self.flip_prob = flip_prob def __call__(self, image, target): if random.random() < self.flip_prob: image = F.hflip(image) target = F.hflip(target) return image, target class RandomCrop(object): def __init__(self, size): self.size = size def __call__(self, image, target): image = pad_if_smaller(image, self.size) target = pad_if_smaller(target, self.size, fill=255) crop_params = T.RandomCrop.get_params(image, (self.size, self.size)) image = F.crop(image, *crop_params) target = F.crop(target, *crop_params) return image, target class CenterCrop(object): def __init__(self, size): self.size = size def __call__(self, image, target): image = F.center_crop(image, self.size) target = F.center_crop(target, self.size) return image, target class ToTensor(object): def __call__(self, image, target): image = F.to_tensor(image) target = torch.as_tensor(np.array(target), dtype=torch.int64) return image, target class Normalize(object): def __init__(self, mean, std): self.mean = mean self.std = std def __call__(self, image, target): image = F.normalize(image, mean=self.mean, std=self.std) return image, target
到此这篇关于详解Python实现图像分割增强的两种方法的文章就介绍到这了,更多相关Python图像分割增强内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!
赞 (0)