Spaces:
Build error
Build error
| import math | |
| from random import choice, choices, randint | |
| import cv2 | |
| import numpy as np | |
| from PIL import Image | |
| from torch.utils.data.dataset import Dataset | |
| from utils import USMSharp_npy, cvtColor, preprocess_input | |
| from .degradations import (circular_lowpass_kernel, random_add_gaussian_noise, | |
| random_add_poisson_noise, random_mixed_kernels) | |
| from .transforms import augment, paired_random_crop | |
| def cv_show(image): | |
| image = np.array(image) | |
| image = cv2.resize(image, (256, 128), interpolation=cv2.INTER_CUBIC) | |
| cv2.imshow('image', image) | |
| cv2.waitKey(0) | |
| cv2.destroyAllWindows() | |
| def get_new_img_size(width, height, img_min_side=600): | |
| if width <= height: | |
| f = float(img_min_side) / width | |
| resized_height = int(f * height) | |
| resized_width = int(img_min_side) | |
| else: | |
| f = float(img_min_side) / height | |
| resized_width = int(f * width) | |
| resized_height = int(img_min_side) | |
| return resized_width, resized_height | |
| class SRGANDataset(Dataset): | |
| def __init__(self, train_lines, lr_shape, hr_shape): | |
| super(SRGANDataset, self).__init__() | |
| self.train_lines = train_lines | |
| self.train_batches = len(train_lines) | |
| self.lr_shape = lr_shape | |
| self.hr_shape = hr_shape | |
| self.scale = int(hr_shape[0]/lr_shape[0]) | |
| self.usmsharp = USMSharp_npy() | |
| # 第一次滤波的参数 | |
| self.blur_kernel_size = 21 | |
| self.kernel_list = ['iso', 'aniso', 'generalized_iso', 'generalized_aniso', 'plateau_iso', 'plateau_aniso'] | |
| self.kernel_prob = [0.45, 0.25, 0.12, 0.03, 0.12, 0.03] | |
| self.sinc_prob = 0.1 | |
| self.blur_sigma = [0.2, 3] | |
| self.betag_range = [0.5, 4] | |
| self.betap_range = [1, 2] | |
| # 第二次滤波的参数 | |
| self.blur_kernel_size2 = 21 | |
| self.kernel_list2 = ['iso', 'aniso', 'generalized_iso', 'generalized_aniso', 'plateau_iso', 'plateau_aniso'] | |
| self.kernel_prob2 = [0.45, 0.25, 0.12, 0.03, 0.12, 0.03] | |
| self.sinc_prob2 = 0.1 | |
| self.blur_sigma2 = [0.2, 3] | |
| self.betag_range2 = [0.5, 4] | |
| self.betap_range2 = [1, 2] | |
| # 最后的sinc滤波 | |
| self.final_sinc_prob = 0.8 | |
| # 卷积核大小从7到21分布 | |
| self.kernel_range = [2 * v + 1 for v in range(3, 11)] | |
| # 使用脉冲张量进行卷积不会产生模糊效果 | |
| self.pulse_tensor = np.zeros(shape=[21, 21], dtype='float32') | |
| self.pulse_tensor[10, 10] = 1 | |
| # 第一次退化的参数 | |
| self.resize_prob = [0.2, 0.7, 0.1] # up, down, keep | |
| self.resize_range = [0.15, 1.5] | |
| self.gaussian_noise_prob = 0.5 | |
| self.noise_range = [1, 30] | |
| self.poisson_scale_range = [0.05, 3] | |
| self.gray_noise_prob = 0.4 | |
| self.jpeg_range = [30, 95] | |
| # 第二次退化的参数 | |
| self.second_blur_prob = 0.8 | |
| self.resize_prob2 = [0.3, 0.4, 0.3] # up, down, keep | |
| self.resize_range2 = [0.3, 1.2] | |
| self.gaussian_noise_prob2= 0.5 | |
| self.noise_range2 = [1, 25] | |
| self.poisson_scale_range2= [0.05, 2.5] | |
| self.gray_noise_prob2 = 0.4 | |
| self.jpeg_range2 = [30, 95] | |
| def __len__(self): | |
| return self.train_batches | |
| def __getitem__(self, index): | |
| index = index % self.train_batches | |
| image_origin = Image.open(self.train_lines[index].split()[0]) | |
| lq, gt = self.get_random_data(image_origin, self.hr_shape) | |
| gt = np.transpose(preprocess_input(np.array(gt, dtype=np.float32), [0.5,0.5,0.5], [0.5,0.5,0.5]), [2,0,1]) | |
| lq = np.transpose(preprocess_input(np.array(lq, dtype=np.float32), [0.5,0.5,0.5], [0.5,0.5,0.5]), [2,0,1]) | |
| return lq, gt | |
| def rand(self, a=0, b=1): | |
| return np.random.rand()*(b-a) + a | |
| def get_random_data(self, image, input_shape): | |
| #------------------------------# | |
| # 读取图像并转换成RGB图像 | |
| # cvtColor将np转Image | |
| #------------------------------# | |
| image = cvtColor(image) | |
| #------------------------------# | |
| # 获得图像的高宽与目标高宽 | |
| #------------------------------# | |
| iw, ih = image.size | |
| h, w = input_shape | |
| scale = min(w/iw, h/ih) | |
| nw = int(iw*scale) | |
| nh = int(ih*scale) | |
| dx = (w-nw)//2 | |
| dy = (h-nh)//2 | |
| #---------------------------------# | |
| # 将图像多余的部分加上灰条 | |
| #---------------------------------# | |
| image = image.resize((nw,nh), Image.BICUBIC) | |
| new_image = Image.new('RGB', (w,h), (128,128,128)) | |
| new_image.paste(image, (dx, dy)) | |
| image = np.array(new_image, np.float32) | |
| rotate = self.rand()<.5 | |
| if rotate: | |
| angle = np.random.randint(-15,15) | |
| a,b = w/2,h/2 | |
| M = cv2.getRotationMatrix2D((a,b),angle,1) | |
| image = cv2.warpAffine(np.array(image), M, (w,h), borderValue=[128,128,128]) | |
| # ------------------------ 生成卷积核以进行第一次退化处理 ------------------------ # | |
| kernel_size = choice(self.kernel_range) | |
| if np.random.uniform() < self.sinc_prob: | |
| # 此sinc过滤器设置适用于[7,21]范围内的内核 | |
| if kernel_size < 13: | |
| omega_c = np.random.uniform(np.pi / 3, np.pi) | |
| else: | |
| omega_c = np.random.uniform(np.pi / 5, np.pi) | |
| kernel = circular_lowpass_kernel(omega_c, kernel_size, pad_to=False) | |
| else: | |
| kernel = random_mixed_kernels( | |
| self.kernel_list, | |
| self.kernel_prob, | |
| kernel_size, | |
| self.blur_sigma, | |
| self.blur_sigma, [-math.pi, math.pi], | |
| self.betag_range, | |
| self.betap_range, | |
| noise_range=None) | |
| # pad kernel | |
| pad_size = (21 - kernel_size) // 2 | |
| kernel = np.pad(kernel, ((pad_size, pad_size), (pad_size, pad_size))) | |
| kernel = kernel.astype(np.float32) | |
| # ------------------------ 生成卷积核以进行第二次退化处理 ------------------------ # | |
| kernel_size = choice(self.kernel_range) | |
| if np.random.uniform() < self.sinc_prob2: | |
| if kernel_size < 13: | |
| omega_c = np.random.uniform(np.pi / 3, np.pi) | |
| else: | |
| omega_c = np.random.uniform(np.pi / 5, np.pi) | |
| kernel2 = circular_lowpass_kernel(omega_c, kernel_size, pad_to=False) | |
| else: | |
| kernel2 = random_mixed_kernels( | |
| self.kernel_list2, | |
| self.kernel_prob2, | |
| kernel_size, | |
| self.blur_sigma2, | |
| self.blur_sigma2, [-math.pi, math.pi], | |
| self.betag_range2, | |
| self.betap_range2, | |
| noise_range=None) | |
| # pad kernel | |
| pad_size = (21 - kernel_size) // 2 | |
| kernel2 = np.pad(kernel2, ((pad_size, pad_size), (pad_size, pad_size))) | |
| kernel2 = kernel2.astype(np.float32) | |
| # ----------------------the final sinc kernel ------------------------- # | |
| if np.random.uniform() < self.final_sinc_prob: | |
| kernel_size = choice(self.kernel_range) | |
| omega_c = np.random.uniform(np.pi / 3, np.pi) | |
| sinc_kernel = circular_lowpass_kernel(omega_c, kernel_size, pad_to=21) | |
| else: | |
| sinc_kernel = self.pulse_tensor | |
| sinc_kernel = sinc_kernel.astype(np.float32) | |
| lq, gt = self.feed_data(image, kernel, kernel2, sinc_kernel) | |
| return lq, gt | |
| def feed_data(self, img_gt, kernel1, kernel2, sinc_kernel): | |
| img_gt = np.array(img_gt, dtype=np.float32) | |
| # 对gt进行锐化 | |
| img_gt = np.clip(img_gt / 255, 0, 1) | |
| gt = self.usmsharp.filt(img_gt) | |
| [ori_w, ori_h, _] = gt.shape | |
| # ---------------------- 根据参数进行第一次退化 -------------------- # | |
| # 模糊处理 | |
| out = cv2.filter2D(img_gt, -1, kernel1) | |
| # 随机 resize | |
| updown_type = choices(['up', 'down', 'keep'], self.resize_prob)[0] | |
| if updown_type == 'up': | |
| scale = np.random.uniform(1, self.resize_range[1]) | |
| elif updown_type == 'down': | |
| scale = np.random.uniform(self.resize_range[0], 1) | |
| else: | |
| scale = 1 | |
| mode = choice(['area', 'bilinear', 'bicubic']) | |
| if mode=='area': | |
| out = cv2.resize(out, (int(ori_h * scale), int(ori_w * scale)), interpolation=cv2.INTER_AREA) | |
| elif mode=='bilinear': | |
| out = cv2.resize(out, (int(ori_h * scale), int(ori_w * scale)), interpolation=cv2.INTER_LINEAR) | |
| else: | |
| out = cv2.resize(out, (int(ori_h * scale), int(ori_w * scale)), interpolation=cv2.INTER_CUBIC) | |
| # 灰度噪声 | |
| gray_noise_prob = self.gray_noise_prob | |
| if np.random.uniform() < self.gaussian_noise_prob: | |
| out = random_add_gaussian_noise( | |
| out, sigma_range=self.noise_range, clip=True, rounds=False, gray_prob=gray_noise_prob) | |
| else: | |
| out = random_add_poisson_noise( | |
| out, | |
| scale_range=self.poisson_scale_range, | |
| gray_prob=gray_noise_prob, | |
| clip=True, | |
| rounds=False) | |
| # JPEG 压缩 | |
| jpeg_p = np.random.uniform(low=self.jpeg_range[0], high=self.jpeg_range[1]) | |
| jpeg_p = int(jpeg_p) | |
| out = np.clip(out, 0, 1) | |
| encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), jpeg_p] | |
| _, encimg = cv2.imencode('.jpg', out * 255., encode_param) | |
| out = np.float32(cv2.imdecode(encimg, 1))/255 | |
| # ---------------------- 根据参数进行第一次退化 -------------------- # | |
| # 模糊 | |
| if np.random.uniform() < self.second_blur_prob: | |
| out = cv2.filter2D(out, -1, kernel2) | |
| # 随机 resize | |
| updown_type = choices(['up', 'down', 'keep'], self.resize_prob2)[0] | |
| if updown_type == 'up': | |
| scale = np.random.uniform(1, self.resize_range2[1]) | |
| elif updown_type == 'down': | |
| scale = np.random.uniform(self.resize_range2[0], 1) | |
| else: | |
| scale = 1 | |
| mode = choice(['area', 'bilinear', 'bicubic']) | |
| if mode == 'area': | |
| out = cv2.resize(out, (int(ori_h / self.scale * scale), int(ori_w / self.scale * scale)), interpolation=cv2.INTER_AREA) | |
| elif mode == 'bilinear': | |
| out = cv2.resize(out, (int(ori_h / self.scale * scale), int(ori_w / self.scale * scale)), interpolation=cv2.INTER_LINEAR) | |
| else: | |
| out = cv2.resize(out, (int(ori_h / self.scale * scale), int(ori_w / self.scale * scale)), interpolation=cv2.INTER_CUBIC) | |
| # 灰度噪声 | |
| gray_noise_prob = self.gray_noise_prob2 | |
| if np.random.uniform() < self.gaussian_noise_prob2: | |
| out = random_add_gaussian_noise( | |
| out, sigma_range=self.noise_range2, clip=True, rounds=False, gray_prob=gray_noise_prob) | |
| else: | |
| out = random_add_poisson_noise( | |
| out, | |
| scale_range=self.poisson_scale_range2, | |
| gray_prob=gray_noise_prob, | |
| clip=True, | |
| rounds=False) | |
| # JPEG压缩+最后的sinc滤波器 | |
| # 我们还需要将图像的大小调整到所需的尺寸。我们把[调整大小+sinc过滤器]组合在一起 | |
| # 作为一个操作。 | |
| # 我们考虑两个顺序。 | |
| # 1. [调整大小+sinc filter] + JPEG压缩 | |
| # 2. 2. JPEG压缩+[调整大小+sinc过滤]。 | |
| # 根据经验,我们发现其他组合(sinc + JPEG + Resize)会引入扭曲的线条。 | |
| if np.random.uniform() < 0.5: | |
| # resize back + the final sinc filter | |
| mode = choice(['area', 'bilinear', 'bicubic']) | |
| if mode == 'area': | |
| out = cv2.resize(out, (ori_h // self.scale, ori_w // self.scale), interpolation=cv2.INTER_AREA) | |
| elif mode == 'bilinear': | |
| out = cv2.resize(out, (ori_h // self.scale, ori_w // self.scale), interpolation=cv2.INTER_LINEAR) | |
| else: | |
| out = cv2.resize(out, (ori_h // self.scale, ori_w // self.scale), interpolation=cv2.INTER_CUBIC) | |
| out = cv2.filter2D(out, -1, sinc_kernel) | |
| # JPEG 压缩 | |
| jpeg_p = np.random.uniform(low=self.jpeg_range[0], high=self.jpeg_range[1]) | |
| jpeg_p = jpeg_p | |
| out = np.clip(out, 0, 1) | |
| encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), jpeg_p] | |
| _, encimg = cv2.imencode('.jpg', out * 255., encode_param) | |
| out = np.float32(cv2.imdecode(encimg, 1)) / 255 | |
| else: | |
| # JPEG 压缩 | |
| jpeg_p = np.random.uniform(low=self.jpeg_range[0], high=self.jpeg_range[1]) | |
| jpeg_p = jpeg_p | |
| out = np.clip(out, 0, 1) | |
| encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), jpeg_p] | |
| _, encimg = cv2.imencode('.jpg', out * 255., encode_param) | |
| out = np.float32(cv2.imdecode(encimg, 1)) / 255 | |
| # resize back + the final sinc filter | |
| mode = choice(['area', 'bilinear', 'bicubic']) | |
| if mode == 'area': | |
| out = cv2.resize(out, (ori_h // self.scale, ori_w // self.scale),interpolation=cv2.INTER_AREA) | |
| elif mode == 'bilinear': | |
| out = cv2.resize(out, (ori_h // self.scale, ori_w // self.scale),interpolation=cv2.INTER_LINEAR) | |
| else: | |
| out = cv2.resize(out, (ori_h // self.scale, ori_w // self.scale),interpolation=cv2.INTER_CUBIC) | |
| lq = np.clip((out * 255.0), 0, 255) | |
| gt = np.clip((gt * 255.0), 0, 255) | |
| return Image.fromarray(np.uint8(lq)), Image.fromarray(np.uint8(gt)) | |
| def SRGAN_dataset_collate(batch): | |
| images_l = [] | |
| images_h = [] | |
| for img_l, img_h in batch: | |
| images_l.append(img_l) | |
| images_h.append(img_h) | |
| return np.array(images_l), np.array(images_h) | |