图像去雾,利用《bringing old photos back to life》 的开源代码

图像去雾,利用《bringing old photos back to life》 的开源代码

修改部分

训练测试

数据集

下载地址

修改部分

图像去雾,利用《bringing old photos back to life》 的开源代码

增改了一些数据处理代码,Create_Bigfile2.py和Load_Bigfilev2为特定任务需要加的代码,这里数据处理用的是原始方法,即将训练数据打包成一个文件,一次性载入,可能会内存爆炸。去雾的如下

图像去雾,利用《bringing old photos back to life》 的开源代码

另外,为了节省内存,可以不使用原始方法,我改写了online_dataset_for_odl_photos.py文件

用于我的加雾论文,此时可以不使用原始的Create_Bigfile和Load_bigfile代码如下

Copyright (c) Microsoft Corporation.

Licensed under the MIT License.

import os.path
import io
import zipfile
from data.base_dataset import BaseDataset, get_params, get_transform, normalize
from data.image_folder import make_dataset
from data.Load_Bigfile import BigFileMemoryLoader
import torchvision.transforms as tfs
from torchvision.transforms import functional as FF

from PIL import Image
import torchvision.transforms as transforms
import numpy as np

import random
import cv2
from io import BytesIO

#图片转矩阵
def pil_to_np(img_PIL):
    '''Converts image in PIL format to np.array.

    From W x H x C [0...255] to C x W x H [0..1]
    '''
    ar = np.array(img_PIL)

    if len(ar.shape) == 3:
        ar = ar.transpose(2, 0, 1)
    else:
        ar = ar[None, ...]

    return ar.astype(np.float32) / 255.

#矩阵转图片
def np_to_pil(img_np):
    '''Converts image in np.array format to PIL image.

    From C x W x H [0..1] to  W x H x C [0...255]
    '''
    ar = np.clip(img_np * 255, 0, 255).astype(np.uint8)

    if img_np.shape[0] == 1:
        ar = ar[0]
    else:
        ar = ar.transpose(1, 2, 0)

    return Image.fromarray(ar)
##
#以下合成噪声图片
##
def synthesize_salt_pepper(image,amount,salt_vs_pepper):

    ## Give PIL, return the noisy PIL

    img_pil=pil_to_np(image)

    out = img_pil.copy()
    p = amount
    q = salt_vs_pepper
    flipped = np.random.choice([True, False], size=img_pil.shape,
                               p=[p, 1 - p])
    salted = np.random.choice([True, False], size=img_pil.shape,
                              p=[q, 1 - q])
    peppered = ~salted
    out[flipped & salted] = 1
    out[flipped & peppered] = 0.

    noisy = np.clip(out, 0, 1).astype(np.float32)

    return np_to_pil(noisy)

def synthesize_gaussian(image,std_l,std_r):

    ## Give PIL, return the noisy PIL

    img_pil=pil_to_np(image)

    mean=0
    std=random.uniform(std_l/255.,std_r/255.)
    gauss=np.random.normal(loc=mean,scale=std,size=img_pil.shape)
    noisy=img_pil+gauss
    noisy=np.clip(noisy,0,1).astype(np.float32)

    return np_to_pil(noisy)

def synthesize_speckle(image,std_l,std_r):

    ## Give PIL, return the noisy PIL

    img_pil=pil_to_np(image)

    mean=0
    std=random.uniform(std_l/255.,std_r/255.)
    gauss=np.random.normal(loc=mean,scale=std,size=img_pil.shape)
    noisy=img_pil+gauss*img_pil
    noisy=np.clip(noisy,0,1).astype(np.float32)

    return np_to_pil(noisy)

#图片缩小
def synthesize_low_resolution(img):
    w,h=img.size

    new_w=random.randint(int(w/2),w)
    new_h=random.randint(int(h/2),h)

    img=img.resize((new_w,new_h),Image.BICUBIC)

    if random.uniform(0,1)<0.5: 2 256 img="img.resize((w,h),Image.NEAREST)" else: h), image.bilinear) return #处理图片 def converttojpeg(im,quality): #在内存中读写bytes with bytesio() as f: im.save(f, format="JPEG" ,quality="quality)" f.seek(0) #使用image.open读出图像,然后转换为rgb通道,去掉透明通道a image.open(f).convert('rgb') #由(高斯)噪声生成图片 blur_image_v2(img): x="np.array(img)" kernel_size_candidate="[(3,3),(5,5),(7,7)]" kernel_size="random.sample(kernel_size_candidate,1)[0]" std="random.uniform(1.,5.)" #print("the gaussian kernel size: (%d,%d) std: %.2f"%(kernel_size[0],kernel_size[1],std)) blur="cv2.GaussianBlur(x,kernel_size,std)" image.fromarray(blur.astype(np.uint8)) #由以上噪声函数随机生成含有噪声的图片 online_add_degradation_v2(img): task_id="np.random.permutation(4)" for in task_id: if and random.uniform(0,1)<0.7: flag="random.choice([1," 2, 3]) 1: 5, 50) 2: 3: random.uniform(0, 0.01), random.uniform(0.3, 0.8)) #根据mask生成带有折痕的图片 #原论文中对于一些复杂的折痕会出现处理不佳的情况,在此进行改进,而不是简单进行加mask, irregular_hole_synthesize(img,mask): img_np="np.array(img).astype('uint8')" mask_np="np.array(mask).astype('uint8')" img_new="img_np*(1-mask_np)+mask_np*255" hole_img="Image.fromarray(img_new.astype('uint8')).convert("RGB")" #l为灰度图像 hole_img,mask.convert("l") #生成全黑三通道图像mask zero_mask(size): mask="Image.fromarray(x).convert("RGB")" ######################################### my ################################ class unpairoldphotos_srv2(basedataset): ## synthetic + real old initialize(self, opt): self.opt="opt" self.isimage="domainA" opt.name self.task="old_photo_restoration_training_vae" self.dir_ab="opt.dataroot" # 载入voc以及真实灰度、彩色图 #domina self.isimage: path_clear="r'/home/vip/shy/ots/clear_images/'" ##self.opt.path_clear path_old="r'/home/vip/shy/Bringing-Old-Photos-Back-to-Life_v1/voc2007/Real_RGB_old'" ##self.opt.path_old path_haze="r'/home/vip/shy/ots/hazy/'" ##self.opt.path_haze #self.load_img_dir_l_old="os.path.join(self.dir_AB,"Real_L_old.bigfile")" self.load_img_dir_rgb_old="path_old" self.load_img_dir_clean="path_clear" self.load_img_dir_synhaze="path_haze" self.img_dir_synhaze="os.listdir(self.load_img_dir_Synhaze)" self.loaded_imgs_synhaze="[os.path.join(self.load_img_dir_Synhaze,img)" self.img_dir_synhaze] self.img_dir_rgb_old="os.listdir(self.load_img_dir_RGB_old)" self.loaded_imgs_rgb_old="[os.path.join(self.load_img_dir_RGB_old,img)" self.img_dir_rgb_old] self.loaded_imgs_clean="[]" path_i self.loaded_imgs_synhaze: p,n="os.path.split(path_i)" pre,ex="os.path.splitext(n)" clear_pre="pre.split('_')[0]" clear_path="os.path.join(path_clear,clear_pre+ex)" self.loaded_imgs_clean.append(clear_path) print('________________filter whose size <256') self.filtered_imgs_clean="[]" self.filtered_imgs_synhaze="[]" self.filtered_imgs_old="[]" print('________________now filter syn clean i range(len(self.loaded_imgs_synhaze)): img_name_syn="self.loaded_imgs_Synhaze[i]" h, w="img.size" img_name_clear="self.loaded_imgs_clean[i]" h < or 256: continue self.filtered_imgs_clean.append(img_name_clear) self.filtered_imgs_synhaze.append(img_name_syn) range(len(self.loaded_imgs_rgb_old)): img_name_old="self.loaded_imgs_RGB_old[i]" self.filtered_imgs_old.append(img_name_old) #dominb: domina not experiment's name ,load voc defultly self.img_dir_clean="os.listdir(self.load_img_dir_clean)" img) self.img_dir_clean] range(len(self.loaded_imgs_clean)): img_name_clean="self.loaded_imgs_clean[i]" self.filtered_imgs_clean.append(img_name_clean) #### print("-------------filter the imgs <256 finished -------------") self.pid="os.getpid()" __getitem__(self, index): is_real_old="0" sampled_dataset="None" degradation="None" #随机抽取一张图片(从合成的老照片 和 真实老照片 中) domain a , contains kinds of data: real_old p="random.uniform(0,2)">=0 and P<1: sampled_dataset="self.filtered_imgs_old" self.load_img_dir="self.load_img_dir_RGB_old" self.num="len(sampled_dataset)" is_real_old="1" if p>=1 and P<2: 2 256 sampled_dataset="self.filtered_imgs_Synhaze" self.load_img_dir="self.load_img_dir_Synhaze" self.num="len(sampled_dataset)" degradation="1" #domin b else: #载入过滤后小于256大小的图 index="random.randint(0,self.Num-1)" img_name="sampled_dataset[index]" a="Image.open(img_name)" path="img_name" ######################################################################### # i, j, h, w="tfs.RandomCrop.get_params(A," output_size="(256," 256)) w) a_tensor="#tfs.ToTensor()(A)" transform_params="get_params(self.opt," a.size) a_transform="get_transform(self.opt," transform_params) b_tensor="inst_tensor" = feat_tensor="0" input_dict="{'label':" a_tensor, 'inst': is_real_old, 'image': 'feat': feat_tensor, 'path': path} return def __len__(self): len(self.filtered_imgs_clean)## actually, this is useless, since the selected just random number #control epoch through iters="len(loaded_imgs_clean)" name(self): 'unpairoldphotos_sr' ###################################################################################3 #非成对的老照片图像载入器(合成的老的和真实的老的照片,他们并非对应的,合成的老的照片由voc数据集经处理生成) class unpairoldphotos_sr(basedataset): ## synthetic + real old initialize(self, opt): self.opt="opt" self.isimage="domainA" in opt.name self.task="old_photo_restoration_training_vae" self.dir_ab="opt.dataroot" 载入voc以及真实灰度、彩色图 #domina if self.isimage: #self.load_img_dir_l_old="os.path.join(self.dir_AB,"Real_L_old.bigfile")" self.load_img_dir_rgb_old="os.path.join(self.dir_AB,"Real_RGB_old.bigfile")" self.load_img_dir_clean="os.path.join(self.dir_AB,"VOC_RGB_JPEGImages.bigfile")" self.load_img_dir_synhaze="os.path.join(self.dir_AB,"VOC_RGB_Synhaze.bigfile")" #self.loaded_imgs_l_old="BigFileMemoryLoader(self.load_img_dir_L_old)" self.loaded_imgs_rgb_old="BigFileMemoryLoader(self.load_img_dir_RGB_old)" self.loaded_imgs_clean="BigFileMemoryLoader(self.load_img_dir_clean)" self.loaded_imgs_synhaze="BigFileMemoryLoader(self.load_img_dir_Synhaze)" #dominb: domina not experiment's name ,load voc defultly #### print("-------------filter imgs whose size <256 voc-------------") self.filtered_imgs_clean="[]" self.filtered_imgs_synhaze="[]" 过滤出voc中小于256的图片 for i range(len(self.loaded_imgs_clean)): img_name,img="self.loaded_imgs_clean[i]" synimg_name,synimg="self.loaded_imgs_Synhaze[i]" h,w="img.size" h<256 or w<256: continue self.filtered_imgs_clean.append((img_name,img)) self.filtered_imgs_synhaze.append((synimg_name,synimg)) print("--------origin image num [%d], filtered result [%d]--------" % ( len(self.loaded_imgs_clean), len(self.filtered_imgs_clean))) filter these images less than self.img_list="os.listdir(load_img_dir)" self.pid="os.getpid()" __getitem__(self, index): is_real_old="0" #随机抽取一张图片(从合成的老照片 和 真实老照片 中) domain , contains kinds of data: real_old p="random.uniform(0,2)">=0 and P<1: # if random.uniform(0,1)<0.5: sampled_dataset="self.loaded_imgs_L_old" self.load_img_dir="self.load_img_dir_L_old" else: is_real_old="1" p>=1 and P<2: 0 256 # sampled_dataset="self.filtered_imgs_Synhaze" self.load_img_dir="self.load_img_dir_Synhaze" degradation="1" #domin b else: #载入过滤后小于256大小的图 sampled_dataset_len="len(sampled_dataset)" index="random.randint(0,sampled_dataset_len-1)" img_name,img="sampled_dataset[index]" #already old #if is not none: #对图片进行降质做旧处理 img="online_add_degradation_v2(img)" path="os.path.join(self.load_img_dir,img_name)" ab="Image.open(path).convert('RGB')" split image into a and apply the same transform to both #随机对图片转换为灰度图 if random.uniform(0,1) <0.1: ## give probability p, we convert rgb l #调整大小 w,h="A.size" w<256 or h<256: 将图片裁剪为256*256,对于一些小于256的老照片,先进行调整大小 since want only crop images (256*256), for those photos whose size smaller than 256, first resize them. transform_params="get_params(self.opt," a.size) a_transform="get_transform(self.opt," transform_params) b_tensor="inst_tensor" = feat_tensor="0" a_tensor="A_transform(A)" #存入字典 #a_tensor : syn imgtensor; #is_real_old: 1:old ; 0:syn #feat input_dict="{'label':" a_tensor, 'inst': is_real_old, 'image': 'feat': feat_tensor, 'path': path} return def __len__(self): len(self.loaded_imgs_clean) actually, this useless, selected just random number name(self): 'unpairoldphotos_sr' ################################# my #################### self.isimage: #成对图像载入器(原始图及其合成旧图) mapping class pairoldphotosv2(basedataset): initialize(self, opt): self.opt="opt" self.isimage="imagan" in opt.name #actually ,useless self.task="old_photo_restoration_training_mapping" self.dir_ab="opt.dataroot" #训练模式,载入 opt.istrain: path_clear="r'/home/vip/shy/ots/clear_images/'" path_haze="r'/home/vip/shy/ots/hazy/'" self.load_img_dir_clean="path_clear" self.load_img_dir_synhaze="path_haze" self.img_dir_synhaze="os.listdir(self.load_img_dir_Synhaze)" self.loaded_imgs_synhaze="[os.path.join(self.load_img_dir_Synhaze,img)" self.img_dir_synhaze] self.loaded_imgs_clean="[]" path_i self.loaded_imgs_synhaze: p,n="os.path.split(path_i)" pre,ex="os.path.splitext(n)" clear_pre="pre.split('_')[0]" clear_path="os.path.join(path_clear,clear_pre+ex)" self.loaded_imgs_clean.append(clear_path) print('________________filter <256') self.filtered_imgs_clean="[]" self.filtered_imgs_synhaze="[]" print('________________now filter clean i range(len(self.loaded_imgs_synhaze)): img_name_syn="self.loaded_imgs_Synhaze[i]" h, w="img.size" img_name_clear="self.loaded_imgs_clean[i]" h < 256: continue self.filtered_imgs_clean.append(img_name_clear) self.filtered_imgs_synhaze.append(img_name_syn) print("--------origin num [%d], filtered result [%d]--------" % ( len(self.loaded_imgs_clean), len(self.filtered_imgs_clean))) #测试模式时,仅载入测试集 self.opt.test_on_synthetic: ############valset######### path_val_clear="r'/home/vip/shy/SOTS/outdoor/gt'" ######none###############self.opt.path_clear path_val_haze="r'/home/vip/shy/SOTS/outdoor/hazy'" #########none#############self.opt.path_haze img) n="os.path.split(path_i)" pre, ex="os.path.splitext(n)" + ex) self.filtered_val_imgs_clean="[]" self.filtered_val_imgs_synhaze="[]" val self.filtered_val_imgs_clean.append(img_name_clear) self.filtered_val_imgs_synhaze.append(img_name_syn) print('________________finished ') ############testset######### path_test_clear="r'/home/vip/shy/SOTS/outdoor/gt'" ##################self.opt.path_test_clear path_test_haze="r'/home/vip/shy/SOTS/outdoor/hazy'" ###################self.opt.path_test_haze self.filtered_test_imgs_clean="[]" self.filtered_test_imgs_synhaze="[]" testset self.filtered_test_imgs_clean.append(img_name_clear) self.filtered_test_imgs_synhaze.append(img_name_syn) len(self.loaded_imgs_synhaze), len(self.filtered_test_imgs_synhaze))) self.pid="os.getpid()" __getitem__(self, index): #训练模式 self.opt.istrain: #(b为清晰voc数据集) img_name_clean="self.filtered_imgs_clean[index]" img_name_synhaze="self.filtered_imgs_Synhaze[index]" s="Image.open(img_name_synhaze)" #生成成对图像(b为清晰voc数据集,a对应的含噪声的图像) ### remind: input corresponding gt #ceshi daima wei xiugai ##################################################### #测试模式 #(b为清晰voc数据集,a对应的含噪声的图像) #valset img_name_b="self.filtered_test_imgs_clean[index]" img_name_a="self.filtered_test_imgs_Synhaze[index]" #testset #去掉透明通道 random.uniform(0,1)<0.1 #获取变换相关参数test_dataset #变换数据,数据增强 b_transform="get_transform(self.opt," inst_tensor, b_tensor, len(self.filtered_imgs_clean) len(self.filtered_test_imgs_clean) 'pairoldphotos' pairoldphotos(basedataset): #训练模式,载入voc "voc_rgb_jpegimages.bigfile") "voc_rgb_synhaze.bigfile") print("-------------filter imgs <256 voc-------------") #过滤出voc中小于256的图片 range(len(self.loaded_imgs_clean)): img_name, synhazeimg_name, synhazeimg="self.loaded_imgs_clean[i]" self.filtered_imgs_clean.append((img_name, img)) self.filtered_imgs_synhaze.append((synhazeimg_name, synhazeimg)) self.loaded_imgs="BigFileMemoryLoader(self.load_img_dir)" img_name_clean,b="self.filtered_imgs_clean[index]" img_name_synhaze,s="self.filtered_imgs_Synhaze[index]" img_name_clean) self.opt.use_v2_degradation: img_name_b,b="self.loaded_imgs[index]" img_name_a) img_name_a,a="self.loaded_imgs[index]" ##test on w, w2="int(w" 2) 0, w2, h)) image.bicubic)(b) #获取变换相关参数 len(self.loaded_imgs) ##################################################################### #成对带折痕图像载入器 pairoldphotos_with_hole(basedataset): #训练模式下,载入成对的带有裂痕的合成图片 #过滤出大小小于256的图片 #载入不规则mask self.loaded_masks="BigFileMemoryLoader(opt.irregular_mask)" #a="A.resize((256,256))" #载入mask mask_name,mask="self.loaded_masks[random.randint(0,len(self.loaded_masks)-1)]" 载入mask mask_name, mask="self.loaded_masks[index%100]" #调整mask大小 self.opt.loadsize), image.nearest) self.opt.random_hole>0.5 and self.opt.isTrain:
            mask=zero_mask(256)
#
        if self.opt.no_hole:
            mask=zero_mask(256)
#
        #&#x7531;mask&#x5408;&#x6210;&#x5E26;&#x6709;&#x6298;&#x75D5;&#x7684;&#x56FE;&#x7247;
        A,_=irregular_hole_synthesize(A,mask)
#
        if not self.opt.isTrain and self.opt.hole_image_no_mask:
            mask=zero_mask(256)
        #&#x83B7;&#x53D6;&#x505A;&#x65E7;&#x53D8;&#x6362;&#x53C2;&#x6570;
        transform_params = get_params(self.opt, A.size)
        A_transform = get_transform(self.opt, transform_params)
        B_transform = get_transform(self.opt, transform_params)
        #&#x5BF9;mask&#x8FDB;&#x884C;&#x76F8;&#x540C;&#x7684;&#x5DE6;&#x53F3;&#x7FFB;&#x8F6C;
        if transform_params['flip'] and self.opt.isTrain:
            mask=mask.transpose(Image.FLIP_LEFT_RIGHT)
        #&#x5F52;&#x4E00;&#x5316;
        mask_tensor = transforms.ToTensor()(mask)
#
#
        B_tensor = inst_tensor = feat_tensor = 0
        A_tensor = A_transform(A)
        B_tensor = B_transform(B)
#
        input_dict = {'label': A_tensor, 'inst': mask_tensor[:1], 'image': B_tensor,
                    'feat': feat_tensor, 'path': path}
        return input_dict
#
    def __len__(self):
#
        if self.opt.isTrain:
            return len(self.filtered_imgs_clean)
#
        else:
            return len(self.loaded_imgs)
#
    def name(self):
        return 'PairOldPhotos_with_hole'</2:></1:></2:></1:></0.5:>

用于去雾时,我改写得代码如下,增加了利用清晰图像和对应的深度图生成雾图的代码,合并至源代码中的online_dataset_for_odl_photos.py中。如下

Copyright (c) Microsoft Corporation.

Licensed under the MIT License.

import os.path
import io
import zipfile
from data.base_dataset import BaseDataset, get_params, get_transform, normalize
from data.image_folder import make_dataset
import torchvision.transforms as transforms
from data.Load_Bigfile import BigFileMemoryLoader
from data.Load_Bigfilev2 import BigFileMemoryLoaderv2

from io import BytesIO
import os
import glob
import cv2, math
import random
import numpy as np
import h5py
import os
from PIL import Image
import scipy.io

def pil_to_np(img_PIL):
    '''Converts image in PIL format to np.array.

    From W x H x C [0...255] to C x W x H [0..1]
    '''
    ar = np.array(img_PIL)

    if len(ar.shape) == 3:
        ar = ar.transpose(2, 0, 1)
    else:
        ar = ar[None, ...]

    return ar.astype(np.float32) / 255.

def np_to_pil(img_np):
    '''Converts image in np.array format to PIL image.

    From C x W x H [0..1] to  W x H x C [0...255]
    '''
    ar = np.clip(img_np * 255, 0, 255).astype(np.uint8)

    if img_np.shape[0] == 1:
        ar = ar[0]
    else:
        ar = ar.transpose(1, 2, 0)

    return Image.fromarray(ar)

def synthesize_salt_pepper(image,amount,salt_vs_pepper):

    ## Give PIL, return the noisy PIL

    img_pil=pil_to_np(image)

    out = img_pil.copy()
    p = amount
    q = salt_vs_pepper
    flipped = np.random.choice([True, False], size=img_pil.shape,
                               p=[p, 1 - p])
    salted = np.random.choice([True, False], size=img_pil.shape,
                              p=[q, 1 - q])
    peppered = ~salted
    out[flipped & salted] = 1
    out[flipped & peppered] = 0.

    noisy = np.clip(out, 0, 1).astype(np.float32)

    return np_to_pil(noisy)

def synthesize_gaussian(image,std_l,std_r):

    ## Give PIL, return the noisy PIL

    img_pil=pil_to_np(image)

    mean=0
    std=random.uniform(std_l/255.,std_r/255.)
    gauss=np.random.normal(loc=mean,scale=std,size=img_pil.shape)
    noisy=img_pil+gauss
    noisy=np.clip(noisy,0,1).astype(np.float32)

    return np_to_pil(noisy)

def synthesize_speckle(image,std_l,std_r):

    ## Give PIL, return the noisy PIL

    img_pil=pil_to_np(image)

    mean=0
    std=random.uniform(std_l/255.,std_r/255.)
    gauss=np.random.normal(loc=mean,scale=std,size=img_pil.shape)
    noisy=img_pil+gauss*img_pil
    noisy=np.clip(noisy,0,1).astype(np.float32)

    return np_to_pil(noisy)

def synthesize_low_resolution(img):
    w,h=img.size

    new_w=random.randint(int(w/2),w)
    new_h=random.randint(int(h/2),h)

    img=img.resize((new_w,new_h),Image.BICUBIC)

    if random.uniform(0,1)<0.5: 1985 2017 img="img.resize((w,h),Image.NEAREST)" else: h), image.bilinear) return def converttojpeg(im,quality): with bytesio() as f: im.save(f, format="JPEG" ,quality="quality)" f.seek(0) image.open(f).convert('rgb') blur_image_v2(img): x="np.array(img)" kernel_size_candidate="[(3,3),(5,5),(7,7)]" kernel_size="random.sample(kernel_size_candidate,1)[0]" std="random.uniform(1.,5.)" #print("the gaussian kernel size: (%d,%d) std: %.2f"%(kernel_size[0],kernel_size[1],std)) blur="cv2.GaussianBlur(x,kernel_size,std)" image.fromarray(blur.astype(np.uint8)) perlin_noise(im,varargin): """ this is the function for adding perlin noise to depth map. it a simplified implementation of paper: an image sunthesizer ken perlin, siggraph, jul. bicubic interpolation used, compared original version. reference: hazerd: outdoor scene dataset and benchmark single dehazing ieee international conference on processing, sep paper additional information project are available at: https: labsites.rochester.edu gsharma research computer-vision hazerd if you use code, please cite our paper. input: im: map varargin{1}: decay term output: result transmission added authors: yanfu zhang: yzh185@ur.rochester.edu li ding: l.ding@rochester.edu gaurav sharma: gaurav.sharma@rochester.edu last update: may :return: # (h, w, c)="im.shape" i="1" nargin="=" 1: l_bound="min(h,w)" while <="l_bound:" d="imresize(randn(i," i)*decay, im.shape, 'bicubic') im="im+d" pass srgb2lrgb(i0): gamma="((I0" + 0.055) 1.055)**2.4 scale="I0" 12.92 np.where (i0> 0.04045, gamma, scale)

def lrgb2srgb(I1):
    gamma =  1.055*I1**(1/2.4)-0.055
    scale = I1 * 12.92
    return np.where (I1 > 0.0031308, gamma, scale)

#return : depth matrix
def get_depth(depth_or_trans_name):
    #depth_or_trans_name&#x4E3A;mat&#x7C7B;&#x578B;&#x6587;&#x4EF6;&#x6216;&#x8005;img&#x7C7B;&#x578B;&#x6587;&#x4EF6;&#x5730;&#x5740;
    data = scipy.io.loadmat(depth_or_trans_name)
    depths = data['imDepth'] #&#x6DF1;&#x5EA6;&#x53D8;&#x91CF;
    #print(data.keys())  #&#x6253;&#x5370;mat&#x6587;&#x4EF6;&#x4E2D;&#x6240;&#x6709;&#x53D8;&#x91CF;
    depths = np.array(depths)
    return depths

def irregular_hole_synthesize(img,mask):

    img_np=np.array(img).astype('uint8')
    mask_np=np.array(mask).astype('uint8')
    mask_np=mask_np/255
    img_new=img_np*(1-mask_np)+mask_np*255

    hole_img=Image.fromarray(img_new.astype('uint8')).convert("RGB")

    return hole_img,mask.convert("L")

def zero_mask(size):
    x=np.zeros((size,size,3)).astype('uint8')
    mask=Image.fromarray(x).convert("RGB")
    return mask

def hazy_simu(img_name,depth_or_trans_name,airlight=0.76,is_imdepth=1): ##for outdoor
"""
    This is the function for haze simulation with the parameters given by
    the paper:
    HAZERD: an outdoor scene dataset and benchmark for single image dehazing
    IEEE Internation Conference on Image Processing, Sep 2017
    The paper and additional information on the project are available at:
    https://labsites.rochester.edu/gsharma/research/computer-vision/hazerd/
    If you use this code, please cite our paper.

    IMPORTANT NOTE: The code uses the convention that pixel locations with a
    depth value of 0 correspond to objects that are very far and for the
    simulation of haze these are placed a distance of 2 times the visual
    range.

    Authors:
    Yanfu Zhang: yzh185@ur.rochester.edu
    Li Ding: l.ding@rochester.edu
    Gaurav Sharma: gaurav.sharma@rochester.edu

    Last update: May 2017

    python version update : Aug 2021
    Authors :
    Haoying Sun : 1913434222@qq.com

    parse inputs and set default values
    Set default parameter values. Some of these are used only if they are not
    passed in

    :param img_name: the directory and name of a haze-free RGB image, the name
                     should be in the format of ..._RGB.jpg
    :param depth_name: the corresponding directory and name of the depth map, in
                     .mat file, the name should be in the format of ..._depth.mat
    :param save_dir: the directory to save the simulated images
    :param pert_perlin: 1 for adding perlin noise, default 0
    :param airlight:  3*1 matrix in the range [0,1]
    :param visual_range: a vector of any size
    :return: image name of hazy image
"""
    # if random.uniform(0, 1) < 0.5:
    visual_range = [0.05, 0.1, 0.2, 0.5, 1]  #  visual range in km #&#x53EF;&#x81EA;&#x884C;&#x8C03;&#x6574;&#xFF0C;&#x6216;&#x8005;&#x4F7F;&#x7528;range&#x51FD;&#x6570;&#x8BBE;&#x7F6E;&#x533A;&#x95F4;&#xFF0C;&#x6B64;&#x65F6;&#x9700;&#x8981;&#x4FEE;&#x6539;beta_param,&#x5C1A;&#x672A;&#x7814;&#x7A76;
    beta_param = 3.912     #Default beta parameter corresponding to visual range of 1000m

    A = airlight
    #print('Simulating hazy image for:{}'.format(img_name))
    VR = random.choice(visual_range)

    #print('Viusal value: {} km'.format(VR) )
    #im1 = cv2.imread(img_name)
    img_pil = pil_to_np(img_name)

    #convert sRGB to linear RGB
    I = srgb2lrgb(img_pil)

    if is_imdepth:
        depths = depth_or_trans_name

        d = depths/1000   # convert meter to kilometer
        if depths.max()==0:
            d = np.where(d == 0,0.01, d) ####
        else:
            d = np.where(d==0,2*VR,d)
        #Set regions where depth value is set to 0 to indicate no valid depth to
        #a distance of two times the visual range. These regions typically
        #correspond to sky areas

        #convert depth map to transmission
        beta = beta_param / VR
        beta_return = beta
        beta = np.ones(d.shape) * beta
        transmission = np.exp((-beta*d))
        transmission_3 = np.array([transmission,transmission,transmission])

        #Obtain simulated linear RGB hazy image.Eq. 3 in the HazeRD paper
        Ic = transmission_3 * I + (1 - transmission_3) * A
    else:
        Ic = pil_to_np(depth_or_trans_name) * I + (1 - pil_to_np(depth_or_trans_name)) * A

    # convert linear RGB to sRGB
    I2 = lrgb2srgb(Ic)
    haze_img = np_to_pil(I2)
    # haze_img = np.asarray(haze_img)
    # haze_img = cv2.cvtColor(haze_img, cv2.COLOR_RGB2BGR)
    # haze_img = Image.fromarray(haze_img)
    return haze_img,airlight,beta_return

def hazy_reside_training(img_name,depth_or_trans_name,is_imdepth=1):
"""
    RESIDE&#x7684; training&#x4E2D;&#xFF1A;A &#xFF1A;(0.7, 1.0) ,   beta&#xFF1A;(0.6, 1.8)
    :param img_name:
    :param depth_or_trans_name:
    :param pert_perlin:
    :param is_imdepth:
    :return:
"""
    beta = random.uniform(0.6, 1.8)
    beta_return = beta
    airlight = random.uniform(0.7, 1.0)

    A = airlight

    #print('Viusal value: {} km'.format(VR) )
    #im1 = cv2.imread(img_name)
    img_pil = pil_to_np(img_name)

    #convert sRGB to linear RGB
    I = srgb2lrgb(img_pil)

    if is_imdepth:
        depths = depth_or_trans_name

        #convert depth map to transmission
        if depths.max()==0:
            d = np.where(depths == 0,1, depths)
        else:
            d = depths / depths.max()
            d = np.where(d == 0, 1, d)

        beta = np.ones(d.shape) * beta
        transmission = np.exp((-beta*d))
        transmission_3 = np.array([transmission,transmission,transmission])

        #Obtain simulated linear RGB hazy image.Eq. 3 in the HazeRD paper
        Ic = transmission_3 * I + (1 - transmission_3) * A

    else:
        Ic = pil_to_np(depth_or_trans_name) * I + (1 - pil_to_np(depth_or_trans_name)) * A

    # convert linear RGB to sRGB
    I2 = lrgb2srgb(Ic)
    #I2 = cv2.cvtColor(I2, cv2.COLOR_BGR2RGB)

    haze_img = np_to_pil(I2)
    # haze_img = np.asarray(haze_img)
    # haze_img = cv2.cvtColor(haze_img, cv2.COLOR_RGB2BGR)
    # haze_img = Image.fromarray(haze_img)
    return haze_img,airlight,beta_return

def hazy_reside_OTS(img_name,depth_or_trans_name,is_imdepth=1):
"""
    RESIDE&#x7684; OTS&#x4E2D;&#xFF1A;A [0.8, 0.85, 0.9, 0.95, 1] ,   beta&#xFF1A;[0.04, 0.06, 0.08, 0.1, 0.12, 0.16, 0.2]
    :param img_name:
    :param depth_or_trans_name:
    :param pert_perlin:
    :param is_imdepth:
    :return:
"""
    beta = random.choice([0.04, 0.06, 0.08, 0.1, 0.12, 0.16, 0.2])
    beta_return = beta
    airlight = random.choice([0.8, 0.85, 0.9, 0.95, 1])
    #print(beta)
    #print(airlight)
    A = airlight

    #print('Viusal value: {} km'.format(VR) )
    #im1 = cv2.imread(img_name)

    #img = cv2.cvtColor(np.asarray(img_name), cv2.COLOR_RGB2BGR)
    img_pil = pil_to_np(img_name)

    #convert sRGB to linear RGB
    I = srgb2lrgb(img_pil)

    if is_imdepth:
        depths = depth_or_trans_name
        #convert depth map to transmission
        if depths.max()==0:
                d = np.where(depths == 0, 1, depths)
        else:
            d = depths/(depths.max())
            d = np.where(d == 0, 1, d)

        beta = np.ones(d.shape) * beta
        transmission = np.exp((-beta*d))
        transmission_3 = np.array([transmission,transmission,transmission])

        #Obtain simulated linear RGB hazy image.Eq. 3 in the HazeRD paper
        Ic = transmission_3 * I + (1 - transmission_3) * A

    else:
        Ic = pil_to_np(depth_or_trans_name) * I + (1 - pil_to_np(depth_or_trans_name)) * A

    # convert linear RGB to sRGB
    I2 = lrgb2srgb(Ic)
    haze_img = np_to_pil(I2)

    #haze_img = np.asarray(haze_img)
    #haze_img = cv2.cvtColor(haze_img, cv2.COLOR_RGB2BGR)
    #haze_img = Image.fromarray(haze_img)
    return haze_img,airlight,beta_return
def online_add_degradation_v2(img,depth_or_trans):
    noise = 0
    task_id=np.random.permutation(4)
    if random.uniform(0,1)<0.3: noise="1" #print('noise') for x in task_id: #为增加更多变化,随机进行30%的丢弃,即<0.7 if and random.uniform(0,1)<0.7: img="blur_image_v2(img)" flag="random.choice([1," 2, 3]) 1: 5, 50) # gaussian white with σ ∈ [5,50] 2: 3: random.uniform(0, 0.01), random.uniform(0.3, 0.8)) #jpeg compression whose level is the range of [40,100] add_haze="random.choice([1,2,3])" img, airlight, beta="hazy_reside_OTS(img," depth_or_trans) elif else: < 0.1:> 0.1 and add_haze < 0.2:
    #         img = hazy_simu(img, depth_or_trans)
    #     else:
    #         img = hazy_reside_training(img, depth_or_trans)
    return img#,noise,airlight,beta

class UnPairOldPhotos_SR(BaseDataset):  ## Synthetic + Real Old
    def initialize(self, opt):
        self.opt = opt
        self.isImage = 'domainA' in opt.name
        self.task = 'old_photo_restoration_training_vae'
        self.dir_AB = opt.dataroot
        if self.isImage:

            self.load_npy_dir_depth=os.path.join(self.dir_AB,"VOC_RGB_Depthnpy.bigfile")
            self.load_img_dir_RGB_old=os.path.join(self.dir_AB,"Real_RGB_old.bigfile")
            self.load_img_dir_clean=os.path.join(self.dir_AB,"VOC_RGB_JPEGImages.bigfile")

            self.loaded_npys_depth=BigFileMemoryLoaderv2(self.load_npy_dir_depth)
            self.loaded_imgs_RGB_old=BigFileMemoryLoader(self.load_img_dir_RGB_old)
            self.loaded_imgs_clean=BigFileMemoryLoader(self.load_img_dir_clean)

        else:
            # self.load_img_dir_clean=os.path.join(self.dir_AB,self.opt.test_dataset)
            self.load_img_dir_clean=os.path.join(self.dir_AB,"VOC_RGB_JPEGImages.bigfile")
            self.loaded_imgs_clean=BigFileMemoryLoader(self.load_img_dir_clean)

            self.load_npy_dir_depth=os.path.join(self.dir_AB,"VOC_RGB_Depthnpy.bigfile")
            self.loaded_npys_depth=BigFileMemoryLoaderv2(self.load_npy_dir_depth)

        ####
        print("-------------Filter the imgs whose size <256 2 256 in voc-------------") self.filtered_imgs_clean="[]" self.filtered_npys_depth="[]" for i range(len(self.loaded_imgs_clean)): img_name,img="self.loaded_imgs_clean[i]" npy_name, npy="self.loaded_npys_depth[i]" h,w="img.size" if h<256 or w<256: continue self.filtered_imgs_clean.append((img_name,img)) self.filtered_npys_depth.append((npy_name, npy)) print("--------origin image num is [%d], filtered result [%d]--------" % ( len(self.loaded_imgs_clean), len(self.filtered_imgs_clean))) ## filter these images whose size less than # self.img_list="os.listdir(load_img_dir)" self.pid="os.getpid()" def __getitem__(self, index): is_real_old="0" sampled_dataset="None" sampled_depthdataset="None" degradation="None" self.isimage: domain a , contains kinds of data: synthetic + real_old p="random.uniform(0,2)">=0 and P<1: #if random.uniform(0,1)<0.5: # buyao huidutu #sampled_dataset="self.loaded_imgs_L_old" #self.load_img_dir="self.load_img_dir_L_old" sampled_dataset="self.loaded_imgs_RGB_old" self.load_img_dir="self.load_img_dir_RGB_old" else: is_real_old="1" if p>=1 and P<2: 256 sampled_dataset="self.filtered_imgs_clean" self.load_img_dir="self.load_img_dir_clean" sampled_depthdataset="self.filtered_npys_depth" self.load_npy_dir="self.load_npy_dir_depth" degradation="1" else: sampled_dataset_len="len(sampled_dataset)" #print('sampled_dataset_len::::',sampled_dataset_len) index="random.randint(0,sampled_dataset_len-1)" img_name,img="sampled_dataset[index]" # print(img_name) print(img) print(index) #print(npy_name) #print(npy) if is not none: npy_name, npy="sampled_depthdataset[index]" img="online_add_degradation_v2(img,npy)" path="os.path.join(self.load_img_dir,img_name)" ab="Image.open(path).convert('RGB')" split image into a and b apply the same transform to both random.uniform(0,1) <0.1: ## give probability p, we convert rgb l w,h="A.size" w<256 or h<256: since want only crop images (256*256), for those old photos whose size smaller than 256, first resize them. transform_params="get_params(self.opt," a.size) a_transform="get_transform(self.opt," transform_params) b_tensor="inst_tensor" = feat_tensor="0" a_tensor="A_transform(A)" input_dict="{'label':" a_tensor, 'inst': is_real_old, 'image': 'feat': feat_tensor, 'path': path} return def __len__(self): len(self.loaded_imgs_clean) actually, this useless, selected just random number name(self): 'unpairoldphotos_sr' class pairoldphotos(basedataset): initialize(self, opt): self.opt="opt" self.isimage="imagegan" in opt.name self.task="old_photo_restoration_training_mapping" self.dir_ab="opt.dataroot" opt.istrain: self.load_img_dir_clean="os.path.join(self.dir_AB," "voc_rgb_jpegimages.bigfile") self.loaded_imgs_clean="BigFileMemoryLoader(self.load_img_dir_clean)" self.load_npy_dir_depth="os.path.join(self.dir_AB," "voc_rgb_depthnpy.bigfile") self.loaded_npys_depth="BigFileMemoryLoaderv2(self.load_npy_dir_depth)" print("-------------filter imgs <256 voc-------------") self.filtered_imgs_clean="[]" self.filtered_npys_depth="[]" i range(len(self.loaded_imgs_clean)): img_name, h, w="img.size" h < 256: continue self.filtered_imgs_clean.append((img_name, img)) self.filtered_npys_depth.append((npy_name, npy)) print("--------origin num [%d], filtered result [%d]--------" % ( len(self.loaded_imgs_clean), len(self.filtered_imgs_clean))) self.loaded_imgs="BigFileMemoryLoader(self.load_img_dir)" self.load_depth_dir="os.path.join(self.dir_AB," opt.test_depthdataset) self.loaded_npys="BigFileMemoryLoaderv2(self.load_depth_dir)" self.pid="os.getpid()" __getitem__(self, index): self.opt.istrain: img_name_clean,b="self.filtered_imgs_clean[index]" npy_name_depth,d="self.filtered_npys_depth[index]" img_name_clean) self.opt.use_v2_degradation: ### remind: input corresponding gt self.opt.test_on_synthetic: img_name_b,b="self.loaded_imgs[index]" npy_name_d,d="self.loaded_npys[index]" a.save('.. mybig_data ' + '.jpg') img_name_a="img_name_B" img_name_a) img_name_a,a="self.loaded_imgs[index]" random.uniform(0,1)<0.1 ##test on w, w2="int(w" 2) 0, w2, h)) image.bicubic)(b) b_transform="get_transform(self.opt," inst_tensor, b_tensor, len(self.filtered_imgs_clean) len(self.loaded_imgs) 'pairoldphotos' #del pairoldphotos_with_hole(basedataset): self.loaded_masks="BigFileMemoryLoader(opt.irregular_mask)" npy_name_depth, d="self.filtered_npys_depth[index]" #a="A.resize((256,256))" mask_name,mask="self.loaded_masks[random.randint(0,len(self.loaded_masks)-1)]" mask_name, mask="self.loaded_masks[index%100]" self.opt.loadsize), image.nearest) self.opt.random_hole>0.5 and self.opt.isTrain:
            mask=zero_mask(256)

        if self.opt.no_hole:
            mask=zero_mask(256)

        A,_=irregular_hole_synthesize(A,mask)

        if not self.opt.isTrain and self.opt.hole_image_no_mask:
            mask=zero_mask(256)

        transform_params = get_params(self.opt, A.size)
        A_transform = get_transform(self.opt, transform_params)
        B_transform = get_transform(self.opt, transform_params)

        if transform_params['flip'] and self.opt.isTrain:
            mask=mask.transpose(Image.FLIP_LEFT_RIGHT)

        mask_tensor = transforms.ToTensor()(mask)

        B_tensor = inst_tensor = feat_tensor = 0
        A_tensor = A_transform(A)
        B_tensor = B_transform(B)

        input_dict = {'label': A_tensor, 'inst': mask_tensor[:1], 'image': B_tensor,
                    'feat': feat_tensor, 'path': path}
        return input_dict

    def __len__(self):

        if self.opt.isTrain:
            return len(self.filtered_imgs_clean)

        else:
            return len(self.loaded_imgs)

    def name(self):
        return 'PairOldPhotos_with_hole'</2:></1:></256></0.3:></0.5:>

把比较重要的改动写了下,以上在之前得博客中有的提到过。

训练测试

run.py里前面有三行存放了训练、测试、数据准备(请查看data文件夹里里的代码,可以不需要此部分)的代码,需要酌情修改。如下

############test############
#python run.py --input_folder /home/vip/shy/HBDH/haze --output_folder /home/vip/shy/HBDH/l1-feat30-01 --GPU 0

############dataset prepare#################
python Create_Bigfile.py

############train A&#x3001;B&#x3001;mapping############
#python train_domain_A.py --use_v2_degradation --continue_train --training_dataset domain_A --name domainA_SR_old_photos --label_nc 0 --loadSize 256 --fineSize 256 --dataroot ../mybig_data/ --no_instance --resize_or_crop crop_only --batchSize 48 --no_html --gpu_ids 0,1 --self_gen --nThreads 4 --n_downsample_global 3 --k_size 4 --use_v2 --mc 64 --start_r 1 --kl 1 --no_cgan --outputs_dir your_output_folder --checkpoints_dir your_ckpt_folder
#python train_domain_B.py --continue_train --training_dataset domain_B --name domainB_old_photos --label_nc 0 --loadSize 256 --fineSize 256 --dataroot ../mybig_data/  --no_instance --resize_or_crop crop_only --batchSize 48 --no_html --gpu_ids 0,1 --self_gen --nThreads 4 --n_downsample_global 3 --k_size 4 --use_v2 --mc 64 --start_r 1 --kl 1 --no_cgan --outputs_dir your_output_folder  --checkpoints_dir your_ckpt_folder
#python train_mapping.py --use_v2_degradation --training_dataset mapping --use_vae_which_epoch latest --continue_train --name mapping_quality --label_nc 0 --loadSize 256 --fineSize 256 --dataroot ../mybig_data/ --no_instance --resize_or_crop crop_only --batchSize 16 --no_html --gpu_ids 0,1 --nThreads 8 --load_pretrainA ./your_ckpt_folder/domainA_SR_old_photos --load_pretrainB ./your_ckpt_folder/domainB_old_photos --l2_feat 60 --n_downsample_global 3 --mc 64 --k_size 4 --start_r 1 --mapping_n_block 6 --map_mc 512 --use_l1_feat --outputs_dir your_output_folder --checkpoints_dir your_ckpt_folder

数据集

注意,以下四个文件为我按照原始论文打包的训练集,其中VOC_RGB_Depthnpy.bigfile文件有两个,1.6G大小的为NYUv2中的深度矩阵(1399张),2.9G的为NYUv2中的深度矩阵和额外我添加的图像对应的深度矩阵(504张裁剪后的HAZERD数据集和85张我收集的天空图像)。VOC_RGB_JPEGImages.bigfile为深度矩阵对应的真实图像。

图像去雾,利用《bringing old photos back to life》 的开源代码

以上的bigfile文件具体截图如下:

VOC_RGB_JPEGImages.bigfile 1.2G如下

图像去雾,利用《bringing old photos back to life》 的开源代码

VOC_RGB_JPEGImages.bigfile 1.69G除了上面NYUv2外,还有我处理的(HAZERD和收集的天空)如下:

图像去雾,利用《bringing old photos back to life》 的开源代码

图像去雾,利用《bringing old photos back to life》 的开源代码

深度矩阵就是上面图像对应的深度npy文件。

另外还是真实雾图,需要自己下载,可以酌情滤掉过于低质的图像,我利用的是开源数据集reside beta

下载地址

根据个人需要下载,里面有些文件过大。

我把我的去雾的代码打包并发布,地址如下:

链接:https://pan.baidu.com/s/18pe6VlqkRB1mvv8a8TYrOA
提取码:Haze

加雾的代码其实很简单,就是把输入和输出反一下,然后让align部分对应的一行代码反一下。

Original: https://blog.csdn.net/Crystal_remember/article/details/122753946
Author: Alocus_
Title: 图像去雾,利用《bringing old photos back to life》 的开源代码

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/645287/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球