import random import numpy as np import cv2 from PIL import Image from PIL import ImageFilter import PIL import tifffile def cv_rotate(image, angle, borderValue): """ rot angle, fill with borderValue """ # grab the dimensions of the image and then determine the # center (h, w) = image.shape[:2] (cX, cY) = (w // 2, h // 2) # grab the rotation matrix (applying the negative of the # angle to rotate clockwise), then grab the sine and cosine # (i.e., the rotation components of the matrix) # -angle位置参数为角度参数负值表示顺时针旋转; 1.0位置参数scale是调整尺寸比例(图像缩放参数),建议0.75 M = cv2.getRotationMatrix2D((cX, cY), -angle, 1.0) cos = np.abs(M[0, 0]) sin = np.abs(M[0, 1]) # compute the new bounding dimensions of the image nW = int((h * sin) + (w * cos)) nH = int((h * cos) + (w * sin)) # adjust the rotation matrix to take into account translation M[0, 2] += (nW / 2) - cX M[1, 2] += (nH / 2) - cY if isinstance(borderValue, int): values = (borderValue, borderValue, borderValue) else: values = borderValue # perform the actual rotation and return the image return cv2.warpAffine(image, M, (nW, nH), borderValue=values) def pil_resize(img, size, order): if size[0] == img.shape[0] and size[1] == img.shape[1]: return img if order == 3: resample = Image.BICUBIC elif order == 0: resample = Image.NEAREST return np.asarray(Image.fromarray(img).resize(size[::-1], resample)) def pil_rescale(img, scale, order): height, width = img.shape[:2] target_size = (int(np.round(height * scale)), int(np.round(width * scale))) return pil_resize(img, target_size, order) def pil_rotate(img, degree, default_value): if isinstance(default_value, tuple): values = (default_value[0], default_value[1], default_value[2], 0) else: values = (default_value, default_value, default_value, 0) img = Image.fromarray(img) if img.mode == 'RGB': # set img padding == default_value img2 = img.convert('RGBA') rot = img2.rotate(degree, expand=1) fff = Image.new('RGBA', rot.size, values) # 灰色 out = Image.composite(rot, fff, rot) img = out.convert(img.mode) else: # set label padding == default_value img2 = img.convert('RGBA') rot = img2.rotate(degree, expand=1) # a white image same size as rotated image fff = Image.new('RGBA', rot.size, values) # create a composite image using the alpha layer of rot as a mask out = Image.composite(rot, fff, rot) img = out.convert(img.mode) return np.asarray(img) def random_resize_long_image_list(img_list, min_long, max_long): target_long = random.randint(min_long, max_long) h, w = img_list[0].shape[:2] if w < h: scale = target_long / h else: scale = target_long / w out = [] for img in img_list: out.append(pil_rescale(img, scale, 3) ) return out def random_resize_long(img, min_long, max_long): target_long = random.randint(min_long, max_long) h, w = img.shape[:2] if w < h: scale = target_long / h else: scale = target_long / w return pil_rescale(img, scale, 3) def random_scale_list(img_list, scale_range, order): """ 输入:图像列表 """ target_scale = scale_range[0] + random.random() * (scale_range[1] - scale_range[0]) if isinstance(img_list, tuple): assert img_list.__len__() == 2 img1 = [] img2 = [] for img in img_list[0]: img1.append(pil_rescale(img, target_scale, order[0])) for img in img_list[1]: img2.append(pil_rescale(img, target_scale, order[1])) return (img1, img2) else: out = [] for img in img_list: out.append(pil_rescale(img, target_scale, order)) return out def random_scale(img, scale_range, order): target_scale = scale_range[0] + random.random() * (scale_range[1] - scale_range[0]) if isinstance(img, tuple): return (pil_rescale(img[0], target_scale, order[0]), pil_rescale(img[1], target_scale, order[1])) else: return pil_rescale(img, target_scale, order) def random_rotate_list(img_list, max_degree, default_values): degree = random.random() * max_degree if isinstance(img_list, tuple): assert img_list.__len__() == 2 img1 = [] img2 = [] for img in img_list[0]: assert isinstance(img, np.ndarray) img1.append((pil_rotate(img, degree, default_values[0]))) for img in img_list[1]: img2.append((pil_rotate(img, degree, default_values[1]))) return (img1, img2) else: out = [] for img in img_list: out.append(pil_rotate(img, degree, default_values)) return out def random_rotate(img, max_degree, default_values): degree = random.random() * max_degree if isinstance(img, tuple): return (pil_rotate(img[0], degree, default_values[0]), pil_rotate(img[1], degree, default_values[1])) else: return pil_rotate(img, degree, default_values) def random_lr_flip_list(img_list): if bool(random.getrandbits(1)): if isinstance(img_list, tuple): assert img_list.__len__() == 2 img1 = list((np.fliplr(m) for m in img_list[0])) img2 = list((np.fliplr(m) for m in img_list[1])) return (img1, img2) else: return list([np.fliplr(m) for m in img_list]) else: return img_list def random_lr_flip(img): if bool(random.getrandbits(1)): if isinstance(img, tuple): return tuple([np.fliplr(m) for m in img]) else: return np.fliplr(img) else: return img def get_random_crop_box(imgsize, cropsize): h, w = imgsize ch = min(cropsize, h) cw = min(cropsize, w) w_space = w - cropsize h_space = h - cropsize if w_space > 0: cont_left = 0 img_left = random.randrange(w_space + 1) else: cont_left = random.randrange(-w_space + 1) img_left = 0 if h_space > 0: cont_top = 0 img_top = random.randrange(h_space + 1) else: cont_top = random.randrange(-h_space + 1) img_top = 0 return cont_top, cont_top + ch, cont_left, cont_left + cw, img_top, img_top + ch, img_left, img_left + cw def random_crop_list(images_list, cropsize, default_values): if isinstance(images_list, tuple): imgsize = images_list[0][0].shape[:2] elif isinstance(images_list, list): imgsize = images_list[0].shape[:2] else: raise RuntimeError('do not support the type of image_list') if isinstance(default_values, int): default_values = (default_values,) box = get_random_crop_box(imgsize, cropsize) if isinstance(images_list, tuple): assert images_list.__len__() == 2 img1 = [] img2 = [] for img in images_list[0]: f = default_values[0] if len(img.shape) == 3: cont = np.ones((cropsize, cropsize, img.shape[2]), img.dtype) * f else: cont = np.ones((cropsize, cropsize), img.dtype) * f cont[box[0]:box[1], box[2]:box[3]] = img[box[4]:box[5], box[6]:box[7]] img1.append(cont) for img in images_list[1]: f = default_values[1] if len(img.shape) == 3: cont = np.ones((cropsize, cropsize, img.shape[2]), img.dtype) * f else: cont = np.ones((cropsize, cropsize), img.dtype) * f cont[box[0]:box[1], box[2]:box[3]] = img[box[4]:box[5], box[6]:box[7]] img2.append(cont) return (img1, img2) else: out = [] for img in images_list: f = default_values if len(img.shape) == 3: cont = np.ones((cropsize, cropsize, img.shape[2]), img.dtype) * f else: cont = np.ones((cropsize, cropsize), img.dtype) * f cont[box[0]:box[1], box[2]:box[3]] = img[box[4]:box[5], box[6]:box[7]] out.append(cont) return out def random_crop(images, cropsize, default_values): if isinstance(images, np.ndarray): images = (images,) if isinstance(default_values, int): default_values = (default_values,) imgsize = images[0].shape[:2] box = get_random_crop_box(imgsize, cropsize) new_images = [] for img, f in zip(images, default_values): if len(img.shape) == 3: cont = np.ones((cropsize, cropsize, img.shape[2]), img.dtype) * f else: cont = np.ones((cropsize, cropsize), img.dtype) * f cont[box[0]:box[1], box[2]:box[3]] = img[box[4]:box[5], box[6]:box[7]] new_images.append(cont) if len(new_images) == 1: new_images = new_images[0] return new_images def top_left_crop(img, cropsize, default_value): h, w = img.shape[:2] ch = min(cropsize, h) cw = min(cropsize, w) if len(img.shape) == 2: container = np.ones((cropsize, cropsize), img.dtype) * default_value else: container = np.ones((cropsize, cropsize, img.shape[2]), img.dtype) * default_value container[:ch, :cw] = img[:ch, :cw] return container def center_crop(img, cropsize, default_value=0): h, w = img.shape[:2] ch = min(cropsize, h) cw = min(cropsize, w) sh = h - cropsize sw = w - cropsize if sw > 0: cont_left = 0 img_left = int(round(sw / 2)) else: cont_left = int(round(-sw / 2)) img_left = 0 if sh > 0: cont_top = 0 img_top = int(round(sh / 2)) else: cont_top = int(round(-sh / 2)) img_top = 0 if len(img.shape) == 2: container = np.ones((cropsize, cropsize), img.dtype) * default_value else: container = np.ones((cropsize, cropsize, img.shape[2]), img.dtype) * default_value container[cont_top:cont_top + ch, cont_left:cont_left + cw] = \ img[img_top:img_top + ch, img_left:img_left + cw] return container def HWC_to_CHW(img): return np.transpose(img, (2, 0, 1)) def pil_blur(img, radius): return np.array(Image.fromarray(img).filter(ImageFilter.GaussianBlur(radius=radius))) def random_blur(img): radius = random.random() # print('add blur: ', radius) if isinstance(img, list): out = [] for im in img: out.append(pil_blur(im, radius)) return out elif isinstance(img, np.ndarray): return pil_blur(img, radius) else: print(img) raise RuntimeError("do not support the input image type!") def save_image(image_numpy, image_path, size=None): """Save a numpy image to the disk Parameters: image_numpy (numpy array) -- input numpy array image_path (str) -- the path of the image """ image_pil = Image.fromarray(np.array(image_numpy, dtype=np.uint8)) if size is not None: image_pil = image_pil.resize(size) image_pil.save(image_path) def im2arr(img_path, mode=1, dtype=np.uint8): """ :param img_path: :param mode: :return: numpy.ndarray, shape: H*W*C """ if mode == 1: img = PIL.Image.open(img_path) arr = np.asarray(img, dtype=dtype) else: arr = tifffile.imread(img_path) if arr.ndim == 3: a, b, c = arr.shape if a < b and a < c: # 当arr为C*H*W时,需要交换通道顺序 arr = arr.transpose([1, 2, 0]) # print('shape: ', arr.shape, 'dytpe: ',arr.dtype) return arr