├── .gitignore ├── ComputerVision ├── Deeplab-Resnet │ ├── .gitignore │ ├── README.md │ ├── data │ │ └── list │ │ │ ├── train_aug.txt │ │ │ └── val.txt │ ├── deeplab_resnet.py │ ├── evalpyt_dgf.py │ ├── predict_dgf.py │ ├── scripts │ │ ├── convert_labels.py │ │ └── convert_mat_to_png.py │ ├── train_dgf.py │ └── utils.py ├── MonoDepth │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── average_gradients.py │ ├── bilinear_sampler.py │ ├── monodepth_dataloader.py │ ├── monodepth_main.py │ ├── monodepth_model.py │ ├── monodepth_simple.py │ ├── requirements.txt │ └── utils │ │ ├── evaluate_kitti.py │ │ ├── evaluation_utils.py │ │ ├── filenames │ │ ├── cityscapes_test_files.txt │ │ ├── cityscapes_train_files.txt │ │ ├── cityscapes_val_files.txt │ │ ├── eigen_test_files.txt │ │ ├── eigen_train_files.txt │ │ ├── eigen_val_files.txt │ │ ├── kitti_stereo_2015_test_files.txt │ │ ├── kitti_test_files.txt │ │ ├── kitti_train_files.txt │ │ └── kitti_val_files.txt │ │ └── kitti_archives_to_download.txt └── Saliency_DSS │ ├── .gitignore │ ├── README.md │ ├── list │ ├── test_cvpr2013.txt │ ├── train_cvpr2013.txt │ └── valid_cvpr2013.txt │ ├── main.py │ ├── models │ └── dss.py │ ├── predict.py │ ├── scripts │ └── preprocess.py │ └── test.py ├── GuidedFilteringLayer ├── GuidedFilter_PyTorch │ ├── README.md │ ├── clean.sh │ ├── guided_filter_pytorch │ │ ├── __init__.py │ │ ├── box_filter.py │ │ └── guided_filter.py │ ├── setup.py │ └── test │ │ ├── gt.jpg │ │ ├── r.jpg │ │ ├── r_fast.jpg │ │ ├── rgb.jpg │ │ ├── test_box_filter.py │ │ ├── test_fast_guided_filter.py │ │ └── test_guided_filter.py └── GuidedFilter_TF │ ├── README.md │ ├── clean.sh │ ├── guided_filter_tf │ ├── __init__.py │ ├── box_filter.py │ └── guided_filter.py │ ├── setup.py │ └── test │ ├── gt.jpg │ ├── r.jpg │ ├── r_fast.jpg │ ├── rgb.jpg │ ├── test_box_filter.py │ ├── test_fast_guided_filter.py │ └── test_guided_filter.py ├── ImageProcessing └── DeepGuidedFilteringNetwork │ ├── .gitignore │ ├── README.md │ ├── dataset.py │ ├── models │ ├── auto_ps │ │ ├── conv_hr_ad_net_latest.pth │ │ ├── conv_hr_net_latest.pth │ │ ├── hr_ad_net_latest.pth │ │ ├── hr_net_latest.pth │ │ └── lr_net_latest.pth │ ├── l0_smooth │ │ ├── conv_hr_ad_net_latest.pth │ │ ├── conv_hr_net_latest.pth │ │ ├── hr_ad_net_latest.pth │ │ ├── hr_net_latest.pth │ │ └── lr_net_latest.pth │ ├── multi_scale_detail_manipulation │ │ ├── conv_hr_ad_net_latest.pth │ │ ├── conv_hr_net_latest.pth │ │ ├── hr_ad_net_latest.pth │ │ ├── hr_net_latest.pth │ │ └── lr_net_latest.pth │ ├── non_local_dehazing │ │ ├── conv_hr_ad_net_latest.pth │ │ ├── conv_hr_net_latest.pth │ │ ├── hr_ad_net_latest.pth │ │ ├── hr_net_latest.pth │ │ └── lr_net_latest.pth │ └── style_transfer │ │ ├── conv_hr_ad_net_latest.pth │ │ ├── conv_hr_net_latest.pth │ │ ├── hr_ad_net_latest.pth │ │ ├── hr_net_latest.pth │ │ └── lr_net_latest.pth │ ├── module.py │ ├── predict.py │ ├── scripts │ ├── auto_ps │ │ ├── generate_list.sh │ │ └── postprocess.py │ ├── convert_dng_to_tif.py │ ├── l0_smooth │ │ ├── L0Smoothing.m │ │ └── prepare_dataset.m │ ├── multi_scale_detail_manipulation │ │ ├── multi_scale_detail_manipulation.m │ │ ├── prepare_dataset.m │ │ ├── sigmoid.m │ │ ├── tonemapLAB.m │ │ ├── wlsFilter.m │ │ └── zeroone.m │ ├── non_local_dehazing │ │ ├── TR1000.txt │ │ ├── adjust.m │ │ ├── estimate_airlight.m │ │ ├── non_local_dehazing.m │ │ ├── prepare_dataset.m │ │ └── wls_optimization.m │ ├── precompute_size.py │ ├── precomputed_size │ │ ├── precomputed_size_1024.txt │ │ ├── precomputed_size_512.txt │ │ └── precomputed_size_random.txt │ ├── resize_image.py │ ├── style_transfer │ │ ├── apply_tranfer_function.m │ │ ├── child_window.m │ │ ├── downsample.m │ │ ├── gaussian_pyramid.m │ │ ├── get_transfer_function.m │ │ ├── images │ │ │ └── ruins.png │ │ ├── laplacian_pyramid.m │ │ ├── llf.m │ │ ├── llf_discrete.m │ │ ├── prepare_dataset.m │ │ ├── pyramid_filter.m │ │ ├── reconstruct_laplacian_pyramid.m │ │ ├── style_transfer.m │ │ └── upsample.m │ └── training_test_split │ │ ├── split.py │ │ ├── test_idx.txt │ │ └── train_idx.txt │ ├── test_base.py │ ├── test_hr.py │ ├── test_time.py │ ├── train_base.py │ ├── train_hr.py │ ├── train_hr_finetune.py │ ├── train_lr.py │ ├── utils.py │ └── vis_utils.py ├── README.md ├── images ├── auto_ps.jpg ├── depth.jpg ├── detail_manipulation.jpg ├── l0_smooth.jpg ├── non_local_dehazing.jpg ├── results.jpg ├── saliency.jpg ├── segmentation.jpg └── style_transfer.jpg └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | # PyCharm 2 | .idea/ 3 | 4 | # Python 5 | __pycache__/ 6 | *.egg-info/ 7 | -------------------------------------------------------------------------------- /ComputerVision/Deeplab-Resnet/.gitignore: -------------------------------------------------------------------------------- 1 | # result 2 | data/deeplab_*/ 3 | 4 | # dataset 5 | data/gt 6 | data/img 7 | 8 | # model 9 | *.pth 10 | -------------------------------------------------------------------------------- /ComputerVision/Deeplab-Resnet/README.md: -------------------------------------------------------------------------------- 1 | # Semantic Segmentation with Deeplab-Resnet-101 2 | 3 | Mean IOU: **73.58%** [Baseline: 71.79%] 4 | 5 | ## Try it on an image! 6 | 1. Download the pretrained model [[Google Drive](https://drive.google.com/open?id=1YXZoZIZNR1ACewiUBp4UDvo_P65cCooK)|[BaiduYunPan](https://pan.baidu.com/s/1dEnpcGfchlZA_fVGdve0ig)]. 7 | 2. Run it now! 8 | ```sh 9 | python predict_dgf.py --img_path [IM_PATH] --snapshots [MODEL_PATH] 10 | ``` 11 | ## Prepare Dataset: PASCAL-VOC 2012 12 | 1. Download and unzip [PASCAL VOC 2012](http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCtrainval_11-May-2012.tar) and [SBD](http://www.eecs.berkeley.edu/Research/Projects/CS/vision/grouping/semantic_contours/benchmark.tgz). 13 | ```sh 14 | ROOT 15 | ├── benchmark_RELEASE 16 | └── VOCdevkit 17 | ``` 18 | 2. Convert *.**mat** to *.**png** for SBD. 19 | ```sh 20 | python scripts/convert_mat_to_png.py --sbd_path [ROOT]/benchmark_RELEASE 21 | ``` 22 | 3. Convert labels for PASCAL VOC 2012. 23 | ```sh 24 | python scripts/convert_labels.py \ 25 | [ROOT]/VOCdevkit/VOC2012/SegmentationClass \ 26 | [ROOT]/VOCdevkit/VOC2012/ImageSets/Segmentation/trainval.txt \ 27 | [ROOT]/VOCdevkit/VOC2012/SegmentationClass_1D 28 | ``` 29 | 4. Combine **PASCAL VOC 2012** and **SBD**. 30 | ```sh 31 | cd [ROOT] 32 | mv VOCdevkit/VOC2012/SegmentationClass_1D/*.png benchmark_RELEASE/dataset/cls_png/ 33 | mv VOCdevkit/VOC2012/JPEGImages/*.jpg benchmark_RELEASE/dataset/img/ 34 | ``` 35 | 5. Soft link. 36 | ```sh 37 | ln -s [ROOT]/benchmark_RELEASE/dataset/cls_png data/gt 38 | ln -s [ROOT]/benchmark_RELEASE/dataset/img data/img 39 | ``` 40 | ## Training 41 | 1. Download MS-COCO pretrained model [[Google Drive](https://drive.google.com/file/d/12ZLRUFQzmC7FFPZpS5tkzOQZLrhG7qt1/view?usp=sharing)|[BaiduYunPan](https://pan.baidu.com/s/1k0ODhkI65_h1szUamtGs0w)], put it in the folder [data](data). 42 | 2. Train the model! 43 | * **WITHOUT** Guided Filtering Layer 44 | ```sh 45 | python train_dgf.py --snapshots snapshots 46 | ``` 47 | * **WITH** Guided Filtering Layer 48 | ```sh 49 | python train_dgf.py --dgf --snapshots snapshots_dgf 50 | ``` 51 | * Finetune 52 | ```sh 53 | python train_dgf.py --dgf --snapshots snapshots_dgf_ft --ft --ft_model_path [MODEL_PATH] 54 | ``` 55 | 56 | 3. Evaluation 57 | * **WITHOUT** Guided Filtering Layer 58 | ```sh 59 | python evalpyt_dgf.py --exp [SAVE_FOLDER] --snapshots [MODEL_PATH] 60 | ``` 61 | * **WITH** Guided Filtering Layer 62 | ```sh 63 | python evalpyt_dgf.py --exp [SAVE_FOLDER] --snapshots [MODEL_PATH] --dgf 64 | ``` 65 | ## Acknowledgement 66 | A part of the code was borrowed from [pytorch-deeplab-resnet](https://github.com/isht7/pytorch-deeplab-resnet). -------------------------------------------------------------------------------- /ComputerVision/Deeplab-Resnet/deeplab_resnet.py: -------------------------------------------------------------------------------- 1 | import torch.nn as nn 2 | 3 | from torch.nn import functional as F 4 | from guided_filter_pytorch.guided_filter import GuidedFilter 5 | 6 | AFFINE = True 7 | 8 | def conv3x3(in_planes, out_planes, stride=1): 9 | "3x3 convolution with padding" 10 | return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, padding=1, bias=False) 11 | 12 | 13 | class BasicBlock(nn.Module): 14 | expansion = 1 15 | 16 | def __init__(self, inplanes, planes, stride=1, downsample=None): 17 | super(BasicBlock, self).__init__() 18 | self.conv1 = conv3x3(inplanes, planes, stride) 19 | self.bn1 = nn.BatchNorm2d(planes, affine=AFFINE) 20 | self.relu = nn.ReLU(inplace=True) 21 | self.conv2 = conv3x3(planes, planes) 22 | self.bn2 = nn.BatchNorm2d(planes, affine=AFFINE) 23 | self.downsample = downsample 24 | self.stride = stride 25 | 26 | def forward(self, x): 27 | residual = x 28 | 29 | out = self.conv1(x) 30 | out = self.bn1(out) 31 | out = self.relu(out) 32 | 33 | out = self.conv2(out) 34 | out = self.bn2(out) 35 | 36 | if self.downsample is not None: 37 | residual = self.downsample(x) 38 | 39 | out += residual 40 | out = self.relu(out) 41 | 42 | return out 43 | 44 | 45 | class Bottleneck(nn.Module): 46 | expansion = 4 47 | 48 | def __init__(self, inplanes, planes, stride=1, dilation_=1, downsample=None): 49 | super(Bottleneck, self).__init__() 50 | self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, stride=stride, bias=False) 51 | self.bn1 = nn.BatchNorm2d(planes, affine=AFFINE) 52 | for i in self.bn1.parameters(): 53 | i.requires_grad = False 54 | padding = 1 55 | if dilation_ == 2: 56 | padding = 2 57 | elif dilation_ == 4: 58 | padding = 4 59 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, 60 | padding=padding, bias=False, dilation=dilation_) 61 | self.bn2 = nn.BatchNorm2d(planes, affine=AFFINE) 62 | for i in self.bn2.parameters(): 63 | i.requires_grad = False 64 | self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=False) 65 | self.bn3 = nn.BatchNorm2d(planes * 4, affine=AFFINE) 66 | for i in self.bn3.parameters(): 67 | i.requires_grad = False 68 | self.relu = nn.ReLU(inplace=True) 69 | self.downsample = downsample 70 | self.stride = stride 71 | 72 | def forward(self, x): 73 | residual = x 74 | 75 | out = self.conv1(x) 76 | out = self.bn1(out) 77 | out = self.relu(out) 78 | 79 | out = self.conv2(out) 80 | out = self.bn2(out) 81 | out = self.relu(out) 82 | 83 | out = self.conv3(out) 84 | out = self.bn3(out) 85 | 86 | if self.downsample is not None: 87 | residual = self.downsample(x) 88 | 89 | out += residual 90 | out = self.relu(out) 91 | 92 | return out 93 | 94 | 95 | class Classifier_Module(nn.Module): 96 | def __init__(self, dilation_series, padding_series, NoLabels): 97 | super(Classifier_Module, self).__init__() 98 | self.conv2d_list = nn.ModuleList() 99 | for dilation, padding in zip(dilation_series, padding_series): 100 | self.conv2d_list.append( 101 | nn.Conv2d(2048, NoLabels, kernel_size=3, stride=1, padding=padding, dilation=dilation, bias=True)) 102 | 103 | for m in self.conv2d_list: 104 | m.weight.data.normal_(0, 0.01) 105 | 106 | def forward(self, x): 107 | out = self.conv2d_list[0](x) 108 | for i in range(len(self.conv2d_list) - 1): 109 | out += self.conv2d_list[i + 1](x) 110 | return out 111 | 112 | 113 | class ResNet(nn.Module): 114 | def __init__(self, block, layers, NoLabels): 115 | self.inplanes = 64 116 | super(ResNet, self).__init__() 117 | self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, 118 | bias=False) 119 | self.bn1 = nn.BatchNorm2d(64, affine=AFFINE) 120 | for i in self.bn1.parameters(): 121 | i.requires_grad = False 122 | self.relu = nn.ReLU(inplace=True) 123 | self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1, ceil_mode=True) 124 | self.layer1 = self._make_layer(block, 64, layers[0]) 125 | self.layer2 = self._make_layer(block, 128, layers[1], stride=2) 126 | self.layer3 = self._make_layer(block, 256, layers[2], stride=1, dilation__=2) 127 | self.layer4 = self._make_layer(block, 512, layers[3], stride=1, dilation__=4) 128 | self.layer5 = self._make_pred_layer(Classifier_Module, [6, 12, 18, 24], [6, 12, 18, 24], NoLabels) 129 | 130 | for m in self.modules(): 131 | if isinstance(m, nn.Conv2d): 132 | m.weight.data.normal_(0, 0.01) 133 | elif isinstance(m, nn.BatchNorm2d): 134 | m.weight.data.fill_(1) 135 | m.bias.data.zero_() 136 | 137 | def _make_layer(self, block, planes, blocks, stride=1, dilation__=1): 138 | downsample = None 139 | if stride != 1 or self.inplanes != planes * block.expansion or dilation__ == 2 or dilation__ == 4: 140 | downsample = nn.Sequential( 141 | nn.Conv2d(self.inplanes, planes * block.expansion, 142 | kernel_size=1, stride=stride, bias=False), 143 | nn.BatchNorm2d(planes * block.expansion, affine=AFFINE), 144 | ) 145 | for i in downsample._modules['1'].parameters(): 146 | i.requires_grad = False 147 | layers = [] 148 | layers.append(block(self.inplanes, planes, stride, dilation_=dilation__, downsample=downsample)) 149 | self.inplanes = planes * block.expansion 150 | for i in range(1, blocks): 151 | layers.append(block(self.inplanes, planes, dilation_=dilation__)) 152 | 153 | return nn.Sequential(*layers) 154 | 155 | def _make_pred_layer(self, block, dilation_series, padding_series, NoLabels): 156 | return block(dilation_series, padding_series, NoLabels) 157 | 158 | def forward(self, x): 159 | x = self.conv1(x) 160 | x = self.bn1(x) 161 | x = self.relu(x) 162 | x = self.maxpool(x) 163 | x = self.layer1(x) 164 | x = self.layer2(x) 165 | x = self.layer3(x) 166 | x = self.layer4(x) 167 | x = self.layer5(x) 168 | 169 | return x 170 | 171 | 172 | class MS_Deeplab(nn.Module): 173 | def __init__(self, block, NoLabels, dgf, dgf_r, dgf_eps): 174 | super(MS_Deeplab, self).__init__() 175 | self.Scale = ResNet(block, [3, 4, 23, 3], NoLabels) # changed to fix #4 176 | 177 | # DGF 178 | self.dgf = dgf 179 | 180 | if self.dgf: 181 | self.guided_map_conv1 = nn.Conv2d(3, 64, 1) 182 | self.guided_map_relu1 = nn.ReLU(inplace=True) 183 | self.guided_map_conv2 = nn.Conv2d(64, NoLabels, 1) 184 | 185 | self.guided_filter = GuidedFilter(dgf_r, dgf_eps) 186 | 187 | def forward(self, x, im=None): 188 | output = self.Scale(x) 189 | 190 | if self.dgf: 191 | g = self.guided_map_relu1(self.guided_map_conv1(im)) 192 | g = self.guided_map_conv2(g) 193 | 194 | output = F.interpolate(output, im.size()[2:], mode='bilinear', align_corners=True) 195 | 196 | output = self.guided_filter(g, output) 197 | 198 | return output 199 | 200 | 201 | def Res_Deeplab(NoLabels=21, dgf=False, dgf_r=4, dgf_eps=1e-2): 202 | model = MS_Deeplab(Bottleneck, NoLabels, dgf, dgf_r, dgf_eps) 203 | return model -------------------------------------------------------------------------------- /ComputerVision/Deeplab-Resnet/evalpyt_dgf.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import cv2 4 | import numpy as np 5 | 6 | import torch 7 | import torch.nn as nn 8 | 9 | from docopt import docopt 10 | from skimage.io import imsave 11 | 12 | from torch.autograd import Variable 13 | 14 | import deeplab_resnet 15 | 16 | from utils import decode_labels 17 | 18 | docstr = """Evaluate ResNet-DeepLab trained on scenes (VOC 2012),a total of 21 labels including background 19 | 20 | Usage: 21 | evalpyt_dgf.py [options] 22 | 23 | Options: 24 | -h, --help Print this message 25 | --testGTpath= Ground truth path prefix [default: data/gt/] 26 | --testIMpath= Sketch images path prefix [default: data/img/] 27 | --NoLabels= The number of different labels in training data, VOC has 21 labels, including background [default: 21] 28 | --gpu0= GPU number [default: 0] 29 | --exp= Experiment name [default: deeplab_res101] 30 | --snapshots= snapshots name [default: None] 31 | --dgf WITH Guided Filtering Layer ? 32 | """ 33 | 34 | 35 | def fast_hist(a, b, n): 36 | k = (a >= 0) & (a < n) 37 | return np.bincount(n * a[k].astype(int) + b[k], minlength=n ** 2).reshape(n, n) 38 | 39 | 40 | def main(): 41 | args = docopt(docstr, version='v0.1') 42 | print(args) 43 | 44 | gpu0 = int(args['--gpu0']) 45 | im_path = args['--testIMpath'] 46 | gt_path = args['--testGTpath'] 47 | 48 | model = deeplab_resnet.Res_Deeplab(int(args['--NoLabels']), args['--dgf'], 4, 1e-2) 49 | model.eval().cuda(gpu0) 50 | 51 | img_list = open('data/list/val.txt').readlines() 52 | saved_state_dict = torch.load(args['--snapshots']) 53 | model.load_state_dict(saved_state_dict) 54 | 55 | save_path = os.path.join('data', args['--exp']) 56 | if not os.path.isdir(save_path): 57 | os.makedirs(save_path) 58 | 59 | max_label = int(args['--NoLabels']) - 1 # labels from 0,1, ... 20(for VOC) 60 | hist = np.zeros((max_label + 1, max_label + 1)) 61 | for idx, i in enumerate(img_list): 62 | print('{}/{} ...'.format(idx + 1, len(img_list))) 63 | 64 | img = cv2.imread(os.path.join(im_path, i[:-1] + '.jpg')).astype(float) 65 | img_original = img.copy() / 255.0 66 | img[:, :, 0] = img[:, :, 0] - 104.008 67 | img[:, :, 1] = img[:, :, 1] - 116.669 68 | img[:, :, 2] = img[:, :, 2] - 122.675 69 | 70 | if args['--dgf']: 71 | inputs = [img, img_original] 72 | else: 73 | inputs = [np.zeros((513, 513, 3))] 74 | inputs[0][:img.shape[0], :img.shape[1], :] = img 75 | 76 | with torch.no_grad(): 77 | output = model(*[torch.from_numpy(i[np.newaxis, :].transpose(0, 3, 1, 2)).float().cuda(gpu0) for i in inputs]) 78 | if not args['--dgf']: 79 | interp = nn.Upsample(size=(513, 513), mode='bilinear', align_corners=True) 80 | output = interp(output) 81 | output = output[:, :, :img.shape[0], :img.shape[1]] 82 | 83 | output = output.cpu().data[0].numpy().transpose(1, 2, 0) 84 | output = np.argmax(output, axis=2) 85 | 86 | vis_output = decode_labels(output) 87 | imsave(os.path.join(save_path, i[:-1] + '.png'), vis_output) 88 | 89 | gt = cv2.imread(os.path.join(gt_path, i[:-1] + '.png'), 0) 90 | hist += fast_hist(gt.flatten(), output.flatten(), max_label + 1) 91 | 92 | miou = np.diag(hist) / (hist.sum(1) + hist.sum(0) - np.diag(hist)) 93 | print("Mean iou = ", np.sum(miou) / len(miou)) 94 | 95 | 96 | if __name__ == '__main__': 97 | main() -------------------------------------------------------------------------------- /ComputerVision/Deeplab-Resnet/predict_dgf.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import cv2 4 | import numpy as np 5 | 6 | import torch 7 | 8 | from docopt import docopt 9 | from skimage.io import imsave 10 | 11 | from torch.autograd import Variable 12 | 13 | import deeplab_resnet 14 | 15 | from utils import decode_labels 16 | 17 | docstr = """Predict with ResNet-DeepLab 18 | 19 | Usage: 20 | predict_dgf.py [options] 21 | 22 | Options: 23 | -h, --help Print this message 24 | --img_path= Sketch images path prefix [default: None] 25 | --gpu0= GPU number [default: 0] 26 | --snapshots= snapshots name [default: None] 27 | """ 28 | 29 | def main(): 30 | args = docopt(docstr, version='v0.1') 31 | print(args) 32 | 33 | gpu0 = int(args['--gpu0']) 34 | 35 | model = deeplab_resnet.Res_Deeplab(21, True, 4, 1e-2) 36 | model.load_state_dict(torch.load(args['--snapshots'])) 37 | model.eval().cuda(gpu0) 38 | 39 | im_path = args['--img_path'] 40 | 41 | img = cv2.imread(im_path).astype(float) 42 | img_original = img.copy() / 255.0 43 | img[:, :, 0] = img[:, :, 0] - 104.008 44 | img[:, :, 1] = img[:, :, 1] - 116.669 45 | img[:, :, 2] = img[:, :, 2] - 122.675 46 | 47 | with torch.no_grad(): 48 | output = model(*[torch.from_numpy(i[np.newaxis, :].transpose(0, 3, 1, 2)).float().cuda(gpu0) for i in [img, img_original]]) 49 | output = output.cpu().data[0].numpy().transpose(1, 2, 0) 50 | output = np.argmax(output, axis=2) 51 | 52 | vis_output = decode_labels(output) 53 | 54 | output_directory = os.path.dirname(im_path) 55 | output_name = os.path.splitext(os.path.basename(im_path))[0] 56 | save_path = os.path.join(output_directory, '{}_labels.png'.format(output_name)) 57 | imsave(save_path, vis_output) 58 | 59 | if __name__ == '__main__': 60 | main() -------------------------------------------------------------------------------- /ComputerVision/Deeplab-Resnet/scripts/convert_labels.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Martin Kersner, m.kersner@gmail.com 3 | # 2016/01/25 4 | 5 | from __future__ import print_function 6 | 7 | import os 8 | import sys 9 | 10 | import numpy as np 11 | 12 | from skimage.io import imread, imsave 13 | 14 | 15 | def pascal_palette(): 16 | palette = {(0, 0, 0): 0, 17 | (128, 0, 0): 1, 18 | (0, 128, 0): 2, 19 | (128, 128, 0): 3, 20 | (0, 0, 128): 4, 21 | (128, 0, 128): 5, 22 | (0, 128, 128): 6, 23 | (128, 128, 128): 7, 24 | (64, 0, 0): 8, 25 | (192, 0, 0): 9, 26 | (64, 128, 0): 10, 27 | (192, 128, 0): 11, 28 | (64, 0, 128): 12, 29 | (192, 0, 128): 13, 30 | (64, 128, 128): 14, 31 | (192, 128, 128): 15, 32 | (0, 64, 0): 16, 33 | (128, 64, 0): 17, 34 | (0, 192, 0): 18, 35 | (128, 192, 0): 19, 36 | (0, 64, 128): 20} 37 | 38 | return palette 39 | 40 | 41 | def convert_from_color_segmentation(arr_3d): 42 | arr_2d = np.ones((arr_3d.shape[0], arr_3d.shape[1]), dtype=np.uint8) * 255 43 | palette = pascal_palette() 44 | 45 | for c, i in palette.items(): 46 | m = np.all(arr_3d == np.array(c).reshape(1, 1, 3), axis=2) 47 | arr_2d[m] = i 48 | 49 | return arr_2d 50 | 51 | 52 | def main(): 53 | path, txt_file, path_converted = process_arguments(sys.argv) 54 | 55 | # Create dir for converted labels 56 | if not os.path.isdir(path_converted): 57 | os.makedirs(path_converted) 58 | 59 | with open(txt_file, 'r') as f: 60 | for img_name in f: 61 | img_base_name = img_name.strip() 62 | img_name = os.path.join(path, img_base_name) + '.png' 63 | img = imread(img_name) 64 | 65 | if (len(img.shape) > 2): 66 | img = convert_from_color_segmentation(img[:,:,:3]) 67 | imsave(os.path.join(path_converted, img_base_name) + '.png', img) 68 | else: 69 | print(img_name, "is not composed of three dimensions, therefore " 70 | "shouldn't be processed by this script.\n" 71 | "Exiting.", file=sys.stderr) 72 | exit() 73 | 74 | 75 | def process_arguments(argv): 76 | if len(argv) != 4: 77 | help() 78 | 79 | path = argv[1] 80 | list_file = argv[2] 81 | new_path = argv[3] 82 | 83 | return path, list_file, new_path 84 | 85 | 86 | def help(): 87 | print('Usage: python convert_labels.py PATH LIST_FILE NEW_PATH\n' 88 | 'PATH points to directory with segmentation image labels.\n' 89 | 'LIST_FILE denotes text file containing names of images in PATH.\n' 90 | 'Names do not include extension of images.\n' 91 | 'NEW_PATH points to directory where converted labels will be stored.' 92 | , file=sys.stderr) 93 | exit() 94 | 95 | if __name__ == '__main__': 96 | main() 97 | -------------------------------------------------------------------------------- /ComputerVision/Deeplab-Resnet/scripts/convert_mat_to_png.py: -------------------------------------------------------------------------------- 1 | import os 2 | import argparse 3 | 4 | import scipy.io 5 | import skimage.io as io 6 | 7 | 8 | def convert_pascal_berkeley_augmented_mat_annotations_to_png(pascal_berkeley_augmented_root): 9 | """ Creates a new folder in the root folder of the dataset with annotations stored in .png. 10 | The function accepts a full path to the root of Berkeley augmented Pascal VOC segmentation 11 | dataset and converts annotations that are stored in .mat files to .png files. It creates 12 | a new folder dataset/cls_png where all the converted files will be located. If this 13 | directory already exists the function does nothing. The Berkley augmented dataset 14 | can be downloaded from here: 15 | http://www.eecs.berkeley.edu/Research/Projects/CS/vision/grouping/semantic_contours/benchmark.tgz 16 | 17 | Parameters 18 | ---------- 19 | pascal_berkeley_augmented_root : string 20 | Full path to the root of augmented Berkley PASCAL VOC dataset. 21 | """ 22 | def read_class_annotation_array_from_berkeley_mat(mat_filename, key='GTcls'): 23 | # Mat to png conversion for http://www.cs.berkeley.edu/~bharath2/codes/SBD/download.html 24 | # 'GTcls' key is for class segmentation 25 | # 'GTinst' key is for instance segmentation 26 | # Credit: https://github.com/martinkersner/train-DeepLab/blob/master/utils.py 27 | mat = scipy.io.loadmat(mat_filename, mat_dtype=True, squeeze_me=True, struct_as_record=False) 28 | return mat[key].Segmentation 29 | 30 | mat_file_extension_string = '.mat' 31 | png_file_extension_string = '.png' 32 | relative_path_to_annotation_mat_files = 'dataset/cls' 33 | relative_path_to_annotation_png_files = 'dataset/cls_png' 34 | 35 | annotation_mat_files_fullpath = os.path.join(pascal_berkeley_augmented_root, 36 | relative_path_to_annotation_mat_files) 37 | annotation_png_save_fullpath = os.path.join(pascal_berkeley_augmented_root, 38 | relative_path_to_annotation_png_files) 39 | # Create the folder where all the converted png files will be placed 40 | # If the folder already exists, do nothing 41 | if not os.path.exists(annotation_png_save_fullpath): 42 | os.makedirs(annotation_png_save_fullpath) 43 | else: 44 | return 45 | 46 | for current_mat_file_name in os.listdir(annotation_mat_files_fullpath): 47 | current_file_name_without_extention = current_mat_file_name[:-len(mat_file_extension_string)] 48 | current_mat_file_full_path = os.path.join(annotation_mat_files_fullpath, current_mat_file_name) 49 | current_png_file_full_path_to_be_saved = os.path.join(annotation_png_save_fullpath, current_file_name_without_extention) 50 | current_png_file_full_path_to_be_saved += png_file_extension_string 51 | 52 | annotation_array = read_class_annotation_array_from_berkeley_mat(current_mat_file_full_path) 53 | 54 | io.imsave(current_png_file_full_path_to_be_saved, annotation_array) 55 | 56 | if __name__ == '__main__': 57 | parser = argparse.ArgumentParser(description='SBD mat to png') 58 | parser.add_argument('--sbd_path', type=str, required=True, help='SBD PATH') 59 | args = parser.parse_args() 60 | 61 | convert_pascal_berkeley_augmented_mat_annotations_to_png(args.sbd_path) 62 | -------------------------------------------------------------------------------- /ComputerVision/Deeplab-Resnet/utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Martin Kersner, m.kersner@gmail.com 3 | # 2016/03/11 4 | import numpy as np 5 | 6 | from PIL import Image 7 | 8 | 9 | # colour map 10 | label_colours = [(0, 0, 0) 11 | # 0=background 12 | , (128, 0, 0), (0, 128, 0), (128, 128, 0), (0, 0, 128), (128, 0, 128) 13 | # 1=aeroplane, 2=bicycle, 3=bird, 4=boat, 5=bottle 14 | , (0, 128, 128), (128, 128, 128), (64, 0, 0), (192, 0, 0), (64, 128, 0) 15 | # 6=bus, 7=car, 8=cat, 9=chair, 10=cow 16 | , (192, 128, 0), (64, 0, 128), (192, 0, 128), (64, 128, 128), (192, 128, 128) 17 | # 11=diningtable, 12=dog, 13=horse, 14=motorbike, 15=person 18 | , (0, 64, 0), (128, 64, 0), (0, 192, 0), (128, 192, 0), (0, 64, 128)] 19 | # 16=potted plant, 17=sheep, 18=sofa, 19=train, 20=tv/monitor 20 | 21 | def decode_labels(mask, num_classes=21): 22 | """Decode segmentation mask. 23 | 24 | Args: 25 | mask: result of inference after taking argmax. 26 | num_classes: number of classes to predict (including background). 27 | 28 | Returns: 29 | A RGB image of the same size as the input. 30 | """ 31 | h, w = mask.shape 32 | 33 | img = Image.new('RGB', (w, h)) 34 | pixels = img.load() 35 | for j_, j in enumerate(mask[:, :]): 36 | for k_, k in enumerate(j): 37 | if k < num_classes: 38 | pixels[k_, j_] = label_colours[k] 39 | output = np.array(img) 40 | 41 | return output 42 | -------------------------------------------------------------------------------- /ComputerVision/MonoDepth/.gitignore: -------------------------------------------------------------------------------- 1 | checkpoints 2 | -------------------------------------------------------------------------------- /ComputerVision/MonoDepth/README.md: -------------------------------------------------------------------------------- 1 | # Monocular Depth Estimation 2 | 3 | RMS: **5.887** [Baseline: 6.081] 4 | 5 | ## Try it on an image ! 6 | 1. **Download** and **Unzip** Pretrained Model 7 | * **WITH** Guided Filtering Layer [[Google Drive](https://drive.google.com/file/d/1dKDYRtZPahoFJZ5ZJNilgHEvT6gG4SC6/view?usp=sharing)|[BaiduYunPan](https://pan.baidu.com/s/1-GkMaRAVym8UEmQ6ia5cHw)] 8 | * **WITHOUT** Guided Filtering Layer [[Google Drive](https://drive.google.com/file/d/1w-f75x8WYRKukoQOP-TYJIq4--W40nrq/view?usp=sharing)|[BaiduYunPan](https://pan.baidu.com/s/19IkFGX5I-zc3Ap5mZHQzOw)] 9 | 2. Run on an Image ! 10 | * **WITHOUT** Guided Filtering Layer 11 | ```sh 12 | python monodepth_simple.py --image_path [IMAGE_PATH] --checkpoint_path [MODEL_PATH] 13 | ``` 14 | * **WITH** Guided Filter as **PostProcessing** 15 | ```sh 16 | python monodepth_simple.py --image_path [IMAGE_PATH] --checkpoint_path [MODEL_PATH] --guided_filter_eval 17 | ``` 18 | * **WITH** Guided Filtering Layer 19 | ```sh 20 | python monodepth_simple.py --image_path [IMAGE_PATH] --checkpoint_path [MODEL_PATH] --guided_filter 21 | ``` 22 | ## Training on KITTI 23 | 1. Download KITTI 24 | ```sh 25 | wget -i utils/kitti_archives_to_download.txt -P [SAVE_FOLDER] 26 | ``` 27 | 2. (**Optional**) Convert *.**png** to *.**jpg** to save space. 28 | ```sh 29 | find [SAVE_FOLDER] -name '*.png' | parallel 'convert {.}.png {.}.jpg && rm {}' 30 | ``` 31 | 3. Let's train the model ! 32 | * **WITHOUT** Guided Filtering Layer 33 | ```sh 34 | python monodepth_main.py --mode train \ 35 | --model_name monodepth_kitti \ 36 | --data_path [SAVE_FOLDER] \ 37 | --filenames_file utils/filenames/kitti_train_files.txt \ 38 | --log_directory checkpoints 39 | ``` 40 | * **WITH** Guided Filtering Layer 41 | ```sh 42 | python monodepth_main.py --mode train \ 43 | --model_name monodepth_kitti_dgf \ 44 | --data_path [SAVE_FOLDER] \ 45 | --filenames_file utils/filenames/kitti_train_files.txt \ 46 | --log_directory checkpoints \ 47 | --guided_filter 48 | ``` 49 | 4. Download [Test Dataset](http://www.cvlibs.net/download.php?file=data_scene_flow.zip) 50 | 5. Testing 51 | * **WITHOUT** Guided Filtering Layer 52 | ```sh 53 | python monodepth_main.py --mode test \ 54 | --data_path [SAVE_FOLDER] \ 55 | --filenames_file utils/filenames/kitti_stereo_2015_test_files.txt \ 56 | --checkpoint_path [MODEL_PATH] 57 | ``` 58 | * **WITH** Guided Filter as **PostProcessing** 59 | ```sh 60 | python monodepth_main.py --mode test \ 61 | --data_path [SAVE_FOLDER] \ 62 | --filenames_file utils/filenames/kitti_stereo_2015_test_files.txt \ 63 | --checkpoint_path [MODEL_PATH] \ 64 | --guided_filter_eval 65 | ``` 66 | * **WITH** Guided Filtering Layer 67 | ```sh 68 | python monodepth_main.py --mode test \ 69 | --data_path [SAVE_FOLDER] \ 70 | --filenames_file utils/filenames/kitti_stereo_2015_test_files.txt \ 71 | --checkpoint_path [MODEL_PATH] \ 72 | --guided_filter 73 | ``` 74 | 5. Evaluation on KITTI 75 | ```sh 76 | python utils/evaluate_kitti.py --split kitti --predicted_disp_path [disparities.npy] --gt_path [SAVE_FOLDER] 77 | ``` 78 | ## Acknowledgement 79 | A part of the code has been borrowed from [monodepth](https://github.com/mrharicot/monodepth). 80 | -------------------------------------------------------------------------------- /ComputerVision/MonoDepth/average_gradients.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 The TensorFlow Authors. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from __future__ import absolute_import, division, print_function 16 | 17 | import tensorflow as tf 18 | 19 | 20 | def average_gradients(tower_grads): 21 | average_grads = [] 22 | for grad_and_vars in zip(*tower_grads): 23 | # Note that each grad_and_vars looks like the following: 24 | # ((grad0_gpu0, var0_gpu0), ... , (grad0_gpuN, var0_gpuN)) 25 | grads = [] 26 | for g, _ in grad_and_vars: 27 | # Add 0 dimension to the gradients to represent the tower. 28 | expanded_g = tf.expand_dims(g, 0) 29 | 30 | # Append on a 'tower' dimension which we will average over below. 31 | grads.append(expanded_g) 32 | 33 | # Average over the 'tower' dimension. 34 | grad = tf.concat(axis=0, values=grads) 35 | grad = tf.reduce_mean(grad, 0) 36 | 37 | # Keep in mind that the Variables are redundant because they are shared 38 | # across towers. So .. we will just return the first tower's pointer to 39 | # the Variable. 40 | v = grad_and_vars[0][1] 41 | grad_and_var = (grad, v) 42 | average_grads.append(grad_and_var) 43 | return average_grads 44 | -------------------------------------------------------------------------------- /ComputerVision/MonoDepth/bilinear_sampler.py: -------------------------------------------------------------------------------- 1 | # Copyright 2016 The TensorFlow Authors. All Rights Reserved. 2 | # Copyright 2017 Modifications Clement Godard. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # ============================================================================== 16 | 17 | from __future__ import absolute_import, division, print_function 18 | 19 | import tensorflow as tf 20 | 21 | 22 | def bilinear_sampler_1d_h(input_images, x_offset, wrap_mode='border', name='bilinear_sampler', **kwargs): 23 | def _repeat(x, n_repeats): 24 | with tf.variable_scope('_repeat'): 25 | rep = tf.tile(tf.expand_dims(x, 1), [1, n_repeats]) 26 | return tf.reshape(rep, [-1]) 27 | 28 | def _interpolate(im, x, y): 29 | with tf.variable_scope('_interpolate'): 30 | # handle both texture border types 31 | if _wrap_mode == 'border': 32 | _edge_size = 1 33 | im = tf.pad(im, [[0, 0], [1, 1], [1, 1], [0, 0]], mode='CONSTANT') 34 | x = x + _edge_size 35 | y = y + _edge_size 36 | elif _wrap_mode == 'edge': 37 | _edge_size = 0 38 | else: 39 | return None 40 | 41 | x = tf.clip_by_value(x, 0.0, _width_f - 1 + 2 * _edge_size) 42 | 43 | x0_f = tf.floor(x) 44 | y0_f = tf.floor(y) 45 | x1_f = x0_f + 1 46 | 47 | x0 = tf.cast(x0_f, tf.int32) 48 | y0 = tf.cast(y0_f, tf.int32) 49 | x1 = tf.cast(tf.minimum(x1_f, _width_f - 1 + 2 * _edge_size), tf.int32) 50 | 51 | dim2 = (_width + 2 * _edge_size) 52 | dim1 = (_width + 2 * _edge_size) * (_height + 2 * _edge_size) 53 | base = _repeat(tf.range(_num_batch) * dim1, _height * _width) 54 | base_y0 = base + y0 * dim2 55 | idx_l = base_y0 + x0 56 | idx_r = base_y0 + x1 57 | 58 | im_flat = tf.reshape(im, tf.stack([-1, _num_channels])) 59 | 60 | pix_l = tf.gather(im_flat, idx_l) 61 | pix_r = tf.gather(im_flat, idx_r) 62 | 63 | weight_l = tf.expand_dims(x1_f - x, 1) 64 | weight_r = tf.expand_dims(x - x0_f, 1) 65 | 66 | return weight_l * pix_l + weight_r * pix_r 67 | 68 | def _transform(input_images, x_offset): 69 | with tf.variable_scope('transform'): 70 | # grid of (x_t, y_t, 1), eq (1) in ref [1] 71 | x_t, y_t = tf.meshgrid(tf.linspace(0.0, _width_f - 1.0, _width), 72 | tf.linspace(0.0, _height_f - 1.0, _height)) 73 | 74 | x_t_flat = tf.reshape(x_t, (1, -1)) 75 | y_t_flat = tf.reshape(y_t, (1, -1)) 76 | 77 | x_t_flat = tf.tile(x_t_flat, tf.stack([_num_batch, 1])) 78 | y_t_flat = tf.tile(y_t_flat, tf.stack([_num_batch, 1])) 79 | 80 | x_t_flat = tf.reshape(x_t_flat, [-1]) 81 | y_t_flat = tf.reshape(y_t_flat, [-1]) 82 | 83 | x_t_flat = x_t_flat + tf.reshape(x_offset, [-1]) * _width_f 84 | 85 | input_transformed = _interpolate(input_images, x_t_flat, y_t_flat) 86 | 87 | output = tf.reshape( 88 | input_transformed, tf.stack([_num_batch, _height, _width, _num_channels])) 89 | return output 90 | 91 | with tf.variable_scope(name): 92 | _num_batch = tf.shape(input_images)[0] 93 | _height = tf.shape(input_images)[1] 94 | _width = tf.shape(input_images)[2] 95 | _num_channels = tf.shape(input_images)[3] 96 | 97 | _height_f = tf.cast(_height, tf.float32) 98 | _width_f = tf.cast(_width, tf.float32) 99 | 100 | _wrap_mode = wrap_mode 101 | 102 | output = _transform(input_images, x_offset) 103 | return output 104 | -------------------------------------------------------------------------------- /ComputerVision/MonoDepth/monodepth_dataloader.py: -------------------------------------------------------------------------------- 1 | # Copyright UCL Business plc 2017. Patent Pending. All rights reserved. 2 | # 3 | # The MonoDepth Software is licensed under the terms of the UCLB ACP-A licence 4 | # which allows for non-commercial use only, the full terms of which are made 5 | # available in the LICENSE file. 6 | # 7 | # For any other use of the software not covered by the UCLB ACP-A Licence, 8 | # please contact info@uclb.com 9 | 10 | """Monodepth data loader. 11 | """ 12 | 13 | from __future__ import absolute_import, division, print_function 14 | 15 | import tensorflow as tf 16 | 17 | 18 | def string_length_tf(t): 19 | return tf.py_func(len, [t], [tf.int64]) 20 | 21 | 22 | class MonodepthDataloader(object): 23 | """monodepth dataloader""" 24 | 25 | def __init__(self, data_path, filenames_file, params, dataset, mode): 26 | self.data_path = data_path 27 | self.params = params 28 | self.dataset = dataset 29 | self.mode = mode 30 | 31 | self.left_image_batch = None 32 | self.right_image_batch = None 33 | 34 | input_queue = tf.train.string_input_producer([filenames_file], shuffle=False) 35 | line_reader = tf.TextLineReader() 36 | _, line = line_reader.read(input_queue) 37 | 38 | split_line = tf.string_split([line]).values 39 | 40 | # we load only one image for test, except if we trained a stereo model 41 | if mode == 'test' and not self.params.do_stereo: 42 | left_image_path = tf.string_join([self.data_path, split_line[0]]) 43 | left_image_o = self.read_image(left_image_path) 44 | else: 45 | left_image_path = tf.string_join([self.data_path, split_line[0]]) 46 | right_image_path = tf.string_join([self.data_path, split_line[1]]) 47 | left_image_o = self.read_image(left_image_path) 48 | right_image_o = self.read_image(right_image_path) 49 | 50 | if mode == 'train': 51 | # randomly flip images 52 | do_flip = tf.random_uniform([], 0, 1) 53 | left_image = tf.cond(do_flip > 0.5, lambda: tf.image.flip_left_right(right_image_o), lambda: left_image_o) 54 | right_image = tf.cond(do_flip > 0.5, lambda: tf.image.flip_left_right(left_image_o), lambda: right_image_o) 55 | 56 | # randomly augment images 57 | do_augment = tf.random_uniform([], 0, 1) 58 | left_image, right_image = tf.cond(do_augment > 0.5, 59 | lambda: self.augment_image_pair(left_image, right_image), 60 | lambda: (left_image, right_image)) 61 | 62 | left_image.set_shape([None, None, 3]) 63 | right_image.set_shape([None, None, 3]) 64 | 65 | # capacity = min_after_dequeue + (num_threads + a small safety margin) * batch_size 66 | min_after_dequeue = 2048 67 | capacity = min_after_dequeue + 4 * params.batch_size 68 | self.left_image_batch, self.right_image_batch = tf.train.shuffle_batch([left_image, right_image], 69 | params.batch_size, capacity, 70 | min_after_dequeue, 71 | params.num_threads) 72 | 73 | elif mode == 'test': 74 | self.left_image_batch = tf.stack([left_image_o, tf.image.flip_left_right(left_image_o)], 0) 75 | self.left_image_batch.set_shape([2, None, None, 3]) 76 | 77 | if self.params.do_stereo: 78 | self.right_image_batch = tf.stack([right_image_o, tf.image.flip_left_right(right_image_o)], 0) 79 | self.right_image_batch.set_shape([2, None, None, 3]) 80 | 81 | def augment_image_pair(self, left_image, right_image): 82 | # randomly shift gamma 83 | random_gamma = tf.random_uniform([], 0.8, 1.2) 84 | left_image_aug = left_image ** random_gamma 85 | right_image_aug = right_image ** random_gamma 86 | 87 | # randomly shift brightness 88 | random_brightness = tf.random_uniform([], 0.5, 2.0) 89 | left_image_aug = left_image_aug * random_brightness 90 | right_image_aug = right_image_aug * random_brightness 91 | 92 | # randomly shift color 93 | random_colors = tf.random_uniform([3], 0.8, 1.2) 94 | white = tf.ones([tf.shape(left_image)[0], tf.shape(left_image)[1]]) 95 | color_image = tf.stack([white * random_colors[i] for i in range(3)], axis=2) 96 | left_image_aug *= color_image 97 | right_image_aug *= color_image 98 | 99 | # saturate 100 | left_image_aug = tf.clip_by_value(left_image_aug, 0, 1) 101 | right_image_aug = tf.clip_by_value(right_image_aug, 0, 1) 102 | 103 | return left_image_aug, right_image_aug 104 | 105 | def read_image(self, image_path): 106 | # tf.decode_image does not return the image size, this is an ugly workaround to handle both jpeg and png 107 | path_length = string_length_tf(image_path)[0] 108 | file_extension = tf.substr(image_path, path_length - 3, 3) 109 | file_cond = tf.equal(file_extension, 'jpg') 110 | 111 | image = tf.cond(file_cond, lambda: tf.image.decode_jpeg(tf.read_file(image_path)), 112 | lambda: tf.image.decode_png(tf.read_file(image_path))) 113 | 114 | # if the dataset is cityscapes, we crop the last fifth to remove the car hood 115 | if self.dataset == 'cityscapes': 116 | o_height = tf.shape(image)[0] 117 | crop_height = (o_height * 4) // 5 118 | image = image[:crop_height, :, :] 119 | 120 | image = tf.image.convert_image_dtype(image, tf.float32) 121 | image = tf.image.resize_images(image, [self.params.height, self.params.width], tf.image.ResizeMethod.AREA) 122 | 123 | return image 124 | -------------------------------------------------------------------------------- /ComputerVision/MonoDepth/monodepth_simple.py: -------------------------------------------------------------------------------- 1 | # Copyright UCL Business plc 2017. Patent Pending. All rights reserved. 2 | # 3 | # The MonoDepth Software is licensed under the terms of the UCLB ACP-A licence 4 | # which allows for non-commercial use only, the full terms of which are made 5 | # available in the LICENSE file. 6 | # 7 | # For any other use of the software not covered by the UCLB ACP-A Licence, 8 | # please contact info@uclb.com 9 | 10 | from __future__ import absolute_import, division, print_function 11 | 12 | # only keep warnings and errors 13 | import os 14 | os.environ['TF_CPP_MIN_LOG_LEVEL'] = '0' 15 | 16 | import argparse 17 | import scipy.misc 18 | import matplotlib.pyplot as plt 19 | 20 | from monodepth_model import * 21 | from average_gradients import * 22 | from monodepth_dataloader import * 23 | 24 | parser = argparse.ArgumentParser(description='Monodepth TensorFlow implementation.') 25 | 26 | parser.add_argument('--encoder', type=str, help='type of encoder, vgg or resnet50', default='vgg') 27 | parser.add_argument('--image_path', type=str, help='path to the image', required=True) 28 | parser.add_argument('--checkpoint_path', type=str, help='path to a specific checkpoint to load', required=True) 29 | parser.add_argument('--input_height', type=int, help='input height', default=256) 30 | parser.add_argument('--input_width', type=int, help='input width', default=512) 31 | parser.add_argument('--guided_filter', action='store_true', default=False) 32 | parser.add_argument('--guided_filter_eval', action='store_true', default=False) 33 | parser.add_argument('--dgf_r', type=int, default=4) 34 | parser.add_argument('--dgf_eps', type=float, default=1e-2) 35 | 36 | args = parser.parse_args() 37 | 38 | 39 | def post_process_disparity(disp): 40 | _, h, w = disp.shape 41 | l_disp = disp[0, :, :] 42 | r_disp = np.fliplr(disp[1, :, :]) 43 | m_disp = 0.5 * (l_disp + r_disp) 44 | l, _ = np.meshgrid(np.linspace(0, 1, w), np.linspace(0, 1, h)) 45 | l_mask = 1.0 - np.clip(20 * (l - 0.05), 0, 1) 46 | r_mask = np.fliplr(l_mask) 47 | return r_mask * l_disp + l_mask * r_disp + (1.0 - l_mask - r_mask) * m_disp 48 | 49 | 50 | def test_simple(params): 51 | """Test function.""" 52 | left = tf.placeholder(tf.float32, [2, args.input_height, args.input_width, 3]) 53 | model = MonodepthModel(params, "test", left, None) 54 | 55 | input_image = scipy.misc.imread(args.image_path, mode="RGB") 56 | original_height, original_width, num_channels = input_image.shape 57 | input_image = scipy.misc.imresize(input_image, [args.input_height, args.input_width], interp='lanczos') 58 | input_image = input_image.astype(np.float32) / 255 59 | input_images = np.stack((input_image, np.fliplr(input_image)), 0) 60 | 61 | # SESSION 62 | config = tf.ConfigProto(allow_soft_placement=True) 63 | sess = tf.Session(config=config) 64 | 65 | # SAVER 66 | train_saver = tf.train.Saver() 67 | 68 | # INIT 69 | sess.run(tf.global_variables_initializer()) 70 | sess.run(tf.local_variables_initializer()) 71 | coordinator = tf.train.Coordinator() 72 | threads = tf.train.start_queue_runners(sess=sess, coord=coordinator) 73 | 74 | # RESTORE 75 | restore_path = args.checkpoint_path.split(".")[0] 76 | train_saver.restore(sess, restore_path) 77 | 78 | disp = sess.run(model.disp_left_est[0], feed_dict={left: input_images}) 79 | disp_pp = post_process_disparity(disp.squeeze()).astype(np.float32) 80 | 81 | output_directory = os.path.dirname(args.image_path) 82 | output_name = os.path.splitext(os.path.basename(args.image_path))[0] 83 | 84 | np.save(os.path.join(output_directory, "{}_disp.npy".format(output_name)), disp_pp) 85 | disp_to_img = scipy.misc.imresize(disp_pp.squeeze(), [original_height, original_width]) 86 | plt.imsave(os.path.join(output_directory, "{}_disp.png".format(output_name)), disp_to_img, cmap='plasma') 87 | 88 | print('done!') 89 | 90 | 91 | def main(_): 92 | params = monodepth_parameters( 93 | encoder=args.encoder, 94 | height=args.input_height, 95 | width=args.input_width, 96 | batch_size=2, 97 | num_threads=1, 98 | num_epochs=1, 99 | do_stereo=False, 100 | wrap_mode="border", 101 | use_deconv=False, 102 | alpha_image_loss=0, 103 | disp_gradient_loss_weight=0, 104 | lr_loss_weight=0, 105 | full_summary=False, 106 | guided_filter=args.guided_filter, 107 | guided_filter_eval=args.guided_filter_eval, 108 | dgf_r=args.dgf_r, 109 | dgf_eps=args.dgf_eps 110 | ) 111 | 112 | test_simple(params) 113 | 114 | 115 | if __name__ == '__main__': 116 | tf.app.run() 117 | -------------------------------------------------------------------------------- /ComputerVision/MonoDepth/requirements.txt: -------------------------------------------------------------------------------- 1 | scipy == 1.0.0 2 | numpy == 1.12.1 3 | guided_filter_tf 4 | matplotlib == 2.1.1 5 | tensorflow_gpu == 1.4.0 6 | -------------------------------------------------------------------------------- /ComputerVision/MonoDepth/utils/evaluate_kitti.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | import cv2 4 | import numpy as np 5 | from evaluation_utils import * 6 | 7 | parser = argparse.ArgumentParser(description='Evaluation on the KITTI dataset') 8 | parser.add_argument('--split', type=str, help='data split, kitti or eigen', required=True) 9 | parser.add_argument('--predicted_disp_path', type=str, help='path to estimated disparities', required=True) 10 | parser.add_argument('--gt_path', type=str, help='path to ground truth disparities', required=True) 11 | parser.add_argument('--min_depth', type=float, help='minimum depth for evaluation', default=1e-3) 12 | parser.add_argument('--max_depth', type=float, help='maximum depth for evaluation', default=80) 13 | parser.add_argument('--eigen_crop', help='if set, crops according to Eigen NIPS14', action='store_true') 14 | parser.add_argument('--garg_crop', help='if set, crops according to Garg ECCV16', action='store_true') 15 | 16 | args = parser.parse_args() 17 | 18 | if __name__ == '__main__': 19 | 20 | pred_disparities = np.load(args.predicted_disp_path) 21 | 22 | if args.split == 'kitti': 23 | num_samples = 200 24 | 25 | gt_disparities = load_gt_disp_kitti(args.gt_path) 26 | gt_depths, pred_depths, pred_disparities_resized = convert_disps_to_depths_kitti(gt_disparities, 27 | pred_disparities) 28 | 29 | elif args.split == 'eigen': 30 | num_samples = 697 31 | test_files = read_text_lines(args.gt_path + 'eigen_test_files.txt') 32 | gt_files, gt_calib, im_sizes, im_files, cams = read_file_data(test_files, args.gt_path) 33 | 34 | num_test = len(im_files) 35 | gt_depths = [] 36 | pred_depths = [] 37 | for t_id in range(num_samples): 38 | camera_id = cams[t_id] # 2 is left, 3 is right 39 | depth = generate_depth_map(gt_calib[t_id], gt_files[t_id], im_sizes[t_id], camera_id, False, True) 40 | gt_depths.append(depth.astype(np.float32)) 41 | 42 | disp_pred = cv2.resize(pred_disparities[t_id], (im_sizes[t_id][1], im_sizes[t_id][0]), 43 | interpolation=cv2.INTER_LINEAR) 44 | disp_pred = disp_pred * disp_pred.shape[1] 45 | 46 | # need to convert from disparity to depth 47 | focal_length, baseline = get_focal_length_baseline(gt_calib[t_id], camera_id) 48 | depth_pred = (baseline * focal_length) / disp_pred 49 | depth_pred[np.isinf(depth_pred)] = 0 50 | 51 | pred_depths.append(depth_pred) 52 | 53 | rms = np.zeros(num_samples, np.float32) 54 | log_rms = np.zeros(num_samples, np.float32) 55 | abs_rel = np.zeros(num_samples, np.float32) 56 | sq_rel = np.zeros(num_samples, np.float32) 57 | d1_all = np.zeros(num_samples, np.float32) 58 | a1 = np.zeros(num_samples, np.float32) 59 | a2 = np.zeros(num_samples, np.float32) 60 | a3 = np.zeros(num_samples, np.float32) 61 | 62 | for i in range(num_samples): 63 | 64 | gt_depth = gt_depths[i] 65 | pred_depth = pred_depths[i] 66 | 67 | pred_depth[pred_depth < args.min_depth] = args.min_depth 68 | pred_depth[pred_depth > args.max_depth] = args.max_depth 69 | 70 | if args.split == 'eigen': 71 | mask = np.logical_and(gt_depth > args.min_depth, gt_depth < args.max_depth) 72 | 73 | if args.garg_crop or args.eigen_crop: 74 | gt_height, gt_width = gt_depth.shape 75 | 76 | # crop used by Garg ECCV16 77 | # if used on gt_size 370x1224 produces a crop of [-218, -3, 44, 1180] 78 | if args.garg_crop: 79 | crop = np.array([0.40810811 * gt_height, 0.99189189 * gt_height, 80 | 0.03594771 * gt_width, 0.96405229 * gt_width]).astype(np.int32) 81 | # crop we found by trial and error to reproduce Eigen NIPS14 results 82 | elif args.eigen_crop: 83 | crop = np.array([0.3324324 * gt_height, 0.91351351 * gt_height, 84 | 0.0359477 * gt_width, 0.96405229 * gt_width]).astype(np.int32) 85 | 86 | crop_mask = np.zeros(mask.shape) 87 | crop_mask[crop[0]:crop[1], crop[2]:crop[3]] = 1 88 | mask = np.logical_and(mask, crop_mask) 89 | 90 | if args.split == 'kitti': 91 | gt_disp = gt_disparities[i] 92 | mask = gt_disp > 0 93 | pred_disp = pred_disparities_resized[i] 94 | 95 | disp_diff = np.abs(gt_disp[mask] - pred_disp[mask]) 96 | bad_pixels = np.logical_and(disp_diff >= 3, (disp_diff / gt_disp[mask]) >= 0.05) 97 | d1_all[i] = 100.0 * bad_pixels.sum() / mask.sum() 98 | 99 | abs_rel[i], sq_rel[i], rms[i], log_rms[i], a1[i], a2[i], a3[i] = compute_errors(gt_depth[mask], 100 | pred_depth[mask]) 101 | 102 | print("{:>10}, {:>10}, {:>10}, {:>10}, {:>10}, {:>10}, {:>10}, {:>10}".format('abs_rel', 'sq_rel', 'rms', 'log_rms', 103 | 'd1_all', 'a1', 'a2', 'a3')) 104 | print("{:10.4f}, {:10.4f}, {:10.3f}, {:10.3f}, {:10.3f}, {:10.3f}, {:10.3f}, {:10.3f}".format(abs_rel.mean(), 105 | sq_rel.mean(), 106 | rms.mean(), 107 | log_rms.mean(), 108 | d1_all.mean(), 109 | a1.mean(), a2.mean(), 110 | a3.mean())) 111 | -------------------------------------------------------------------------------- /ComputerVision/MonoDepth/utils/evaluation_utils.py: -------------------------------------------------------------------------------- 1 | import os 2 | from collections import Counter 3 | 4 | import cv2 5 | import numpy as np 6 | from scipy.interpolate import LinearNDInterpolator 7 | 8 | 9 | def compute_errors(gt, pred): 10 | thresh = np.maximum((gt / pred), (pred / gt)) 11 | a1 = (thresh < 1.25).mean() 12 | a2 = (thresh < 1.25 ** 2).mean() 13 | a3 = (thresh < 1.25 ** 3).mean() 14 | 15 | rmse = (gt - pred) ** 2 16 | rmse = np.sqrt(rmse.mean()) 17 | 18 | rmse_log = (np.log(gt) - np.log(pred)) ** 2 19 | rmse_log = np.sqrt(rmse_log.mean()) 20 | 21 | abs_rel = np.mean(np.abs(gt - pred) / gt) 22 | 23 | sq_rel = np.mean(((gt - pred) ** 2) / gt) 24 | 25 | return abs_rel, sq_rel, rmse, rmse_log, a1, a2, a3 26 | 27 | 28 | ############################################################################### 29 | ####################### KITTI 30 | 31 | width_to_focal = dict() 32 | width_to_focal[1242] = 721.5377 33 | width_to_focal[1241] = 718.856 34 | width_to_focal[1224] = 707.0493 35 | width_to_focal[1238] = 718.3351 36 | 37 | 38 | def load_gt_disp_kitti(path): 39 | gt_disparities = [] 40 | for i in range(200): 41 | disp = cv2.imread(path + "/training/disp_noc_0/" + str(i).zfill(6) + "_10.png", -1) 42 | disp = disp.astype(np.float32) / 256 43 | gt_disparities.append(disp) 44 | return gt_disparities 45 | 46 | 47 | def convert_disps_to_depths_kitti(gt_disparities, pred_disparities): 48 | gt_depths = [] 49 | pred_depths = [] 50 | pred_disparities_resized = [] 51 | 52 | for i in range(len(gt_disparities)): 53 | gt_disp = gt_disparities[i] 54 | height, width = gt_disp.shape 55 | 56 | pred_disp = pred_disparities[i] 57 | pred_disp = width * cv2.resize(pred_disp, (width, height), interpolation=cv2.INTER_LINEAR) 58 | 59 | pred_disparities_resized.append(pred_disp) 60 | 61 | mask = gt_disp > 0 62 | 63 | gt_depth = width_to_focal[width] * 0.54 / (gt_disp + (1.0 - mask)) 64 | pred_depth = width_to_focal[width] * 0.54 / pred_disp 65 | 66 | gt_depths.append(gt_depth) 67 | pred_depths.append(pred_depth) 68 | return gt_depths, pred_depths, pred_disparities_resized 69 | 70 | 71 | ############################################################################### 72 | ####################### EIGEN 73 | 74 | def read_text_lines(file_path): 75 | f = open(file_path, 'r') 76 | lines = f.readlines() 77 | f.close() 78 | lines = [l.rstrip() for l in lines] 79 | return lines 80 | 81 | 82 | def read_file_data(files, data_root): 83 | gt_files = [] 84 | gt_calib = [] 85 | im_sizes = [] 86 | im_files = [] 87 | cams = [] 88 | num_probs = 0 89 | for filename in files: 90 | filename = filename.split()[0] 91 | splits = filename.split('/') 92 | date = splits[0] 93 | im_id = splits[4][:10] 94 | 95 | im = filename 96 | vel = '{}/{}/velodyne_points/data/{}.bin'.format(splits[0], splits[1], im_id) 97 | 98 | if os.path.isfile(data_root + im): 99 | gt_files.append(data_root + vel) 100 | gt_calib.append(data_root + date + '/') 101 | im_sizes.append(cv2.imread(data_root + im).shape[:2]) 102 | im_files.append(data_root + im) 103 | cams.append(2) 104 | else: 105 | num_probs += 1 106 | print('{} missing'.format(data_root + im)) 107 | print(num_probs, 'files missing') 108 | 109 | return gt_files, gt_calib, im_sizes, im_files, cams 110 | 111 | 112 | def load_velodyne_points(file_name): 113 | # adapted from https://github.com/hunse/kitti 114 | points = np.fromfile(file_name, dtype=np.float32).reshape(-1, 4) 115 | points[:, 3] = 1.0 # homogeneous 116 | return points 117 | 118 | 119 | def lin_interp(shape, xyd): 120 | # taken from https://github.com/hunse/kitti 121 | m, n = shape 122 | ij, d = xyd[:, 1::-1], xyd[:, 2] 123 | f = LinearNDInterpolator(ij, d, fill_value=0) 124 | J, I = np.meshgrid(np.arange(n), np.arange(m)) 125 | IJ = np.vstack([I.flatten(), J.flatten()]).T 126 | disparity = f(IJ).reshape(shape) 127 | return disparity 128 | 129 | 130 | def read_calib_file(path): 131 | # taken from https://github.com/hunse/kitti 132 | float_chars = set("0123456789.e+- ") 133 | data = {} 134 | with open(path, 'r') as f: 135 | for line in f.readlines(): 136 | key, value = line.split(':', 1) 137 | value = value.strip() 138 | data[key] = value 139 | if float_chars.issuperset(value): 140 | # try to cast to float array 141 | try: 142 | data[key] = np.array([float(v) for v in value.split(' ')]) 143 | except ValueError: 144 | # casting error: data[key] already eq. value, so pass 145 | pass 146 | 147 | return data 148 | 149 | 150 | def get_focal_length_baseline(calib_dir, cam): 151 | cam2cam = read_calib_file(calib_dir + 'calib_cam_to_cam.txt') 152 | P2_rect = cam2cam['P_rect_02'].reshape(3, 4) 153 | P3_rect = cam2cam['P_rect_03'].reshape(3, 4) 154 | 155 | # cam 2 is left of camera 0 -6cm 156 | # cam 3 is to the right +54cm 157 | b2 = P2_rect[0, 3] / -P2_rect[0, 0] 158 | b3 = P3_rect[0, 3] / -P3_rect[0, 0] 159 | baseline = b3 - b2 160 | 161 | if cam == 2: 162 | focal_length = P2_rect[0, 0] 163 | elif cam == 3: 164 | focal_length = P3_rect[0, 0] 165 | 166 | return focal_length, baseline 167 | 168 | 169 | def sub2ind(matrixSize, rowSub, colSub): 170 | m, n = matrixSize 171 | return rowSub * (n - 1) + colSub - 1 172 | 173 | 174 | def generate_depth_map(calib_dir, velo_file_name, im_shape, cam=2, interp=False, vel_depth=False): 175 | # load calibration files 176 | cam2cam = read_calib_file(calib_dir + 'calib_cam_to_cam.txt') 177 | velo2cam = read_calib_file(calib_dir + 'calib_velo_to_cam.txt') 178 | velo2cam = np.hstack((velo2cam['R'].reshape(3, 3), velo2cam['T'][..., np.newaxis])) 179 | velo2cam = np.vstack((velo2cam, np.array([0, 0, 0, 1.0]))) 180 | 181 | # compute projection matrix velodyne->image plane 182 | R_cam2rect = np.eye(4) 183 | R_cam2rect[:3, :3] = cam2cam['R_rect_00'].reshape(3, 3) 184 | P_rect = cam2cam['P_rect_0' + str(cam)].reshape(3, 4) 185 | P_velo2im = np.dot(np.dot(P_rect, R_cam2rect), velo2cam) 186 | 187 | # load velodyne points and remove all behind image plane (approximation) 188 | # each row of the velodyne data is forward, left, up, reflectance 189 | velo = load_velodyne_points(velo_file_name) 190 | velo = velo[velo[:, 0] >= 0, :] 191 | 192 | # project the points to the camera 193 | velo_pts_im = np.dot(P_velo2im, velo.T).T 194 | velo_pts_im[:, :2] = velo_pts_im[:, :2] / velo_pts_im[:, 2][..., np.newaxis] 195 | 196 | if vel_depth: 197 | velo_pts_im[:, 2] = velo[:, 0] 198 | 199 | # check if in bounds 200 | # use minus 1 to get the exact same value as KITTI matlab code 201 | velo_pts_im[:, 0] = np.round(velo_pts_im[:, 0]) - 1 202 | velo_pts_im[:, 1] = np.round(velo_pts_im[:, 1]) - 1 203 | val_inds = (velo_pts_im[:, 0] >= 0) & (velo_pts_im[:, 1] >= 0) 204 | val_inds = val_inds & (velo_pts_im[:, 0] < im_shape[1]) & (velo_pts_im[:, 1] < im_shape[0]) 205 | velo_pts_im = velo_pts_im[val_inds, :] 206 | 207 | # project to image 208 | depth = np.zeros((im_shape)) 209 | depth[velo_pts_im[:, 1].astype(np.int), velo_pts_im[:, 0].astype(np.int)] = velo_pts_im[:, 2] 210 | 211 | # find the duplicate points and choose the closest depth 212 | inds = sub2ind(depth.shape, velo_pts_im[:, 1], velo_pts_im[:, 0]) 213 | dupe_inds = [item for item, count in Counter(inds).items() if count > 1] 214 | for dd in dupe_inds: 215 | pts = np.where(inds == dd)[0] 216 | x_loc = int(velo_pts_im[pts[0], 0]) 217 | y_loc = int(velo_pts_im[pts[0], 1]) 218 | depth[y_loc, x_loc] = velo_pts_im[pts, 2].min() 219 | depth[depth < 0] = 0 220 | 221 | if interp: 222 | # interpolate the depth map to fill in holes 223 | depth_interp = lin_interp(im_shape, velo_pts_im) 224 | return depth, depth_interp 225 | else: 226 | return depth 227 | -------------------------------------------------------------------------------- /ComputerVision/MonoDepth/utils/kitti_archives_to_download.txt: -------------------------------------------------------------------------------- 1 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_calib.zip 2 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0001/2011_09_26_drive_0001_sync.zip 3 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0002/2011_09_26_drive_0002_sync.zip 4 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0005/2011_09_26_drive_0005_sync.zip 5 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0009/2011_09_26_drive_0009_sync.zip 6 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0011/2011_09_26_drive_0011_sync.zip 7 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0013/2011_09_26_drive_0013_sync.zip 8 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0014/2011_09_26_drive_0014_sync.zip 9 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0015/2011_09_26_drive_0015_sync.zip 10 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0017/2011_09_26_drive_0017_sync.zip 11 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0018/2011_09_26_drive_0018_sync.zip 12 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0019/2011_09_26_drive_0019_sync.zip 13 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0020/2011_09_26_drive_0020_sync.zip 14 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0022/2011_09_26_drive_0022_sync.zip 15 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0023/2011_09_26_drive_0023_sync.zip 16 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0027/2011_09_26_drive_0027_sync.zip 17 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0028/2011_09_26_drive_0028_sync.zip 18 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0029/2011_09_26_drive_0029_sync.zip 19 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0032/2011_09_26_drive_0032_sync.zip 20 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0035/2011_09_26_drive_0035_sync.zip 21 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0036/2011_09_26_drive_0036_sync.zip 22 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0039/2011_09_26_drive_0039_sync.zip 23 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0046/2011_09_26_drive_0046_sync.zip 24 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0048/2011_09_26_drive_0048_sync.zip 25 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0051/2011_09_26_drive_0051_sync.zip 26 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0052/2011_09_26_drive_0052_sync.zip 27 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0056/2011_09_26_drive_0056_sync.zip 28 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0057/2011_09_26_drive_0057_sync.zip 29 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0059/2011_09_26_drive_0059_sync.zip 30 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0060/2011_09_26_drive_0060_sync.zip 31 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0061/2011_09_26_drive_0061_sync.zip 32 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0064/2011_09_26_drive_0064_sync.zip 33 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0070/2011_09_26_drive_0070_sync.zip 34 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0079/2011_09_26_drive_0079_sync.zip 35 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0084/2011_09_26_drive_0084_sync.zip 36 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0086/2011_09_26_drive_0086_sync.zip 37 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0087/2011_09_26_drive_0087_sync.zip 38 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0091/2011_09_26_drive_0091_sync.zip 39 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0093/2011_09_26_drive_0093_sync.zip 40 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0095/2011_09_26_drive_0095_sync.zip 41 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0096/2011_09_26_drive_0096_sync.zip 42 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0101/2011_09_26_drive_0101_sync.zip 43 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0104/2011_09_26_drive_0104_sync.zip 44 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0106/2011_09_26_drive_0106_sync.zip 45 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0113/2011_09_26_drive_0113_sync.zip 46 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_26_drive_0117/2011_09_26_drive_0117_sync.zip 47 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_28_calib.zip 48 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_28_drive_0001/2011_09_28_drive_0001_sync.zip 49 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_28_drive_0002/2011_09_28_drive_0002_sync.zip 50 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_29_calib.zip 51 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_29_drive_0004/2011_09_29_drive_0004_sync.zip 52 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_29_drive_0026/2011_09_29_drive_0026_sync.zip 53 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_29_drive_0071/2011_09_29_drive_0071_sync.zip 54 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_30_calib.zip 55 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_30_drive_0016/2011_09_30_drive_0016_sync.zip 56 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_30_drive_0018/2011_09_30_drive_0018_sync.zip 57 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_30_drive_0020/2011_09_30_drive_0020_sync.zip 58 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_30_drive_0027/2011_09_30_drive_0027_sync.zip 59 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_30_drive_0028/2011_09_30_drive_0028_sync.zip 60 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_30_drive_0033/2011_09_30_drive_0033_sync.zip 61 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_09_30_drive_0034/2011_09_30_drive_0034_sync.zip 62 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_10_03_calib.zip 63 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_10_03_drive_0027/2011_10_03_drive_0027_sync.zip 64 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_10_03_drive_0034/2011_10_03_drive_0034_sync.zip 65 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_10_03_drive_0042/2011_10_03_drive_0042_sync.zip 66 | http://kitti.is.tue.mpg.de/kitti/raw_data/2011_10_03_drive_0047/2011_10_03_drive_0047_sync.zip 67 | -------------------------------------------------------------------------------- /ComputerVision/Saliency_DSS/.gitignore: -------------------------------------------------------------------------------- 1 | checkpoints* 2 | results* 3 | -------------------------------------------------------------------------------- /ComputerVision/Saliency_DSS/README.md: -------------------------------------------------------------------------------- 1 | # Saliency Detection with DSS 2 | 3 | Max F-measure: **91.75%** [Baseline: 90.61%] 4 | 5 | ## Try on an image! 6 | 1. Download the pretrained model [[Google Drive](https://drive.google.com/open?id=1ZxbAAJw9BxCKj2e2QsBmCnjWLFlCGLf1)|[BaiduYunPan](https://pan.baidu.com/s/1pgOMh3V50lRa6slbIW_SKQ)]. 7 | 2. Try it now! 8 | ```sh 9 | python predict.py --im_path [IM_PATH] \ 10 | --netG [MODEL_PATH] \ 11 | --thres [-1|161] \ 12 | --dgf --nn_dgf \ 13 | --post_sigmoid --cuda 14 | ``` 15 | ## Training on MSRA-B 16 | 1. Download and **unzip** the saliency dataset [MSRA-B](http://mftp.mmcheng.net/Data/MSRA-B.zip). 17 | 2. Make **A-B** (Image-Label) pairs. 18 | ```sh 19 | python scripts/preprocess.py --data_path [MSRA-B_ROOT] --mode train 20 | python scripts/preprocess.py --data_path [MSRA-B_ROOT] --mode valid 21 | python scripts/preprocess.py --data_path [MSRA-B_ROOT] --mode test 22 | ``` 23 | 3. Start training! 24 | * **WITHOUT** Guided Filtering Layer 25 | ```sh 26 | python main.py --dataroot [MSRA-B_ROOT]/AB --cuda --experiment [EXP_NAME] 27 | ``` 28 | * **WITH** Guided Filtering Layer 29 | ```sh 30 | python main.py --dataroot [MSRA-B_ROOT]/AB --cuda --experiment [EXP_NAME] --dgf 31 | ``` 32 | * Finetune 33 | ```sh 34 | python main.py --dataroot [MSRA-B_ROOT]/AB --cuda --experiment [EXP_NAME] --netG [MODEL_PATH] --dgf 35 | ``` 36 | 37 | 4. Evaluation 38 | ```sh 39 | python test.py --dataroot [MSRA-B_ROOT]/AB/test \ 40 | --netG [MODEL_PATH] --cuda \ 41 | --experiment [SAVE_FOLDER] \ 42 | --nn_dgf --post_sigmoid --dgf 43 | ``` 44 | 5. Calculate metrics 45 | 1. Install [SalMetric](https://github.com/Andrew-Qibin/SalMetric). 46 | ```sh 47 | git clone https://github.com/Andrew-Qibin/SalMetric && cd SalMetric 48 | mkdir build && cd build 49 | cmake .. && make 50 | ``` 51 | 2. Calculate ! 52 | ```sh 53 | cd [SAVE_FOLDER] 54 | [SalMetric_ROOT]/build/salmetric test.txt [WORKER_NUM] 55 | ``` 56 | ## Acknowledgement 57 | A part of the code was adapted from [DSS](https://github.com/Andrew-Qibin/DSS). -------------------------------------------------------------------------------- /ComputerVision/Saliency_DSS/main.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | import os 4 | import math 5 | import argparse 6 | 7 | import numpy as np 8 | 9 | import torch 10 | import torch.nn as nn 11 | import torch.utils.data 12 | import torch.nn.parallel 13 | import torch.optim as optim 14 | import torch.backends.cudnn as cudnn 15 | import torch.optim.lr_scheduler as lrs 16 | 17 | import torchvision.datasets as dset 18 | import torchvision.models as visionmodels 19 | import torchvision.transforms as transforms 20 | 21 | from torch.autograd import Variable 22 | 23 | import models.dss as dss 24 | 25 | parser = argparse.ArgumentParser() 26 | parser.add_argument('--dataroot', required=True, help='path to dataset') 27 | parser.add_argument('--workers', type=int, help='number of data loading workers', default=2) 28 | parser.add_argument('--niter', type=int, default=25, help='number of epochs to train for') 29 | parser.add_argument('--lrG', type=float, default=0.00001, help='learning rate for Generator, default=0.00005') 30 | parser.add_argument('--cuda', action='store_true', help='enables cuda') 31 | parser.add_argument('--netG', default='', help="path to netG (to continue training)") 32 | parser.add_argument('--dgf', action='store_true', help='enables dgf') 33 | parser.add_argument('--dgf_r', type=int, default=8, help='dgf radius') 34 | parser.add_argument('--dgf_eps', type=float, default=1e-2, help='dgf eps') 35 | parser.add_argument('--experiment', default='checkpoints', help='Where to store samples and models') 36 | opt = parser.parse_args() 37 | print(opt) 38 | 39 | 40 | def weights_init(m): 41 | for p in m.modules(): 42 | if isinstance(p, nn.Conv2d): 43 | n = p.kernel_size[0] * p.kernel_size[1] * p.out_channels 44 | p.weight.data.normal_(0, math.sqrt(2. / n)) 45 | elif isinstance(p, nn.BatchNorm2d): 46 | p.weight.data.normal_(1.0, 0.02) 47 | p.bias.data.fill_(0) 48 | elif isinstance(p, nn.ConvTranspose2d): 49 | n = p.kernel_size[1] 50 | factor = (n + 1) // 2 51 | if n % 2 == 1: 52 | center = factor - 1 53 | else: 54 | center = factor - 0.5 55 | og = np.ogrid[:n, :n] 56 | weights_np = (1 - abs(og[0] - center) / factor) * (1 - abs(og[1] - center) / factor) 57 | p.weight.data.copy_(torch.from_numpy(weights_np)) 58 | 59 | 60 | # fine-tune from VGG16 61 | def fine_tune(net): 62 | vgg_16 = visionmodels.vgg16(pretrained=True) 63 | net.conv1.conv1_1.weight.data.copy_(vgg_16.features[0].weight.data) 64 | net.conv1.conv1_2.weight.data.copy_(vgg_16.features[2].weight.data) 65 | net.conv2.conv2_1.weight.data.copy_(vgg_16.features[5].weight.data) 66 | net.conv2.conv2_2.weight.data.copy_(vgg_16.features[7].weight.data) 67 | net.conv3.conv3_1.weight.data.copy_(vgg_16.features[10].weight.data) 68 | net.conv3.conv3_2.weight.data.copy_(vgg_16.features[12].weight.data) 69 | net.conv3.conv3_3.weight.data.copy_(vgg_16.features[14].weight.data) 70 | net.conv4.conv4_1.weight.data.copy_(vgg_16.features[17].weight.data) 71 | net.conv4.conv4_2.weight.data.copy_(vgg_16.features[19].weight.data) 72 | net.conv4.conv4_3.weight.data.copy_(vgg_16.features[21].weight.data) 73 | net.conv5.conv5_1.weight.data.copy_(vgg_16.features[24].weight.data) 74 | net.conv5.conv5_2.weight.data.copy_(vgg_16.features[26].weight.data) 75 | net.conv5.conv5_3.weight.data.copy_(vgg_16.features[28].weight.data) 76 | 77 | net.conv1.conv1_1.bias.data.copy_(vgg_16.features[0].bias.data) 78 | net.conv1.conv1_2.bias.data.copy_(vgg_16.features[2].bias.data) 79 | net.conv2.conv2_1.bias.data.copy_(vgg_16.features[5].bias.data) 80 | net.conv2.conv2_2.bias.data.copy_(vgg_16.features[7].bias.data) 81 | net.conv3.conv3_1.bias.data.copy_(vgg_16.features[10].bias.data) 82 | net.conv3.conv3_2.bias.data.copy_(vgg_16.features[12].bias.data) 83 | net.conv3.conv3_3.bias.data.copy_(vgg_16.features[14].bias.data) 84 | net.conv4.conv4_1.bias.data.copy_(vgg_16.features[17].bias.data) 85 | net.conv4.conv4_2.bias.data.copy_(vgg_16.features[19].bias.data) 86 | net.conv4.conv4_3.bias.data.copy_(vgg_16.features[21].bias.data) 87 | net.conv5.conv5_1.bias.data.copy_(vgg_16.features[24].bias.data) 88 | net.conv5.conv5_2.bias.data.copy_(vgg_16.features[26].bias.data) 89 | net.conv5.conv5_3.bias.data.copy_(vgg_16.features[28].bias.data) 90 | return net 91 | 92 | 93 | cudnn.benchmark = True 94 | 95 | if not os.path.isdir(opt.experiment): 96 | os.makedirs(opt.experiment) 97 | 98 | # folder dataset 99 | dataset = dset.ImageFolder(root=os.path.join(opt.dataroot, 'train'), 100 | transform=transforms.Compose([ 101 | transforms.ToTensor(), 102 | ])) 103 | dataloader = torch.utils.data.DataLoader(dataset, batch_size=1, 104 | shuffle=True, num_workers=opt.workers) 105 | normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], 106 | std=[0.229, 0.224, 0.225]) 107 | 108 | netG = dss.network_dss(3, opt.dgf, opt.dgf_r, opt.dgf_eps, False) 109 | criterion = nn.BCELoss() 110 | netG.apply(weights_init) 111 | netG = fine_tune(netG) 112 | print('=>finetune from the VGG16... done !') 113 | if opt.netG: # load checkpoint if needed 114 | checkpoint = torch.load(opt.netG) 115 | model_dict = netG.state_dict() 116 | model_dict.update(checkpoint) 117 | netG.load_state_dict(model_dict) 118 | print(netG) 119 | 120 | real_B = torch.FloatTensor() 121 | real_A = torch.FloatTensor() 122 | real_x = torch.FloatTensor() 123 | if opt.cuda: 124 | netG.cuda() 125 | 126 | # setup optimizer 127 | optimizerG = optim.RMSprop(netG.parameters(), lr=opt.lrG) 128 | schedulerG = lrs.MultiStepLR(optimizerG, milestones=[5, 15], gamma=0.1) 129 | 130 | gen_iterations = 0 131 | for epoch in range(opt.niter): 132 | data_iter = iter(dataloader) 133 | schedulerG.step() 134 | 135 | for idx, (data, _) in enumerate(data_iter): 136 | w = data.size(3) // 2 137 | h = data.size(2) 138 | real_B.resize_(data.size(0), 1, h, w).copy_(data[:, :1, :, w:]) 139 | real_A.resize_(3, h, w).copy_(data[0, :3, :, 0:w]) 140 | real_A = normalize(real_A) 141 | real_A.unsqueeze_(0) 142 | 143 | real_x.resize_(1, 3, h, w).copy_(data[:1, :3, :, 0:w]) 144 | input_G = Variable(real_A) 145 | if opt.cuda: 146 | real_x = real_x.cuda() 147 | real_B = real_B.cuda() 148 | input_G = input_G.cuda() 149 | 150 | fake_B, side1, side2, side3, side4, side5, side6 = netG(input_G, Variable(real_x)) 151 | 152 | errG_bce = criterion(fake_B, Variable(real_B)) 153 | 154 | optimizerG.zero_grad() 155 | errG_bce.backward() 156 | optimizerG.step() 157 | 158 | gen_iterations += 1 159 | 160 | print('[%d/%d][%d/%d] Loss_bce %f' 161 | % (epoch, opt.niter, idx, len(dataloader), errG_bce.item())) 162 | if gen_iterations % 2000 == 0: 163 | torch.save(netG.state_dict(), '{0}/bfn1_netG_iter_{1}.pth'.format(opt.experiment, gen_iterations)) 164 | -------------------------------------------------------------------------------- /ComputerVision/Saliency_DSS/predict.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | import os 4 | import argparse 5 | 6 | import numpy as np 7 | 8 | import torch.utils.data 9 | import torch.backends.cudnn as cudnn 10 | 11 | import torchvision.transforms as transforms 12 | 13 | from PIL import Image 14 | from skimage.io import imsave 15 | 16 | from torch.autograd import Variable 17 | 18 | import models.dss as dss 19 | 20 | from guided_filter_pytorch.guided_filter import GuidedFilter 21 | 22 | 23 | parser = argparse.ArgumentParser() 24 | parser.add_argument('--im_path', required=True, help="path to image") 25 | parser.add_argument('--netG', required=True, help="path to netG (to continue training)") 26 | parser.add_argument('--cuda', action='store_true', help='enables cuda') 27 | parser.add_argument('--nn_dgf', action='store_true', help='enables dgf') 28 | parser.add_argument('--nn_dgf_r', type=int, default=8, help='dgf radius') 29 | parser.add_argument('--nn_dgf_eps', type=float, default=1e-2, help='dgf eps') 30 | parser.add_argument('--post_sigmoid', action='store_true', help='sigmoid after dgf') 31 | parser.add_argument('--dgf', action='store_true', help='enables dgf') 32 | parser.add_argument('--dgf_r', type=int, default=8, help='dgf radius') 33 | parser.add_argument('--dgf_eps', type=float, default=1e-2, help='dgf eps') 34 | parser.add_argument('--thres', type=int, default=161, help='clip by threshold') 35 | opt = parser.parse_args() 36 | print(opt) 37 | 38 | cudnn.benchmark = True 39 | netG = dss.network_dss(3, opt.nn_dgf, opt.nn_dgf_r, opt.nn_dgf_eps, opt.post_sigmoid) 40 | netG.load_state_dict(torch.load(opt.netG)) 41 | if opt.dgf: 42 | dgf = GuidedFilter(opt.dgf_r, opt.dgf_eps) 43 | if opt.cuda: 44 | netG = netG.cuda() 45 | if opt.dgf: 46 | dgf = dgf.cuda() 47 | 48 | img = transforms.ToTensor()(Image.open(opt.im_path).convert('RGB')) 49 | real_x = img.unsqueeze(0) 50 | real_A = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])(img) 51 | real_A.unsqueeze_(0) 52 | input_G = Variable(real_A) 53 | input_x = Variable(real_x) 54 | 55 | if opt.cuda: 56 | input_G = input_G.cuda() 57 | input_x = input_x.cuda() 58 | 59 | with torch.no_grad(): 60 | fake_B, side_out1, side_out2, side_out3, side_out4, side_out5, side_out6 = netG(input_G, input_x) 61 | if opt.dgf: 62 | input_x = input_x.sum(1, keepdim=True) 63 | image_B = dgf(input_x, fake_B).clamp(0, 1) 64 | else: 65 | image_B = fake_B 66 | 67 | image_B = image_B.data.cpu().mul(255).numpy().squeeze().astype(np.uint8) 68 | if opt.thres > 0: 69 | image_B[image_B >= opt.thres] = 255 70 | image_B[image_B <= opt.thres] = 0 71 | 72 | output_directory = os.path.dirname(opt.im_path) 73 | output_name = os.path.splitext(os.path.basename(opt.im_path))[0] 74 | save_path = os.path.join(output_directory, '{}_labels.png'.format(output_name)) 75 | imsave(save_path, image_B) 76 | -------------------------------------------------------------------------------- /ComputerVision/Saliency_DSS/scripts/preprocess.py: -------------------------------------------------------------------------------- 1 | import os 2 | import argparse 3 | 4 | import numpy as np 5 | 6 | from skimage.color import grey2rgb 7 | from skimage.io import imread, imsave 8 | 9 | parser = argparse.ArgumentParser(description='Make A-B pairs.') 10 | parser.add_argument('--data_path', type=str, required=True, help='DATA_ROOT') 11 | parser.add_argument('--mode', type=str, default='train', help='train|valid|test') 12 | args = parser.parse_args() 13 | 14 | ROOT = args.data_path 15 | file = 'list/{}_cvpr2013.txt'.format(args.mode) 16 | target_folder = 'AB/{}/{}'.format(args.mode, args.mode) 17 | 18 | target_folder = os.path.join(ROOT, target_folder) 19 | if not os.path.isdir(target_folder): 20 | os.makedirs(target_folder) 21 | 22 | with open(file) as f: 23 | for line in f: 24 | line = line.strip() 25 | 26 | A = imread(os.path.join(ROOT, line.replace('.png', '.jpg'))) 27 | B = grey2rgb(imread(os.path.join(ROOT, line))) 28 | out = np.hstack([A, B]) 29 | 30 | imsave(os.path.join(target_folder, line), out) 31 | -------------------------------------------------------------------------------- /ComputerVision/Saliency_DSS/test.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | import os 4 | import argparse 5 | 6 | import numpy as np 7 | 8 | import torch.utils.data 9 | import torch.backends.cudnn as cudnn 10 | 11 | import torchvision.datasets as dset 12 | import torchvision.transforms as transforms 13 | 14 | from skimage.io import imsave 15 | 16 | from torch.autograd import Variable 17 | 18 | import models.dss as dss 19 | 20 | from guided_filter_pytorch.guided_filter import GuidedFilter 21 | 22 | 23 | parser = argparse.ArgumentParser() 24 | parser.add_argument('--dataroot', required=True, help='path to dataset') 25 | parser.add_argument('--netG', required=True, help="path to netG (to continue training)") 26 | parser.add_argument('--workers', type=int, help='number of data loading workers', default=2) 27 | parser.add_argument('--cuda', action='store_true', help='enables cuda') 28 | parser.add_argument('--nn_dgf', action='store_true', help='enables dgf') 29 | parser.add_argument('--nn_dgf_r', type=int, default=8, help='dgf radius') 30 | parser.add_argument('--nn_dgf_eps', type=float, default=1e-2, help='dgf eps') 31 | parser.add_argument('--post_sigmoid', action='store_true', help='sigmoid after dgf') 32 | parser.add_argument('--dgf', action='store_true', help='enables dgf') 33 | parser.add_argument('--dgf_r', type=int, default=8, help='dgf radius') 34 | parser.add_argument('--dgf_eps', type=float, default=1e-2, help='dgf eps') 35 | parser.add_argument('--experiment', default='results', help='Where to store samples and models') 36 | opt = parser.parse_args() 37 | print(opt) 38 | 39 | if not os.path.isdir(opt.experiment): 40 | os.makedirs(opt.experiment) 41 | 42 | cudnn.benchmark = True 43 | 44 | normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], 45 | std=[0.229, 0.224, 0.225]) 46 | dataset = dset.ImageFolder(root=opt.dataroot, 47 | transform=transforms.Compose([ 48 | transforms.ToTensor()])) 49 | dataloader = torch.utils.data.DataLoader(dataset, batch_size=1, 50 | shuffle=False, num_workers=int(opt.workers)) 51 | 52 | netG = dss.network_dss(3, opt.nn_dgf, opt.nn_dgf_r, opt.nn_dgf_eps, opt.post_sigmoid) 53 | netG.load_state_dict(torch.load(opt.netG)) 54 | if opt.dgf: 55 | dgf = GuidedFilter(opt.dgf_r, opt.dgf_eps) 56 | real_A = torch.FloatTensor() 57 | real_x = torch.FloatTensor() 58 | real_B = torch.FloatTensor() 59 | if opt.cuda: 60 | netG = netG.cuda() 61 | if opt.dgf: 62 | dgf = dgf.cuda() 63 | 64 | test_list = [] 65 | for idx, (data, _) in enumerate(iter(dataloader)): 66 | print(idx) 67 | 68 | w = data.size(3) // 2 69 | h = data.size(2) 70 | real_B.resize_(h, w).copy_(data[0, 0, :, w:]) 71 | real_A.resize_(3, h, w).copy_(data[0, :3, :, 0:w]) 72 | real_A = normalize(real_A) 73 | real_A.unsqueeze_(0) 74 | 75 | real_x.resize_(1, 3, h, w).copy_(data[:1, :3, :, 0:w]) 76 | 77 | input_G = Variable(real_A) 78 | input_x = Variable(real_x) 79 | if opt.cuda: 80 | input_G = input_G.cuda() 81 | input_x = input_x.cuda() 82 | 83 | with torch.no_grad(): 84 | fake_B, side_out1, side_out2, side_out3, side_out4, side_out5, side_out6 = netG(input_G, input_x) 85 | 86 | if opt.dgf: 87 | input_x = input_x.sum(1, keepdim=True) 88 | image_B = dgf(input_x, fake_B).clamp(0, 1) 89 | else: 90 | image_B = fake_B 91 | image_B = image_B.data.cpu() 92 | 93 | imsave(os.path.join(opt.experiment, '{}_sal.png'.format(idx)), image_B.mul(255).numpy().squeeze().astype(np.uint8)) 94 | imsave(os.path.join(opt.experiment, '{}.png'.format(idx)), real_B.mul(255).cpu().numpy().squeeze().astype(np.uint8)) 95 | 96 | test_list.append('{}_sal.png {}.png'.format(idx, idx)) 97 | 98 | with open(os.path.join(opt.experiment, 'test.txt'), 'w') as f: 99 | f.write('\n'.join(test_list)) 100 | -------------------------------------------------------------------------------- /GuidedFilteringLayer/GuidedFilter_PyTorch/README.md: -------------------------------------------------------------------------------- 1 | # Fast End-to-End Trainable Guided Filter 2 | [[Project]](http://wuhuikai.me/DeepGuidedFilterProject) [[Paper]](http://wuhuikai.me/DeepGuidedFilterProject/deep_guided_filter.pdf) [[arXiv]](https://arxiv.org/abs/1803.05619) [[Demo]](http://wuhuikai.me/DeepGuidedFilterProject#demo) [[Home]](http://wuhuikai.me) 3 | 4 | Official implementation of **Fast End-to-End Trainable Guided Filter**. 5 | **Faster**, **Better** and **Lighter** for pixel-wise image prediction. 6 | 7 | ## Paper 8 | **Fast End-to-End Trainable Guided Filter** 9 | Huikai Wu, Shuai Zheng, Junge Zhang, Kaiqi Huang 10 | CVPR 2018 11 | 12 | ## Install 13 | ``` 14 | pip install guided-filter-pytorch 15 | ``` 16 | ## Usage 17 | ``` 18 | from guided_filter_pytorch.guided_filter import FastGuidedFilter 19 | 20 | hr_y = FastGuidedFilter(r, eps)(lr_x, lr_y, hr_x) 21 | ``` 22 | ``` 23 | from guided_filter_pytorch.guided_filter import GuidedFilter 24 | 25 | hr_y = GuidedFilter(r, eps)(hr_x, init_hr_y) 26 | ``` 27 | ``` 28 | from guided_filter_pytorch.guided_filter import ConvGuidedFilter 29 | 30 | hr_y = ConvGuidedFilter(r, norm)(lr_x, lr_y, hr_x) 31 | ``` 32 | ## Citation 33 | ``` 34 | @inproceedings{wu2017fast, 35 | title = {Fast End-to-End Trainable Guided Filter}, 36 | author = {Wu, Huikai and Zheng, Shuai and Zhang, Junge and Huang, Kaiqi}, 37 | booktitle = {CVPR}, 38 | year = {2018} 39 | } 40 | ``` -------------------------------------------------------------------------------- /GuidedFilteringLayer/GuidedFilter_PyTorch/clean.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | pip uninstall guided_filter_pytorch 4 | rm -rf guided_filter_pytorch.egg-info/ 5 | -------------------------------------------------------------------------------- /GuidedFilteringLayer/GuidedFilter_PyTorch/guided_filter_pytorch/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/GuidedFilteringLayer/GuidedFilter_PyTorch/guided_filter_pytorch/__init__.py -------------------------------------------------------------------------------- /GuidedFilteringLayer/GuidedFilter_PyTorch/guided_filter_pytorch/box_filter.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | 4 | def diff_x(input, r): 5 | assert input.dim() == 4 6 | 7 | left = input[:, :, r:2 * r + 1] 8 | middle = input[:, :, 2 * r + 1: ] - input[:, :, :-2 * r - 1] 9 | right = input[:, :, -1: ] - input[:, :, -2 * r - 1: -r - 1] 10 | 11 | output = torch.cat([left, middle, right], dim=2) 12 | 13 | return output 14 | 15 | def diff_y(input, r): 16 | assert input.dim() == 4 17 | 18 | left = input[:, :, :, r:2 * r + 1] 19 | middle = input[:, :, :, 2 * r + 1: ] - input[:, :, :, :-2 * r - 1] 20 | right = input[:, :, :, -1: ] - input[:, :, :, -2 * r - 1: -r - 1] 21 | 22 | output = torch.cat([left, middle, right], dim=3) 23 | 24 | return output 25 | 26 | class BoxFilter(nn.Module): 27 | def __init__(self, r): 28 | super(BoxFilter, self).__init__() 29 | 30 | self.r = r 31 | 32 | def forward(self, x): 33 | assert x.dim() == 4 34 | 35 | return diff_y(diff_x(x.cumsum(dim=2), self.r).cumsum(dim=3), self.r) -------------------------------------------------------------------------------- /GuidedFilteringLayer/GuidedFilter_PyTorch/guided_filter_pytorch/guided_filter.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from torch.nn import functional as F 4 | from torch.autograd import Variable 5 | 6 | from .box_filter import BoxFilter 7 | 8 | class FastGuidedFilter(nn.Module): 9 | def __init__(self, r, eps=1e-8): 10 | super(FastGuidedFilter, self).__init__() 11 | 12 | self.r = r 13 | self.eps = eps 14 | self.boxfilter = BoxFilter(r) 15 | 16 | 17 | def forward(self, lr_x, lr_y, hr_x): 18 | n_lrx, c_lrx, h_lrx, w_lrx = lr_x.size() 19 | n_lry, c_lry, h_lry, w_lry = lr_y.size() 20 | n_hrx, c_hrx, h_hrx, w_hrx = hr_x.size() 21 | 22 | assert n_lrx == n_lry and n_lry == n_hrx 23 | assert c_lrx == c_hrx and (c_lrx == 1 or c_lrx == c_lry) 24 | assert h_lrx == h_lry and w_lrx == w_lry 25 | assert h_lrx > 2*self.r+1 and w_lrx > 2*self.r+1 26 | 27 | ## N 28 | N = self.boxfilter(Variable(lr_x.data.new().resize_((1, 1, h_lrx, w_lrx)).fill_(1.0))) 29 | 30 | ## mean_x 31 | mean_x = self.boxfilter(lr_x) / N 32 | ## mean_y 33 | mean_y = self.boxfilter(lr_y) / N 34 | ## cov_xy 35 | cov_xy = self.boxfilter(lr_x * lr_y) / N - mean_x * mean_y 36 | ## var_x 37 | var_x = self.boxfilter(lr_x * lr_x) / N - mean_x * mean_x 38 | 39 | ## A 40 | A = cov_xy / (var_x + self.eps) 41 | ## b 42 | b = mean_y - A * mean_x 43 | 44 | ## mean_A; mean_b 45 | mean_A = F.interpolate(A, (h_hrx, w_hrx), mode='bilinear', align_corners=True) 46 | mean_b = F.interpolate(b, (h_hrx, w_hrx), mode='bilinear', align_corners=True) 47 | 48 | return mean_A*hr_x+mean_b 49 | 50 | 51 | class GuidedFilter(nn.Module): 52 | def __init__(self, r, eps=1e-8): 53 | super(GuidedFilter, self).__init__() 54 | 55 | self.r = r 56 | self.eps = eps 57 | self.boxfilter = BoxFilter(r) 58 | 59 | 60 | def forward(self, x, y): 61 | n_x, c_x, h_x, w_x = x.size() 62 | n_y, c_y, h_y, w_y = y.size() 63 | 64 | assert n_x == n_y 65 | assert c_x == 1 or c_x == c_y 66 | assert h_x == h_y and w_x == w_y 67 | assert h_x > 2 * self.r + 1 and w_x > 2 * self.r + 1 68 | 69 | # N 70 | N = self.boxfilter(Variable(x.data.new().resize_((1, 1, h_x, w_x)).fill_(1.0))) 71 | 72 | # mean_x 73 | mean_x = self.boxfilter(x) / N 74 | # mean_y 75 | mean_y = self.boxfilter(y) / N 76 | # cov_xy 77 | cov_xy = self.boxfilter(x * y) / N - mean_x * mean_y 78 | # var_x 79 | var_x = self.boxfilter(x * x) / N - mean_x * mean_x 80 | 81 | # A 82 | A = cov_xy / (var_x + self.eps) 83 | # b 84 | b = mean_y - A * mean_x 85 | 86 | # mean_A; mean_b 87 | mean_A = self.boxfilter(A) / N 88 | mean_b = self.boxfilter(b) / N 89 | 90 | return mean_A * x + mean_b 91 | 92 | class ConvGuidedFilter(nn.Module): 93 | def __init__(self, radius=1, norm=nn.BatchNorm2d): 94 | super(ConvGuidedFilter, self).__init__() 95 | 96 | self.box_filter = nn.Conv2d(3, 3, kernel_size=3, padding=radius, dilation=radius, bias=False, groups=3) 97 | self.conv_a = nn.Sequential(nn.Conv2d(6, 32, kernel_size=1, bias=False), 98 | norm(32), 99 | nn.ReLU(inplace=True), 100 | nn.Conv2d(32, 32, kernel_size=1, bias=False), 101 | norm(32), 102 | nn.ReLU(inplace=True), 103 | nn.Conv2d(32, 3, kernel_size=1, bias=False)) 104 | self.box_filter.weight.data[...] = 1.0 105 | 106 | def forward(self, x_lr, y_lr, x_hr): 107 | _, _, h_lrx, w_lrx = x_lr.size() 108 | _, _, h_hrx, w_hrx = x_hr.size() 109 | 110 | N = self.box_filter(x_lr.data.new().resize_((1, 3, h_lrx, w_lrx)).fill_(1.0)) 111 | ## mean_x 112 | mean_x = self.box_filter(x_lr)/N 113 | ## mean_y 114 | mean_y = self.box_filter(y_lr)/N 115 | ## cov_xy 116 | cov_xy = self.box_filter(x_lr * y_lr)/N - mean_x * mean_y 117 | ## var_x 118 | var_x = self.box_filter(x_lr * x_lr)/N - mean_x * mean_x 119 | 120 | ## A 121 | A = self.conv_a(torch.cat([cov_xy, var_x], dim=1)) 122 | ## b 123 | b = mean_y - A * mean_x 124 | 125 | ## mean_A; mean_b 126 | mean_A = F.interpolate(A, (h_hrx, w_hrx), mode='bilinear', align_corners=True) 127 | mean_b = F.interpolate(b, (h_hrx, w_hrx), mode='bilinear', align_corners=True) 128 | 129 | return mean_A * x_hr + mean_b 130 | -------------------------------------------------------------------------------- /GuidedFilteringLayer/GuidedFilter_PyTorch/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from setuptools import setup, find_packages 3 | 4 | try: 5 | import pypandoc 6 | long_description = pypandoc.convert('README.md', 'rst') 7 | long_description = long_description.replace("\r", "") 8 | except (IOError, ImportError): 9 | long_description = '' 10 | 11 | setup( 12 | name="guided_filter_pytorch", 13 | version="3.7.5", 14 | description="Deep Guided Filtering Layer for PyTorch", 15 | long_description=long_description, 16 | url="https://github.com/wuhuikai/DeepGuidedFilter", 17 | author="wuhuikai", 18 | author_email="huikaiwu@icloud.com", 19 | # Exclude the build files. 20 | packages=find_packages(exclude=["test"]), 21 | zip_safe=True 22 | ) -------------------------------------------------------------------------------- /GuidedFilteringLayer/GuidedFilter_PyTorch/test/gt.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/GuidedFilteringLayer/GuidedFilter_PyTorch/test/gt.jpg -------------------------------------------------------------------------------- /GuidedFilteringLayer/GuidedFilter_PyTorch/test/r.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/GuidedFilteringLayer/GuidedFilter_PyTorch/test/r.jpg -------------------------------------------------------------------------------- /GuidedFilteringLayer/GuidedFilter_PyTorch/test/r_fast.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/GuidedFilteringLayer/GuidedFilter_PyTorch/test/r_fast.jpg -------------------------------------------------------------------------------- /GuidedFilteringLayer/GuidedFilter_PyTorch/test/rgb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/GuidedFilteringLayer/GuidedFilter_PyTorch/test/rgb.jpg -------------------------------------------------------------------------------- /GuidedFilteringLayer/GuidedFilter_PyTorch/test/test_box_filter.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | import torch 4 | import numpy as np 5 | 6 | from skimage import img_as_float 7 | from skimage.io import imread 8 | 9 | from torch.autograd import gradcheck, Variable 10 | 11 | from guided_filter_pytorch.box_filter import BoxFilter 12 | 13 | ## BoxFilter 14 | print('BoxFilter:') 15 | # check forward 16 | y = BoxFilter(3)(Variable(torch.from_numpy(np.reshape(np.arange(1, 73), (1, 1, 8, 9))).cuda())).data.cpu().numpy() 17 | assert np.isclose(y.mean(), 1137.6, 0.1) 18 | assert np.isclose(y.std(), 475.2, 0.1) 19 | print('\tForward passed') 20 | # forward on img 21 | im = Variable(torch.from_numpy(np.transpose(img_as_float(imread('test/rgb.jpg')), (2, 0, 1))[None]).float().cuda()) 22 | start_time = time.time() 23 | r = BoxFilter(64)(im) 24 | end_time = time.time() 25 | print('\tForward on img ...') 26 | print('\t\tTime: {}'.format(end_time-start_time)) 27 | 28 | r = r.data.cpu().numpy().squeeze().transpose(1, 2, 0) 29 | assert np.isclose(r[:,:,0].mean(), 10305.0, 0.1) 30 | assert np.isclose(r[:,:,0].std(), 2206.4, 0.1) 31 | assert np.isclose(r[:,:,1].mean(), 7536.0, 0.1) 32 | assert np.isclose(r[:,:,1].std(), 2117.0, 0.1) 33 | assert np.isclose(r[:,:,2].mean(), 6203.0, 0.1) 34 | assert np.isclose(r[:,:,2].std(), 2772.3, 0.1) 35 | print('\tPassed ...') 36 | 37 | # backward | check grad 38 | test = gradcheck(BoxFilter(3), (Variable(torch.rand((3, 5, 8, 9)).double().cuda(), requires_grad=True), ), eps=1e-6, atol=1e-4) 39 | print('\tGrad Check Result:', test) -------------------------------------------------------------------------------- /GuidedFilteringLayer/GuidedFilter_PyTorch/test/test_fast_guided_filter.py: -------------------------------------------------------------------------------- 1 | import time 2 | import random 3 | 4 | import torch 5 | import numpy as np 6 | 7 | from skimage import img_as_float 8 | from skimage.io import imread, imsave 9 | from skimage.transform import resize 10 | 11 | from torch.autograd import gradcheck, Variable 12 | 13 | from guided_filter_pytorch.guided_filter import FastGuidedFilter 14 | 15 | ## GuidedFilter 16 | print('FastGuidedFilter:') 17 | ## check forward 18 | # forward on img 19 | rgb = img_as_float(imread('test/rgb.jpg')) 20 | gt = img_as_float(imread('test/gt.jpg')) 21 | x_w, x_h = rgb.shape[:2] 22 | w, h = x_w // 8, x_h // 8 23 | lr_rgb = resize(rgb, (w, h), order=0, mode='reflect') 24 | lr_gt = resize(gt, (w, h), order=0, mode='reflect') 25 | inputs = [Variable(torch.from_numpy(i.transpose((2, 0, 1))[None]).float().cuda()) for i in [lr_rgb, lr_gt, rgb]] 26 | f = FastGuidedFilter(8, 0).cuda() 27 | start_time = time.time() 28 | r = f(*inputs) 29 | end_time = time.time() 30 | print('\tForward on img ...') 31 | print('\t\tTime: {}'.format(end_time-start_time)) 32 | r = r.data.cpu().numpy().squeeze().transpose(1, 2, 0) 33 | r = np.asarray(r.clip(0, 1)*255, dtype=np.uint8) 34 | imsave('test/r_fast.jpg', r) 35 | 36 | # backward | check grad 37 | test = gradcheck(FastGuidedFilter(2, random.random()).double().cuda(), 38 | (Variable(torch.rand((2, 3, 6, 7)).double().cuda(), requires_grad=True), 39 | Variable(torch.rand((2, 3, 6, 7)).double().cuda(), requires_grad=True), 40 | Variable(torch.rand((2, 3, 11, 12)).double().cuda(), requires_grad=True)), eps=1e-6, atol=1e-4) 41 | print('\tGrad Check Result:', test) -------------------------------------------------------------------------------- /GuidedFilteringLayer/GuidedFilter_PyTorch/test/test_guided_filter.py: -------------------------------------------------------------------------------- 1 | import time 2 | import random 3 | 4 | import torch 5 | import numpy as np 6 | 7 | from skimage import img_as_float 8 | from skimage.io import imread, imsave 9 | from skimage.transform import resize 10 | 11 | from torch.autograd import gradcheck, Variable 12 | 13 | from guided_filter_pytorch.guided_filter import GuidedFilter 14 | 15 | ## GuidedFilter 16 | print('GuidedFilter:') 17 | ## check forward 18 | # forward on img 19 | rgb = img_as_float(imread('test/rgb.jpg')) 20 | gt = img_as_float(imread('test/gt.jpg')) 21 | inputs = [Variable(torch.from_numpy(i.transpose((2, 0, 1))[None]).float().cuda()) for i in [rgb, gt]] 22 | f = GuidedFilter(8, 0).cuda() 23 | start_time = time.time() 24 | r = f(*inputs) 25 | end_time = time.time() 26 | print('\tForward on img ...') 27 | print('\t\tTime: {}'.format(end_time-start_time)) 28 | r = r.data.cpu().numpy().squeeze().transpose(1, 2, 0) 29 | r = np.asarray(r.clip(0, 1)*255, dtype=np.uint8) 30 | imsave('test/r.jpg', r) 31 | 32 | # backward | check grad 33 | test = gradcheck(GuidedFilter(2, random.random()).double().cuda(), 34 | (Variable(torch.rand((2, 3, 6, 7)).double().cuda(), requires_grad=True), 35 | Variable(torch.rand((2, 3, 6, 7)).double().cuda(), requires_grad=True)), eps=1e-6, atol=1e-4) 36 | print('\tGrad Check Result:', test) -------------------------------------------------------------------------------- /GuidedFilteringLayer/GuidedFilter_TF/README.md: -------------------------------------------------------------------------------- 1 | # Fast End-to-End Trainable Guided Filter 2 | [[Project]](http://wuhuikai.me/DeepGuidedFilterProject) [[Paper]](http://wuhuikai.me/DeepGuidedFilterProject/deep_guided_filter.pdf) [[arXiv]](https://arxiv.org/abs/1803.05619) [[Demo]](http://wuhuikai.me/DeepGuidedFilterProject#demo) [[Home]](http://wuhuikai.me) 3 | 4 | Official implementation of **Fast End-to-End Trainable Guided Filter**. 5 | **Faster**, **Better** and **Lighter** for image processing and dense prediction. 6 | 7 | ## Paper 8 | **Fast End-to-End Trainable Guided Filter** 9 | Huikai Wu, Shuai Zheng, Junge Zhang, Kaiqi Huang 10 | CVPR 2018 11 | 12 | ## Install 13 | ``` 14 | pip install guided-filter-tf 15 | ``` 16 | ## Usage 17 | ``` 18 | from guided_filter_tf.guided_filter import fast_guided_filter 19 | 20 | hr_y = fast_guided_filter(lr_x, lr_y, hr_x, r, eps, nhwc) 21 | ``` 22 | ``` 23 | from guided_filter_tf.guided_filter import guided_filter 24 | hr_y = guided_filter(hr_x, init_hr_y, r, eps, nhwc) 25 | ``` 26 | ## Citation 27 | ``` 28 | @inproceedings{wu2017fast, 29 | title = {Fast End-to-End Trainable Guided Filter}, 30 | author = {Wu, Huikai and Zheng, Shuai and Zhang, Junge and Huang, Kaiqi}, 31 | booktitle = {CVPR}, 32 | year = {2018} 33 | } 34 | ``` -------------------------------------------------------------------------------- /GuidedFilteringLayer/GuidedFilter_TF/clean.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | pip uninstall guided_filter_tf 4 | rm -rf guided_filter_tf.egg-info/ 5 | -------------------------------------------------------------------------------- /GuidedFilteringLayer/GuidedFilter_TF/guided_filter_tf/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/GuidedFilteringLayer/GuidedFilter_TF/guided_filter_tf/__init__.py -------------------------------------------------------------------------------- /GuidedFilteringLayer/GuidedFilter_TF/guided_filter_tf/box_filter.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | 3 | 4 | def diff_x(input, r): 5 | assert input.shape.ndims == 4 6 | 7 | left = input[:, :, r:2 * r + 1] 8 | middle = input[:, :, 2 * r + 1: ] - input[:, :, :-2 * r - 1] 9 | right = input[:, :, -1: ] - input[:, :, -2 * r - 1: -r - 1] 10 | 11 | output = tf.concat([left, middle, right], axis=2) 12 | 13 | return output 14 | 15 | 16 | def diff_y(input, r): 17 | assert input.shape.ndims == 4 18 | 19 | left = input[:, :, :, r:2 * r + 1] 20 | middle = input[:, :, :, 2 * r + 1: ] - input[:, :, :, :-2 * r - 1] 21 | right = input[:, :, :, -1: ] - input[:, :, :, -2 * r - 1: -r - 1] 22 | 23 | output = tf.concat([left, middle, right], axis=3) 24 | 25 | return output 26 | 27 | 28 | def box_filter(x, r): 29 | assert x.shape.ndims == 4 30 | 31 | return diff_y(tf.cumsum(diff_x(tf.cumsum(x, axis=2), r), axis=3), r) 32 | -------------------------------------------------------------------------------- /GuidedFilteringLayer/GuidedFilter_TF/guided_filter_tf/guided_filter.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | 3 | from .box_filter import box_filter 4 | 5 | 6 | def guided_filter(x, y, r, eps=1e-8, nhwc=False): 7 | assert x.shape.ndims == 4 and y.shape.ndims == 4 8 | 9 | # data format 10 | if nhwc: 11 | x = tf.transpose(x, [0, 3, 1, 2]) 12 | y = tf.transpose(y, [0, 3, 1, 2]) 13 | 14 | # shape check 15 | x_shape = tf.shape(x) 16 | y_shape = tf.shape(y) 17 | 18 | assets = [tf.assert_equal( x_shape[0], y_shape[0]), 19 | tf.assert_equal( x_shape[2:], y_shape[2:]), 20 | tf.assert_greater(x_shape[2:], 2 * r + 1), 21 | tf.Assert(tf.logical_or(tf.equal(x_shape[1], 1), 22 | tf.equal(x_shape[1], y_shape[1])), [x_shape, y_shape])] 23 | 24 | with tf.control_dependencies(assets): 25 | x = tf.identity(x) 26 | 27 | # N 28 | N = box_filter(tf.ones((1, 1, x_shape[2], x_shape[3]), dtype=x.dtype), r) 29 | 30 | # mean_x 31 | mean_x = box_filter(x, r) / N 32 | # mean_y 33 | mean_y = box_filter(y, r) / N 34 | # cov_xy 35 | cov_xy = box_filter(x * y, r) / N - mean_x * mean_y 36 | # var_x 37 | var_x = box_filter(x * x, r) / N - mean_x * mean_x 38 | 39 | # A 40 | A = cov_xy / (var_x + eps) 41 | # b 42 | b = mean_y - A * mean_x 43 | 44 | mean_A = box_filter(A, r) / N 45 | mean_b = box_filter(b, r) / N 46 | 47 | output = mean_A * x + mean_b 48 | 49 | if nhwc: 50 | output = tf.transpose(output, [0, 2, 3, 1]) 51 | 52 | return output 53 | 54 | 55 | def fast_guided_filter(lr_x, lr_y, hr_x, r, eps=1e-8, nhwc=False): 56 | assert lr_x.shape.ndims == 4 and lr_y.shape.ndims == 4 and hr_x.shape.ndims == 4 57 | 58 | # data format 59 | if nhwc: 60 | lr_x = tf.transpose(lr_x, [0, 3, 1, 2]) 61 | lr_y = tf.transpose(lr_y, [0, 3, 1, 2]) 62 | hr_x = tf.transpose(hr_x, [0, 3, 1, 2]) 63 | 64 | # shape check 65 | lr_x_shape = tf.shape(lr_x) 66 | lr_y_shape = tf.shape(lr_y) 67 | hr_x_shape = tf.shape(hr_x) 68 | 69 | assets = [tf.assert_equal( lr_x_shape[0], lr_y_shape[0]), 70 | tf.assert_equal( lr_x_shape[0], hr_x_shape[0]), 71 | tf.assert_equal( lr_x_shape[1], hr_x_shape[1]), 72 | tf.assert_equal( lr_x_shape[2:], lr_y_shape[2:]), 73 | tf.assert_greater(lr_x_shape[2:], 2 * r + 1), 74 | tf.Assert(tf.logical_or(tf.equal(lr_x_shape[1], 1), 75 | tf.equal(lr_x_shape[1], lr_y_shape[1])), [lr_x_shape, lr_y_shape])] 76 | 77 | with tf.control_dependencies(assets): 78 | lr_x = tf.identity(lr_x) 79 | 80 | # N 81 | N = box_filter(tf.ones((1, 1, lr_x_shape[2], lr_x_shape[3]), dtype=lr_x.dtype), r) 82 | 83 | # mean_x 84 | mean_x = box_filter(lr_x, r) / N 85 | # mean_y 86 | mean_y = box_filter(lr_y, r) / N 87 | # cov_xy 88 | cov_xy = box_filter(lr_x * lr_y, r) / N - mean_x * mean_y 89 | # var_x 90 | var_x = box_filter(lr_x * lr_x, r) / N - mean_x * mean_x 91 | 92 | # A 93 | A = cov_xy / (var_x + eps) 94 | # b 95 | b = mean_y - A * mean_x 96 | 97 | # mean_A; mean_b 98 | A = tf.transpose(A, [0, 2, 3, 1]) 99 | b = tf.transpose(b, [0, 2, 3, 1]) 100 | hr_x = tf.transpose(hr_x, [0, 2, 3, 1]) 101 | 102 | mean_A = tf.image.resize(A, hr_x_shape[2:]) 103 | mean_b = tf.image.resize(b, hr_x_shape[2:]) 104 | 105 | output = mean_A * hr_x + mean_b 106 | 107 | if not nhwc: 108 | output = tf.transpose(output, [0, 3, 1, 2]) 109 | 110 | return output 111 | -------------------------------------------------------------------------------- /GuidedFilteringLayer/GuidedFilter_TF/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from setuptools import setup, find_packages 3 | 4 | try: 5 | import pypandoc 6 | long_description = pypandoc.convert('README.md', 'rst') 7 | long_description = long_description.replace("\r", "") 8 | except (IOError, ImportError): 9 | long_description = '' 10 | 11 | setup( 12 | name="guided_filter_tf", 13 | version="1.1.1", 14 | description="Deep Guided Filtering Layer for TensorFlow", 15 | long_description=long_description, 16 | url="https://github.com/wuhuikai/DeepGuidedFilter", 17 | author="wuhuikai", 18 | author_email="huikaiwu@icloud.com", 19 | # Exclude the build files. 20 | packages=find_packages(exclude=["test"]), 21 | zip_safe=True 22 | ) -------------------------------------------------------------------------------- /GuidedFilteringLayer/GuidedFilter_TF/test/gt.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/GuidedFilteringLayer/GuidedFilter_TF/test/gt.jpg -------------------------------------------------------------------------------- /GuidedFilteringLayer/GuidedFilter_TF/test/r.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/GuidedFilteringLayer/GuidedFilter_TF/test/r.jpg -------------------------------------------------------------------------------- /GuidedFilteringLayer/GuidedFilter_TF/test/r_fast.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/GuidedFilteringLayer/GuidedFilter_TF/test/r_fast.jpg -------------------------------------------------------------------------------- /GuidedFilteringLayer/GuidedFilter_TF/test/rgb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/GuidedFilteringLayer/GuidedFilter_TF/test/rgb.jpg -------------------------------------------------------------------------------- /GuidedFilteringLayer/GuidedFilter_TF/test/test_box_filter.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | import numpy as np 4 | import tensorflow as tf 5 | 6 | from skimage import img_as_float 7 | from skimage.io import imread 8 | 9 | from guided_filter_tf.box_filter import box_filter 10 | 11 | ## BoxFilter 12 | print('BoxFilter:') 13 | # check forward 14 | input = tf.constant(np.reshape(np.arange(1, 73), (1, 1, 8, 9))) 15 | output = box_filter(input, 3) 16 | 17 | with tf.Session() as sess: 18 | y = sess.run(output) 19 | 20 | assert np.isclose(y.mean(), 1137.6, 0.1) 21 | assert np.isclose(y.std(), 475.2, 0.1) 22 | print('\tForward passed') 23 | # forward on img 24 | im = tf.constant(np.transpose(img_as_float(imread('test/rgb.jpg')), (2, 0, 1))[None]) 25 | output = box_filter(im, 64) 26 | with tf.Session() as sess: 27 | start_time = time.time() 28 | r = sess.run(output) 29 | end_time = time.time() 30 | 31 | print('\tForward on img ...') 32 | print('\t\tTime: {}'.format(end_time - start_time)) 33 | r = r.squeeze().transpose(1, 2, 0) 34 | assert np.isclose(r[:, :, 0].mean(), 10305.0, 0.1) 35 | assert np.isclose(r[:, :, 0].std(), 2206.4, 0.1) 36 | assert np.isclose(r[:, :, 1].mean(), 7536.0, 0.1) 37 | assert np.isclose(r[:, :, 1].std(), 2117.0, 0.1) 38 | assert np.isclose(r[:, :, 2].mean(), 6203.0, 0.1) 39 | assert np.isclose(r[:, :, 2].std(), 2772.3, 0.1) 40 | print('\tPassed ...') 41 | -------------------------------------------------------------------------------- /GuidedFilteringLayer/GuidedFilter_TF/test/test_fast_guided_filter.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | import numpy as np 4 | import tensorflow as tf 5 | 6 | from skimage import img_as_float 7 | from skimage.io import imread, imsave 8 | from skimage.transform import resize 9 | 10 | from guided_filter_tf.guided_filter import fast_guided_filter 11 | 12 | ## GuidedFilter 13 | print('FastGuidedFilter:') 14 | ## check forward 15 | # forward on img 16 | rgb = img_as_float(imread('test/rgb.jpg')) 17 | gt = img_as_float(imread('test/gt.jpg')) 18 | x_w, x_h = rgb.shape[:2] 19 | w, h = x_w // 8, x_h // 8 20 | lr_rgb = resize(rgb, (w, h), order=0, mode='reflect') 21 | lr_gt = resize(gt, (w, h), order=0, mode='reflect') 22 | lr_x, lr_y, hr_x = [tf.constant(i.transpose((2, 0, 1))[None], dtype=tf.float32) for i in [lr_rgb, lr_gt, gt]] 23 | output = fast_guided_filter(lr_x, lr_y, hr_x, 8, 0) 24 | 25 | with tf.Session() as sess: 26 | start_time = time.time() 27 | r = sess.run(output) 28 | end_time = time.time() 29 | print('\tForward on img ...') 30 | print('\t\tTime: {}'.format(end_time - start_time)) 31 | 32 | r = r.squeeze().transpose(1, 2, 0) 33 | r = np.asarray(r.clip(0, 1) * 255, dtype=np.uint8) 34 | imsave('test/r_fast.jpg', r) -------------------------------------------------------------------------------- /GuidedFilteringLayer/GuidedFilter_TF/test/test_guided_filter.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | import numpy as np 4 | import tensorflow as tf 5 | 6 | from skimage import img_as_float 7 | from skimage.io import imread, imsave 8 | 9 | from guided_filter_tf.guided_filter import guided_filter 10 | 11 | ## GuidedFilter 12 | print('GuidedFilter:') 13 | ## check forward 14 | # forward on img 15 | rgb = img_as_float(imread('test/rgb.jpg')) 16 | gt = img_as_float(imread('test/gt.jpg')) 17 | x, y = [tf.constant(i.transpose((2, 0, 1))[None]) for i in [rgb, gt]] 18 | output = guided_filter(x, y, 64, 0) 19 | 20 | with tf.Session() as sess: 21 | start_time = time.time() 22 | r = sess.run(output) 23 | end_time = time.time() 24 | print('\tForward on img ...') 25 | print('\t\tTime: {}'.format(end_time - start_time)) 26 | 27 | r = r.squeeze().transpose(1, 2, 0) 28 | r = np.asarray(r.clip(0, 1) * 255, dtype=np.uint8) 29 | imsave('test/r.jpg', r) -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/.gitignore: -------------------------------------------------------------------------------- 1 | # Training 2 | checkpoints/ 3 | tensorboard_logs/ 4 | tensorboard_stats/ 5 | 6 | # Test 7 | results/ 8 | time/ 9 | 10 | # Dataset 11 | dataset 12 | 13 | # Training/Test list 14 | train_test_list 15 | -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/README.md: -------------------------------------------------------------------------------- 1 | # DGF for Image Processing 2 | ## Prepare Dataset 3 | 1. Download MIT-Adobe FiveK [Dataset](https://data.csail.mit.edu/graphics/fivek/fivek_dataset.tar). 4 | ```sh 5 | dataset 6 | ├── ...... 7 | └── fivek 8 | ├── ...... 9 | └── raw_photos 10 | ├── HQa1to700 11 | │ └── photos 12 | │ ├── a0001-jmac_DSC1459.dng 13 | │ └── ...... 14 | └── ...... 15 | ``` 16 | 2. Convert from ***.dng** to ***.tif**. 17 | ```sh 18 | cd scripts 19 | python convert_dng_to_tif.py 20 | ``` 21 | 3. Generate Training/Test set with different resolution. 22 | ```sh 23 | cd scripts 24 | 25 | python precompute_size.py --min 512 26 | python precompute_size.py --min 1024 27 | python precompute_size.py --random 28 | 29 | python resize_image.py --file_name 512 30 | python resize_image.py --file_name 1024 31 | python resize_image.py --file_name random 32 | ``` 33 | 4. Generate Ground Truth for each task. 34 | * L0 smoothing / Multi-scale detail manipulation / Style transfer / Non-local dehazing 35 | ```sh 36 | cd scripts/[l0_smooth|multi_scale_detail_manipulation|style_transfer|non_local_dehazing] 37 | 38 | matlab -r "prepare_dataset( '512'); exit" -nodisplay 39 | matlab -r "prepare_dataset( '1024'); exit" -nodisplay 40 | matlab -r "prepare_dataset('random'); exit" -nodisplay 41 | ``` 42 | * Image retouching (Auto-PS, Auto Beautification) 43 | 1. Generate / Download Ground Truth 44 | ```sh 45 | dataset 46 | ├── ...... 47 | └── fivek 48 | ├── ...... 49 | └── gts 50 | ├── a0001-jmac_DSC1459.tif 51 | └── ...... 52 | ``` 53 | * **Option 1**: Generate ground truth with Adobe Lightroom by following the [instruction](https://data.csail.mit.edu/graphics/fivek/). 54 | * **Option 2 (Preferred)**: Download from the website. 55 | ```sh 56 | cd scripts/auto_ps 57 | 58 | # Expert [A|B|C|D|E] 59 | bash generate_list.sh [a|b|c|d|e] 60 | 61 | cd ../../dataset/fivek && mkdir gts && cd gts 62 | # Option 1: single thread 63 | wget -i ../../../scripts/auto_ps/img_list_[a|b|c|d|e].csv 64 | # Option 2: multi thread 65 | sudo apt-get install aria2 66 | aria2c -j 100 -i ../../../scripts/auto_ps/img_list_[a|b|c|d|e].csv 67 | ``` 68 | 2. Postprocess 69 | ```sh 70 | cd scripts/auto_ps 71 | python postprocess.py 72 | 73 | cd .. 74 | python resize_image.py --file_name 512 --task auto_ps 75 | python resize_image.py --file_name 1024 --task auto_ps 76 | python resize_image.py --file_name random --task auto_ps 77 | ``` 78 | 5. Split Training/Test set 79 | ```sh 80 | cd scripts/training_test_split 81 | python split.py --set 512 \ 82 | --task [l0_smooth|multi_scale_detail_manipulation|style_transfer|non_local_dehazing|auto_ps] 83 | python split.py --set 1024 \ 84 | --task [l0_smooth|multi_scale_detail_manipulation|style_transfer|non_local_dehazing|auto_ps] 85 | python split.py --set random \ 86 | --task [l0_smooth|multi_scale_detail_manipulation|style_transfer|non_local_dehazing|auto_ps] 87 | ``` 88 | 89 | ## Training 90 | * Option 1: Train from scratch 91 | ```sh 92 | python train_hr.py --task [l0_smooth|multi_scale_detail_manipulation|style_transfer|non_local_dehazing|auto_ps] \ 93 | --name [HR|HR_AD|CONV_HR|CONV_HR_AD] \ 94 | --model [deep_guided_filter|deep_guided_filter_advanced|deep_conv_guided_filter|deep_conv_guided_filter_adv] 95 | ``` 96 | * Option 2: Train with low-resolution data + Finetune 97 | ```sh 98 | python train_lr.py --task [l0_smooth|multi_scale_detail_manipulation|style_transfer|non_local_dehazing|auto_ps] 99 | 100 | python train_hr_finetune.py --task [l0_smooth|multi_scale_detail_manipulation|style_transfer|non_local_dehazing|auto_ps] \ 101 | --name [HR_FT|HR_AD_FT|CONV_HR_FT|CONV_HR_AD_FT] \ 102 | --model [deep_guided_filter|deep_guided_filter_advanced|deep_conv_guided_filter|deep_conv_guided_filter_adv] 103 | ``` 104 | **NOTE**: 105 | * deep_guided_filter: **DGFb** 106 | * deep_guided_filter_advanced: **DGF** 107 | * deep_conv_guided_filter: **DGFbc** 108 | * deep_conv_guided_filter_adv: **DGFc** 109 | 110 | ## Evaluate 111 | ```sh 112 | python test_hr.py --task [l0_smooth|multi_scale_detail_manipulation|style_transfer|non_local_dehazing|auto_ps] \ 113 | --name [LR|HR|HR_AD|CONV_HR|CONV_HR_AD|HR_FT|HR_AD_FT|CONV_HR_FT|CONV_HR_AD_FT] \ 114 | --model [guided_filter|deep_guided_filter|deep_guided_filter_advanced|deep_conv_guided_filter|deep_conv_guided_filter_adv] 115 | ``` 116 | **NOTE**: 117 | * guided_filter: **DGFs** 118 | * deep_guided_filter: **DGFb** 119 | * deep_guided_filter_advanced: **DGF** 120 | * deep_conv_guided_filter: **DGFbc** 121 | * deep_conv_guided_filter_adv: **DGFc** 122 | 123 | ## Running Time 124 | ```sh 125 | python test_time.py --model_id [0|1|2|3|4|5] 126 | ``` 127 | **NOTE**: 128 | * 0: **DGFb** 129 | * 1: GuidedFilteringLayer 130 | * 2: **DGF** 131 | * 3: ConvGuidedFilteringLayer 132 | * 4: **DGFbc** 133 | * 5: **DGFc** 134 | 135 | ## Predict 136 | ```sh 137 | python predict.py --task [l0_smooth|multi_scale_detail_manipulation|style_transfer|non_local_dehazing|auto_ps] \ 138 | [--img_path IMG_PATH | --img_list IMG_LIST] \ 139 | --save_folder SAVE_FOLDER \ 140 | --model [guided_filter|deep_guided_filter|deep_guided_filter_advanced|deep_conv_guided_filter|deep_conv_guided_filter_adv] \ 141 | --low_size 64 \ 142 | --gpu 0 \ 143 | [--gray] 144 | ``` 145 | **NOTE**: 146 | * --model 147 | * guided_filter: **DGFs** 148 | * deep_guided_filter: **DGFb** 149 | * deep_guided_filter_advanced: **DGF** 150 | * deep_conv_guided_filter: **DGFbc** 151 | * deep_conv_guided_filter_adv: **DGFc** 152 | * --gray: It's better to generate gray images for style transfer. 153 | 154 | ## Acknowledgement 155 | A part of the code was adapted from [FastImageProcessing](https://github.com/CQFIO/FastImageProcessing). -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/dataset.py: -------------------------------------------------------------------------------- 1 | import os 2 | import random 3 | 4 | from PIL import Image 5 | 6 | import torch.utils.data as data 7 | from torchvision import transforms 8 | 9 | 10 | def default_loader(path): 11 | return Image.open(path).convert('RGB') 12 | 13 | class Transforms(object): 14 | def __init__(self, transformer): 15 | self.transformer = transformer 16 | 17 | def __call__(self, imgs): 18 | return [self.transformer(img) for img in imgs] 19 | 20 | class RandomTransforms(object): 21 | def __init__(self, transformer): 22 | self.transformer = transformer 23 | 24 | def __call__(self, imgs): 25 | if random.random() < 0.5: 26 | return imgs 27 | 28 | return [self.transformer(img) for img in imgs] 29 | 30 | class RandomCrop(object): 31 | def __init__(self, size): 32 | self.size = size 33 | 34 | def __call__(self, imgs): 35 | w, h = imgs[0].size 36 | if w == self.size and h == self.size: 37 | return imgs 38 | 39 | x1 = random.randint(0, w - self.size) 40 | y1 = random.randint(0, h - self.size) 41 | 42 | return [img.crop(x1, y1, x1+self.size, y1+self.size) for img in imgs] 43 | 44 | class RandomRotate(object): 45 | def __call__(self, imgs): 46 | angle = random.randrange(4) 47 | if angle == 0: 48 | return imgs 49 | 50 | return [im.rotate(90*angle) for im in imgs] 51 | 52 | class Compose(object): 53 | def __init__(self, transforms): 54 | self.transforms = [t for t in transforms if t is not None] 55 | 56 | def __call__(self, imgs): 57 | for t in self.transforms: 58 | imgs = t(imgs) 59 | return imgs 60 | 61 | class SuDataset(data.Dataset): 62 | def __init__(self, root, list_path, low_size=64, fine_size=-1, loader=default_loader): 63 | super(SuDataset, self).__init__() 64 | 65 | with open(list_path) as f: 66 | imgs = sorted([line.strip().split(',') for line in f]) 67 | imgs = [[os.path.join(root, p) for p in group] for group in imgs] 68 | 69 | self.imgs = imgs 70 | self.loader = loader 71 | 72 | def append(imgs): 73 | imgs.append(transforms.Scale(low_size, interpolation=Image.NEAREST)(imgs[0])) 74 | imgs.append(transforms.Scale(low_size, interpolation=Image.NEAREST)(imgs[1])) 75 | return imgs 76 | 77 | self.transform = Compose([ 78 | RandomCrop(fine_size) if fine_size > 0 else None, 79 | transforms.Lambda(append), 80 | Transforms(transforms.ToTensor()) 81 | ]) 82 | 83 | def get_path(self, idx): 84 | return self.imgs[idx][0] 85 | 86 | def __getitem__(self, index): 87 | # input_img, gt_img 88 | imgs = [self.loader(path) for path in self.imgs[index]] 89 | 90 | # input_img, gt_img, low_res_input_img, low_res_gt_img 91 | if self.transform is not None: 92 | imgs = self.transform(imgs) 93 | 94 | return imgs 95 | 96 | def __len__(self): 97 | return len(self.imgs) 98 | 99 | class PreSuDataset(data.Dataset): 100 | def __init__(self, img_list, low_size=64, loader=default_loader): 101 | super(PreSuDataset, self).__init__() 102 | 103 | self.imgs = list(img_list) 104 | self.loader = loader 105 | 106 | def append(imgs): 107 | imgs.append(transforms.Scale(low_size, interpolation=Image.NEAREST)(imgs[0])) 108 | return imgs 109 | 110 | self.transform = Compose([ 111 | transforms.Lambda(append), 112 | Transforms(transforms.ToTensor()) 113 | ]) 114 | 115 | def get_path(self, idx): 116 | return self.imgs[idx] 117 | 118 | def __getitem__(self, index): 119 | # input_img 120 | imgs = [self.loader(self.imgs[index])] 121 | 122 | # input_img, low_res_input_img 123 | if self.transform is not None: 124 | imgs = self.transform(imgs) 125 | 126 | return imgs 127 | 128 | def __len__(self): 129 | return len(self.imgs) -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/models/auto_ps/conv_hr_ad_net_latest.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/ImageProcessing/DeepGuidedFilteringNetwork/models/auto_ps/conv_hr_ad_net_latest.pth -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/models/auto_ps/conv_hr_net_latest.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/ImageProcessing/DeepGuidedFilteringNetwork/models/auto_ps/conv_hr_net_latest.pth -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/models/auto_ps/hr_ad_net_latest.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/ImageProcessing/DeepGuidedFilteringNetwork/models/auto_ps/hr_ad_net_latest.pth -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/models/auto_ps/hr_net_latest.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/ImageProcessing/DeepGuidedFilteringNetwork/models/auto_ps/hr_net_latest.pth -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/models/auto_ps/lr_net_latest.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/ImageProcessing/DeepGuidedFilteringNetwork/models/auto_ps/lr_net_latest.pth -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/models/l0_smooth/conv_hr_ad_net_latest.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/ImageProcessing/DeepGuidedFilteringNetwork/models/l0_smooth/conv_hr_ad_net_latest.pth -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/models/l0_smooth/conv_hr_net_latest.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/ImageProcessing/DeepGuidedFilteringNetwork/models/l0_smooth/conv_hr_net_latest.pth -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/models/l0_smooth/hr_ad_net_latest.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/ImageProcessing/DeepGuidedFilteringNetwork/models/l0_smooth/hr_ad_net_latest.pth -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/models/l0_smooth/hr_net_latest.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/ImageProcessing/DeepGuidedFilteringNetwork/models/l0_smooth/hr_net_latest.pth -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/models/l0_smooth/lr_net_latest.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/ImageProcessing/DeepGuidedFilteringNetwork/models/l0_smooth/lr_net_latest.pth -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/models/multi_scale_detail_manipulation/conv_hr_ad_net_latest.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/ImageProcessing/DeepGuidedFilteringNetwork/models/multi_scale_detail_manipulation/conv_hr_ad_net_latest.pth -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/models/multi_scale_detail_manipulation/conv_hr_net_latest.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/ImageProcessing/DeepGuidedFilteringNetwork/models/multi_scale_detail_manipulation/conv_hr_net_latest.pth -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/models/multi_scale_detail_manipulation/hr_ad_net_latest.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/ImageProcessing/DeepGuidedFilteringNetwork/models/multi_scale_detail_manipulation/hr_ad_net_latest.pth -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/models/multi_scale_detail_manipulation/hr_net_latest.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/ImageProcessing/DeepGuidedFilteringNetwork/models/multi_scale_detail_manipulation/hr_net_latest.pth -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/models/multi_scale_detail_manipulation/lr_net_latest.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/ImageProcessing/DeepGuidedFilteringNetwork/models/multi_scale_detail_manipulation/lr_net_latest.pth -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/models/non_local_dehazing/conv_hr_ad_net_latest.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/ImageProcessing/DeepGuidedFilteringNetwork/models/non_local_dehazing/conv_hr_ad_net_latest.pth -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/models/non_local_dehazing/conv_hr_net_latest.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/ImageProcessing/DeepGuidedFilteringNetwork/models/non_local_dehazing/conv_hr_net_latest.pth -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/models/non_local_dehazing/hr_ad_net_latest.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/ImageProcessing/DeepGuidedFilteringNetwork/models/non_local_dehazing/hr_ad_net_latest.pth -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/models/non_local_dehazing/hr_net_latest.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/ImageProcessing/DeepGuidedFilteringNetwork/models/non_local_dehazing/hr_net_latest.pth -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/models/non_local_dehazing/lr_net_latest.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/ImageProcessing/DeepGuidedFilteringNetwork/models/non_local_dehazing/lr_net_latest.pth -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/models/style_transfer/conv_hr_ad_net_latest.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/ImageProcessing/DeepGuidedFilteringNetwork/models/style_transfer/conv_hr_ad_net_latest.pth -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/models/style_transfer/conv_hr_net_latest.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/ImageProcessing/DeepGuidedFilteringNetwork/models/style_transfer/conv_hr_net_latest.pth -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/models/style_transfer/hr_ad_net_latest.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/ImageProcessing/DeepGuidedFilteringNetwork/models/style_transfer/hr_ad_net_latest.pth -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/models/style_transfer/hr_net_latest.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/ImageProcessing/DeepGuidedFilteringNetwork/models/style_transfer/hr_net_latest.pth -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/models/style_transfer/lr_net_latest.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/ImageProcessing/DeepGuidedFilteringNetwork/models/style_transfer/lr_net_latest.pth -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/module.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | 4 | from torch.nn import init 5 | 6 | from guided_filter_pytorch.guided_filter import FastGuidedFilter, ConvGuidedFilter 7 | 8 | def weights_init_identity(m): 9 | classname = m.__class__.__name__ 10 | if classname.find('Conv') != -1: 11 | n_out, n_in, h, w = m.weight.data.size() 12 | # Last Layer 13 | if n_out < n_in: 14 | init.xavier_uniform_(m.weight.data) 15 | return 16 | 17 | # Except Last Layer 18 | m.weight.data.zero_() 19 | ch, cw = h // 2, w // 2 20 | for i in range(n_in): 21 | m.weight.data[i, i, ch, cw] = 1.0 22 | 23 | elif classname.find('BatchNorm2d') != -1: 24 | init.constant_(m.weight.data, 1.0) 25 | init.constant_(m.bias.data, 0.0) 26 | 27 | class AdaptiveNorm(nn.Module): 28 | def __init__(self, n): 29 | super(AdaptiveNorm, self).__init__() 30 | 31 | self.w_0 = nn.Parameter(torch.Tensor([1.0])) 32 | self.w_1 = nn.Parameter(torch.Tensor([0.0])) 33 | 34 | self.bn = nn.BatchNorm2d(n, momentum=0.999, eps=0.001) 35 | 36 | def forward(self, x): 37 | return self.w_0 * x + self.w_1 * self.bn(x) 38 | 39 | def build_lr_net(norm=AdaptiveNorm, layer=5): 40 | layers = [ 41 | nn.Conv2d(3, 24, kernel_size=3, stride=1, padding=1, dilation=1, bias=False), 42 | norm(24), 43 | nn.LeakyReLU(0.2, inplace=True), 44 | ] 45 | 46 | for l in range(1, layer): 47 | layers += [nn.Conv2d(24, 24, kernel_size=3, stride=1, padding=2**l, dilation=2**l, bias=False), 48 | norm(24), 49 | nn.LeakyReLU(0.2, inplace=True)] 50 | 51 | layers += [ 52 | nn.Conv2d(24, 24, kernel_size=3, stride=1, padding=1, dilation=1, bias=False), 53 | norm(24), 54 | nn.LeakyReLU(0.2, inplace=True), 55 | 56 | nn.Conv2d(24, 3, kernel_size=1, stride=1, padding=0, dilation=1) 57 | ] 58 | 59 | net = nn.Sequential(*layers) 60 | 61 | net.apply(weights_init_identity) 62 | 63 | return net 64 | 65 | class DeepGuidedFilter(nn.Module): 66 | def __init__(self, radius=1, eps=1e-8): 67 | super(DeepGuidedFilter, self).__init__() 68 | self.lr = build_lr_net() 69 | self.gf = FastGuidedFilter(radius, eps) 70 | 71 | def forward(self, x_lr, x_hr): 72 | return self.gf(x_lr, self.lr(x_lr), x_hr).clamp(0, 1) 73 | 74 | def init_lr(self, path): 75 | self.lr.load_state_dict(torch.load(path)) 76 | 77 | class DeepGuidedFilterAdvanced(DeepGuidedFilter): 78 | def __init__(self, radius=1, eps=1e-4): 79 | super(DeepGuidedFilterAdvanced, self).__init__(radius, eps) 80 | 81 | self.guided_map = nn.Sequential( 82 | nn.Conv2d(3, 15, 1, bias=False), 83 | AdaptiveNorm(15), 84 | nn.LeakyReLU(0.2, inplace=True), 85 | nn.Conv2d(15, 3, 1) 86 | ) 87 | self.guided_map.apply(weights_init_identity) 88 | 89 | def forward(self, x_lr, x_hr): 90 | return self.gf(self.guided_map(x_lr), self.lr(x_lr), self.guided_map(x_hr)) 91 | 92 | class DeepGuidedFilterConvGF(nn.Module): 93 | def __init__(self, radius=1, layer=5): 94 | super(DeepGuidedFilterConvGF, self).__init__() 95 | self.lr = build_lr_net(layer=layer) 96 | self.gf = ConvGuidedFilter(radius, norm=AdaptiveNorm) 97 | 98 | def forward(self, x_lr, x_hr): 99 | return self.gf(x_lr, self.lr(x_lr), x_hr).clamp(0, 1) 100 | 101 | def init_lr(self, path): 102 | self.lr.load_state_dict(torch.load(path)) 103 | 104 | class DeepGuidedFilterGuidedMapConvGF(DeepGuidedFilterConvGF): 105 | def __init__(self, radius=1, dilation=0, c=16, layer=5): 106 | super(DeepGuidedFilterGuidedMapConvGF, self).__init__(radius, layer) 107 | 108 | self.guided_map = nn.Sequential( 109 | nn.Conv2d(3, c, 1, bias=False) if dilation==0 else \ 110 | nn.Conv2d(3, c, 3, padding=dilation, dilation=dilation, bias=False), 111 | AdaptiveNorm(c), 112 | nn.LeakyReLU(0.2, inplace=True), 113 | nn.Conv2d(c, 3, 1) 114 | ) 115 | 116 | def forward(self, x_lr, x_hr): 117 | return self.gf(self.guided_map(x_lr), self.lr(x_lr), self.guided_map(x_hr)).clamp(0, 1) 118 | -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/predict.py: -------------------------------------------------------------------------------- 1 | import os 2 | import argparse 3 | 4 | import torch 5 | from torch.autograd import Variable 6 | 7 | from tqdm import tqdm 8 | 9 | from dataset import PreSuDataset 10 | from utils import tensor_to_img, calc_metric, Config 11 | from module import DeepGuidedFilter, DeepGuidedFilterAdvanced, DeepGuidedFilterConvGF, DeepGuidedFilterGuidedMapConvGF 12 | 13 | from skimage.io import imsave 14 | 15 | parser = argparse.ArgumentParser(description='Predict with Deep Guided Filtering Networks') 16 | parser.add_argument('--task', type=str, default='auto_ps', help='TASK') 17 | parser.add_argument('--img_path', type=str, default=None, help='IMG_PATH') 18 | parser.add_argument('--img_list', type=str, default=None, help='IMG_LIST') 19 | parser.add_argument('--save_folder', type=str, required=True, help='SAVE_FOLDER') 20 | parser.add_argument('--model', type=str, default='deep_guided_filter', help='model') 21 | 22 | parser.add_argument('--low_size', type=int, default=64, help='LOW_SIZE') 23 | parser.add_argument('--gpu', type=int, default=0, help='GPU') 24 | parser.add_argument('--gray', default=False, action='store_true', help='GPU') 25 | args = parser.parse_args() 26 | 27 | # Test Images 28 | img_list = [] 29 | if args.img_path is not None: 30 | img_list.append(args.img_path) 31 | if args.img_list is not None: 32 | with open(args.img_list) as f: 33 | for line in f: 34 | img_list.append(line.strip()) 35 | assert len(img_list) > 0 36 | 37 | # Save Folder 38 | if not os.path.isdir(args.save_folder): 39 | os.makedirs(args.save_folder) 40 | 41 | # Model 42 | if args.model in ['guided_filter', 'deep_guided_filter']: 43 | model = DeepGuidedFilter() 44 | elif args.model == 'deep_guided_filter_advanced': 45 | model = DeepGuidedFilterAdvanced() 46 | elif args.model == 'deep_conv_guided_filter': 47 | model = DeepGuidedFilterConvGF() 48 | elif args.model == 'deep_conv_guided_filter_adv': 49 | model = DeepGuidedFilterGuidedMapConvGF() 50 | else: 51 | print('Not a valid model!') 52 | exit(-1) 53 | 54 | model2name = {'guided_filter': 'lr', 55 | 'deep_guided_filter': 'hr', 56 | 'deep_guided_filter_advanced': 'hr_ad', 57 | 'deep_conv_guided_filter': 'conv_hr', 58 | 'deep_conv_guided_filter_adv': 'conv_hr_ad'} 59 | model_path = os.path.join('models', args.task, '{}_net_latest.pth'.format(model2name[args.model])) 60 | 61 | if args.model == 'guided_filter': 62 | model.init_lr(model_path) 63 | else: 64 | model.load_state_dict(torch.load(model_path)) 65 | 66 | # data set 67 | test_data = PreSuDataset(img_list, low_size=args.low_size) 68 | 69 | # GPU 70 | if args.gpu >= 0: 71 | with torch.cuda.device(args.gpu): 72 | model.cuda() 73 | 74 | # test 75 | i_bar = tqdm(total=len(test_data), desc='#Images') 76 | for idx, imgs in enumerate(test_data): 77 | name = os.path.basename(test_data.get_path(idx)) 78 | 79 | lr_x, hr_x = imgs[1].unsqueeze(0), imgs[0].unsqueeze(0) 80 | if args.gpu >= 0: 81 | with torch.cuda.device(args.gpu): 82 | lr_x = lr_x.cuda() 83 | hr_x = hr_x.cuda() 84 | imgs = model(Variable(lr_x), Variable(hr_x)).data.cpu() 85 | 86 | for img in imgs: 87 | img = tensor_to_img(img, transpose=True) 88 | if args.gray: 89 | img = img.mean(axis=2).astype(img.dtype) 90 | imsave(os.path.join(args.save_folder, name), img) 91 | 92 | i_bar.update() -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/scripts/auto_ps/generate_list.sh: -------------------------------------------------------------------------------- 1 | wget -O- http://groups.csail.mit.edu/graphics/fivek_dataset/ | sed -n 's/.*\([id][mn][g]\/[^"]*\.[td][in][fg]\).*/\1/p' | sed -n '/tiff16_'$1'/p' | sed -e 's#^#http://groups.csail.mit.edu/graphics/fivek_dataset/#' | head -999999999999 > img_list_$1.csv 2 | -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/scripts/auto_ps/postprocess.py: -------------------------------------------------------------------------------- 1 | import io 2 | import os 3 | import glob 4 | 5 | import warnings 6 | warnings.simplefilter('ignore') 7 | 8 | import numpy as np 9 | 10 | import PIL 11 | from PIL import Image 12 | from PIL import ImageCms 13 | 14 | from skimage.io import imread, imsave 15 | 16 | from multiprocessing import Pool 17 | 18 | RGB_PATH = '../../dataset/rgb/tiff' 19 | GT_PATH = '../../dataset/fivek/gts' 20 | GT_SAVE = '../../dataset/auto_ps/tiff' 21 | N_PROCESS = 48 22 | 23 | def preprocess(path): 24 | # IMG NAME 25 | name = os.path.splitext(os.path.basename(path))[0] 26 | gt_path = os.path.join(GT_SAVE, '{}.tif'.format(name)) 27 | 28 | if os.path.isfile(gt_path): 29 | return 30 | 31 | rgb = imread(path) 32 | 33 | # Read GT 34 | try: 35 | gt = Image.open(os.path.join(GT_PATH, '{}.tif'.format(name))) 36 | gt = ImageCms.profileToProfile(gt, 37 | io.BytesIO(gt.info.get('icc_profile')), 38 | ImageCms.createProfile('sRGB')) 39 | except Exception as e: 40 | print(path) 41 | return 42 | 43 | w_rgb, h_rgb = rgb.shape[:2] 44 | h_gt, w_gt = gt.size 45 | 46 | print(h_gt, w_gt) 47 | print(h_rgb, w_rgb) 48 | 49 | if w_rgb != w_gt or h_rgb != h_gt: 50 | gt = gt.resize((h_rgb, w_rgb), resample=PIL.Image.BICUBIC) 51 | 52 | w_rgb, h_rgb = rgb.shape[:2] 53 | h_gt, w_gt = gt.size 54 | 55 | assert w_rgb == w_gt and h_rgb == h_gt 56 | 57 | # GT 58 | imsave(gt_path, np.asarray(gt)) 59 | 60 | if not os.path.isdir(GT_SAVE): 61 | os.makedirs(GT_SAVE) 62 | 63 | imgs_path = sorted(glob.glob(os.path.join(RGB_PATH, '*.tif'))) 64 | 65 | Pool(N_PROCESS).map(preprocess, imgs_path) -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/scripts/convert_dng_to_tif.py: -------------------------------------------------------------------------------- 1 | import os 2 | import glob 3 | 4 | import warnings 5 | warnings.simplefilter('ignore') 6 | 7 | import rawpy 8 | 9 | from skimage.io import imsave 10 | 11 | from multiprocessing import Pool 12 | 13 | RAW_PATH = '../dataset/fivek/raw_photos' 14 | RGB_SAVE = '../dataset/rgb/tiff' 15 | N_PROCESS = 48 16 | 17 | def center_crop(im, tw, th): 18 | w, h = im.shape[:2] 19 | if w == tw and h == th: 20 | return im 21 | 22 | w_p = int(round((w - tw) / 2)) 23 | h_p = int(round((h - th) / 2)) 24 | 25 | return im[w_p:w_p+tw, h_p:h_p+th] 26 | 27 | def preprocess(path): 28 | # IMG NAME 29 | name = os.path.splitext(os.path.basename(path))[0] 30 | rgb_path = os.path.join(RGB_SAVE, '{}.tif'.format(name)) 31 | 32 | if os.path.isfile(rgb_path): 33 | return 34 | 35 | # Read RAW Image 36 | rgb = rawpy.imread(path).postprocess() 37 | 38 | # Color 39 | imsave(rgb_path, rgb) 40 | 41 | if not os.path.isdir(RGB_SAVE): 42 | os.makedirs(RGB_SAVE) 43 | 44 | imgs_path = sorted(glob.glob(os.path.join(RAW_PATH, 'HQ*', 'photos', '*.dng'))) 45 | 46 | Pool(N_PROCESS).map(preprocess, imgs_path) -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/scripts/l0_smooth/L0Smoothing.m: -------------------------------------------------------------------------------- 1 | % Distribution code Version 1.0 -- 09/23/2011 by Jiaya Jia Copyright 2011, The Chinese University of Hong Kong. 2 | % 3 | % The Code is created based on the method described in the following paper 4 | % [1] "Image Smoothing via L0 Gradient Minimization", Li Xu, Cewu Lu, Yi Xu, Jiaya Jia, ACM Transactions on Graphics, 5 | % (SIGGRAPH Asia 2011), 2011. 6 | % 7 | % The code and the algorithm are for non-comercial use only. 8 | 9 | 10 | function S = L0Smoothing(Im, lambda, kappa) 11 | %L0Smooth - Image Smoothing via L0 Gradient Minimization 12 | % S = L0Smooth(Im, lambda, kappa) performs L0 graidient smoothing of input 13 | % image Im, with smoothness weight lambda and rate kappa. 14 | % 15 | % Paras: 16 | % @Im : Input UINT8 image, both grayscale and color images are acceptable. 17 | % @lambda: Smoothing parameter controlling the degree of smooth. (See [1]) 18 | % Typically it is within the range [1e-3, 1e-1], 2e-2 by default. 19 | % @kappa : Parameter that controls the rate. (See [1]) 20 | % Small kappa results in more iteratioins and with sharper edges. 21 | % We select kappa in (1, 2]. 22 | % kappa = 2 is suggested for natural images. 23 | % 24 | % Example 25 | % ========== 26 | % Im = imread('pflower.jpg'); 27 | % S = L0Smooth(Im); % Default Parameters (lambda = 2e-2, kappa = 2) 28 | % figure, imshow(Im), figure, imshow(S); 29 | 30 | 31 | if ~exist('kappa','var') 32 | kappa = 2.0; 33 | end 34 | if ~exist('lambda','var') 35 | lambda = 2e-2; 36 | end 37 | S = im2double(Im); 38 | betamax = 1e5; 39 | fx = [1, -1]; 40 | fy = [1; -1]; 41 | [N,M,D] = size(Im); 42 | sizeI2D = [N,M]; 43 | otfFx = psf2otf(fx,sizeI2D); 44 | otfFy = psf2otf(fy,sizeI2D); 45 | Normin1 = fft2(S); 46 | Denormin2 = abs(otfFx).^2 + abs(otfFy ).^2; 47 | if D>1 48 | Denormin2 = repmat(Denormin2,[1,1,D]); 49 | end 50 | beta = 2*lambda; 51 | while beta < betamax 52 | Denormin = 1 + beta*Denormin2; 53 | % h-v subproblem 54 | h = [diff(S,1,2), S(:,1,:) - S(:,end,:)]; 55 | v = [diff(S,1,1); S(1,:,:) - S(end,:,:)]; 56 | if D==1 57 | t = (h.^2+v.^2)0 22 | diff0 = sigmoid((L-L0)/100,val0)*100; 23 | else 24 | diff0 = (1+val0)*(L-L0); 25 | end 26 | end 27 | 28 | if val1==0 29 | diff1 = L0-L1; 30 | else 31 | if val1>0 32 | diff1 = sigmoid((L0-L1)/100,val1)*100; 33 | else 34 | diff1 = (1+val1)*(L0-L1); 35 | end 36 | end 37 | 38 | if val2==0 39 | base = exposure*L1; 40 | else 41 | if val2>0 42 | base = (sigmoid((exposure*L1-56)/100,val2)*100)+56; 43 | else 44 | base = (1+val2)*(exposure*L1-56) + 56; 45 | end 46 | end 47 | 48 | 49 | if gamma == 1 50 | res = base + diff1 + diff0; 51 | else 52 | maxBase = max(base(:)); 53 | res = (zeroone(base).^gamma)*maxBase + diff1 + diff0; 54 | end 55 | 56 | if saturation == 0 57 | lab(:,:,1) = res; 58 | else 59 | lab(:,:,1) = res; 60 | lab(:,:,2) = lab(:,:,2) * saturation; 61 | lab(:,:,3) = lab(:,:,3) * saturation; 62 | end 63 | 64 | cform = makecform('lab2srgb'); 65 | res = applycform(lab, cform); 66 | -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/scripts/multi_scale_detail_manipulation/wlsFilter.m: -------------------------------------------------------------------------------- 1 | function OUT = wlsFilter(IN, lambda, alpha, L) 2 | %WLSFILTER Edge-preserving smoothing based on the weighted least squares(WLS) 3 | % optimization framework, as described in Farbman, Fattal, Lischinski, and 4 | % Szeliski, "Edge-Preserving Decompositions for Multi-Scale Tone and Detail 5 | % Manipulation", ACM Transactions on Graphics, 27(3), August 2008. 6 | % 7 | % Given an input image IN, we seek a new image OUT, which, on the one hand, 8 | % is as close as possible to IN, and, at the same time, is as smooth as 9 | % possible everywhere, except across significant gradients in L. 10 | % 11 | % 12 | % Input arguments: 13 | % ---------------- 14 | % IN Input image (2-D, double, N-by-M matrix). 15 | % 16 | % lambda Balances between the data term and the smoothness 17 | % term. Increasing lambda will produce smoother images. 18 | % Default value is 1.0 19 | % 20 | % alpha Gives a degree of control over the affinities by non- 21 | % lineary scaling the gradients. Increasing alpha will 22 | % result in sharper preserved edges. Default value: 1.2 23 | % 24 | % L Source image for the affinity matrix. Same dimensions 25 | % as the input image IN. Default: log(IN) 26 | % 27 | % 28 | % Example 29 | % ------- 30 | % RGB = imread('peppers.png'); 31 | % I = double(rgb2gray(RGB)); 32 | % I = I./max(I(:)); 33 | % res = wlsFilter(I, 0.5); 34 | % figure, imshow(I), figure, imshow(res) 35 | % res = wlsFilter(I, 2, 2); 36 | % figure, imshow(res) 37 | 38 | if(~exist('L', 'var')), 39 | L = log(IN+eps); 40 | end 41 | 42 | if(~exist('alpha', 'var')), 43 | alpha = 1.2; 44 | end 45 | 46 | if(~exist('lambda', 'var')), 47 | lambda = 1; 48 | end 49 | 50 | smallNum = 0.0001; 51 | 52 | [r,c] = size(IN); 53 | k = r*c; 54 | 55 | % Compute affinities between adjacent pixels based on gradients of L 56 | dy = diff(L, 1, 1); 57 | dy = -lambda./(abs(dy).^alpha + smallNum); 58 | dy = padarray(dy, [1 0], 'post'); 59 | dy = dy(:); 60 | 61 | dx = diff(L, 1, 2); 62 | dx = -lambda./(abs(dx).^alpha + smallNum); 63 | dx = padarray(dx, [0 1], 'post'); 64 | dx = dx(:); 65 | 66 | 67 | % Construct a five-point spatially inhomogeneous Laplacian matrix 68 | B(:,1) = dx; 69 | B(:,2) = dy; 70 | d = [-r,-1]; 71 | A = spdiags(B,d,k,k); 72 | 73 | e = dx; 74 | w = padarray(dx, r, 'pre'); w = w(1:end-r); 75 | s = dy; 76 | n = padarray(dy, 1, 'pre'); n = n(1:end-1); 77 | 78 | D = 1-(e+w+s+n); 79 | A = A + A' + spdiags(D, 0, k, k); 80 | 81 | % Solve 82 | OUT = A\IN(:); 83 | OUT = reshape(OUT, r, c); -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/scripts/multi_scale_detail_manipulation/zeroone.m: -------------------------------------------------------------------------------- 1 | function out = zeroone(in) 2 | 3 | maxIn = max(in(:)); 4 | minIn = min(in(:)); 5 | 6 | out = (in-minIn)/(maxIn-minIn); -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/scripts/non_local_dehazing/adjust.m: -------------------------------------------------------------------------------- 1 | function adj = adjust(img,percen) 2 | %Contrast stretch utility function. Clip percen percentages of the pixels, 3 | %while avoiding a drastic change to the white-balance. 4 | % 5 | % This is a utility function used by the non-local image dehazing algorithm 6 | % described in the paper: 7 | % Non-Local Image Dehazing. Berman, D. and Treibitz, T. and Avidan S., CVPR2016, 8 | % which can be found at: 9 | % www.eng.tau.ac.il/~berman/NonLocalDehazing/NonLocalDehazing_CVPR2016.pdf 10 | % If you use this code, please cite our paper. 11 | % 12 | % The software code of the Non-Local Image Dehazing algorithm is provided 13 | % under the attached LICENSE.md 14 | 15 | if ~exist('percen','var') || isempty(percen), percen=[0.01 0.99]; end; 16 | 17 | % linear contrast stretch to [0,1], identical on all colors 18 | minn=min(img(:)); 19 | img=img-minn; 20 | img=img./max(img(:)); 21 | 22 | % limit the change magnitude so the WB would not be drastically changed 23 | contrast_limit = stretchlim(img,percen); 24 | val = 0.2; 25 | contrast_limit(2,:) = max(contrast_limit(2,:), 0.2); 26 | contrast_limit(2,:) = val*contrast_limit(2,:) + (1-val)*max(contrast_limit(2,:), mean(contrast_limit(2,:))); 27 | contrast_limit(1,:) = val*contrast_limit(1,:) + (1-val)*min(contrast_limit(1,:), mean(contrast_limit(1,:))); 28 | adj=imadjust(img,contrast_limit,[],1); 29 | -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/scripts/non_local_dehazing/estimate_airlight.m: -------------------------------------------------------------------------------- 1 | function [ Aout ] = estimate_airlight( img, Amin, Amax, N, spacing, K, thres ) 2 | %Estimate airlight of an image, using a 3*2D Hough transform, where each 3 | %point votes for a given location using a fixed set of angles. 4 | % 5 | % This is an implementation of our paper: 6 | % Dana Berman, Tali Treibitz, Shai Avidan, 7 | % "Air-light Estimation using Haze-Lines", ICCP 2017 8 | % 9 | % Input arguments: 10 | % img - input image (mandatory) 11 | % Amin (Amax) - minimal (maximal) value if the air-light. Optional 12 | % Can be used to reduce the search space and save time 13 | % Either a scalar (identical for all color channels) or a 3 14 | % value vector (different range for each color channel) 15 | % N - number of colors clusters to use (the image is converted to an 16 | % indexed image of at most N different cluster). Optional 17 | % spacing - air-light candidates' resolution, 1/M in the paper. Optional 18 | % K - angular resolution. Optional 19 | % thres - cone resolution, optional, default recommended 20 | 21 | 22 | %% Verify input params, set defaults when necessary (same as published results) 23 | if ~exist('thres','var') || isempty(thres), thres = 0.01 ; end; 24 | if ~exist('spacing','var') || isempty(spacing), spacing = 0.02 ; end; %1/M in the paper 25 | if ~exist('n_colors','var') || isempty(N), N = 1000 ; end; %number of colors clusters 26 | if ~exist('K','var') || isempty(K), K = 40 ; end; %number of angles 27 | 28 | % Define search range for the air-light. The search range is different for each 29 | % color channel. These values were used in all of our experiments. 30 | if ~exist('Amin','var') || isempty(Amin), Amin = [0,0.05,0.1]; end; 31 | if ~exist('Amax','var') || isempty(Amax), Amax = 1; end; 32 | 33 | % Air-light search range, accept a scalar if identical for all color channels 34 | if isscalar(Amin), Amin = repmat(Amin,1,3); end 35 | if isscalar(Amax), Amax = repmat(Amax,1,3); end 36 | 37 | %% Convert input image to an indexed image 38 | [img_ind, points] = rgb2ind(img, N); 39 | [h,w,~] = size(img); 40 | % Remove empty clusters 41 | idx_in_use = unique(img_ind(:)); 42 | idx_to_remove = setdiff(0:(size(points,1)-1),idx_in_use); 43 | points(idx_to_remove+1,:) = []; 44 | img_ind_sequential = zeros(h,w); 45 | for kk = 1:length(idx_in_use) 46 | img_ind_sequential(img_ind==idx_in_use(kk)) = kk; 47 | end 48 | % Now the min value of img_ind_sequential is 1 rather then 0, and the indices 49 | % correspond to points 50 | 51 | % Count the occurences if each index - this is the clusters' weight 52 | [points_weight,~] = histcounts(img_ind_sequential(:),size(points,1)); 53 | points_weight = points_weight./(h*w); 54 | if ~ismatrix(points), points = reshape(points,[],3); end % verify dim 55 | 56 | %% Define arrays of candidate air-light values and angles 57 | angle_list = reshape(linspace(0, pi, K),[],1); 58 | % Use angle_list(1:end-1) since angle_list(end)==pi, which is the same line 59 | % in 2D as since angle_list(1)==0 60 | directions_all = [sin(angle_list(1:end-1)) , cos(angle_list(1:end-1)) ]; 61 | 62 | % Air-light candidates in each color channel 63 | ArangeR = Amin(1):spacing:Amax(1); 64 | ArangeG = Amin(2):spacing:Amax(2); 65 | ArangeB = Amin(3):spacing:Amax(3); 66 | 67 | %% Estimate air-light in each pair of color channels 68 | % Estimate RG 69 | Aall = generate_Avals(ArangeR, ArangeG); 70 | [~, AvoteRG] = vote_2D(points(:,1:2), points_weight, directions_all, Aall, thres ); 71 | % Estimate GB 72 | Aall = generate_Avals(ArangeG, ArangeB); 73 | [~, AvoteGB] = vote_2D(points(:,2:3), points_weight, directions_all, Aall, thres ); 74 | % Estimate RB 75 | Aall = generate_Avals(ArangeR, ArangeB); 76 | [~, AvoteRB] = vote_2D(points(:,[1,3]), points_weight, directions_all, Aall, thres); 77 | 78 | %% Find most probable airlight from marginal probabilities (2D arrays) 79 | % Normalize (otherwise the numbers are quite large) 80 | max_val = max( [max(AvoteRB(:)) , max(AvoteRG(:)) , max(AvoteGB(:)) ]); 81 | AvoteRG2 = AvoteRG./max_val; 82 | AvoteGB2 = AvoteGB./max_val; 83 | AvoteRB2 = AvoteRB./max_val; 84 | % Generate 3D volumes from 3 different 2D arrays 85 | A11 = repmat( reshape(AvoteRG2, length(ArangeG),length(ArangeR))', 1,1,length(ArangeB)); 86 | tmp = reshape(AvoteRB2, length(ArangeB),length(ArangeR))'; 87 | A22 = repmat(reshape(tmp, length(ArangeR),1,length(ArangeB)) , 1,length(ArangeG),1); 88 | tmp2 = reshape(AvoteGB2, length(ArangeB),length(ArangeG))'; 89 | A33 = repmat(reshape(tmp2, 1, length(ArangeG),length(ArangeB)) , length(ArangeR),1,1); 90 | AvoteAll = A11.*A22.*A33; 91 | [~, idx] = max(AvoteAll(:)); 92 | [idx_r,idx_g,idx_b] = ind2sub([length(ArangeR),length(ArangeG),length(ArangeB)],idx); 93 | Aout = [ArangeR(idx_r), ArangeG(idx_g), ArangeB(idx_b)]; 94 | 95 | 96 | end % function estimate_airlight_2D 97 | 98 | %% Sub functions 99 | 100 | function Aall = generate_Avals(Avals1, Avals2) 101 | %Generate a list of air-light candidates of 2-channels, using two lists of 102 | %values in a single channel each 103 | %Aall's length is length(Avals1)*length(Avals2) 104 | Avals1 = reshape(Avals1,[],1); 105 | Avals2 = reshape(Avals2,[],1); 106 | A1 = kron(Avals1, ones(length(Avals2),1)); 107 | A2 = kron(ones(length(Avals1),1), Avals2); 108 | Aall = [A1, A2]; 109 | end % function generate_Avals 110 | 111 | function [Aout, Avote2] = vote_2D(points, points_weight, directions_all, Aall, thres) 112 | n_directions = size(directions_all,1); 113 | accumulator_votes_idx = false(size(Aall,1), size(points,1), n_directions); 114 | for i_point = 1:size(points,1) 115 | for i_direction = 1:n_directions 116 | % save time and ignore irelevant points from the get-go 117 | idx_to_use = find( (Aall(:, 1) > points(i_point, 1)) & (Aall(:, 2) > points(i_point, 2))); 118 | if isempty(idx_to_use), continue; end 119 | 120 | % calculate distance between all A options and the line defined by 121 | % i_point and i_direction. If the distance is smaller than a thres, 122 | % increase the cell in accumulator 123 | dist1 = sqrt(sum([Aall(idx_to_use, 1)-points(i_point, 1), Aall(idx_to_use, 2)-points(i_point, 2)].^2,2)); 124 | %dist1 = dist1 - min(dist1); 125 | dist1 = dist1./sqrt(2) + 1; 126 | 127 | dist = -points(i_point, 1)*directions_all(i_direction,2) + ... 128 | points(i_point, 2)*directions_all(i_direction,1) + ... 129 | Aall(idx_to_use, 1)*directions_all(i_direction,2) - ... 130 | Aall(idx_to_use, 2)*directions_all(i_direction,1); 131 | idx = abs(dist)<2*thres.*dist1; 132 | if ~any(idx), continue; end 133 | 134 | idx_full = idx_to_use(idx); 135 | accumulator_votes_idx(idx_full, i_point,i_direction) = true; 136 | end 137 | end 138 | % use only haze-lined that are supported by 2 points or more 139 | accumulator_votes_idx2 = (sum(uint8(accumulator_votes_idx),2))>=2; 140 | accumulator_votes_idx = bsxfun(@and, accumulator_votes_idx ,accumulator_votes_idx2); 141 | accumulator_unique = zeros(size(Aall,1),1); 142 | for iA = 1:size(Aall,1) 143 | idx_to_use = find(Aall(iA, 1) > points(:, 1) & (Aall(iA, 2) > points(:, 2))); 144 | points_dist = sqrt((Aall(iA,1) - points(idx_to_use,1)).^2+(Aall(iA,2) - points(idx_to_use,2)).^2); 145 | points_weight_dist = points_weight(idx_to_use).*(5.*exp(-reshape(points_dist,1,[]))+1); 146 | accumulator_unique(iA) = sum(points_weight_dist(any(accumulator_votes_idx(iA,idx_to_use,:),3))); 147 | end 148 | [~, Aestimate_idx] = max(accumulator_unique); 149 | Aout = Aall(Aestimate_idx,:); 150 | Avote2 = accumulator_unique; 151 | 152 | end % function vote_2D 153 | -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/scripts/non_local_dehazing/non_local_dehazing.m: -------------------------------------------------------------------------------- 1 | function [img_dehazed, transmission] = non_local_dehazing(img_hazy, air_light, gamma) 2 | %The core implementation of "Non-Local Image Dehazing", CVPR 2016 3 | % 4 | % The details of the algorithm are described in our paper: 5 | % Non-Local Image Dehazing. Berman, D. and Treibitz, T. and Avidan S., CVPR2016, 6 | % which can be found at: 7 | % www.eng.tau.ac.il/~berman/NonLocalDehazing/NonLocalDehazing_CVPR2016.pdf 8 | % If you use this code, please cite the paper. 9 | % 10 | % Input arguments: 11 | % ---------------- 12 | % img_hazy - A hazy image in the range [0,255], type: uint8 13 | % air_light - As estimated by prior methods, normalized to the range [0,1] 14 | % gamma - Radiometric correction. If empty, 1 is assumed 15 | % 16 | % Output arguments: 17 | % ---------------- 18 | % img_dehazed - The restored radiance of the scene (uint8) 19 | % transmission - Transmission map of the scene, in the range [0,1] 20 | % 21 | % Author: Dana Berman, 2016. 22 | % 23 | % The software code of the Non-Local Image Dehazing algorithm is provided 24 | % under the attached LICENSE.md 25 | 26 | 27 | %% Validate input 28 | [h,w,n_colors] = size(img_hazy); 29 | if (n_colors ~= 3) % input verification 30 | error(['Non-Local Dehazing reuires an RGB image, while input ',... 31 | 'has only ',num2str(n_colors),' dimensions']); 32 | end 33 | 34 | if ~exist('air_light','var') || isempty(air_light) || (numel(air_light)~=3) 35 | error('Dehazing on sphere requires an RGB airlight'); 36 | end 37 | 38 | if ~exist('gamma','var') || isempty(gamma), gamma = 1; end 39 | 40 | img_hazy = im2double(img_hazy); 41 | img_hazy_corrected = img_hazy.^gamma; % radiometric correction 42 | 43 | 44 | %% Find Haze-lines 45 | % Translate the coordinate system to be air_light-centric (Eq. (3)) 46 | dist_from_airlight = double(zeros(h,w,n_colors)); 47 | for color_idx=1:n_colors 48 | dist_from_airlight(:,:,color_idx) = img_hazy_corrected(:,:,color_idx) - air_light(:,:,color_idx); 49 | end 50 | 51 | % Calculate radius (Eq. (5)) 52 | radius = sqrt( dist_from_airlight(:,:,1).^2 + dist_from_airlight(:,:,2).^2 +dist_from_airlight(:,:,3).^2 ); 53 | 54 | % Cluster the pixels to haze-lines 55 | % Use a KD-tree impementation for fast clustering according to their angles 56 | dist_unit_radius = reshape(dist_from_airlight,[h*w,n_colors]); 57 | dist_norm = sqrt(sum(dist_unit_radius.^2,2)); 58 | dist_unit_radius = bsxfun(@rdivide, dist_unit_radius, dist_norm); 59 | n_points = 1000; 60 | % load pre-calculated uniform tesselation of the unit-sphere 61 | fid = fopen(['TR',num2str(n_points),'.txt']); 62 | points = cell2mat(textscan(fid,'%f %f %f')) ; 63 | fclose(fid); 64 | mdl = KDTreeSearcher(points); 65 | ind = knnsearch(mdl, dist_unit_radius); 66 | 67 | 68 | %% Estimating Initial Transmission 69 | 70 | % Estimate radius as the maximal radius in each haze-line (Eq. (11)) 71 | K = accumarray(ind,radius(:),[n_points,1],@max); 72 | radius_new = reshape( K(ind), h, w); 73 | 74 | % Estimate transmission as radii ratio (Eq. (12)) 75 | transmission_estimation = radius./radius_new; 76 | 77 | % Limit the transmission to the range [trans_min, 1] for numerical stability 78 | trans_min = 0.1; 79 | transmission_estimation = min(max(transmission_estimation, trans_min),1); 80 | 81 | 82 | %% Regularization 83 | 84 | % Apply lower bound from the image (Eqs. (13-14)) 85 | trans_lower_bound = 1 - min(bsxfun(@rdivide,img_hazy_corrected,reshape(air_light,1,1,3)) ,[],3); 86 | transmission_estimation = max(transmission_estimation, trans_lower_bound); 87 | 88 | % Solve optimization problem (Eq. (15)) 89 | % find bin counts for reliability - small bins (#pixels<50) do not comply with 90 | % the model assumptions and should be disregarded 91 | bin_count = accumarray(ind,1,[n_points,1]); 92 | bin_count_map = reshape(bin_count(ind),h,w); 93 | bin_eval_fun = @(x) min(1, x/50); 94 | 95 | % Calculate std - this is the data-term weight of Eq. (15) 96 | K_std = accumarray(ind,radius(:),[n_points,1],@std); 97 | radius_std = reshape( K_std(ind), h, w); 98 | radius_eval_fun = @(r) min(1, 3*max(0.001, r-0.1)); 99 | radius_reliability = radius_eval_fun(radius_std./max(radius_std(:))); 100 | data_term_weight = bin_eval_fun(bin_count_map).*radius_reliability; 101 | lambda = 0.1; 102 | transmission = wls_optimization(transmission_estimation, data_term_weight, img_hazy, lambda); 103 | 104 | 105 | %% Dehazing 106 | % (Eq. (16)) 107 | img_dehazed = zeros(h,w,n_colors); 108 | leave_haze = 1.06; % leave a bit of haze for a natural look (set to 1 to reduce all haze) 109 | for color_idx = 1:3 110 | img_dehazed(:,:,color_idx) = ( img_hazy_corrected(:,:,color_idx) - ... 111 | (1-leave_haze.*transmission).*air_light(color_idx) )./ max(transmission,trans_min); 112 | end 113 | 114 | % Limit each pixel value to the range [0, 1] (avoid numerical problems) 115 | img_dehazed(img_dehazed>1) = 1; 116 | img_dehazed(img_dehazed<0) = 0; 117 | img_dehazed = img_dehazed.^(1/gamma); % radiometric correction 118 | 119 | % For display, we perform a global linear contrast stretch on the output, 120 | % clipping 0.5% of the pixel values both in the shadows and in the highlights 121 | adj_percent = [0.005, 0.995]; 122 | img_dehazed = adjust(img_dehazed,adj_percent); 123 | 124 | img_dehazed = im2uint8(img_dehazed); 125 | 126 | end % function non_local_dehazing 127 | -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/scripts/non_local_dehazing/prepare_dataset.m: -------------------------------------------------------------------------------- 1 | function prepare_dataset(image_size) 2 | SAVE_PATH = strcat('../../dataset/non_local_dehazing/', image_size); 3 | imgs = dir(strcat('../../dataset/rgb/', image_size, '/*.tif')); 4 | 5 | mkdir(SAVE_PATH); 6 | parfor idx = 1:length(imgs) 7 | path = fullfile(imgs(idx).folder, imgs(idx).name); 8 | im = imread(path); 9 | 10 | gamma = 1; 11 | A = reshape(estimate_airlight(im2double(im).^(gamma)),1,1,3); 12 | [gt, ~] = non_local_dehazing(im, A, gamma); 13 | 14 | save_path = fullfile(SAVE_PATH, imgs(idx).name); 15 | imwrite(gt, save_path); 16 | end 17 | end -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/scripts/non_local_dehazing/wls_optimization.m: -------------------------------------------------------------------------------- 1 | function out = wls_optimization(in, data_weight, guidance, lambda) 2 | %Weighted Least Squares optimization solver. 3 | % Given an input image IN, we seek a new image OUT, which, on the one hand, 4 | % is as close as possible to IN, and, at the same time, is as smooth as 5 | % possible everywhere, except across significant gradients in the hazy image. 6 | % 7 | % Input arguments: 8 | % ---------------- 9 | % in - Input image (2-D, double, N-by-M matrix). 10 | % data_weight - High values indicate it is accurate, small values 11 | % indicate it's not. 12 | % guidance - Source image for the affinity matrix. Same dimensions 13 | % as the input image IN. Default: log(IN) 14 | % lambda - Balances between the data term and the smoothness 15 | % term. Increasing lambda will produce smoother images. 16 | % Default value is 0.05 17 | % 18 | % This function is based on the implementation of the WLS Filer by Farbman, 19 | % Fattal, Lischinski and Szeliski, "Edge-Preserving Decompositions for 20 | % Multi-Scale Tone and Detail Manipulation", ACM Transactions on Graphics, 2008 21 | % The original function can be downloaded from: 22 | % http://www.cs.huji.ac.il/~danix/epd/wlsFilter.m 23 | 24 | 25 | small_num = 0.00001; 26 | 27 | if ~exist('lambda','var') || isempty(lambda), lambda = 0.05; end 28 | 29 | [h,w,~] = size(guidance); 30 | k = h*w; 31 | guidance = rgb2gray(guidance); 32 | 33 | % Compute affinities between adjacent pixels based on gradients of guidance 34 | dy = diff(guidance, 1, 1); 35 | dy = -lambda./(sum(abs(dy).^2,3) + small_num); 36 | dy = padarray(dy, [1 0], 'post'); 37 | dy = dy(:); 38 | 39 | dx = diff(guidance, 1, 2); 40 | dx = -lambda./(sum(abs(dx).^2,3) + small_num); 41 | dx = padarray(dx, [0 1], 'post'); 42 | dx = dx(:); 43 | 44 | 45 | % Construct a five-point spatially inhomogeneous Laplacian matrix 46 | B = [dx, dy]; 47 | d = [-h,-1]; 48 | tmp = spdiags(B,d,k,k); 49 | 50 | ea = dx; 51 | we = padarray(dx, h, 'pre'); we = we(1:end-h); 52 | so = dy; 53 | no = padarray(dy, 1, 'pre'); no = no(1:end-1); 54 | 55 | D = -(ea+we+so+no); 56 | Asmoothness = tmp + tmp' + spdiags(D, 0, k, k); 57 | 58 | % Normalize data weight 59 | data_weight = data_weight - min(data_weight(:)) ; 60 | data_weight = 1.*data_weight./(max(data_weight(:))+small_num); 61 | 62 | % Make sure we have a boundary condition for the top line: 63 | % It will be the minimum of the transmission in each column 64 | % With reliability 0.8 65 | reliability_mask = data_weight(1,:) < 0.6; % find missing boundary condition 66 | in_row1 = min( in,[], 1); 67 | data_weight(1,reliability_mask) = 0.8; 68 | in(1,reliability_mask) = in_row1(reliability_mask); 69 | 70 | Adata = spdiags(data_weight(:), 0, k, k); 71 | 72 | A = Adata + Asmoothness; 73 | b = Adata*in(:); 74 | 75 | % Solve 76 | % out = lsqnonneg(A,b); 77 | out = A\b; 78 | out = reshape(out, h, w); 79 | -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/scripts/precompute_size.py: -------------------------------------------------------------------------------- 1 | import os 2 | import csv 3 | import random 4 | import argparse 5 | from skimage.io import imread 6 | from multiprocessing import Pool 7 | 8 | parser = argparse.ArgumentParser(description='Precompute size') 9 | parser.add_argument('--min', type=int, default=512, help='MIN_SIZE_TOTAL') 10 | parser.add_argument('--random', action='store_true', default=False, help='RANDOM') 11 | args = parser.parse_args() 12 | 13 | RANDOM = args.random 14 | MIN_SIZE_TOTAL = args.min 15 | ##################################### 16 | SEED = 1 17 | N_PROCESS = 12 18 | MAX_SIZE_TOTAL = 2048 19 | IN_PATH = '../dataset/rgb/tiff' 20 | SAVE_PATH = 'precomputed_size' 21 | ##################################### 22 | 23 | if not os.path.isdir(SAVE_PATH): 24 | os.makedirs(SAVE_PATH) 25 | 26 | random.seed(SEED) 27 | FILE_NAME = 'random' if RANDOM else str(MIN_SIZE_TOTAL) 28 | 29 | def compute_size(name): 30 | # Read IN 31 | im = imread(os.path.join(IN_PATH, name)) 32 | w, h = im.shape[:2] 33 | if RANDOM: 34 | min_size = min(w, h) 35 | size = int(min_size * random.uniform( 36 | min(MIN_SIZE_TOTAL / min_size, 1.0), 37 | min(MAX_SIZE_TOTAL / min_size, 1.0))) 38 | else: 39 | size = MIN_SIZE_TOTAL 40 | if w < h: 41 | width, height = (size, int(size / w * h)) 42 | else: 43 | width, height = (int(size / h * w), size) 44 | 45 | return name, width, height 46 | 47 | imgs_name = sorted(os.listdir(IN_PATH)) 48 | result = Pool(N_PROCESS).map(compute_size, imgs_name) 49 | with open(os.path.join(SAVE_PATH, 'precomputed_size_{}.txt'.format(FILE_NAME)), 'w') as f: 50 | csv.writer(f).writerows(result) -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/scripts/resize_image.py: -------------------------------------------------------------------------------- 1 | import os 2 | import csv 3 | import argparse 4 | import warnings 5 | warnings.simplefilter('ignore') 6 | 7 | from skimage import img_as_uint 8 | from skimage.io import imread 9 | from skimage.io import imsave 10 | from skimage.transform import resize 11 | 12 | from multiprocessing import Pool 13 | 14 | parser = argparse.ArgumentParser(description='Resize Image') 15 | parser.add_argument('--file_name', type=str, default='512', help='FILE_NAME') 16 | parser.add_argument('--task', type=str, default='rgb', help='TASK') 17 | args = parser.parse_args() 18 | 19 | FILE_NAME = args.file_name 20 | TASK = args.task 21 | ####################################### 22 | N_PROCESS = 12 23 | ROOT = '../dataset/{}'.format(TASK) 24 | 25 | def prepare_dataset(name, w, h): 26 | # IMG NAME 27 | save_path = os.path.join(SAVE, name) 28 | 29 | if os.path.isfile(save_path): 30 | return 31 | 32 | # Read IN 33 | rgb = resize(imread(os.path.join(ROOT, 'tiff', name)), (int(w), int(h)), mode='reflect') 34 | 35 | imsave(save_path, img_as_uint(rgb)) 36 | 37 | SAVE = os.path.join(ROOT, FILE_NAME) 38 | if not os.path.isdir(SAVE): 39 | os.makedirs(SAVE) 40 | 41 | with open('precomputed_size/precomputed_size_{}.txt'.format(FILE_NAME)) as f: 42 | reader = csv.reader(f) 43 | Pool(N_PROCESS).starmap(prepare_dataset, reader) -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/scripts/style_transfer/apply_tranfer_function.m: -------------------------------------------------------------------------------- 1 | function O=apply_tranfer_function(I,f) 2 | % apply a transfer function 3 | % intput: 4 | % -I is the image in [0 1] to which apply the transfer function 5 | % -f is the transfer function given as a vector of size 256 6 | index=max(min(floor(255.*I),255),0); 7 | x=min((255.*I-index)./255,255); 8 | f(257)=1; 9 | O=((1-x).*f(index+1)+(x).*f(index+2)); 10 | end 11 | -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/scripts/style_transfer/child_window.m: -------------------------------------------------------------------------------- 1 | function child = child_window(parent,N) 2 | % for a parent subwindow [r1 r2 c1 c2], find the corresponding 3 | % child subwindow at the coarser pyramid level N levels up 4 | 5 | if ~exist('N','var') 6 | N = 1; 7 | end 8 | 9 | child = parent; 10 | for K = 1:N 11 | child = (child+1)/2; 12 | child([1 3]) = ceil(child([1 3])); 13 | child([2 4]) = floor(child([2 4])); 14 | end 15 | 16 | end -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/scripts/style_transfer/downsample.m: -------------------------------------------------------------------------------- 1 | % Downsampling procedure. 2 | % 3 | % Arguments: 4 | % 'I': image 5 | % downsampling filter 'filter', should be a 2D separable filter. 6 | % 'border_mode' should be 'circular', 'symmetric', or 'replicate'. See 'imfilter'. 7 | % subwindow indices 'subwindow', given as [r1 r2 c1 c2] (optional) 8 | % 9 | % tom.mertens@gmail.com, August 2007 10 | % sam.hasinoff@gmail.com, March 2011 [handle subwindows, reweighted boundaries] 11 | % 12 | 13 | function [R,subwindow_child] = downsample(I, filter, subwindow) 14 | 15 | r = size(I,1); 16 | c = size(I,2); 17 | if ~exist('subwindow','var') 18 | subwindow = [1 r 1 c]; 19 | end 20 | subwindow_child = child_window(subwindow); 21 | 22 | border_mode = 'reweighted'; 23 | %border_mode = 'symmetric'; 24 | 25 | switch border_mode 26 | case 'reweighted' 27 | % low pass, convolve with 2D separable filter 28 | R = imfilter(I,filter); 29 | 30 | % reweight, brute force weights from 1's in valid image positions 31 | Z = imfilter(ones(size(I)),filter); 32 | R = R./Z; 33 | 34 | otherwise 35 | % low pass, convolve with 2D separable filter 36 | R = imfilter(I,filter,border_mode); 37 | end 38 | 39 | % decimate 40 | reven = mod(subwindow(1),2)==0; 41 | ceven = mod(subwindow(3),2)==0; 42 | R = R(1+reven:2:r, 1+ceven:2:c, :); 43 | 44 | end -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/scripts/style_transfer/gaussian_pyramid.m: -------------------------------------------------------------------------------- 1 | % Construction of Gaussian pyramid 2 | % 3 | % Arguments: 4 | % image 'I' 5 | % 'nlev', number of levels in the pyramid (optional) 6 | % subwindow indices 'subwindow', given as [r1 r2 c1 c2] (optional) 7 | % 8 | % tom.mertens@gmail.com, August 2007 9 | % sam.hasinoff@gmail.com, March 2011 [modified to handle subwindows] 10 | % 11 | 12 | function pyr = gaussian_pyramid(I,nlev,subwindow) 13 | 14 | r = size(I,1); 15 | c = size(I,2); 16 | if ~exist('subwindow','var') 17 | subwindow = [1 r 1 c]; 18 | end 19 | if ~exist('nlev','var') 20 | nlev = numlevels([r c]); % build highest possible pyramid 21 | end 22 | 23 | % start by copying the image to the finest level 24 | pyr = cell(nlev,1); 25 | pyr{1} = I; 26 | 27 | % recursively downsample the image 28 | filter = pyramid_filter; 29 | for l = 2:nlev 30 | I = downsample(I,filter,subwindow); 31 | pyr{l} = I; 32 | end -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/scripts/style_transfer/get_transfer_function.m: -------------------------------------------------------------------------------- 1 | function f=get_transfer_function(I,M) 2 | % input: 3 | % I : image in [0 1] with stat you want to be transfered 4 | % M : image in [0 1] with stat you want to get to 5 | % output 6 | % f : table with transfer values of size 256 and values in [0,1] 7 | 8 | % get cdf of the input values 9 | x=linspace(0,1,256); 10 | h1=hist(I(:),x); 11 | cdf1=cumsum(h1)./sum(h1); 12 | 13 | % get cdf target values (more resolution is needed because we want to invert it) 14 | x=linspace(0,1,256^2); 15 | h2=hist(M(:),x); 16 | cdf2=cumsum(h2)./sum(h2); 17 | f=linspace(0,1,256); 18 | 19 | % get f=cdf2^{-1}(cdf1) 20 | for i=1:256 21 | f(i)=find(cdf2>=cdf1(i),1)./(256*256); 22 | end 23 | 24 | end 25 | -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/scripts/style_transfer/images/ruins.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/ImageProcessing/DeepGuidedFilteringNetwork/scripts/style_transfer/images/ruins.png -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/scripts/style_transfer/laplacian_pyramid.m: -------------------------------------------------------------------------------- 1 | % Contruction of Laplacian pyramid 2 | % 3 | % Arguments: 4 | % image 'I' 5 | % 'nlev', number of levels in the pyramid (optional) 6 | % subwindow indices 'subwindow', given as [r1 r2 c1 c2] (optional) 7 | % 8 | % tom.mertens@gmail.com, August 2007 9 | % sam.hasinoff@gmail.com, March 2011 [modified to handle subwindows] 10 | % 11 | % 12 | % More information: 13 | % 'The Laplacian Pyramid as a Compact Image Code' 14 | % Burt, P., and Adelson, E. H., 15 | % IEEE Transactions on Communication, COM-31:532-540 (1983). 16 | % 17 | 18 | function pyr = laplacian_pyramid(I,nlev,subwindow) 19 | 20 | r = size(I,1); 21 | c = size(I,2); 22 | if ~exist('subwindow','var') 23 | subwindow = [1 r 1 c]; 24 | end 25 | if ~exist('nlev','var') 26 | nlev = numlevels([r c]); % build highest possible pyramid 27 | end 28 | 29 | % recursively build pyramid 30 | pyr = cell(nlev,1); 31 | filter = pyramid_filter; 32 | J = I; 33 | for l = 1:nlev - 1 34 | % apply low pass filter, and downsample 35 | [I,subwindow_child] = downsample(J,filter,subwindow); 36 | 37 | % in each level, store difference between image and upsampled low pass version 38 | pyr{l} = J - upsample(I,filter,subwindow); 39 | 40 | J = I; % continue with low pass image 41 | subwindow = subwindow_child; 42 | end 43 | pyr{nlev} = J; % the coarest level contains the residual low pass image 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/scripts/style_transfer/llf.m: -------------------------------------------------------------------------------- 1 | % Perform the local laplacian filter using the function 2 | % f(x,ref)=x+fact*(I-ref)*exp(-(I-ref)²/(2*sigma²)) 3 | 4 | % Perform the local laplacian filter using any function 5 | 6 | % This script implements edge-aware detail and tone manipulation as 7 | % described in : 8 | % Fast and Robust Pyramid-based Image Processing. 9 | % Mathieu Aubry, Sylvain Paris, Samuel W. Hasinoff, Jan Kautz, and Frédo Durand. 10 | % MIT technical report, November 2011 11 | 12 | % INPUT 13 | % I : input greyscale image 14 | % r : a function handle to the remaping function 15 | % N : number discretisation values of the intensity 16 | % 17 | 18 | % OUTPUT 19 | % F : filtered image 20 | 21 | % aubry.mathieu@gmail.com Sept 2012 22 | 23 | 24 | function [F]=llf(I,sigma,fact,N) 25 | 26 | [height width]=size(I); 27 | n_levels=ceil(log(min(height,width))-log(2))+2; 28 | discretisation=linspace(0,1,N); 29 | discretisation_step=discretisation(2); 30 | 31 | input_gaussian_pyr=gaussian_pyramid(I,n_levels); 32 | output_laplace_pyr=laplacian_pyramid(I,n_levels); 33 | output_laplace_pyr{n_levels}=input_gaussian_pyr{n_levels}; 34 | 35 | for ref=discretisation 36 | I_remap=fact*(I-ref).*exp(-(I-ref).*(I-ref)./(2*sigma*sigma)); 37 | temp_laplace_pyr=laplacian_pyramid(I_remap,n_levels); 38 | for level=1:n_levels-1 39 | output_laplace_pyr{level}=output_laplace_pyr{level}+... 40 | (abs(input_gaussian_pyr{level}-ref)= 0: 71 | with torch.cuda.device(config.GPU): 72 | config.model.cuda() 73 | 74 | # test 75 | i_bar = tqdm(total=len(test_data), desc='#Images') 76 | for idx, imgs in enumerate(test_data): 77 | name = os.path.basename(test_data.get_path(idx)) 78 | 79 | imgs = config.forward(imgs, config) 80 | 81 | for path, img in zip(config.save_paths, imgs): 82 | imsave(os.path.join(path, name), tensor_to_img(img, transpose=True)) 83 | 84 | i_bar.update() 85 | 86 | if config.compare_paths is None: 87 | compare(config.save_paths[0], os.path.join(config.IMG, config.TASK, str(config.SET_NAME))) 88 | else: 89 | for pre, gt in config.compare_paths: 90 | compare(pre, gt) -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/test_hr.py: -------------------------------------------------------------------------------- 1 | import copy 2 | import argparse 3 | 4 | from torch.autograd import Variable 5 | 6 | from module import DeepGuidedFilter, DeepGuidedFilterAdvanced, DeepGuidedFilterConvGF, DeepGuidedFilterGuidedMapConvGF 7 | 8 | from test_base import * 9 | 10 | parser = argparse.ArgumentParser(description='Evaluate Deep Guided Filtering Networks') 11 | parser.add_argument('--task', type=str, default='l0_smooth', help='TASK') 12 | parser.add_argument('--name', type=str, default='HR', help='NAME') 13 | parser.add_argument('--model', type=str, default='deep_guided_filter', help='model') 14 | args = parser.parse_args() 15 | 16 | config = copy.deepcopy(default_config) 17 | 18 | config.TASK = args.task 19 | config.NAME = args.name 20 | config.SET_NAME = 1024 21 | 22 | # model 23 | if args.model in ['guided_filter', 'deep_guided_filter']: 24 | model = DeepGuidedFilter() 25 | elif args.model == 'deep_guided_filter_advanced': 26 | model = DeepGuidedFilterAdvanced() 27 | elif args.model == 'deep_conv_guided_filter': 28 | model = DeepGuidedFilterConvGF() 29 | elif args.model == 'deep_conv_guided_filter_adv': 30 | model = DeepGuidedFilterGuidedMapConvGF() 31 | else: 32 | print('Not a valid model!') 33 | exit(-1) 34 | 35 | if args.model == 'guided_filter': 36 | model.init_lr(os.path.join(config.MODEL_PATH, config.TASK, 'LR', 'snapshots', 'net_latest.pth')) 37 | else: 38 | model.load_state_dict( 39 | torch.load( 40 | os.path.join(config.MODEL_PATH, 41 | config.TASK, 42 | config.NAME, 43 | 'snapshots', 44 | 'net_latest.pth') 45 | ) 46 | ) 47 | 48 | config.model = model 49 | 50 | # forward 51 | def forward(imgs, config): 52 | lr_x, hr_x = imgs[2].unsqueeze(0), imgs[0].unsqueeze(0) 53 | if config.GPU >= 0: 54 | with torch.cuda.device(config.GPU): 55 | lr_x = lr_x.cuda() 56 | hr_x = hr_x.cuda() 57 | 58 | return config.model(Variable(lr_x), Variable(hr_x)).data.cpu() 59 | config.forward = forward 60 | 61 | run(config) -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/test_time.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | import argparse 4 | 5 | import torch 6 | from torch.autograd import Variable 7 | 8 | from module import AdaptiveNorm, DeepGuidedFilter, DeepGuidedFilterAdvanced, FastGuidedFilter, ConvGuidedFilter, DeepGuidedFilterConvGF, DeepGuidedFilterGuidedMapConvGF 9 | 10 | parser = argparse.ArgumentParser(description='Runing time') 11 | parser.add_argument('--gpu', type=int, default= 0, help='GPU') 12 | parser.add_argument('--low_size', type=int, default= 64, help='LOW_SIZE') 13 | parser.add_argument('--full_size', type=int, default=2048, help='FULL_SIZE') 14 | parser.add_argument('--iter_size', type=int, default= 100, help='TOTAL_ITER') 15 | parser.add_argument('--model_id', type=int, default= 0, help='MODEL_ID') 16 | args = parser.parse_args() 17 | 18 | SAVE_FOLDER = 'time' 19 | GPU = args.gpu 20 | LOW_SIZE = args.low_size 21 | FULL_SIZE = args.full_size 22 | TOTAL_ITER = args.iter_size 23 | MODEL_ID = args.model_id 24 | 25 | # model - forward 26 | model_forward = [ 27 | ('deep_guided_filter', (DeepGuidedFilter(), lambda model, imgs: model(imgs[0], imgs[1]))), 28 | ('deep_guided_filter_layer', (FastGuidedFilter(1, 1e-8), lambda model, imgs: model(imgs[0], imgs[0], imgs[1]))), 29 | ('deep_guided_filter_advanced', (DeepGuidedFilterAdvanced(), lambda model, imgs: model(imgs[0], imgs[1]))), 30 | ('deep_conv_guided_filter_layer', (ConvGuidedFilter(1, AdaptiveNorm), lambda model, imgs: model(imgs[0], imgs[0], imgs[1]))), 31 | ('deep_conv_guided_filter', (DeepGuidedFilterConvGF(), lambda model, imgs: model(imgs[0], imgs[1]))), 32 | ('deep_conv_guided_filter_adv', (DeepGuidedFilterGuidedMapConvGF(), lambda model, imgs: model(imgs[0], imgs[1]))) 33 | ] 34 | 35 | # mkdir 36 | if not os.path.isdir(SAVE_FOLDER): 37 | os.makedirs(SAVE_FOLDER) 38 | 39 | # prepare img 40 | imgs = [torch.rand((1, 3, LOW_SIZE, LOW_SIZE)), torch.rand((1, 3, FULL_SIZE, FULL_SIZE))] 41 | if GPU >= 0: 42 | with torch.cuda.device(GPU): 43 | imgs = [img.cuda() for img in imgs] 44 | imgs = [Variable(img, requires_grad=False) for img in imgs] 45 | 46 | # prepare model 47 | name, (model, forward) = model_forward[MODEL_ID] 48 | if GPU >= 0: 49 | with torch.cuda.device(GPU): 50 | model = model.cuda() 51 | model.eval() 52 | 53 | # Warm up 54 | for _ in range(TOTAL_ITER): 55 | forward(model, imgs) 56 | 57 | # Test 58 | print('Test {} ...'.format(name)) 59 | 60 | t = time.time() 61 | for _ in range(TOTAL_ITER): 62 | forward(model, imgs) 63 | mean_time = (time.time()-t)/TOTAL_ITER 64 | 65 | print('\tmean time: {}'.format(mean_time)) 66 | 67 | # Log 68 | file_name = '{}_time.txt' if GPU >= 0 else '{}_time_cpu.txt' 69 | mode = 'a+' if os.path.isfile(os.path.join(SAVE_FOLDER, file_name.format(FULL_SIZE))) else 'w' 70 | with open(os.path.join(SAVE_FOLDER, file_name.format(FULL_SIZE)), mode) as f: 71 | f.write('{},{}\n'.format(name, mean_time)) 72 | -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/train_base.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | 4 | import torch 5 | 6 | from torch import nn 7 | from torch import optim 8 | from torch.autograd import Variable 9 | from torch.utils.data import DataLoader 10 | 11 | from utils import Config 12 | from dataset import SuDataset 13 | from vis_utils import VisUtils 14 | 15 | 16 | default_config = Config( 17 | TASK = None, 18 | NAME = 'LR', 19 | N_START = 0, 20 | N_EPOCH = 150, 21 | DATA_SET = 512, 22 | FINE_SIZE = -1, 23 | #################### CONSTANT ##################### 24 | IMG = 'dataset', 25 | SAVE = 'checkpoints', 26 | LIST = 'train_test_list', 27 | BATCH = 1, 28 | SHOW_INTERVEL = 64, 29 | N_PROCESS = 4, 30 | LOW_SIZE = 64, 31 | GPU = 0, 32 | LR = 0.0001, 33 | # clip 34 | clip = None, 35 | # model 36 | model = None, 37 | # forward 38 | forward = None, 39 | # img size 40 | exceed_limit = None, 41 | # vis 42 | vis = None 43 | ) 44 | 45 | def run(config, keep_vis=False): 46 | assert config.TASK is not None, 'Please set task name: TASK' 47 | 48 | save_path = os.path.join(config.SAVE, config.TASK, config.NAME) 49 | path = os.path.join(save_path, 'snapshots') 50 | if not os.path.isdir(path): 51 | os.makedirs(path) 52 | 53 | # data set 54 | train_data = SuDataset(config.IMG, 55 | os.path.join(config.LIST, 56 | config.TASK, 57 | 'train_{}.csv'.format(config.DATA_SET)), 58 | low_size=config.LOW_SIZE, 59 | fine_size=config.FINE_SIZE) 60 | train_loader = DataLoader(train_data, batch_size=config.BATCH, shuffle=True, num_workers=config.N_PROCESS) 61 | 62 | # loss 63 | criterion = nn.MSELoss() 64 | 65 | if config.GPU >= 0: 66 | with torch.cuda.device(config.GPU): 67 | config.model.cuda() 68 | criterion.cuda() 69 | 70 | # setup optimizer 71 | optimizer = optim.Adam(config.model.parameters(), lr=config.LR) 72 | 73 | if config.vis is None: 74 | config.vis = VisUtils(os.path.join(config.TASK, config.NAME), len(train_loader), config.N_EPOCH) 75 | else: 76 | config.vis.reset(len(train_loader), config.N_EPOCH) 77 | for epoch in range(config.N_START, config.N_START+config.N_EPOCH): 78 | total_loss = 0 79 | for idx, imgs in enumerate(train_loader): 80 | if config.exceed_limit is not None and config.exceed_limit(imgs[0].size()[2:]): 81 | config.vis.update({}) 82 | continue 83 | 84 | t = time.time() 85 | 86 | y, gt = config.forward(imgs, config) 87 | loss = criterion(y, Variable(gt)) 88 | # backward 89 | optimizer.zero_grad() 90 | loss.backward() 91 | if config.clip is not None: 92 | torch.nn.utils.clip_grad_norm(config.model.parameters(), config.clip) 93 | optimizer.step() 94 | 95 | ##################### PLOT/SHOW ###################### 96 | global_step = epoch*len(train_loader)+idx 97 | 98 | loss = loss.item() * 255 * 255 99 | total_loss += loss 100 | 101 | config.vis.writer.add_scalars('loss', { 102 | 'instance_loss': loss, 103 | 'mean_loss': total_loss/(idx+1) 104 | }, global_step=global_step) 105 | config.vis.writer.add_scalar('time', time.time()-t, global_step=global_step) 106 | config.vis.update({'loss': total_loss/(idx+1), 'time': time.time()-t}) 107 | 108 | if idx % (config.SHOW_INTERVEL//config.BATCH) == 0: 109 | for name, param in config.model.named_parameters(): 110 | if param.grad is not None: 111 | config.vis.writer.add_scalar('grad/'+name, param.grad.data.norm(2), global_step=global_step) 112 | 113 | # save 114 | torch.save(config.model.state_dict(), os.path.join(save_path, 'snapshots', 'net_epoch_{}.pth'.format(epoch))) 115 | torch.save(config.model.state_dict(), os.path.join(save_path, 'snapshots', 'net_latest.pth')) 116 | config.vis.next_epoch() 117 | 118 | if not keep_vis: 119 | config.vis.close() -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/train_hr.py: -------------------------------------------------------------------------------- 1 | import copy 2 | import argparse 3 | 4 | from train_base import * 5 | 6 | from module import DeepGuidedFilter, DeepGuidedFilterAdvanced, DeepGuidedFilterConvGF, DeepGuidedFilterGuidedMapConvGF 7 | 8 | parser = argparse.ArgumentParser(description='Train Deep Guided Filtering Networks') 9 | parser.add_argument('--task', type=str, default='l0_smooth', help='TASK') 10 | parser.add_argument('--name', type=str, default='HR', help='NAME') 11 | parser.add_argument('--model', type=str, default='deep_guided_filter', help='model') 12 | args = parser.parse_args() 13 | 14 | config = copy.deepcopy(default_config) 15 | 16 | config.TASK = args.task 17 | config.NAME = args.name 18 | config.N_EPOCH = 150 19 | config.DATA_SET = 512 20 | 21 | # model 22 | if args.model == 'deep_guided_filter': 23 | config.model = DeepGuidedFilter() 24 | elif args.model == 'deep_guided_filter_advanced': 25 | config.model = DeepGuidedFilterAdvanced() 26 | elif args.model == 'deep_conv_guided_filter': 27 | config.model = DeepGuidedFilterConvGF() 28 | elif args.model == 'deep_conv_guided_filter_adv': 29 | config.model = DeepGuidedFilterGuidedMapConvGF() 30 | else: 31 | print('Not a valid model!') 32 | exit(-1) 33 | 34 | def forward(imgs, config): 35 | x_hr, gt_hr, x_lr = imgs[:3] 36 | if config.GPU >= 0: 37 | with torch.cuda.device(config.GPU): 38 | x_hr, gt_hr, x_lr = x_hr.cuda(), gt_hr.cuda(), x_lr.cuda() 39 | 40 | return config.model(Variable(x_lr), Variable(x_hr)), gt_hr 41 | 42 | config.forward = forward 43 | config.clip = 0.01 44 | 45 | run(config, keep_vis=True) 46 | 47 | ########################################## 48 | config.N_START = config.N_EPOCH 49 | config.N_EPOCH = 30 50 | config.DATA_SET = 'random' 51 | config.exceed_limit = lambda size: size[0]*size[1] > 2048**2 52 | 53 | run(config) -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/train_hr_finetune.py: -------------------------------------------------------------------------------- 1 | import copy 2 | import argparse 3 | 4 | from train_base import * 5 | 6 | from module import DeepGuidedFilter, DeepGuidedFilterAdvanced, DeepGuidedFilterConvGF, DeepGuidedFilterGuidedMapConvGF 7 | 8 | parser = argparse.ArgumentParser(description='Finetune Deep Guided Filtering Networks') 9 | parser.add_argument('--task', type=str, default='l0_smooth', help='TASK') 10 | parser.add_argument('--name', type=str, default='HR_FT', help='NAME') 11 | parser.add_argument('--model', type=str, default='deep_guided_filter', help='model') 12 | args = parser.parse_args() 13 | 14 | config = copy.deepcopy(default_config) 15 | 16 | config.TASK = args.task 17 | config.NAME = args.name 18 | config.N_EPOCH = 30 19 | config.DATA_SET = 'random' 20 | 21 | # model 22 | if args.model == 'deep_guided_filter': 23 | config.model = DeepGuidedFilter() 24 | elif args.model == 'deep_guided_filter_advanced': 25 | config.model = DeepGuidedFilterAdvanced() 26 | elif args.model == 'deep_conv_guided_filter': 27 | config.model = DeepGuidedFilterConvGF() 28 | elif args.model == 'deep_conv_guided_filter_adv': 29 | config.model = DeepGuidedFilterGuidedMapConvGF() 30 | else: 31 | print('Not a valid model!') 32 | exit(-1) 33 | config.model.init_lr(os.path.join(config.SAVE, config.TASK, 'LR', 'snapshots', 'net_latest.pth')) 34 | 35 | def forward(imgs, config): 36 | x_hr, gt_hr, x_lr = imgs[:3] 37 | if config.GPU >= 0: 38 | with torch.cuda.device(config.GPU): 39 | x_hr, gt_hr, x_lr = x_hr.cuda(), gt_hr.cuda(), x_lr.cuda() 40 | 41 | return config.model(Variable(x_lr), Variable(x_hr)), gt_hr 42 | 43 | config.forward = forward 44 | config.exceed_limit = lambda size: size[0]*size[1] > 2048**2 45 | config.clip = 0.01 46 | 47 | run(config) -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/train_lr.py: -------------------------------------------------------------------------------- 1 | import copy 2 | import argparse 3 | 4 | from train_base import * 5 | 6 | from module import build_lr_net 7 | 8 | parser = argparse.ArgumentParser(description='Train Deep Guided Filtering Networks') 9 | parser.add_argument('--task', type=str, default='l0_smooth', help='TASK') 10 | args = parser.parse_args() 11 | 12 | config = copy.deepcopy(default_config) 13 | 14 | config.TASK = args.task 15 | config.NAME = 'LR' 16 | config.N_EPOCH = 150 17 | config.DATA_SET = 512 18 | 19 | # model 20 | config.model = build_lr_net() 21 | 22 | def forward(imgs, config): 23 | x, y = imgs[2:] 24 | if config.GPU >= 0: 25 | with torch.cuda.device(config.GPU): 26 | x, y = x.cuda(), y.cuda() 27 | 28 | return config.model(Variable(x)), y 29 | 30 | config.forward = forward 31 | 32 | run(config) -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/utils.py: -------------------------------------------------------------------------------- 1 | import os 2 | import numpy as np 3 | 4 | import warnings 5 | warnings.simplefilter('ignore') 6 | 7 | from multiprocessing import Pool 8 | 9 | from skimage import img_as_ubyte 10 | from skimage.io import imread 11 | from skimage.color import grey2rgb 12 | from skimage.transform import resize 13 | from skimage.measure import compare_mse, compare_psnr, compare_ssim 14 | 15 | class Config(object): 16 | def __init__(self, **params): 17 | for k, v in params.items(): 18 | self.__dict__[k] = v 19 | 20 | def tensor_to_img(tensor, transpose=False): 21 | im = np.asarray(np.clip(np.squeeze(tensor.numpy()) * 255, 0, 255), dtype=np.uint8) 22 | if transpose: 23 | im = im.transpose((1, 2, 0)) 24 | 25 | return im 26 | 27 | def calc_metric_with_np(pre_im, gt_im, multichannel=True): 28 | return compare_mse(pre_im, gt_im),\ 29 | compare_psnr(pre_im, gt_im),\ 30 | compare_ssim(pre_im, gt_im, multichannel=multichannel) 31 | 32 | def calc_metric_per_img(im_name, pre_path, gt_path, opts={}): 33 | pre_im_path = os.path.join(pre_path, im_name) 34 | gt_im_path = os.path.join(gt_path, im_name) 35 | 36 | assert os.path.isfile(pre_im_path) 37 | assert os.path.isfile(gt_im_path) or os.path.islink(gt_im_path) 38 | 39 | pre = img_as_ubyte(imread(pre_im_path)) 40 | gt = img_as_ubyte(imread(gt_im_path)) 41 | if gt.ndim == 2: 42 | gt = grey2rgb(gt) 43 | if pre.shape != gt.shape: 44 | gt = img_as_ubyte(resize(gt, pre.shape[:2], mode='reflect')) 45 | 46 | return calc_metric_with_np(pre, gt, **opts) 47 | 48 | def calc_metric(pre_path, gt_path, n_process=8): 49 | params = [(im_name, pre_path, gt_path) for im_name in os.listdir(pre_path)] 50 | return np.asarray(Pool(n_process).starmap(calc_metric_per_img, params)) -------------------------------------------------------------------------------- /ImageProcessing/DeepGuidedFilteringNetwork/vis_utils.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from tqdm import tqdm 4 | 5 | from tensorboardX import SummaryWriter 6 | 7 | class VisUtils(object): 8 | def __init__(self, name, n_iter, n_epoch, log_dir='tensorboard_logs', stat_dir='tensorboard_stats'): 9 | self.n_iter = n_iter 10 | self.stat_dir = os.path.join(stat_dir, name) 11 | if not os.path.isdir(self.stat_dir): 12 | os.makedirs(self.stat_dir) 13 | 14 | self.e_bar = tqdm(total=n_epoch, desc='#Epoch') 15 | self.i_bar = tqdm(total=n_iter, desc=' #Iter', leave=False) 16 | 17 | self.writer = SummaryWriter(log_dir=os.path.join(log_dir, name)) 18 | 19 | def reset(self, n_iter, n_epoch): 20 | self.e_bar.close() 21 | self.i_bar.close() 22 | self.e_bar = tqdm(total=n_epoch, desc='#Epoch') 23 | self.i_bar = tqdm(total=n_iter, desc=' #Iter', leave=False) 24 | 25 | 26 | def update(self, post_fix): 27 | self.i_bar.set_postfix(**post_fix) 28 | self.i_bar.update() 29 | 30 | def next_epoch(self): 31 | self.e_bar.update() 32 | 33 | self.i_bar.close() 34 | self.i_bar = tqdm(total=self.n_iter, desc=' #Iter', leave=False) 35 | 36 | def close(self): 37 | self.writer.export_scalars_to_json(os.path.join(self.stat_dir, 'scalars.json')) 38 | self.writer.close() -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Fast End-to-End Trainable Guided Filter 2 | [[Project]](http://wuhuikai.me/DeepGuidedFilterProject) [[Paper]](http://wuhuikai.me/DeepGuidedFilterProject/deep_guided_filter.pdf) [[arXiv]](https://arxiv.org/abs/1803.05619) [[Demo]](http://wuhuikai.me/DeepGuidedFilterProject#demo) [[Home]](http://wuhuikai.me) 3 | 4 | Official implementation of **Fast End-to-End Trainable Guided Filter**. 5 | **Faster**, **Better** and **Lighter** for pixel-wise image prediction. 6 | 7 | ## Overview 8 | ![](images/results.jpg) 9 | 10 | **DeepGuidedFilter** is the author's implementation of: 11 | 12 | **Fast End-to-End Trainable Guided Filter** 13 | Huikai Wu, Shuai Zheng, Junge Zhang, Kaiqi Huang 14 | CVPR 2018 15 | 16 | With our method, FCNs can run **10-100** times faster w/o performance drop. 17 | 18 | Contact: Hui-Kai Wu (huikaiwu@icloud.com) 19 | 20 | ## Get Started 21 | ### Prepare Environment [Python>=3.6] 22 | 1. Download source code from GitHub. 23 | ```sh 24 | git clone https://github.com/wuhuikai/DeepGuidedFilter 25 | 26 | cd DeepGuidedFilter && git checkout release 27 | ``` 28 | 2. Install dependencies. 29 | ```sh 30 | conda install opencv=3.4 31 | conda install pytorch=1.1 torchvision=0.2 cudatoolkit=9.0 -c pytorch 32 | 33 | pip install -r requirements.txt 34 | ``` 35 | 3. (**Optional**) Install dependencies for MonoDepth. 36 | ```sh 37 | cd ComputerVision/MonoDepth 38 | 39 | pip install -r requirements.txt 40 | ``` 41 | ### Ready to **GO** ! 42 | #### Image Processing 43 | ```sh 44 | cd ImageProcessing/DeepGuidedFilteringNetwork 45 | 46 | python predict.py --task auto_ps \ 47 | --img_path ../../images/auto_ps.jpg \ 48 | --save_folder . \ 49 | --model deep_guided_filter_advanced \ 50 | --low_size 64 \ 51 | --gpu 0 52 | ``` 53 | See [Here](ImageProcessing/DeepGuidedFilteringNetwork/#predict) or `python predict.py -h` for more details. 54 | #### Semantic Segmentation with Deeplab-Resnet 55 | 1. Enter the directory. 56 | ```sh 57 | cd ComputerVision/Deeplab-Resnet 58 | ``` 59 | 2. Download the pretrained model [[Google Drive](https://drive.google.com/open?id=1YXZoZIZNR1ACewiUBp4UDvo_P65cCooK)|[BaiduYunPan](https://pan.baidu.com/s/1dEnpcGfchlZA_fVGdve0ig)]. 60 | 3. Run it now ! 61 | ```sh 62 | python predict_dgf.py --img_path ../../images/segmentation.jpg --snapshots [MODEL_PATH] 63 | ``` 64 | Note: 65 | 1. Result is in `../../images`. 66 | 2. Run `python predict_dgf.py -h` for more details. 67 | #### Saliency Detection with DSS 68 | 1. Enter the directory. 69 | ```sh 70 | cd ComputerVision/Saliency_DSS 71 | ``` 72 | 2. Download the pretrained model [[Google Drive](https://drive.google.com/open?id=1ZxbAAJw9BxCKj2e2QsBmCnjWLFlCGLf1)|[BaiduYunPan](https://pan.baidu.com/s/1pgOMh3V50lRa6slbIW_SKQ)]. 73 | 3. Try it now ! 74 | ```sh 75 | python predict.py --im_path ../../images/saliency.jpg \ 76 | --netG [MODEL_PATH] \ 77 | --thres 161 \ 78 | --dgf --nn_dgf \ 79 | --post_sigmoid --cuda 80 | ``` 81 | Note: 82 | 1. Result is in `../../images`. 83 | 2. See [Here](ComputerVision/Saliency_DSS/#try_on_an_image) or `python predict.py -h` for more details. 84 | #### Monocular Depth Estimation 85 | 1. Enter the directory. 86 | ```sh 87 | cd ComputerVision/MonoDepth 88 | ``` 89 | 2. **Download** and **Unzip** Pretrained Model [[Google Drive](https://drive.google.com/file/d/1dKDYRtZPahoFJZ5ZJNilgHEvT6gG4SC6/view?usp=sharing)|[BaiduYunPan](https://pan.baidu.com/s/1-GkMaRAVym8UEmQ6ia5cHw)] 90 | 2. Run on an Image 91 | ```sh 92 | python monodepth_simple.py --image_path ../../images/depth.jpg --checkpoint_path [MODEL_PATH] --guided_filter 93 | ``` 94 | Note: 95 | 1. Result is in `../../images`. 96 | 2. See [Here](ComputerVision/MonoDepth/#try_it_on_an_image) or `python monodepth_simple.py -h` for more details. 97 | 98 | ## Guided Filtering Layer 99 | ### Install Released Version 100 | * PyTorch Version 101 | ```sh 102 | pip install guided-filter-pytorch 103 | ``` 104 | * Tensorflow Version 105 | ```sh 106 | pip install guided-filter-tf 107 | ``` 108 | ### Usage 109 | * PyTorch Version 110 | ```python 111 | from guided_filter_pytorch.guided_filter import FastGuidedFilter 112 | 113 | hr_y = FastGuidedFilter(r, eps)(lr_x, lr_y, hr_x) 114 | ``` 115 | ```python 116 | from guided_filter_pytorch.guided_filter import GuidedFilter 117 | 118 | hr_y = GuidedFilter(r, eps)(hr_x, init_hr_y) 119 | ``` 120 | ``` 121 | from guided_filter_pytorch.guided_filter import ConvGuidedFilter 122 | 123 | hr_y = ConvGuidedFilter(r, norm)(lr_x, lr_y, hr_x) 124 | ``` 125 | * Tensorflow Version 126 | ```python 127 | from guided_filter_tf.guided_filter import fast_guided_filter 128 | 129 | hr_y = fast_guided_filter(lr_x, lr_y, hr_x, r, eps, nhwc) 130 | ``` 131 | ```python 132 | from guided_filter_tf.guided_filter import guided_filter 133 | 134 | hr_y = guided_filter(hr_x, init_hr_y, r, eps, nhwc) 135 | ``` 136 | ## Training from scratch 137 | ### Prepare Training Environment 138 | ```sh 139 | git checkout master 140 | 141 | conda install opencv=3.4 142 | conda install pytorch=1.1 torchvision=0.2 cudatoolkit=9.0 -c pytorch 143 | 144 | pip uninstall Pillow 145 | pip install -r requirements.txt 146 | 147 | # (Optional) For MonoDepth 148 | pip install -r ComputerVision/MonoDepth/requirements.txt 149 | ``` 150 | ### Start to Train 151 | * [Image Processing](ImageProcessing/DeepGuidedFilteringNetwork) 152 | * [Semantic Segmentation with Deeplab-Resnet](ComputerVision/Deeplab-Resnet) 153 | * [Saliency Detection with DSS](ComputerVision/Saliency_DSS) 154 | * [Monocular Depth Estimation](ComputerVision/MonoDepth) 155 | 156 | ## Citation 157 | ``` 158 | @inproceedings{wu2017fast, 159 | title = {Fast End-to-End Trainable Guided Filter}, 160 | author = {Wu, Huikai and Zheng, Shuai and Zhang, Junge and Huang, Kaiqi}, 161 | booktitle = {CVPR}, 162 | year = {2018} 163 | } 164 | ``` -------------------------------------------------------------------------------- /images/auto_ps.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/images/auto_ps.jpg -------------------------------------------------------------------------------- /images/depth.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/images/depth.jpg -------------------------------------------------------------------------------- /images/detail_manipulation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/images/detail_manipulation.jpg -------------------------------------------------------------------------------- /images/l0_smooth.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/images/l0_smooth.jpg -------------------------------------------------------------------------------- /images/non_local_dehazing.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/images/non_local_dehazing.jpg -------------------------------------------------------------------------------- /images/results.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/images/results.jpg -------------------------------------------------------------------------------- /images/saliency.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/images/saliency.jpg -------------------------------------------------------------------------------- /images/segmentation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/images/segmentation.jpg -------------------------------------------------------------------------------- /images/style_transfer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wuhuikai/DeepGuidedFilter/0caaf2d78e2333ccbd7fcb01dafa685cad98f1b1/images/style_transfer.jpg -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Pillow==6.1.0 2 | tqdm == 4.36.1 3 | scipy == 1.3.1 4 | rawpy == 0.13.1 5 | docopt == 0.6.2 6 | matplotlib == 3.1.1 7 | tensorboardX == 1.8 8 | guided_filter_pytorch == 3.7.5 9 | scikit_image == 0.15.0 10 | --------------------------------------------------------------------------------