diff --git a/.gitattributes b/.gitattributes index c7d9f3332a950355d5a77d85000f05e6f45435ea..d37e224cd93b53fe708e2515bc83d8d32e6ea99a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,27 +2,20 @@ *.arrow filter=lfs diff=lfs merge=lfs -text *.bin filter=lfs diff=lfs merge=lfs -text *.bz2 filter=lfs diff=lfs merge=lfs -text -*.ckpt filter=lfs diff=lfs merge=lfs -text *.ftz filter=lfs diff=lfs merge=lfs -text *.gz filter=lfs diff=lfs merge=lfs -text *.h5 filter=lfs diff=lfs merge=lfs -text *.joblib filter=lfs diff=lfs merge=lfs -text *.lfs.* filter=lfs diff=lfs merge=lfs -text -*.mlmodel filter=lfs diff=lfs merge=lfs -text *.model filter=lfs diff=lfs merge=lfs -text *.msgpack filter=lfs diff=lfs merge=lfs -text -*.npy filter=lfs diff=lfs merge=lfs -text -*.npz filter=lfs diff=lfs merge=lfs -text *.onnx filter=lfs diff=lfs merge=lfs -text *.ot filter=lfs diff=lfs merge=lfs -text *.parquet filter=lfs diff=lfs merge=lfs -text *.pb filter=lfs diff=lfs merge=lfs -text -*.pickle filter=lfs diff=lfs merge=lfs -text -*.pkl filter=lfs diff=lfs merge=lfs -text *.pt filter=lfs diff=lfs merge=lfs -text *.pth filter=lfs diff=lfs merge=lfs -text *.rar filter=lfs diff=lfs merge=lfs -text -*.safetensors filter=lfs diff=lfs merge=lfs -text saved_model/**/* filter=lfs diff=lfs merge=lfs -text *.tar.* filter=lfs diff=lfs merge=lfs -text *.tflite filter=lfs diff=lfs merge=lfs -text @@ -30,5 +23,6 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text *.wasm filter=lfs diff=lfs merge=lfs -text *.xz filter=lfs diff=lfs merge=lfs -text *.zip filter=lfs diff=lfs merge=lfs -text -*.zst filter=lfs diff=lfs merge=lfs -text +*.zstandard filter=lfs diff=lfs merge=lfs -text *tfevents* filter=lfs diff=lfs merge=lfs -text +*.jpg filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..424fe7449885bd62782c3919ced2542cc1b21a27 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +__pycache__ +data/ +.idea +checkpoints/ +results/ +pretrained/ +.DS_Store +gradio_cached_examples/ +pretrain/ diff --git a/App_main.py b/App_main.py new file mode 100644 index 0000000000000000000000000000000000000000..b8b39f1959b1e0e9d511234a5923149def090a64 --- /dev/null +++ b/App_main.py @@ -0,0 +1,114 @@ +import numpy as np + +import models +import gradio as gr + +# os.system('nvidia-smi') +# os.system('ls /usr/local') +# os.system('pip install torch torchvision --extra-index-url https://download.pytorch.org/whl/cu113') +import torch +from torchvision import transforms +from torchvision.transforms import InterpolationMode + +device = 'cuda:0' if torch.cuda.is_available() else 'cpu' + + +def construct_sample(img, mean=0.5, std=0.5): + img = transforms.ToTensor()(img) + img = transforms.Resize(48, InterpolationMode.BICUBIC)(img) + img = transforms.Normalize(mean, std)(img) + return img + +def build_model(cp): + model_spec = torch.load(cp, map_location='cpu')['model'] + print(model_spec['args']) + model = models.make(model_spec, load_sd=True).to(device) + return model + + +# Function for building extraction +def sr_func(img, cp, scale): + if cp == 'UC': + checkpoint = 'pretrain/UC_FunSR_RDN.pth' + elif cp == 'AID': + checkpoint = 'pretrain/AID_FunSR_RDN.pth' + else: + raise NotImplementedError + sample = construct_sample(img) + print('Use: ', device) + model = build_model(checkpoint) + model.eval() + sample = sample.to(device) + sample = sample.unsqueeze(0) + + ori_size = torch.tensor(sample.shape[2:]) # BCHW + target_size = ori_size * scale + target_size = target_size.long() + lr_target_size_img = torch.nn.functional.interpolate(sample, scale_factor=scale, mode='nearest') + with torch.no_grad(): + pred = model(sample, target_size.tolist()) + + if isinstance(pred, list): + pred = pred[-1] + pred = pred * 0.5 + 0.5 + + pred *= 255 + pred = pred[0].detach().cpu() + lr_target_size_img = lr_target_size_img * 0.5 + 0.5 + lr_target_size_img = 255 * lr_target_size_img[0].detach().cpu() + + lr_target_size_img = torch.clamp(lr_target_size_img, 0, 255).permute(1,2,0).numpy().astype(np.uint8) + pred = torch.clamp(pred, 0, 255).permute(1,2,0).numpy().astype(np.uint8) + + line = np.ones((pred.shape[0], 5, 3), dtype=np.uint8) * 255 + pred = np.concatenate((lr_target_size_img, line, pred), axis=1) + return pred + +title = "FunSR" +description = "Gradio demo for continuous remote sensing image super-resolution. Upload image from UCMerced or AID Dataset or click any one of the examples, " \ + "Then change the upscaling magnification, and click \"Submit\" and wait for the super-resolved result. \n" \ + "Paper: Continuous Remote Sensing Image Super-Resolution based on Context Interaction in Implicit Function Space" + +article = "

FunSR Project " \ + "Page

" + +default_scale = 4.0 +examples = [ + ['examples/AID_school_161_LR.png', 'AID', default_scale], + ['examples/AID_bridge_19_LR.png', 'AID', default_scale], + ['examples/AID_parking_60_LR.png', 'AID', default_scale], + ['examples/AID_commercial_32_LR.png', 'AID', default_scale], + + ['examples/UC_airplane95_LR.png', 'UC', default_scale], + ['examples/UC_freeway35_LR.png', 'UC', default_scale], + ['examples/UC_storagetanks54_LR.png', 'UC', default_scale], + ['examples/UC_airplane00_LR.png', 'UC', default_scale], +] + +with gr.Blocks() as demo: + image_input = gr.inputs.Image(type='pil', label='Input Img') + # with gr.Row().style(equal_height=True): + # image_LR_output = gr.outputs.Image(label='LR Img', type='numpy') + image_output = gr.outputs.Image(label='SR Result', type='numpy') + with gr.Row(): + checkpoint = gr.inputs.Radio(['WHU', 'INRIA'], label='Checkpoint') + scale = gr.Slider(1, 12, value=4.0, step=0.1, label='scale') + +io = gr.Interface(fn=sr_func, + inputs=[image_input, + checkpoint, + scale + ], + outputs=[ + # image_LR_output, + image_output + ], + title=title, + description=description, + article=article, + allow_flagging='auto', + examples=examples, + cache_examples=True, + layout="grid" + ) +io.launch() diff --git a/README.md b/README.md index 26bedfccb849062b7160c0b3913e67f7b5d61c7f..6f4938b48397e042a36b937bb8450a3e928fdf9e 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,11 @@ --- title: FunSR -emoji: 👀 -colorFrom: blue +emoji: 🐢 +colorFrom: red colorTo: yellow sdk: gradio -sdk_version: 3.19.1 -app_file: app.py +sdk_version: 3.18.0 +app_file: App_main.py pinned: false --- - Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference diff --git a/configs/baselines/test_INR_liif_metasr_aliif.yaml b/configs/baselines/test_INR_liif_metasr_aliif.yaml new file mode 100644 index 0000000000000000000000000000000000000000..808b69c3dff4077fc9040331ff397ad81320eab2 --- /dev/null +++ b/configs/baselines/test_INR_liif_metasr_aliif.yaml @@ -0,0 +1,24 @@ +test_dataset: + dataset: + name: hr_data_loader + args: +# root_path: /data/kyanchen/datasets/UC/256 +# split_file: data_split/UC_split.json + root_path: /data/kyanchen/datasets/AID + split_file: data_split/AID_split.json + split_key: test + cache: none + wrapper: + name: inr_fixed_scale_sr_warp + args: + scale_ratio: 4 + patch_size: 48 + augment: false + val_mode: false + test_mode: true + return_cell: true + batch_size: 1 +eval_type: psnr+ssim +data_norm: + inp: {sub: [0.5], div: [0.5]} + gt: {sub: [0.5], div: [0.5]} \ No newline at end of file diff --git a/configs/baselines/train_1x-5x_INR_aliif.yaml b/configs/baselines/train_1x-5x_INR_aliif.yaml new file mode 100644 index 0000000000000000000000000000000000000000..78301d138ceed8f705bc179e8855219dfc4fd425 --- /dev/null +++ b/configs/baselines/train_1x-5x_INR_aliif.yaml @@ -0,0 +1,98 @@ +train_dataset: + dataset: + name: hr_data_loader + args: +# root_path: /data/kyanchen/datasets/UC/256 +# split_file: data_split/UC_split.json + root_path: /data/kyanchen/datasets/AID + split_file: data_split/AID_split.json + split_key: train + cache: none + wrapper: + name: inr_range_scale_sr_warp + args: + max_scale_ratio: 5 + patch_size: 48 + augment: true + sample_q: 1024 + val_mode: false + test_mode: false + return_cell: true + batch_size: 48 + num_workers: 4 + +val_dataset: + dataset: + name: hr_data_loader + args: +# root_path: /data/kyanchen/datasets/UC/256 +# split_file: data_split/UC_split.json + root_path: /data/kyanchen/datasets/AID + split_file: data_split/AID_split.json + split_key: val + first_k: 128 + cache: none + wrapper: + name: inr_range_scale_sr_warp + args: + max_scale_ratio: 5 + patch_size: 48 + augment: false + sample_q: 1024 + val_mode: true + test_mode: false + return_cell: true + batch_size: 48 + num_workers: 4 + +eval_type: psnr+ssim + +data_norm: + inp: {sub: [0.5], div: [0.5]} + gt: {sub: [0.5], div: [0.5]} + +model: + name: aliif + args: + encoder_spec: +# name: edsr-baseline +# name: rdn + name: rcan + args: + no_upsampling: true + imnet_spec: + name: mlp_pw + args: + out_dim: 3 + hidden_list: [16, 16, 16, 16] + pdn_spec: + name: ExpansionNet + args: + in_dim: 580 + out_dim: 10 + hidden_list: [ 256, 256, 256, 256 ] + basis_spec: + name: basis + args: + basis_num: 10 + hidden: 16 + state: train + path: ./save/test/epoch-last.pth + +optimizer: + name: adamw + args: + lr: 1.e-4 + +epoch_max: 3000 + +lr_scheduler: +# name: CosineAnnealingLR +# T_max: 1500 +# eta_min: 1.e-7 + name: MultiStepLR + milestones: [2000] + gamma: 0.1 + +epoch_val_interval: 40 +epoch_save_interval: 300 diff --git a/configs/baselines/train_1x-5x_INR_diinn_arbrcan_sadn_overnet.yaml b/configs/baselines/train_1x-5x_INR_diinn_arbrcan_sadn_overnet.yaml new file mode 100644 index 0000000000000000000000000000000000000000..14bbb447b6847ea78d4330aab2b4d79f7b6c0e55 --- /dev/null +++ b/configs/baselines/train_1x-5x_INR_diinn_arbrcan_sadn_overnet.yaml @@ -0,0 +1,81 @@ +train_dataset: + dataset: + name: hr_data_loader + args: +# root_path: /data/kyanchen/datasets/UC/256 +# split_file: data_split/UC_split.json + root_path: /data/kyanchen/datasets/AID + split_file: data_split/AID_split.json + split_key: train + cache: none + wrapper: + name: inr_diinn_select_scale_sr_warp + args: + scales: [2, 2.5, 3, 3.5, 4] + patch_size: 48 + augment: true + val_mode: false + test_mode: false + batch_size: 32 + num_workers: 4 + +val_dataset: + dataset: + name: hr_data_loader + args: +# root_path: /data/kyanchen/datasets/UC/256 +# split_file: data_split/UC_split.json + root_path: /data/kyanchen/datasets/AID + split_file: data_split/AID_split.json + split_key: val + first_k: 128 + cache: none + wrapper: + name: cnn_fixed_scale_sr_warp + args: + scale_ratio: 5 + patch_size: 48 + augment: false + val_mode: true + test_mode: false + batch_size: 8 + num_workers: 4 + +eval_type: psnr+ssim + +data_norm: + img: {sub: [0.5], div: [0.5]} + gt: {sub: [0.5], div: [0.5]} + +model: +# name: diinn +# name: arbrcan +# name: sadnarc +# name: edsr-sadn +# name: rdn-sadn + name: overnet + args: + encoder_spec: +# name: edsr-baseline +# name: rdn + name: rcan + args: + no_upsampling: true + +optimizer: + name: adamw + args: + lr: 1.e-4 + +epoch_max: 3000 + +lr_scheduler: +# name: CosineAnnealingLR +# T_max: 1500 +# eta_min: 1.e-7 + name: MultiStepLR + milestones: [2000] + gamma: 0.1 + +epoch_val_interval: 40 +epoch_save_interval: 300 diff --git a/configs/baselines/train_1x-5x_INR_liif.yaml b/configs/baselines/train_1x-5x_INR_liif.yaml new file mode 100644 index 0000000000000000000000000000000000000000..db544ebf25d388e7845d8ae2cdcb372948b48f6c --- /dev/null +++ b/configs/baselines/train_1x-5x_INR_liif.yaml @@ -0,0 +1,85 @@ +train_dataset: + dataset: + name: hr_data_loader + args: +# root_path: /data/kyanchen/datasets/UC/256 +# split_file: data_split/UC_split.json + root_path: /data/kyanchen/datasets/AID + split_file: data_split/AID_split.json + split_key: train + cache: none + wrapper: + name: inr_range_scale_sr_warp + args: + max_scale_ratio: 5 + patch_size: 48 + augment: true + sample_q: 1024 + val_mode: false + test_mode: false + return_cell: true + batch_size: 64 + num_workers: 4 + +val_dataset: + dataset: + name: hr_data_loader + args: +# root_path: /data/kyanchen/datasets/UC/256 +# split_file: data_split/UC_split.json + root_path: /data/kyanchen/datasets/AID + split_file: data_split/AID_split.json + split_key: val + first_k: 128 + cache: none + wrapper: + name: inr_range_scale_sr_warp + args: + max_scale_ratio: 5 + patch_size: 48 + augment: false + sample_q: 1024 + val_mode: true + test_mode: false + return_cell: true + batch_size: 64 + num_workers: 4 + +eval_type: psnr+ssim + +data_norm: + inp: {sub: [0.5], div: [0.5]} + gt: {sub: [0.5], div: [0.5]} + +model: + name: liif + args: + encoder_spec: +# name: edsr-baseline +# name: rdn + name: rcan + args: + no_upsampling: true + imnet_spec: + name: mlp + args: + out_dim: 3 + hidden_list: [256, 256, 256, 256] + +optimizer: + name: adamw + args: + lr: 1.e-4 + +epoch_max: 4000 + +lr_scheduler: +# name: CosineAnnealingLR +# T_max: 1500 +# eta_min: 1.e-7 + name: MultiStepLR + milestones: [2500] + gamma: 0.1 + +epoch_val_interval: 40 +epoch_save_interval: 300 diff --git a/configs/baselines/train_1x-5x_INR_metasr.yaml b/configs/baselines/train_1x-5x_INR_metasr.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0c6faa1e0b290aa89d6fe43e5a40789b98f0c65f --- /dev/null +++ b/configs/baselines/train_1x-5x_INR_metasr.yaml @@ -0,0 +1,80 @@ +train_dataset: + dataset: + name: hr_data_loader + args: +# root_path: /data/kyanchen/datasets/UC/256 +# split_file: data_split/UC_split.json + root_path: /data/kyanchen/datasets/AID + split_file: data_split/AID_split.json + split_key: train + cache: none + wrapper: + name: inr_range_scale_sr_warp + args: + max_scale_ratio: 5 + patch_size: 48 + augment: true + sample_q: 1024 + val_mode: false + test_mode: false + return_cell: true + batch_size: 64 + num_workers: 4 + +val_dataset: + dataset: + name: hr_data_loader + args: +# root_path: /data/kyanchen/datasets/UC/256 +# split_file: data_split/UC_split.json + root_path: /data/kyanchen/datasets/AID + split_file: data_split/AID_split.json + split_key: val + first_k: 128 + cache: none + wrapper: + name: inr_range_scale_sr_warp + args: + max_scale_ratio: 5 + patch_size: 48 + augment: false + sample_q: 1024 + val_mode: true + test_mode: false + return_cell: true + batch_size: 64 + num_workers: 4 + +eval_type: psnr+ssim + +data_norm: + inp: {sub: [0.5], div: [0.5]} + gt: {sub: [0.5], div: [0.5]} + +model: + name: metasr + args: + encoder_spec: +# name: edsr-baseline +# name: rdn + name: rcan + args: + no_upsampling: true + +optimizer: + name: adamw + args: + lr: 1.e-4 + +epoch_max: 3000 + +lr_scheduler: +# name: CosineAnnealingLR +# T_max: 1500 +# eta_min: 1.e-7 + name: MultiStepLR + milestones: [2000] + gamma: 0.1 + +epoch_val_interval: 40 +epoch_save_interval: 300 diff --git a/configs/test_CNN.yaml b/configs/test_CNN.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7977706ec641383b44299596393b161265241729 --- /dev/null +++ b/configs/test_CNN.yaml @@ -0,0 +1,25 @@ +test_dataset: + dataset: + name: hr_data_loader + args: +# root_path: /data/kyanchen/datasets/UC/256 +# split_file: data_split/UC_split.json + root_path: /data/kyanchen/datasets/AID + split_file: data_split/AID_split.json + split_key: test + cache: none + wrapper: + name: cnn_fixed_scale_sr_warp + args: + scale_ratio: 5 + patch_size: 48 + augment: false + val_mode: false + test_mode: true + batch_size: 8 + +eval_type: psnr+ssim + +data_norm: + img: {sub: [0.5], div: [0.5]} + gt: {sub: [0.5], div: [0.5]} \ No newline at end of file diff --git a/configs/test_INR_diinn_arbrcan_funsr_overnet.yaml b/configs/test_INR_diinn_arbrcan_funsr_overnet.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5863b5c879bb862dd50699ab49904e3bac3d013b --- /dev/null +++ b/configs/test_INR_diinn_arbrcan_funsr_overnet.yaml @@ -0,0 +1,25 @@ +test_dataset: + dataset: + name: hr_data_loader + args: +# root_path: /data/kyanchen/datasets/UC/256 +# split_file: data_split/UC_split.json + root_path: /data/kyanchen/datasets/AID + split_file: data_split/AID_split.json + split_key: test + cache: none + wrapper: + name: cnn_fixed_scale_sr_warp + args: + scale_ratio: 5 + patch_size: 48 + augment: false + val_mode: false + test_mode: true + batch_size: 8 + +eval_type: psnr+ssim + +data_norm: + img: {sub: [0.5], div: [0.5]} + gt: {sub: [0.5], div: [0.5]} diff --git a/configs/test_interpolate.yaml b/configs/test_interpolate.yaml new file mode 100644 index 0000000000000000000000000000000000000000..da5446b5d9427227ebe8765297a4242dd43982e9 --- /dev/null +++ b/configs/test_interpolate.yaml @@ -0,0 +1,24 @@ +test_dataset: + dataset: + name: hr_data_loader + args: +# root_path: /data/kyanchen/datasets/UC/256 +# split_file: data_split/UC_split.json + root_path: /data/kyanchen/datasets/AID + split_file: data_split/AID_split.json + split_key: test + cache: none + wrapper: + name: cnn_fixed_scale_sr_warp + args: + scale_ratio: 4 + patch_size: 48 + test_mode: true + augment: false + batch_size: 64 + +eval_type: psnr+ssim + +data_norm: + img: {sub: [0.5], div: [0.5]} + gt: {sub: [0.5], div: [0.5]} \ No newline at end of file diff --git a/configs/train_1x-5x_INR_funsr.yaml b/configs/train_1x-5x_INR_funsr.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9872cfcc21e4146d9acbad1ae447b84f934fdcfd --- /dev/null +++ b/configs/train_1x-5x_INR_funsr.yaml @@ -0,0 +1,115 @@ +train_dataset: + dataset: + name: hr_data_loader + args: + root_path: /data/kyanchen/datasets/UC/256 + split_file: data_split/UC_split.json +# root_path: /data/kyanchen/datasets/AID +# split_file: data_split/AID_split.json + split_key: train + cache: none + wrapper: + name: inr_diinn_select_scale_sr_warp + args: + scales: [2, 2.5, 3, 3.5, 4] +# scales: [1.5, 1.7, 2, 2.3, 2.5, 2.7, 3, 3.3, 3.5, 3.7, 4, 4.3, 4.5, 4.7, 5] + patch_size: 48 + augment: true + val_mode: false + test_mode: false + batch_size: 8 + num_workers: 4 + +val_dataset: + dataset: + name: hr_data_loader + args: + root_path: /data/kyanchen/datasets/UC/256 + split_file: data_split/UC_split.json +# root_path: /data/kyanchen/datasets/AID +# split_file: data_split/AID_split.json + split_key: test +# first_k: 128 + cache: none + wrapper: + name: cnn_fixed_scale_sr_warp + args: + scale_ratio: 2 + patch_size: 48 + augment: false + val_mode: false + test_mode: true + batch_size: 4 + num_workers: 4 + +eval_type: psnr+ssim + +data_norm: + img: {sub: [0.5], div: [0.5]} + gt: {sub: [0.5], div: [0.5]} + +model: + name: funsr + args: + encoder_spec: + name: edsr-baseline +# name: rdn +# name: rcan + args: + no_upsampling: true + has_multiscale: true + neck: + name: transformer_neck + args: + d_dim: 256 + downsample: true + has_pe: true + has_norm: true + class_token: true + num_encoder_layers: 3 + decoder: + name: sirens + args: + num_inner_layers: 9 + is_residual: true + global_decoder: + name: sirens + is_proj: true + args: + num_inner_layers: 9 + is_residual: true + encoder_rgb: true + n_forward_times: 1 + encode_hr_coord: true + has_bn: true + encode_scale_ratio: true + local_unfold: false + weight_gen_func: 'nearest-exact' # bilinear, nearest-exact,bicubic + +optimizer: + name: adamw + args: + lr: 0.0001 +#optimizer: +# name: adam +# args: +# lr: 0.0001 + +epoch_max: 4000 + +lr_scheduler: +# name: CosineAnnealingLR +# T_max: 1500 +# eta_min: 1.e-7 + name: CosineAnnealingWarmUpLR + epochs: 4000 + warm_up_epochs: 50 + eta_min: 1.e-8 + +# name: MultiStepLR +# milestones: [2000, 3000] +# gamma: 0.1 + +#resume: checkpoints/EXP20221215_00/epoch-last.pth +epoch_val_interval: 50 +epoch_save_interval: 300 diff --git a/configs/train_CNN.yaml b/configs/train_CNN.yaml new file mode 100644 index 0000000000000000000000000000000000000000..da0ca249c49e7caf10b4a99715a7a371596ee595 --- /dev/null +++ b/configs/train_CNN.yaml @@ -0,0 +1,94 @@ +train_dataset: + dataset: + name: hr_data_loader + args: +# root_path: /data/kyanchen/datasets/UC/256 +# split_file: data_split/UC_split.json + root_path: /data/kyanchen/datasets/AID + split_file: data_split/AID_split.json + split_key: train + cache: none + wrapper: + name: cnn_fixed_scale_sr_warp + args: + scale_ratio: 2 + patch_size: 48 + augment: true + val_mode: false + test_mode: false + batch_size: 96 + num_workers: 8 + +val_dataset: + dataset: + name: hr_data_loader + args: +# root_path: /data/kyanchen/datasets/UC/256 +# split_file: data_split/UC_split.json + root_path: /data/kyanchen/datasets/AID + split_file: data_split/AID_split.json + split_key: val + cache: none + wrapper: + name: cnn_fixed_scale_sr_warp + args: + scale_ratio: 2 + patch_size: 48 + augment: false + val_mode: true + test_mode: false + batch_size: 32 + num_workers: 4 + +data_norm: + img: {sub: [0.5], div: [0.5]} + gt: {sub: [0.5], div: [0.5]} + +#model: +# name: TransENet +# args: +# scale_ratio: 2 + +#model: +# name: SRCNN +# args: +# scale_ratio: 2 + +#model: +# name: FSRCNN +# args: +# scale_ratio: 2 + +#model: +# name: LGCNET +# args: +# scale_ratio: 2 + +#model: +# name: DCM +# args: +# scale_ratio: 2 + +model: + name: VDSR + args: + scale_ratio: 2 + +optimizer: + name: adamw + args: + lr: 0.0001 + +epoch_max: 1300 +#epoch_max: 2000 + +lr_scheduler: +# name: CosineAnnealingLR +# T_max: 300 +# eta_min: 1.e-6 + name: MultiStepLR + milestones: [1000] + gamma: 0.5 + +epoch_val_interval: 50 +epoch_save_interval: 300 diff --git a/data_split/AID_split.json b/data_split/AID_split.json new file mode 100644 index 0000000000000000000000000000000000000000..886b2570b3fab7e9ac0372247afaa6635ad76b95 --- /dev/null +++ b/data_split/AID_split.json @@ -0,0 +1 @@ +{"train": ["Pond/pond_94.jpg", "Pond/pond_44.jpg", "Pond/pond_362.jpg", "Pond/pond_307.jpg", "Pond/pond_23.jpg", "Pond/pond_205.jpg", "Pond/pond_25.jpg", "Pond/pond_211.jpg", "Pond/pond_18.jpg", "Pond/pond_287.jpg", "Pond/pond_218.jpg", "Pond/pond_393.jpg", "Pond/pond_65.jpg", "Pond/pond_266.jpg", "Pond/pond_367.jpg", "Pond/pond_178.jpg", "Pond/pond_403.jpg", "Pond/pond_27.jpg", "Pond/pond_346.jpg", "Pond/pond_249.jpg", "Pond/pond_351.jpg", "Pond/pond_33.jpg", "Pond/pond_62.jpg", "Pond/pond_138.jpg", "Pond/pond_43.jpg", "Pond/pond_207.jpg", "Pond/pond_316.jpg", "Pond/pond_383.jpg", "Pond/pond_11.jpg", "Pond/pond_130.jpg", "Pond/pond_246.jpg", "Pond/pond_378.jpg", "Pond/pond_353.jpg", "Pond/pond_285.jpg", "Pond/pond_273.jpg", "Pond/pond_213.jpg", "Pond/pond_153.jpg", "Pond/pond_419.jpg", "Pond/pond_107.jpg", "Pond/pond_48.jpg", "Pond/pond_315.jpg", "Pond/pond_216.jpg", "Pond/pond_85.jpg", "Pond/pond_210.jpg", "Pond/pond_36.jpg", "Pond/pond_294.jpg", "Pond/pond_121.jpg", "Pond/pond_92.jpg", "Pond/pond_110.jpg", "Pond/pond_31.jpg", "Pond/pond_69.jpg", "Pond/pond_112.jpg", "Pond/pond_215.jpg", "Pond/pond_47.jpg", "Pond/pond_296.jpg", "Pond/pond_397.jpg", "Pond/pond_258.jpg", "Pond/pond_95.jpg", "Pond/pond_333.jpg", "Pond/pond_234.jpg", "Pond/pond_14.jpg", "Pond/pond_371.jpg", "Pond/pond_363.jpg", "Pond/pond_108.jpg", "Pond/pond_302.jpg", "Pond/pond_105.jpg", "Pond/pond_167.jpg", "Pond/pond_399.jpg", "Pond/pond_336.jpg", "Pond/pond_396.jpg", "Pond/pond_269.jpg", "Pond/pond_314.jpg", "Pond/pond_87.jpg", "Pond/pond_123.jpg", "Pond/pond_260.jpg", "Pond/pond_16.jpg", "Pond/pond_368.jpg", "Pond/pond_64.jpg", "Pond/pond_324.jpg", "Pond/pond_284.jpg", "Pond/pond_292.jpg", "Pond/pond_381.jpg", "Pond/pond_410.jpg", "Pond/pond_230.jpg", "Pond/pond_17.jpg", "Pond/pond_168.jpg", "Pond/pond_391.jpg", "Pond/pond_128.jpg", "Pond/pond_195.jpg", "Pond/pond_198.jpg", "Pond/pond_203.jpg", "Pond/pond_196.jpg", "Pond/pond_84.jpg", "Pond/pond_6.jpg", "Pond/pond_221.jpg", "Pond/pond_117.jpg", "Pond/pond_290.jpg", "Pond/pond_181.jpg", "Pond/pond_236.jpg", "Pond/pond_241.jpg", "Pond/pond_5.jpg", "Pond/pond_91.jpg", "Pond/pond_256.jpg", "Pond/pond_277.jpg", "Pond/pond_384.jpg", "Pond/pond_93.jpg", "Pond/pond_401.jpg", "Pond/pond_382.jpg", "Pond/pond_330.jpg", "Pond/pond_71.jpg", "Pond/pond_206.jpg", "Pond/pond_395.jpg", "Pond/pond_190.jpg", "Pond/pond_412.jpg", "Pond/pond_415.jpg", "Pond/pond_264.jpg", "Pond/pond_188.jpg", "Pond/pond_54.jpg", "Pond/pond_170.jpg", "Pond/pond_97.jpg", "Pond/pond_225.jpg", "Pond/pond_337.jpg", "Pond/pond_347.jpg", "Pond/pond_142.jpg", "Pond/pond_49.jpg", "Pond/pond_303.jpg", "Pond/pond_248.jpg", "Pond/pond_41.jpg", "Pond/pond_262.jpg", "Pond/pond_134.jpg", "Pond/pond_280.jpg", "Pond/pond_354.jpg", "Pond/pond_158.jpg", "Pond/pond_161.jpg", "Pond/pond_67.jpg", "Pond/pond_193.jpg", "Pond/pond_74.jpg", "Pond/pond_156.jpg", "Pond/pond_250.jpg", "Pond/pond_402.jpg", "Pond/pond_226.jpg", "Pond/pond_102.jpg", "Pond/pond_24.jpg", "Pond/pond_118.jpg", "Pond/pond_192.jpg", "Pond/pond_298.jpg", "Pond/pond_282.jpg", "Pond/pond_98.jpg", "Pond/pond_255.jpg", "Pond/pond_252.jpg", "Pond/pond_2.jpg", "Pond/pond_356.jpg", "Pond/pond_265.jpg", "Pond/pond_223.jpg", "Pond/pond_127.jpg", "Pond/pond_30.jpg", "Pond/pond_278.jpg", "Pond/pond_228.jpg", "Pond/pond_286.jpg", "Pond/pond_328.jpg", "Pond/pond_159.jpg", "Pond/pond_407.jpg", "Pond/pond_254.jpg", "Pond/pond_289.jpg", "Pond/pond_231.jpg", "Pond/pond_372.jpg", "Pond/pond_58.jpg", "Pond/pond_222.jpg", "Pond/pond_308.jpg", "Pond/pond_152.jpg", "Pond/pond_109.jpg", "Pond/pond_101.jpg", "Pond/pond_310.jpg", "Pond/pond_237.jpg", "Pond/pond_114.jpg", "Pond/pond_345.jpg", "Pond/pond_208.jpg", "Pond/pond_155.jpg", "Pond/pond_106.jpg", "Pond/pond_37.jpg", "Pond/pond_55.jpg", "Pond/pond_163.jpg", "Pond/pond_247.jpg", "Pond/pond_385.jpg", "Pond/pond_420.jpg", "Pond/pond_408.jpg", "Pond/pond_172.jpg", "Pond/pond_39.jpg", "Pond/pond_243.jpg", "Pond/pond_132.jpg", "Pond/pond_253.jpg", "Pond/pond_229.jpg", "Pond/pond_414.jpg", "Pond/pond_113.jpg", "Pond/pond_165.jpg", "Pond/pond_370.jpg", "Pond/pond_297.jpg", "Pond/pond_240.jpg", "Pond/pond_45.jpg", "Pond/pond_329.jpg", "Pond/pond_334.jpg", "Pond/pond_40.jpg", "Pond/pond_343.jpg", "Pond/pond_390.jpg", "Pond/pond_139.jpg", "Pond/pond_149.jpg", "Pond/pond_166.jpg", "Pond/pond_261.jpg", "Pond/pond_21.jpg", "Pond/pond_59.jpg", "Pond/pond_173.jpg", "Pond/pond_72.jpg", "Pond/pond_349.jpg", "Pond/pond_162.jpg", "Pond/pond_304.jpg", "Pond/pond_418.jpg", "Pond/pond_157.jpg", "Pond/pond_340.jpg", "Pond/pond_394.jpg", "Pond/pond_38.jpg", "Pond/pond_409.jpg", "Pond/pond_238.jpg", "Pond/pond_10.jpg", "Pond/pond_129.jpg", "Pond/pond_187.jpg", "Pond/pond_184.jpg", "Pond/pond_259.jpg", "Pond/pond_86.jpg", "Pond/pond_317.jpg", "Pond/pond_272.jpg", "Pond/pond_116.jpg", "Pond/pond_217.jpg", "Pond/pond_131.jpg", "Pond/pond_377.jpg", "Pond/pond_331.jpg", "Pond/pond_53.jpg", "Pond/pond_7.jpg", "Pond/pond_357.jpg", "Pond/pond_70.jpg", "Pond/pond_89.jpg", "Pond/pond_214.jpg", "Pond/pond_245.jpg", "Pond/pond_50.jpg", "Pond/pond_319.jpg", "Pond/pond_398.jpg", "Pond/pond_361.jpg", "Pond/pond_416.jpg", "Pond/pond_242.jpg", "Pond/pond_29.jpg", "Pond/pond_150.jpg", "Pond/pond_12.jpg", "Pond/pond_15.jpg", "Pond/pond_326.jpg", "Pond/pond_176.jpg", "Pond/pond_57.jpg", "Pond/pond_359.jpg", "Pond/pond_77.jpg", "Pond/pond_52.jpg", "Pond/pond_19.jpg", "Pond/pond_75.jpg", "Pond/pond_281.jpg", "Pond/pond_73.jpg", "Pond/pond_76.jpg", "Pond/pond_387.jpg", "Pond/pond_78.jpg", "Pond/pond_339.jpg", "Pond/pond_145.jpg", "Pond/pond_63.jpg", "Pond/pond_283.jpg", "Pond/pond_137.jpg", "Pond/pond_341.jpg", "Pond/pond_311.jpg", "Pond/pond_8.jpg", "Pond/pond_320.jpg", "Pond/pond_79.jpg", "Pond/pond_306.jpg", "Pond/pond_174.jpg", "Pond/pond_305.jpg", "Pond/pond_20.jpg", "Pond/pond_267.jpg", "Pond/pond_313.jpg", "Pond/pond_275.jpg", "Pond/pond_380.jpg", "Pond/pond_60.jpg", "Pond/pond_389.jpg", "Pond/pond_309.jpg", "Pond/pond_301.jpg", "Pond/pond_321.jpg", "Pond/pond_111.jpg", "Pond/pond_233.jpg", "Pond/pond_365.jpg", "Pond/pond_179.jpg", "Pond/pond_133.jpg", "Pond/pond_189.jpg", "Pond/pond_392.jpg", "Pond/pond_293.jpg", "Pond/pond_185.jpg", "Pond/pond_146.jpg", "Pond/pond_183.jpg", "Pond/pond_115.jpg", "Pond/pond_244.jpg", "Pond/pond_42.jpg", "Pond/pond_417.jpg", "Pond/pond_300.jpg", "Pond/pond_212.jpg", "Pond/pond_191.jpg", "Pond/pond_83.jpg", "Pond/pond_358.jpg", "Pond/pond_169.jpg", "Pond/pond_122.jpg", "Pond/pond_204.jpg", "Pond/pond_32.jpg", "Pond/pond_143.jpg", "Pond/pond_350.jpg", "Pond/pond_232.jpg", "Pond/pond_140.jpg", "Pond/pond_268.jpg", "Pond/pond_1.jpg", "Pond/pond_46.jpg", "Pond/pond_348.jpg", "Pond/pond_9.jpg", "Pond/pond_386.jpg", "Pond/pond_202.jpg", "Pond/pond_35.jpg", "Pond/pond_182.jpg", "Pond/pond_318.jpg", "Forest/forest_207.jpg", "Forest/forest_80.jpg", "Forest/forest_133.jpg", "Forest/forest_232.jpg", "Forest/forest_23.jpg", "Forest/forest_180.jpg", "Forest/forest_84.jpg", "Forest/forest_57.jpg", "Forest/forest_27.jpg", "Forest/forest_219.jpg", "Forest/forest_190.jpg", "Forest/forest_118.jpg", "Forest/forest_76.jpg", "Forest/forest_28.jpg", "Forest/forest_228.jpg", "Forest/forest_132.jpg", "Forest/forest_93.jpg", "Forest/forest_75.jpg", "Forest/forest_119.jpg", "Forest/forest_54.jpg", "Forest/forest_43.jpg", "Forest/forest_94.jpg", "Forest/forest_172.jpg", "Forest/forest_48.jpg", "Forest/forest_152.jpg", "Forest/forest_64.jpg", "Forest/forest_74.jpg", "Forest/forest_140.jpg", "Forest/forest_127.jpg", "Forest/forest_229.jpg", "Forest/forest_91.jpg", "Forest/forest_6.jpg", "Forest/forest_244.jpg", "Forest/forest_218.jpg", "Forest/forest_97.jpg", "Forest/forest_95.jpg", "Forest/forest_206.jpg", "Forest/forest_168.jpg", "Forest/forest_215.jpg", "Forest/forest_193.jpg", "Forest/forest_248.jpg", "Forest/forest_208.jpg", "Forest/forest_30.jpg", "Forest/forest_82.jpg", "Forest/forest_176.jpg", "Forest/forest_16.jpg", "Forest/forest_242.jpg", "Forest/forest_110.jpg", "Forest/forest_125.jpg", "Forest/forest_56.jpg", "Forest/forest_160.jpg", "Forest/forest_147.jpg", "Forest/forest_10.jpg", "Forest/forest_184.jpg", "Forest/forest_188.jpg", "Forest/forest_204.jpg", "Forest/forest_33.jpg", "Forest/forest_241.jpg", "Forest/forest_198.jpg", "Forest/forest_68.jpg", "Forest/forest_144.jpg", "Forest/forest_128.jpg", "Forest/forest_5.jpg", "Forest/forest_117.jpg", "Forest/forest_162.jpg", "Forest/forest_123.jpg", "Forest/forest_131.jpg", "Forest/forest_29.jpg", "Forest/forest_216.jpg", "Forest/forest_122.jpg", "Forest/forest_209.jpg", "Forest/forest_107.jpg", "Forest/forest_217.jpg", "Forest/forest_8.jpg", "Forest/forest_157.jpg", "Forest/forest_7.jpg", "Forest/forest_77.jpg", "Forest/forest_129.jpg", "Forest/forest_90.jpg", "Forest/forest_9.jpg", "Forest/forest_230.jpg", "Forest/forest_189.jpg", "Forest/forest_62.jpg", "Forest/forest_154.jpg", "Forest/forest_1.jpg", "Forest/forest_12.jpg", "Forest/forest_66.jpg", "Forest/forest_36.jpg", "Forest/forest_58.jpg", "Forest/forest_203.jpg", "Forest/forest_146.jpg", "Forest/forest_41.jpg", "Forest/forest_135.jpg", "Forest/forest_224.jpg", "Forest/forest_24.jpg", "Forest/forest_222.jpg", "Forest/forest_13.jpg", "Forest/forest_235.jpg", "Forest/forest_150.jpg", "Forest/forest_103.jpg", "Forest/forest_170.jpg", "Forest/forest_34.jpg", "Forest/forest_210.jpg", "Forest/forest_105.jpg", "Forest/forest_112.jpg", "Forest/forest_113.jpg", "Forest/forest_183.jpg", "Forest/forest_98.jpg", "Forest/forest_121.jpg", "Forest/forest_70.jpg", "Forest/forest_130.jpg", "Forest/forest_51.jpg", "Forest/forest_138.jpg", "Forest/forest_79.jpg", "Forest/forest_20.jpg", "Forest/forest_52.jpg", "Forest/forest_126.jpg", "Forest/forest_46.jpg", "Forest/forest_60.jpg", "Forest/forest_136.jpg", "Forest/forest_86.jpg", "Forest/forest_89.jpg", "Forest/forest_200.jpg", "Forest/forest_202.jpg", "Forest/forest_139.jpg", "Forest/forest_171.jpg", "Forest/forest_169.jpg", "Forest/forest_249.jpg", "Forest/forest_142.jpg", "Forest/forest_179.jpg", "Forest/forest_148.jpg", "Forest/forest_158.jpg", "Forest/forest_81.jpg", "Forest/forest_45.jpg", "Forest/forest_166.jpg", "Forest/forest_100.jpg", "Forest/forest_111.jpg", "Forest/forest_187.jpg", "Forest/forest_108.jpg", "Forest/forest_114.jpg", "Forest/forest_196.jpg", "Forest/forest_211.jpg", "Forest/forest_72.jpg", "Forest/forest_178.jpg", "Forest/forest_22.jpg", "Forest/forest_205.jpg", "Forest/forest_88.jpg", "Forest/forest_151.jpg", "Forest/forest_177.jpg", "Forest/forest_50.jpg", "Forest/forest_143.jpg", "Forest/forest_155.jpg", "Forest/forest_2.jpg", "Forest/forest_35.jpg", "Forest/forest_96.jpg", "Forest/forest_164.jpg", "Forest/forest_223.jpg", "Forest/forest_245.jpg", "Forest/forest_116.jpg", "Forest/forest_159.jpg", "Forest/forest_243.jpg", "Forest/forest_124.jpg", "Forest/forest_214.jpg", "Forest/forest_32.jpg", "Forest/forest_115.jpg", "Forest/forest_238.jpg", "Forest/forest_37.jpg", "Forest/forest_44.jpg", "Forest/forest_26.jpg", "Forest/forest_85.jpg", "Forest/forest_55.jpg", "Forest/forest_14.jpg", "Forest/forest_173.jpg", "Forest/forest_19.jpg", "Forest/forest_106.jpg", "Forest/forest_186.jpg", "Forest/forest_78.jpg", "Forest/forest_137.jpg", "Forest/forest_25.jpg", "Forest/forest_199.jpg", "Forest/forest_175.jpg", "Forest/forest_65.jpg", "Forest/forest_3.jpg", "Forest/forest_195.jpg", "Forest/forest_182.jpg", "Forest/forest_246.jpg", "Forest/forest_156.jpg", "Forest/forest_73.jpg", "Forest/forest_31.jpg", "Forest/forest_153.jpg", "River/river_256.jpg", "River/river_125.jpg", "River/river_126.jpg", "River/river_332.jpg", "River/river_409.jpg", "River/river_174.jpg", "River/river_220.jpg", "River/river_312.jpg", "River/river_21.jpg", "River/river_213.jpg", "River/river_198.jpg", "River/river_30.jpg", "River/river_335.jpg", "River/river_4.jpg", "River/river_71.jpg", "River/river_149.jpg", "River/river_82.jpg", "River/river_201.jpg", "River/river_347.jpg", "River/river_360.jpg", "River/river_86.jpg", "River/river_182.jpg", "River/river_301.jpg", "River/river_290.jpg", "River/river_388.jpg", "River/river_42.jpg", "River/river_259.jpg", "River/river_123.jpg", "River/river_178.jpg", "River/river_394.jpg", "River/river_235.jpg", "River/river_2.jpg", "River/river_124.jpg", "River/river_377.jpg", "River/river_114.jpg", "River/river_40.jpg", "River/river_9.jpg", "River/river_358.jpg", "River/river_154.jpg", "River/river_146.jpg", "River/river_228.jpg", "River/river_231.jpg", "River/river_130.jpg", "River/river_15.jpg", "River/river_128.jpg", "River/river_399.jpg", "River/river_145.jpg", "River/river_307.jpg", "River/river_406.jpg", "River/river_28.jpg", "River/river_234.jpg", "River/river_148.jpg", "River/river_285.jpg", "River/river_173.jpg", "River/river_303.jpg", "River/river_215.jpg", "River/river_245.jpg", "River/river_352.jpg", "River/river_139.jpg", "River/river_355.jpg", "River/river_6.jpg", "River/river_238.jpg", "River/river_289.jpg", "River/river_212.jpg", "River/river_376.jpg", "River/river_55.jpg", "River/river_341.jpg", "River/river_66.jpg", "River/river_276.jpg", "River/river_334.jpg", "River/river_323.jpg", "River/river_161.jpg", "River/river_314.jpg", "River/river_50.jpg", "River/river_108.jpg", "River/river_395.jpg", "River/river_345.jpg", "River/river_260.jpg", "River/river_85.jpg", "River/river_313.jpg", "River/river_131.jpg", "River/river_155.jpg", "River/river_369.jpg", "River/river_392.jpg", "River/river_364.jpg", "River/river_33.jpg", "River/river_138.jpg", "River/river_379.jpg", "River/river_87.jpg", "River/river_222.jpg", "River/river_398.jpg", "River/river_380.jpg", "River/river_329.jpg", "River/river_232.jpg", "River/river_321.jpg", "River/river_186.jpg", "River/river_100.jpg", "River/river_101.jpg", "River/river_47.jpg", "River/river_159.jpg", "River/river_207.jpg", "River/river_389.jpg", "River/river_107.jpg", "River/river_319.jpg", "River/river_76.jpg", "River/river_209.jpg", "River/river_194.jpg", "River/river_309.jpg", "River/river_169.jpg", "River/river_251.jpg", "River/river_143.jpg", "River/river_162.jpg", "River/river_214.jpg", "River/river_117.jpg", "River/river_236.jpg", "River/river_373.jpg", "River/river_219.jpg", "River/river_226.jpg", "River/river_96.jpg", "River/river_267.jpg", "River/river_46.jpg", "River/river_115.jpg", "River/river_69.jpg", "River/river_62.jpg", "River/river_297.jpg", "River/river_370.jpg", "River/river_135.jpg", "River/river_274.jpg", "River/river_252.jpg", "River/river_180.jpg", "River/river_229.jpg", "River/river_287.jpg", "River/river_58.jpg", "River/river_26.jpg", "River/river_249.jpg", "River/river_244.jpg", "River/river_151.jpg", "River/river_330.jpg", "River/river_401.jpg", "River/river_333.jpg", "River/river_292.jpg", "River/river_120.jpg", "River/river_164.jpg", "River/river_132.jpg", "River/river_7.jpg", "River/river_191.jpg", "River/river_304.jpg", "River/river_382.jpg", "River/river_253.jpg", "River/river_158.jpg", "River/river_109.jpg", "River/river_56.jpg", "River/river_391.jpg", "River/river_172.jpg", "River/river_20.jpg", "River/river_248.jpg", "River/river_103.jpg", "River/river_324.jpg", "River/river_61.jpg", "River/river_255.jpg", "River/river_137.jpg", "River/river_344.jpg", "River/river_205.jpg", "River/river_105.jpg", "River/river_273.jpg", "River/river_397.jpg", "River/river_375.jpg", "River/river_349.jpg", "River/river_239.jpg", "River/river_410.jpg", "River/river_197.jpg", "River/river_271.jpg", "River/river_93.jpg", "River/river_247.jpg", "River/river_35.jpg", "River/river_270.jpg", "River/river_36.jpg", "River/river_104.jpg", "River/river_317.jpg", "River/river_94.jpg", "River/river_167.jpg", "River/river_217.jpg", "River/river_141.jpg", "River/river_54.jpg", "River/river_316.jpg", "River/river_81.jpg", "River/river_269.jpg", "River/river_18.jpg", "River/river_16.jpg", "River/river_372.jpg", "River/river_176.jpg", "River/river_157.jpg", "River/river_204.jpg", "River/river_13.jpg", "River/river_78.jpg", "River/river_45.jpg", "River/river_343.jpg", "River/river_99.jpg", "River/river_310.jpg", "River/river_65.jpg", "River/river_363.jpg", "River/river_39.jpg", "River/river_184.jpg", "River/river_34.jpg", "River/river_187.jpg", "River/river_14.jpg", "River/river_48.jpg", "River/river_240.jpg", "River/river_199.jpg", "River/river_368.jpg", "River/river_79.jpg", "River/river_342.jpg", "River/river_142.jpg", "River/river_405.jpg", "River/river_318.jpg", "River/river_37.jpg", "River/river_5.jpg", "River/river_119.jpg", "River/river_160.jpg", "River/river_315.jpg", "River/river_381.jpg", "River/river_190.jpg", "River/river_374.jpg", "River/river_97.jpg", "River/river_367.jpg", "River/river_365.jpg", "River/river_1.jpg", "River/river_237.jpg", "River/river_210.jpg", "River/river_357.jpg", "River/river_196.jpg", "River/river_346.jpg", "River/river_136.jpg", "River/river_282.jpg", "River/river_241.jpg", "River/river_258.jpg", "River/river_27.jpg", "River/river_339.jpg", "River/river_224.jpg", "River/river_118.jpg", "River/river_202.jpg", "River/river_353.jpg", "River/river_299.jpg", "River/river_91.jpg", "River/river_288.jpg", "River/river_163.jpg", "River/river_266.jpg", "River/river_113.jpg", "River/river_134.jpg", "River/river_277.jpg", "River/river_378.jpg", "River/river_359.jpg", "River/river_110.jpg", "River/river_10.jpg", "River/river_89.jpg", "River/river_106.jpg", "River/river_166.jpg", "River/river_262.jpg", "River/river_111.jpg", "River/river_265.jpg", "River/river_168.jpg", "River/river_23.jpg", "River/river_279.jpg", "River/river_75.jpg", "River/river_264.jpg", "River/river_192.jpg", "River/river_362.jpg", "River/river_150.jpg", "River/river_337.jpg", "River/river_77.jpg", "River/river_250.jpg", "River/river_116.jpg", "River/river_156.jpg", "River/river_354.jpg", "River/river_84.jpg", "River/river_402.jpg", "River/river_322.jpg", "River/river_8.jpg", "River/river_200.jpg", "River/river_246.jpg", "River/river_24.jpg", "River/river_356.jpg", "River/river_208.jpg", "River/river_92.jpg", "River/river_177.jpg", "River/river_227.jpg", "River/river_183.jpg", "River/river_32.jpg", "River/river_393.jpg", "River/river_386.jpg", "River/river_57.jpg", "River/river_283.jpg", "River/river_311.jpg", "River/river_403.jpg", "River/river_400.jpg", "River/river_206.jpg", "River/river_112.jpg", "River/river_140.jpg", "River/river_320.jpg", "River/river_185.jpg", "River/river_306.jpg", "River/river_170.jpg", "River/river_88.jpg", "River/river_188.jpg", "River/river_29.jpg", "River/river_83.jpg", "River/river_223.jpg", "River/river_189.jpg", "River/river_171.jpg", "River/river_152.jpg", "River/river_22.jpg", "River/river_294.jpg", "River/river_102.jpg", "River/river_11.jpg", "River/river_43.jpg", "River/river_218.jpg", "River/river_129.jpg", "River/river_408.jpg", "Resort/resort_128.jpg", "Resort/resort_60.jpg", "Resort/resort_256.jpg", "Resort/resort_221.jpg", "Resort/resort_52.jpg", "Resort/resort_165.jpg", "Resort/resort_8.jpg", "Resort/resort_80.jpg", "Resort/resort_266.jpg", "Resort/resort_208.jpg", "Resort/resort_149.jpg", "Resort/resort_57.jpg", "Resort/resort_197.jpg", "Resort/resort_47.jpg", "Resort/resort_187.jpg", "Resort/resort_179.jpg", "Resort/resort_270.jpg", "Resort/resort_241.jpg", "Resort/resort_58.jpg", "Resort/resort_172.jpg", "Resort/resort_29.jpg", "Resort/resort_198.jpg", "Resort/resort_262.jpg", "Resort/resort_261.jpg", "Resort/resort_46.jpg", "Resort/resort_36.jpg", "Resort/resort_215.jpg", "Resort/resort_65.jpg", "Resort/resort_98.jpg", "Resort/resort_109.jpg", "Resort/resort_182.jpg", "Resort/resort_106.jpg", "Resort/resort_105.jpg", "Resort/resort_258.jpg", "Resort/resort_238.jpg", "Resort/resort_170.jpg", "Resort/resort_267.jpg", "Resort/resort_119.jpg", "Resort/resort_219.jpg", "Resort/resort_214.jpg", "Resort/resort_247.jpg", "Resort/resort_193.jpg", "Resort/resort_248.jpg", "Resort/resort_95.jpg", "Resort/resort_42.jpg", "Resort/resort_116.jpg", "Resort/resort_19.jpg", "Resort/resort_130.jpg", "Resort/resort_156.jpg", "Resort/resort_159.jpg", "Resort/resort_74.jpg", "Resort/resort_129.jpg", "Resort/resort_63.jpg", "Resort/resort_186.jpg", "Resort/resort_140.jpg", "Resort/resort_209.jpg", "Resort/resort_227.jpg", "Resort/resort_190.jpg", "Resort/resort_93.jpg", "Resort/resort_287.jpg", "Resort/resort_111.jpg", "Resort/resort_91.jpg", "Resort/resort_250.jpg", "Resort/resort_103.jpg", "Resort/resort_222.jpg", "Resort/resort_24.jpg", "Resort/resort_252.jpg", "Resort/resort_75.jpg", "Resort/resort_110.jpg", "Resort/resort_280.jpg", "Resort/resort_67.jpg", "Resort/resort_73.jpg", "Resort/resort_216.jpg", "Resort/resort_259.jpg", "Resort/resort_147.jpg", "Resort/resort_7.jpg", "Resort/resort_218.jpg", "Resort/resort_20.jpg", "Resort/resort_41.jpg", "Resort/resort_23.jpg", "Resort/resort_3.jpg", "Resort/resort_265.jpg", "Resort/resort_64.jpg", "Resort/resort_263.jpg", "Resort/resort_150.jpg", "Resort/resort_90.jpg", "Resort/resort_251.jpg", "Resort/resort_92.jpg", "Resort/resort_55.jpg", "Resort/resort_226.jpg", "Resort/resort_225.jpg", "Resort/resort_196.jpg", "Resort/resort_244.jpg", "Resort/resort_174.jpg", "Resort/resort_191.jpg", "Resort/resort_48.jpg", "Resort/resort_126.jpg", "Resort/resort_223.jpg", "Resort/resort_56.jpg", "Resort/resort_104.jpg", "Resort/resort_66.jpg", "Resort/resort_231.jpg", "Resort/resort_181.jpg", "Resort/resort_45.jpg", "Resort/resort_211.jpg", "Resort/resort_11.jpg", "Resort/resort_175.jpg", "Resort/resort_85.jpg", "Resort/resort_1.jpg", "Resort/resort_37.jpg", "Resort/resort_107.jpg", "Resort/resort_14.jpg", "Resort/resort_81.jpg", "Resort/resort_100.jpg", "Resort/resort_173.jpg", "Resort/resort_152.jpg", "Resort/resort_142.jpg", "Resort/resort_230.jpg", "Resort/resort_70.jpg", "Resort/resort_163.jpg", "Resort/resort_213.jpg", "Resort/resort_77.jpg", "Resort/resort_160.jpg", "Resort/resort_271.jpg", "Resort/resort_141.jpg", "Resort/resort_38.jpg", "Resort/resort_12.jpg", "Resort/resort_183.jpg", "Resort/resort_16.jpg", "Resort/resort_13.jpg", "Resort/resort_192.jpg", "Resort/resort_133.jpg", "Resort/resort_249.jpg", "Resort/resort_180.jpg", "Resort/resort_283.jpg", "Resort/resort_34.jpg", "Resort/resort_139.jpg", "Resort/resort_79.jpg", "Resort/resort_229.jpg", "Resort/resort_71.jpg", "Resort/resort_164.jpg", "Resort/resort_117.jpg", "Resort/resort_157.jpg", "Resort/resort_205.jpg", "Resort/resort_202.jpg", "Resort/resort_32.jpg", "Resort/resort_89.jpg", "Resort/resort_27.jpg", "Resort/resort_68.jpg", "Resort/resort_204.jpg", "Resort/resort_276.jpg", "Resort/resort_264.jpg", "Resort/resort_169.jpg", "Resort/resort_54.jpg", "Resort/resort_145.jpg", "Resort/resort_101.jpg", "Resort/resort_236.jpg", "Resort/resort_255.jpg", "Resort/resort_39.jpg", "Resort/resort_53.jpg", "Resort/resort_282.jpg", "Resort/resort_166.jpg", "Resort/resort_220.jpg", "Resort/resort_83.jpg", "Resort/resort_30.jpg", "Resort/resort_269.jpg", "Resort/resort_254.jpg", "Resort/resort_51.jpg", "Resort/resort_285.jpg", "Resort/resort_199.jpg", "Resort/resort_243.jpg", "Resort/resort_177.jpg", "Resort/resort_138.jpg", "Resort/resort_17.jpg", "Resort/resort_35.jpg", "Resort/resort_25.jpg", "Resort/resort_22.jpg", "Resort/resort_144.jpg", "Resort/resort_277.jpg", "Resort/resort_194.jpg", "Resort/resort_21.jpg", "Resort/resort_242.jpg", "Resort/resort_15.jpg", "Resort/resort_99.jpg", "Resort/resort_88.jpg", "Resort/resort_260.jpg", "Resort/resort_120.jpg", "Resort/resort_153.jpg", "Resort/resort_273.jpg", "Resort/resort_217.jpg", "Resort/resort_4.jpg", "Resort/resort_43.jpg", "Resort/resort_18.jpg", "Resort/resort_155.jpg", "Resort/resort_189.jpg", "Resort/resort_253.jpg", "Resort/resort_61.jpg", "Resort/resort_33.jpg", "Resort/resort_289.jpg", "Resort/resort_272.jpg", "Resort/resort_49.jpg", "Resort/resort_132.jpg", "Resort/resort_115.jpg", "Resort/resort_113.jpg", "Resort/resort_207.jpg", "Resort/resort_5.jpg", "Resort/resort_274.jpg", "Resort/resort_114.jpg", "Resort/resort_82.jpg", "Resort/resort_69.jpg", "Resort/resort_201.jpg", "Resort/resort_268.jpg", "Resort/resort_96.jpg", "Resort/resort_59.jpg", "Resort/resort_94.jpg", "Resort/resort_239.jpg", "Resort/resort_286.jpg", "Resort/resort_234.jpg", "Resort/resort_233.jpg", "Resort/resort_143.jpg", "Resort/resort_148.jpg", "Resort/resort_210.jpg", "Playground/playground_61.jpg", "Playground/playground_153.jpg", "Playground/playground_136.jpg", "Playground/playground_157.jpg", "Playground/playground_145.jpg", "Playground/playground_79.jpg", "Playground/playground_358.jpg", "Playground/playground_71.jpg", "Playground/playground_255.jpg", "Playground/playground_51.jpg", "Playground/playground_55.jpg", "Playground/playground_344.jpg", "Playground/playground_213.jpg", "Playground/playground_237.jpg", "Playground/playground_37.jpg", "Playground/playground_175.jpg", "Playground/playground_5.jpg", "Playground/playground_124.jpg", "Playground/playground_161.jpg", "Playground/playground_241.jpg", "Playground/playground_144.jpg", "Playground/playground_355.jpg", "Playground/playground_359.jpg", "Playground/playground_17.jpg", "Playground/playground_347.jpg", "Playground/playground_315.jpg", "Playground/playground_60.jpg", "Playground/playground_286.jpg", "Playground/playground_42.jpg", "Playground/playground_27.jpg", "Playground/playground_361.jpg", "Playground/playground_94.jpg", "Playground/playground_24.jpg", "Playground/playground_240.jpg", "Playground/playground_325.jpg", "Playground/playground_250.jpg", "Playground/playground_263.jpg", "Playground/playground_22.jpg", "Playground/playground_162.jpg", "Playground/playground_336.jpg", "Playground/playground_323.jpg", "Playground/playground_87.jpg", "Playground/playground_80.jpg", "Playground/playground_287.jpg", "Playground/playground_56.jpg", "Playground/playground_172.jpg", "Playground/playground_272.jpg", "Playground/playground_33.jpg", "Playground/playground_357.jpg", "Playground/playground_38.jpg", "Playground/playground_97.jpg", "Playground/playground_234.jpg", "Playground/playground_188.jpg", "Playground/playground_43.jpg", "Playground/playground_3.jpg", "Playground/playground_261.jpg", "Playground/playground_11.jpg", "Playground/playground_217.jpg", "Playground/playground_139.jpg", "Playground/playground_6.jpg", "Playground/playground_158.jpg", "Playground/playground_34.jpg", "Playground/playground_322.jpg", "Playground/playground_277.jpg", "Playground/playground_45.jpg", "Playground/playground_249.jpg", "Playground/playground_243.jpg", "Playground/playground_4.jpg", "Playground/playground_141.jpg", "Playground/playground_151.jpg", "Playground/playground_342.jpg", "Playground/playground_116.jpg", "Playground/playground_271.jpg", "Playground/playground_310.jpg", "Playground/playground_64.jpg", "Playground/playground_68.jpg", "Playground/playground_329.jpg", "Playground/playground_41.jpg", "Playground/playground_57.jpg", "Playground/playground_190.jpg", "Playground/playground_99.jpg", "Playground/playground_288.jpg", "Playground/playground_174.jpg", "Playground/playground_15.jpg", "Playground/playground_113.jpg", "Playground/playground_362.jpg", "Playground/playground_100.jpg", "Playground/playground_8.jpg", "Playground/playground_200.jpg", "Playground/playground_368.jpg", "Playground/playground_156.jpg", "Playground/playground_93.jpg", "Playground/playground_83.jpg", "Playground/playground_236.jpg", "Playground/playground_369.jpg", "Playground/playground_345.jpg", "Playground/playground_247.jpg", "Playground/playground_147.jpg", "Playground/playground_118.jpg", "Playground/playground_242.jpg", "Playground/playground_114.jpg", "Playground/playground_351.jpg", "Playground/playground_281.jpg", "Playground/playground_205.jpg", "Playground/playground_295.jpg", "Playground/playground_164.jpg", "Playground/playground_307.jpg", "Playground/playground_220.jpg", "Playground/playground_208.jpg", "Playground/playground_230.jpg", "Playground/playground_293.jpg", "Playground/playground_95.jpg", "Playground/playground_18.jpg", "Playground/playground_16.jpg", "Playground/playground_278.jpg", "Playground/playground_72.jpg", "Playground/playground_131.jpg", "Playground/playground_328.jpg", "Playground/playground_279.jpg", "Playground/playground_98.jpg", "Playground/playground_244.jpg", "Playground/playground_102.jpg", "Playground/playground_319.jpg", "Playground/playground_170.jpg", "Playground/playground_215.jpg", "Playground/playground_115.jpg", "Playground/playground_254.jpg", "Playground/playground_256.jpg", "Playground/playground_350.jpg", "Playground/playground_78.jpg", "Playground/playground_39.jpg", "Playground/playground_185.jpg", "Playground/playground_354.jpg", "Playground/playground_366.jpg", "Playground/playground_338.jpg", "Playground/playground_105.jpg", "Playground/playground_146.jpg", "Playground/playground_31.jpg", "Playground/playground_12.jpg", "Playground/playground_89.jpg", "Playground/playground_91.jpg", "Playground/playground_152.jpg", "Playground/playground_120.jpg", "Playground/playground_191.jpg", "Playground/playground_7.jpg", "Playground/playground_46.jpg", "Playground/playground_267.jpg", "Playground/playground_364.jpg", "Playground/playground_67.jpg", "Playground/playground_49.jpg", "Playground/playground_352.jpg", "Playground/playground_349.jpg", "Playground/playground_304.jpg", "Playground/playground_101.jpg", "Playground/playground_292.jpg", "Playground/playground_248.jpg", "Playground/playground_330.jpg", "Playground/playground_69.jpg", "Playground/playground_283.jpg", "Playground/playground_20.jpg", "Playground/playground_19.jpg", "Playground/playground_365.jpg", "Playground/playground_203.jpg", "Playground/playground_258.jpg", "Playground/playground_165.jpg", "Playground/playground_201.jpg", "Playground/playground_134.jpg", "Playground/playground_229.jpg", "Playground/playground_58.jpg", "Playground/playground_52.jpg", "Playground/playground_176.jpg", "Playground/playground_106.jpg", "Playground/playground_332.jpg", "Playground/playground_225.jpg", "Playground/playground_150.jpg", "Playground/playground_186.jpg", "Playground/playground_339.jpg", "Playground/playground_10.jpg", "Playground/playground_149.jpg", "Playground/playground_29.jpg", "Playground/playground_202.jpg", "Playground/playground_48.jpg", "Playground/playground_198.jpg", "Playground/playground_133.jpg", "Playground/playground_199.jpg", "Playground/playground_327.jpg", "Playground/playground_92.jpg", "Playground/playground_54.jpg", "Playground/playground_168.jpg", "Playground/playground_252.jpg", "Playground/playground_228.jpg", "Playground/playground_23.jpg", "Playground/playground_117.jpg", "Playground/playground_222.jpg", "Playground/playground_233.jpg", "Playground/playground_219.jpg", "Playground/playground_135.jpg", "Playground/playground_276.jpg", "Playground/playground_224.jpg", "Playground/playground_300.jpg", "Playground/playground_65.jpg", "Playground/playground_297.jpg", "Playground/playground_212.jpg", "Playground/playground_264.jpg", "Playground/playground_125.jpg", "Playground/playground_109.jpg", "Playground/playground_223.jpg", "Playground/playground_211.jpg", "Playground/playground_110.jpg", "Playground/playground_182.jpg", "Playground/playground_130.jpg", "Playground/playground_231.jpg", "Playground/playground_75.jpg", "Playground/playground_301.jpg", "Playground/playground_171.jpg", "Playground/playground_111.jpg", "Playground/playground_77.jpg", "Playground/playground_312.jpg", "Playground/playground_70.jpg", "Playground/playground_189.jpg", "Playground/playground_112.jpg", "Playground/playground_367.jpg", "Playground/playground_195.jpg", "Playground/playground_318.jpg", "Playground/playground_356.jpg", "Playground/playground_313.jpg", "Playground/playground_123.jpg", "Playground/playground_9.jpg", "Playground/playground_209.jpg", "Playground/playground_36.jpg", "Playground/playground_25.jpg", "Playground/playground_13.jpg", "Playground/playground_207.jpg", "Playground/playground_289.jpg", "Playground/playground_76.jpg", "Playground/playground_127.jpg", "Playground/playground_74.jpg", "Playground/playground_28.jpg", "Playground/playground_148.jpg", "Playground/playground_178.jpg", "Playground/playground_44.jpg", "Playground/playground_226.jpg", "Playground/playground_63.jpg", "Playground/playground_335.jpg", "Playground/playground_246.jpg", "Playground/playground_306.jpg", "Playground/playground_268.jpg", "Playground/playground_346.jpg", "Playground/playground_251.jpg", "Playground/playground_314.jpg", "Playground/playground_305.jpg", "Playground/playground_66.jpg", "Playground/playground_30.jpg", "Playground/playground_210.jpg", "Playground/playground_290.jpg", "Playground/playground_84.jpg", "Playground/playground_167.jpg", "Playground/playground_137.jpg", "Playground/playground_324.jpg", "Playground/playground_269.jpg", "Playground/playground_138.jpg", "Playground/playground_341.jpg", "Playground/playground_266.jpg", "Playground/playground_280.jpg", "Playground/playground_275.jpg", "Playground/playground_180.jpg", "Playground/playground_260.jpg", "Playground/playground_298.jpg", "Playground/playground_232.jpg", "Playground/playground_259.jpg", "Playground/playground_294.jpg", "Playground/playground_302.jpg", "Playground/playground_53.jpg", "Playground/playground_316.jpg", "Playground/playground_337.jpg", "Playground/playground_206.jpg", "Playground/playground_245.jpg", "Playground/playground_333.jpg", "Playground/playground_40.jpg", "Playground/playground_59.jpg", "Playground/playground_334.jpg", "Playground/playground_32.jpg", "Playground/playground_291.jpg", "Playground/playground_348.jpg", "Playground/playground_173.jpg", "Playground/playground_86.jpg", "Bridge/bridge_341.jpg", "Bridge/bridge_101.jpg", "Bridge/bridge_183.jpg", "Bridge/bridge_282.jpg", "Bridge/bridge_31.jpg", "Bridge/bridge_270.jpg", "Bridge/bridge_288.jpg", "Bridge/bridge_240.jpg", "Bridge/bridge_197.jpg", "Bridge/bridge_249.jpg", "Bridge/bridge_47.jpg", "Bridge/bridge_132.jpg", "Bridge/bridge_144.jpg", "Bridge/bridge_83.jpg", "Bridge/bridge_263.jpg", "Bridge/bridge_157.jpg", "Bridge/bridge_113.jpg", "Bridge/bridge_67.jpg", "Bridge/bridge_109.jpg", "Bridge/bridge_3.jpg", "Bridge/bridge_22.jpg", "Bridge/bridge_40.jpg", "Bridge/bridge_343.jpg", "Bridge/bridge_12.jpg", "Bridge/bridge_141.jpg", "Bridge/bridge_349.jpg", "Bridge/bridge_70.jpg", "Bridge/bridge_106.jpg", "Bridge/bridge_215.jpg", "Bridge/bridge_172.jpg", "Bridge/bridge_188.jpg", "Bridge/bridge_150.jpg", "Bridge/bridge_117.jpg", "Bridge/bridge_52.jpg", "Bridge/bridge_90.jpg", "Bridge/bridge_190.jpg", "Bridge/bridge_290.jpg", "Bridge/bridge_82.jpg", "Bridge/bridge_104.jpg", "Bridge/bridge_21.jpg", "Bridge/bridge_291.jpg", "Bridge/bridge_301.jpg", "Bridge/bridge_2.jpg", "Bridge/bridge_62.jpg", "Bridge/bridge_162.jpg", "Bridge/bridge_26.jpg", "Bridge/bridge_330.jpg", "Bridge/bridge_8.jpg", "Bridge/bridge_13.jpg", "Bridge/bridge_165.jpg", "Bridge/bridge_105.jpg", "Bridge/bridge_220.jpg", "Bridge/bridge_160.jpg", "Bridge/bridge_227.jpg", "Bridge/bridge_192.jpg", "Bridge/bridge_50.jpg", "Bridge/bridge_15.jpg", "Bridge/bridge_48.jpg", "Bridge/bridge_25.jpg", "Bridge/bridge_59.jpg", "Bridge/bridge_173.jpg", "Bridge/bridge_294.jpg", "Bridge/bridge_84.jpg", "Bridge/bridge_71.jpg", "Bridge/bridge_255.jpg", "Bridge/bridge_284.jpg", "Bridge/bridge_95.jpg", "Bridge/bridge_14.jpg", "Bridge/bridge_318.jpg", "Bridge/bridge_118.jpg", "Bridge/bridge_344.jpg", "Bridge/bridge_178.jpg", "Bridge/bridge_211.jpg", "Bridge/bridge_171.jpg", "Bridge/bridge_237.jpg", "Bridge/bridge_187.jpg", "Bridge/bridge_300.jpg", "Bridge/bridge_261.jpg", "Bridge/bridge_170.jpg", "Bridge/bridge_265.jpg", "Bridge/bridge_85.jpg", "Bridge/bridge_217.jpg", "Bridge/bridge_332.jpg", "Bridge/bridge_23.jpg", "Bridge/bridge_36.jpg", "Bridge/bridge_126.jpg", "Bridge/bridge_44.jpg", "Bridge/bridge_139.jpg", "Bridge/bridge_102.jpg", "Bridge/bridge_194.jpg", "Bridge/bridge_143.jpg", "Bridge/bridge_79.jpg", "Bridge/bridge_185.jpg", "Bridge/bridge_303.jpg", "Bridge/bridge_81.jpg", "Bridge/bridge_103.jpg", "Bridge/bridge_46.jpg", "Bridge/bridge_39.jpg", "Bridge/bridge_231.jpg", "Bridge/bridge_254.jpg", "Bridge/bridge_289.jpg", "Bridge/bridge_325.jpg", "Bridge/bridge_276.jpg", "Bridge/bridge_16.jpg", "Bridge/bridge_243.jpg", "Bridge/bridge_128.jpg", "Bridge/bridge_216.jpg", "Bridge/bridge_260.jpg", "Bridge/bridge_236.jpg", "Bridge/bridge_77.jpg", "Bridge/bridge_158.jpg", "Bridge/bridge_218.jpg", "Bridge/bridge_142.jpg", "Bridge/bridge_78.jpg", "Bridge/bridge_140.jpg", "Bridge/bridge_179.jpg", "Bridge/bridge_131.jpg", "Bridge/bridge_297.jpg", "Bridge/bridge_293.jpg", "Bridge/bridge_326.jpg", "Bridge/bridge_94.jpg", "Bridge/bridge_151.jpg", "Bridge/bridge_333.jpg", "Bridge/bridge_176.jpg", "Bridge/bridge_64.jpg", "Bridge/bridge_351.jpg", "Bridge/bridge_120.jpg", "Bridge/bridge_308.jpg", "Bridge/bridge_209.jpg", "Bridge/bridge_285.jpg", "Bridge/bridge_225.jpg", "Bridge/bridge_345.jpg", "Bridge/bridge_145.jpg", "Bridge/bridge_212.jpg", "Bridge/bridge_135.jpg", "Bridge/bridge_342.jpg", "Bridge/bridge_360.jpg", "Bridge/bridge_127.jpg", "Bridge/bridge_234.jpg", "Bridge/bridge_251.jpg", "Bridge/bridge_298.jpg", "Bridge/bridge_20.jpg", "Bridge/bridge_1.jpg", "Bridge/bridge_252.jpg", "Bridge/bridge_88.jpg", "Bridge/bridge_334.jpg", "Bridge/bridge_348.jpg", "Bridge/bridge_313.jpg", "Bridge/bridge_138.jpg", "Bridge/bridge_32.jpg", "Bridge/bridge_317.jpg", "Bridge/bridge_75.jpg", "Bridge/bridge_54.jpg", "Bridge/bridge_204.jpg", "Bridge/bridge_96.jpg", "Bridge/bridge_159.jpg", "Bridge/bridge_336.jpg", "Bridge/bridge_119.jpg", "Bridge/bridge_114.jpg", "Bridge/bridge_92.jpg", "Bridge/bridge_327.jpg", "Bridge/bridge_310.jpg", "Bridge/bridge_292.jpg", "Bridge/bridge_315.jpg", "Bridge/bridge_35.jpg", "Bridge/bridge_286.jpg", "Bridge/bridge_153.jpg", "Bridge/bridge_130.jpg", "Bridge/bridge_163.jpg", "Bridge/bridge_129.jpg", "Bridge/bridge_195.jpg", "Bridge/bridge_100.jpg", "Bridge/bridge_246.jpg", "Bridge/bridge_244.jpg", "Bridge/bridge_305.jpg", "Bridge/bridge_57.jpg", "Bridge/bridge_242.jpg", "Bridge/bridge_24.jpg", "Bridge/bridge_93.jpg", "Bridge/bridge_283.jpg", "Bridge/bridge_311.jpg", "Bridge/bridge_321.jpg", "Bridge/bridge_122.jpg", "Bridge/bridge_314.jpg", "Bridge/bridge_74.jpg", "Bridge/bridge_186.jpg", "Bridge/bridge_340.jpg", "Bridge/bridge_214.jpg", "Bridge/bridge_205.jpg", "Bridge/bridge_115.jpg", "Bridge/bridge_256.jpg", "Bridge/bridge_328.jpg", "Bridge/bridge_166.jpg", "Bridge/bridge_193.jpg", "Bridge/bridge_61.jpg", "Bridge/bridge_184.jpg", "Bridge/bridge_161.jpg", "Bridge/bridge_38.jpg", "Bridge/bridge_266.jpg", "Bridge/bridge_226.jpg", "Bridge/bridge_133.jpg", "Bridge/bridge_97.jpg", "Bridge/bridge_307.jpg", "Bridge/bridge_352.jpg", "Bridge/bridge_207.jpg", "Bridge/bridge_30.jpg", "Bridge/bridge_110.jpg", "Bridge/bridge_60.jpg", "Bridge/bridge_112.jpg", "Bridge/bridge_43.jpg", "Bridge/bridge_359.jpg", "Bridge/bridge_277.jpg", "Bridge/bridge_350.jpg", "Bridge/bridge_306.jpg", "Bridge/bridge_203.jpg", "Bridge/bridge_137.jpg", "Bridge/bridge_63.jpg", "Bridge/bridge_247.jpg", "Bridge/bridge_189.jpg", "Bridge/bridge_11.jpg", "Bridge/bridge_239.jpg", "Bridge/bridge_198.jpg", "Bridge/bridge_257.jpg", "Bridge/bridge_335.jpg", "Bridge/bridge_123.jpg", "Bridge/bridge_222.jpg", "Bridge/bridge_42.jpg", "Bridge/bridge_49.jpg", "Bridge/bridge_210.jpg", "Bridge/bridge_232.jpg", "Bridge/bridge_33.jpg", "Bridge/bridge_279.jpg", "Bridge/bridge_5.jpg", "Bridge/bridge_296.jpg", "Bridge/bridge_320.jpg", "Bridge/bridge_268.jpg", "Bridge/bridge_72.jpg", "Bridge/bridge_316.jpg", "Bridge/bridge_338.jpg", "Bridge/bridge_116.jpg", "Bridge/bridge_354.jpg", "Bridge/bridge_181.jpg", "Bridge/bridge_45.jpg", "Bridge/bridge_87.jpg", "Bridge/bridge_323.jpg", "Bridge/bridge_148.jpg", "Bridge/bridge_152.jpg", "Bridge/bridge_200.jpg", "Bridge/bridge_219.jpg", "Bridge/bridge_271.jpg", "Bridge/bridge_124.jpg", "Bridge/bridge_168.jpg", "Bridge/bridge_281.jpg", "Bridge/bridge_238.jpg", "Bridge/bridge_267.jpg", "Bridge/bridge_73.jpg", "Bridge/bridge_175.jpg", "Bridge/bridge_206.jpg", "Bridge/bridge_302.jpg", "Bridge/bridge_99.jpg", "Bridge/bridge_355.jpg", "Bridge/bridge_224.jpg", "Bridge/bridge_125.jpg", "Bridge/bridge_356.jpg", "Bridge/bridge_331.jpg", "Bridge/bridge_299.jpg", "Bridge/bridge_339.jpg", "Bridge/bridge_191.jpg", "Bridge/bridge_56.jpg", "Bridge/bridge_10.jpg", "Bridge/bridge_37.jpg", "Bridge/bridge_182.jpg", "Bridge/bridge_7.jpg", "Bridge/bridge_322.jpg", "Bridge/bridge_9.jpg", "Bridge/bridge_264.jpg", "Bridge/bridge_136.jpg", "Bridge/bridge_121.jpg", "Park/park_178.jpg", "Park/park_118.jpg", "Park/park_273.jpg", "Park/park_205.jpg", "Park/park_268.jpg", "Park/park_289.jpg", "Park/park_278.jpg", "Park/park_219.jpg", "Park/park_57.jpg", "Park/park_216.jpg", "Park/park_159.jpg", "Park/park_40.jpg", "Park/park_1.jpg", "Park/park_279.jpg", "Park/park_299.jpg", "Park/park_207.jpg", "Park/park_193.jpg", "Park/park_152.jpg", "Park/park_211.jpg", "Park/park_44.jpg", "Park/park_85.jpg", "Park/park_245.jpg", "Park/park_261.jpg", "Park/park_99.jpg", "Park/park_154.jpg", "Park/park_229.jpg", "Park/park_122.jpg", "Park/park_97.jpg", "Park/park_214.jpg", "Park/park_70.jpg", "Park/park_162.jpg", "Park/park_135.jpg", "Park/park_65.jpg", "Park/park_238.jpg", "Park/park_104.jpg", "Park/park_236.jpg", "Park/park_27.jpg", "Park/park_271.jpg", "Park/park_38.jpg", "Park/park_112.jpg", "Park/park_117.jpg", "Park/park_276.jpg", "Park/park_285.jpg", "Park/park_322.jpg", "Park/park_123.jpg", "Park/park_320.jpg", "Park/park_237.jpg", "Park/park_284.jpg", "Park/park_198.jpg", "Park/park_101.jpg", "Park/park_226.jpg", "Park/park_264.jpg", "Park/park_196.jpg", "Park/park_329.jpg", "Park/park_16.jpg", "Park/park_113.jpg", "Park/park_34.jpg", "Park/park_308.jpg", "Park/park_334.jpg", "Park/park_222.jpg", "Park/park_36.jpg", "Park/park_20.jpg", "Park/park_342.jpg", "Park/park_72.jpg", "Park/park_171.jpg", "Park/park_335.jpg", "Park/park_102.jpg", "Park/park_11.jpg", "Park/park_269.jpg", "Park/park_147.jpg", "Park/park_181.jpg", "Park/park_302.jpg", "Park/park_62.jpg", "Park/park_76.jpg", "Park/park_132.jpg", "Park/park_124.jpg", "Park/park_249.jpg", "Park/park_348.jpg", "Park/park_241.jpg", "Park/park_161.jpg", "Park/park_188.jpg", "Park/park_343.jpg", "Park/park_137.jpg", "Park/park_14.jpg", "Park/park_90.jpg", "Park/park_8.jpg", "Park/park_316.jpg", "Park/park_221.jpg", "Park/park_287.jpg", "Park/park_184.jpg", "Park/park_200.jpg", "Park/park_220.jpg", "Park/park_337.jpg", "Park/park_63.jpg", "Park/park_336.jpg", "Park/park_304.jpg", "Park/park_52.jpg", "Park/park_143.jpg", "Park/park_103.jpg", "Park/park_212.jpg", "Park/park_294.jpg", "Park/park_254.jpg", "Park/park_234.jpg", "Park/park_350.jpg", "Park/park_60.jpg", "Park/park_176.jpg", "Park/park_231.jpg", "Park/park_89.jpg", "Park/park_290.jpg", "Park/park_244.jpg", "Park/park_32.jpg", "Park/park_43.jpg", "Park/park_314.jpg", "Park/park_105.jpg", "Park/park_209.jpg", "Park/park_313.jpg", "Park/park_349.jpg", "Park/park_4.jpg", "Park/park_134.jpg", "Park/park_315.jpg", "Park/park_2.jpg", "Park/park_306.jpg", "Park/park_257.jpg", "Park/park_242.jpg", "Park/park_243.jpg", "Park/park_100.jpg", "Park/park_88.jpg", "Park/park_146.jpg", "Park/park_293.jpg", "Park/park_166.jpg", "Park/park_160.jpg", "Park/park_3.jpg", "Park/park_307.jpg", "Park/park_29.jpg", "Park/park_191.jpg", "Park/park_183.jpg", "Park/park_144.jpg", "Park/park_317.jpg", "Park/park_15.jpg", "Park/park_262.jpg", "Park/park_180.jpg", "Park/park_9.jpg", "Park/park_232.jpg", "Park/park_142.jpg", "Park/park_77.jpg", "Park/park_172.jpg", "Park/park_281.jpg", "Park/park_128.jpg", "Park/park_84.jpg", "Park/park_28.jpg", "Park/park_248.jpg", "Park/park_344.jpg", "Park/park_298.jpg", "Park/park_283.jpg", "Park/park_201.jpg", "Park/park_253.jpg", "Park/park_288.jpg", "Park/park_331.jpg", "Park/park_165.jpg", "Park/park_164.jpg", "Park/park_58.jpg", "Park/park_168.jpg", "Park/park_345.jpg", "Park/park_240.jpg", "Park/park_149.jpg", "Park/park_127.jpg", "Park/park_187.jpg", "Park/park_347.jpg", "Park/park_75.jpg", "Park/park_170.jpg", "Park/park_311.jpg", "Park/park_156.jpg", "Park/park_163.jpg", "Park/park_173.jpg", "Park/park_291.jpg", "Park/park_109.jpg", "Park/park_247.jpg", "Park/park_275.jpg", "Park/park_175.jpg", "Park/park_296.jpg", "Park/park_50.jpg", "Park/park_239.jpg", "Park/park_195.jpg", "Park/park_10.jpg", "Park/park_46.jpg", "Park/park_251.jpg", "Park/park_18.jpg", "Park/park_69.jpg", "Park/park_326.jpg", "Park/park_155.jpg", "Park/park_126.jpg", "Park/park_125.jpg", "Park/park_79.jpg", "Park/park_252.jpg", "Park/park_277.jpg", "Park/park_318.jpg", "Park/park_223.jpg", "Park/park_56.jpg", "Park/park_139.jpg", "Park/park_235.jpg", "Park/park_71.jpg", "Park/park_260.jpg", "Park/park_81.jpg", "Park/park_6.jpg", "Park/park_185.jpg", "Park/park_177.jpg", "Park/park_80.jpg", "Park/park_131.jpg", "Park/park_346.jpg", "Park/park_151.jpg", "Park/park_130.jpg", "Park/park_300.jpg", "Park/park_119.jpg", "Park/park_37.jpg", "Park/park_91.jpg", "Park/park_133.jpg", "Park/park_49.jpg", "Park/park_330.jpg", "Park/park_48.jpg", "Park/park_68.jpg", "Park/park_303.jpg", "Park/park_267.jpg", "Park/park_208.jpg", "Park/park_218.jpg", "Park/park_286.jpg", "Park/park_35.jpg", "Park/park_21.jpg", "Park/park_107.jpg", "Park/park_189.jpg", "Park/park_199.jpg", "Park/park_64.jpg", "Park/park_22.jpg", "Park/park_186.jpg", "Park/park_340.jpg", "Park/park_332.jpg", "Park/park_94.jpg", "Park/park_53.jpg", "Park/park_324.jpg", "Park/park_192.jpg", "Park/park_87.jpg", "Park/park_106.jpg", "Park/park_17.jpg", "Park/park_98.jpg", "Park/park_230.jpg", "Park/park_120.jpg", "Park/park_41.jpg", "Park/park_312.jpg", "Park/park_282.jpg", "Park/park_309.jpg", "Park/park_323.jpg", "Park/park_54.jpg", "Park/park_263.jpg", "Park/park_158.jpg", "Park/park_179.jpg", "Park/park_138.jpg", "Park/park_82.jpg", "Park/park_74.jpg", "Park/park_7.jpg", "Park/park_202.jpg", "Park/park_19.jpg", "Park/park_295.jpg", "Park/park_111.jpg", "Park/park_197.jpg", "Park/park_341.jpg", "Park/park_190.jpg", "Park/park_59.jpg", "Park/park_233.jpg", "Park/park_129.jpg", "Park/park_174.jpg", "Park/park_225.jpg", "Center/center_65.jpg", "Center/center_124.jpg", "Center/center_25.jpg", "Center/center_18.jpg", "Center/center_83.jpg", "Center/center_103.jpg", "Center/center_180.jpg", "Center/center_252.jpg", "Center/center_70.jpg", "Center/center_42.jpg", "Center/center_59.jpg", "Center/center_41.jpg", "Center/center_126.jpg", "Center/center_17.jpg", "Center/center_183.jpg", "Center/center_4.jpg", "Center/center_128.jpg", "Center/center_200.jpg", "Center/center_247.jpg", "Center/center_207.jpg", "Center/center_163.jpg", "Center/center_120.jpg", "Center/center_72.jpg", "Center/center_53.jpg", "Center/center_151.jpg", "Center/center_97.jpg", "Center/center_39.jpg", "Center/center_55.jpg", "Center/center_170.jpg", "Center/center_51.jpg", "Center/center_204.jpg", "Center/center_6.jpg", "Center/center_172.jpg", "Center/center_149.jpg", "Center/center_40.jpg", "Center/center_81.jpg", "Center/center_85.jpg", "Center/center_62.jpg", "Center/center_144.jpg", "Center/center_171.jpg", "Center/center_148.jpg", "Center/center_186.jpg", "Center/center_211.jpg", "Center/center_109.jpg", "Center/center_256.jpg", "Center/center_9.jpg", "Center/center_253.jpg", "Center/center_243.jpg", "Center/center_177.jpg", "Center/center_185.jpg", "Center/center_75.jpg", "Center/center_153.jpg", "Center/center_229.jpg", "Center/center_104.jpg", "Center/center_198.jpg", "Center/center_250.jpg", "Center/center_209.jpg", "Center/center_178.jpg", "Center/center_156.jpg", "Center/center_166.jpg", "Center/center_71.jpg", "Center/center_176.jpg", "Center/center_131.jpg", "Center/center_82.jpg", "Center/center_117.jpg", "Center/center_251.jpg", "Center/center_118.jpg", "Center/center_162.jpg", "Center/center_89.jpg", "Center/center_191.jpg", "Center/center_8.jpg", "Center/center_202.jpg", "Center/center_157.jpg", "Center/center_96.jpg", "Center/center_216.jpg", "Center/center_67.jpg", "Center/center_210.jpg", "Center/center_237.jpg", "Center/center_68.jpg", "Center/center_94.jpg", "Center/center_2.jpg", "Center/center_136.jpg", "Center/center_19.jpg", "Center/center_64.jpg", "Center/center_242.jpg", "Center/center_169.jpg", "Center/center_123.jpg", "Center/center_147.jpg", "Center/center_116.jpg", "Center/center_188.jpg", "Center/center_152.jpg", "Center/center_155.jpg", "Center/center_88.jpg", "Center/center_133.jpg", "Center/center_50.jpg", "Center/center_140.jpg", "Center/center_60.jpg", "Center/center_37.jpg", "Center/center_12.jpg", "Center/center_54.jpg", "Center/center_158.jpg", "Center/center_33.jpg", "Center/center_164.jpg", "Center/center_174.jpg", "Center/center_142.jpg", "Center/center_47.jpg", "Center/center_205.jpg", "Center/center_32.jpg", "Center/center_236.jpg", "Center/center_22.jpg", "Center/center_10.jpg", "Center/center_184.jpg", "Center/center_189.jpg", "Center/center_192.jpg", "Center/center_182.jpg", "Center/center_159.jpg", "Center/center_11.jpg", "Center/center_234.jpg", "Center/center_106.jpg", "Center/center_130.jpg", "Center/center_227.jpg", "Center/center_36.jpg", "Center/center_190.jpg", "Center/center_154.jpg", "Center/center_145.jpg", "Center/center_228.jpg", "Center/center_121.jpg", "Center/center_146.jpg", "Center/center_245.jpg", "Center/center_76.jpg", "Center/center_138.jpg", "Center/center_225.jpg", "Center/center_219.jpg", "Center/center_240.jpg", "Center/center_21.jpg", "Center/center_193.jpg", "Center/center_35.jpg", "Center/center_230.jpg", "Center/center_248.jpg", "Center/center_28.jpg", "Center/center_38.jpg", "Center/center_125.jpg", "Center/center_27.jpg", "Center/center_232.jpg", "Center/center_127.jpg", "Center/center_48.jpg", "Center/center_5.jpg", "Center/center_143.jpg", "Center/center_29.jpg", "Center/center_56.jpg", "Center/center_238.jpg", "Center/center_135.jpg", "Center/center_3.jpg", "Center/center_114.jpg", "Center/center_122.jpg", "Center/center_30.jpg", "Center/center_74.jpg", "Center/center_259.jpg", "Center/center_195.jpg", "Center/center_201.jpg", "Center/center_87.jpg", "Center/center_233.jpg", "Center/center_217.jpg", "Center/center_161.jpg", "Center/center_113.jpg", "Center/center_31.jpg", "Center/center_132.jpg", "Center/center_14.jpg", "Center/center_168.jpg", "Center/center_26.jpg", "Center/center_7.jpg", "Center/center_66.jpg", "Center/center_92.jpg", "Center/center_241.jpg", "Center/center_61.jpg", "Center/center_208.jpg", "Center/center_119.jpg", "Center/center_111.jpg", "Center/center_203.jpg", "Center/center_34.jpg", "Center/center_173.jpg", "Center/center_212.jpg", "Center/center_175.jpg", "Center/center_187.jpg", "Center/center_199.jpg", "Center/center_23.jpg", "Center/center_63.jpg", "Center/center_223.jpg", "Center/center_52.jpg", "Center/center_167.jpg", "Center/center_112.jpg", "Center/center_257.jpg", "Center/center_194.jpg", "Center/center_57.jpg", "Center/center_221.jpg", "Center/center_129.jpg", "Center/center_101.jpg", "Center/center_110.jpg", "Square/square_81.jpg", "Square/square_265.jpg", "Square/square_267.jpg", "Square/square_279.jpg", "Square/square_141.jpg", "Square/square_31.jpg", "Square/square_124.jpg", "Square/square_40.jpg", "Square/square_99.jpg", "Square/square_106.jpg", "Square/square_162.jpg", "Square/square_201.jpg", "Square/square_224.jpg", "Square/square_209.jpg", "Square/square_122.jpg", "Square/square_114.jpg", "Square/square_43.jpg", "Square/square_278.jpg", "Square/square_324.jpg", "Square/square_270.jpg", "Square/square_284.jpg", "Square/square_223.jpg", "Square/square_97.jpg", "Square/square_60.jpg", "Square/square_89.jpg", "Square/square_301.jpg", "Square/square_86.jpg", "Square/square_280.jpg", "Square/square_215.jpg", "Square/square_287.jpg", "Square/square_167.jpg", "Square/square_190.jpg", "Square/square_24.jpg", "Square/square_58.jpg", "Square/square_297.jpg", "Square/square_214.jpg", "Square/square_178.jpg", "Square/square_133.jpg", "Square/square_299.jpg", "Square/square_186.jpg", "Square/square_105.jpg", "Square/square_250.jpg", "Square/square_29.jpg", "Square/square_142.jpg", "Square/square_53.jpg", "Square/square_254.jpg", "Square/square_56.jpg", "Square/square_281.jpg", "Square/square_104.jpg", "Square/square_82.jpg", "Square/square_307.jpg", "Square/square_304.jpg", "Square/square_17.jpg", "Square/square_225.jpg", "Square/square_159.jpg", "Square/square_110.jpg", "Square/square_88.jpg", "Square/square_229.jpg", "Square/square_136.jpg", "Square/square_174.jpg", "Square/square_15.jpg", "Square/square_78.jpg", "Square/square_52.jpg", "Square/square_153.jpg", "Square/square_76.jpg", "Square/square_48.jpg", "Square/square_4.jpg", "Square/square_135.jpg", "Square/square_274.jpg", "Square/square_35.jpg", "Square/square_219.jpg", "Square/square_180.jpg", "Square/square_198.jpg", "Square/square_300.jpg", "Square/square_21.jpg", "Square/square_8.jpg", "Square/square_251.jpg", "Square/square_294.jpg", "Square/square_271.jpg", "Square/square_91.jpg", "Square/square_295.jpg", "Square/square_245.jpg", "Square/square_323.jpg", "Square/square_138.jpg", "Square/square_57.jpg", "Square/square_33.jpg", "Square/square_183.jpg", "Square/square_192.jpg", "Square/square_28.jpg", "Square/square_65.jpg", "Square/square_321.jpg", "Square/square_197.jpg", "Square/square_117.jpg", "Square/square_111.jpg", "Square/square_276.jpg", "Square/square_150.jpg", "Square/square_257.jpg", "Square/square_49.jpg", "Square/square_315.jpg", "Square/square_50.jpg", "Square/square_248.jpg", "Square/square_193.jpg", "Square/square_164.jpg", "Square/square_242.jpg", "Square/square_66.jpg", "Square/square_285.jpg", "Square/square_168.jpg", "Square/square_239.jpg", "Square/square_196.jpg", "Square/square_205.jpg", "Square/square_318.jpg", "Square/square_290.jpg", "Square/square_172.jpg", "Square/square_12.jpg", "Square/square_140.jpg", "Square/square_261.jpg", "Square/square_16.jpg", "Square/square_204.jpg", "Square/square_90.jpg", "Square/square_259.jpg", "Square/square_137.jpg", "Square/square_249.jpg", "Square/square_69.jpg", "Square/square_129.jpg", "Square/square_156.jpg", "Square/square_233.jpg", "Square/square_218.jpg", "Square/square_11.jpg", "Square/square_273.jpg", "Square/square_268.jpg", "Square/square_42.jpg", "Square/square_292.jpg", "Square/square_176.jpg", "Square/square_165.jpg", "Square/square_38.jpg", "Square/square_200.jpg", "Square/square_220.jpg", "Square/square_85.jpg", "Square/square_103.jpg", "Square/square_227.jpg", "Square/square_230.jpg", "Square/square_166.jpg", "Square/square_23.jpg", "Square/square_46.jpg", "Square/square_312.jpg", "Square/square_144.jpg", "Square/square_303.jpg", "Square/square_329.jpg", "Square/square_286.jpg", "Square/square_306.jpg", "Square/square_185.jpg", "Square/square_207.jpg", "Square/square_2.jpg", "Square/square_113.jpg", "Square/square_7.jpg", "Square/square_143.jpg", "Square/square_316.jpg", "Square/square_311.jpg", "Square/square_96.jpg", "Square/square_151.jpg", "Square/square_208.jpg", "Square/square_93.jpg", "Square/square_253.jpg", "Square/square_9.jpg", "Square/square_95.jpg", "Square/square_212.jpg", "Square/square_169.jpg", "Square/square_202.jpg", "Square/square_125.jpg", "Square/square_246.jpg", "Square/square_145.jpg", "Square/square_291.jpg", "Square/square_94.jpg", "Square/square_112.jpg", "Square/square_54.jpg", "Square/square_32.jpg", "Square/square_13.jpg", "Square/square_296.jpg", "Square/square_161.jpg", "Square/square_275.jpg", "Square/square_317.jpg", "Square/square_131.jpg", "Square/square_30.jpg", "Square/square_252.jpg", "Square/square_264.jpg", "Square/square_189.jpg", "Square/square_127.jpg", "Square/square_262.jpg", "Square/square_328.jpg", "Square/square_237.jpg", "Square/square_222.jpg", "Square/square_231.jpg", "Square/square_256.jpg", "Square/square_75.jpg", "Square/square_232.jpg", "Square/square_128.jpg", "Square/square_184.jpg", "Square/square_182.jpg", "Square/square_74.jpg", "Square/square_188.jpg", "Square/square_47.jpg", "Square/square_149.jpg", "Square/square_18.jpg", "Square/square_308.jpg", "Square/square_154.jpg", "Square/square_84.jpg", "Square/square_175.jpg", "Square/square_63.jpg", "Square/square_277.jpg", "Square/square_148.jpg", "Square/square_37.jpg", "Square/square_44.jpg", "Square/square_160.jpg", "Square/square_228.jpg", "Square/square_255.jpg", "Square/square_70.jpg", "Square/square_163.jpg", "Square/square_191.jpg", "Square/square_27.jpg", "Square/square_171.jpg", "Square/square_199.jpg", "Square/square_3.jpg", "Square/square_181.jpg", "Square/square_55.jpg", "Square/square_236.jpg", "Square/square_269.jpg", "Square/square_77.jpg", "Square/square_314.jpg", "Square/square_120.jpg", "Square/square_203.jpg", "Square/square_41.jpg", "Square/square_19.jpg", "Square/square_327.jpg", "Square/square_309.jpg", "Square/square_102.jpg", "Square/square_235.jpg", "Square/square_272.jpg", "Square/square_322.jpg", "Square/square_213.jpg", "Square/square_6.jpg", "Square/square_73.jpg", "Square/square_238.jpg", "Square/square_139.jpg", "Square/square_194.jpg", "Square/square_71.jpg", "Square/square_51.jpg", "Square/square_293.jpg", "Square/square_147.jpg", "Square/square_210.jpg", "Square/square_155.jpg", "Square/square_157.jpg", "Square/square_152.jpg", "Square/square_177.jpg", "Square/square_288.jpg", "BaseballField/baseballfield_121.jpg", "BaseballField/baseballfield_85.jpg", "BaseballField/baseballfield_173.jpg", "BaseballField/baseballfield_96.jpg", "BaseballField/baseballfield_209.jpg", "BaseballField/baseballfield_3.jpg", "BaseballField/baseballfield_92.jpg", "BaseballField/baseballfield_146.jpg", "BaseballField/baseballfield_144.jpg", "BaseballField/baseballfield_36.jpg", "BaseballField/baseballfield_50.jpg", "BaseballField/baseballfield_33.jpg", "BaseballField/baseballfield_48.jpg", "BaseballField/baseballfield_20.jpg", "BaseballField/baseballfield_169.jpg", "BaseballField/baseballfield_95.jpg", "BaseballField/baseballfield_63.jpg", "BaseballField/baseballfield_150.jpg", "BaseballField/baseballfield_41.jpg", "BaseballField/baseballfield_120.jpg", "BaseballField/baseballfield_57.jpg", "BaseballField/baseballfield_168.jpg", "BaseballField/baseballfield_119.jpg", "BaseballField/baseballfield_71.jpg", "BaseballField/baseballfield_13.jpg", "BaseballField/baseballfield_185.jpg", "BaseballField/baseballfield_188.jpg", "BaseballField/baseballfield_103.jpg", "BaseballField/baseballfield_158.jpg", "BaseballField/baseballfield_186.jpg", "BaseballField/baseballfield_196.jpg", "BaseballField/baseballfield_68.jpg", "BaseballField/baseballfield_174.jpg", "BaseballField/baseballfield_183.jpg", "BaseballField/baseballfield_125.jpg", "BaseballField/baseballfield_166.jpg", "BaseballField/baseballfield_218.jpg", "BaseballField/baseballfield_40.jpg", "BaseballField/baseballfield_197.jpg", "BaseballField/baseballfield_198.jpg", "BaseballField/baseballfield_201.jpg", "BaseballField/baseballfield_78.jpg", "BaseballField/baseballfield_157.jpg", "BaseballField/baseballfield_171.jpg", "BaseballField/baseballfield_211.jpg", "BaseballField/baseballfield_176.jpg", "BaseballField/baseballfield_47.jpg", "BaseballField/baseballfield_101.jpg", "BaseballField/baseballfield_17.jpg", "BaseballField/baseballfield_67.jpg", "BaseballField/baseballfield_39.jpg", "BaseballField/baseballfield_127.jpg", "BaseballField/baseballfield_148.jpg", "BaseballField/baseballfield_11.jpg", "BaseballField/baseballfield_145.jpg", "BaseballField/baseballfield_43.jpg", "BaseballField/baseballfield_82.jpg", "BaseballField/baseballfield_18.jpg", "BaseballField/baseballfield_160.jpg", "BaseballField/baseballfield_59.jpg", "BaseballField/baseballfield_99.jpg", "BaseballField/baseballfield_122.jpg", "BaseballField/baseballfield_23.jpg", "BaseballField/baseballfield_191.jpg", "BaseballField/baseballfield_203.jpg", "BaseballField/baseballfield_88.jpg", "BaseballField/baseballfield_193.jpg", "BaseballField/baseballfield_107.jpg", "BaseballField/baseballfield_29.jpg", "BaseballField/baseballfield_34.jpg", "BaseballField/baseballfield_214.jpg", "BaseballField/baseballfield_91.jpg", "BaseballField/baseballfield_53.jpg", "BaseballField/baseballfield_73.jpg", "BaseballField/baseballfield_118.jpg", "BaseballField/baseballfield_154.jpg", "BaseballField/baseballfield_156.jpg", "BaseballField/baseballfield_147.jpg", "BaseballField/baseballfield_189.jpg", "BaseballField/baseballfield_97.jpg", "BaseballField/baseballfield_113.jpg", "BaseballField/baseballfield_51.jpg", "BaseballField/baseballfield_178.jpg", "BaseballField/baseballfield_130.jpg", "BaseballField/baseballfield_45.jpg", "BaseballField/baseballfield_14.jpg", "BaseballField/baseballfield_153.jpg", "BaseballField/baseballfield_16.jpg", "BaseballField/baseballfield_86.jpg", "BaseballField/baseballfield_151.jpg", "BaseballField/baseballfield_111.jpg", "BaseballField/baseballfield_109.jpg", "BaseballField/baseballfield_58.jpg", "BaseballField/baseballfield_90.jpg", "BaseballField/baseballfield_72.jpg", "BaseballField/baseballfield_80.jpg", "BaseballField/baseballfield_114.jpg", "BaseballField/baseballfield_52.jpg", "BaseballField/baseballfield_129.jpg", "BaseballField/baseballfield_126.jpg", "BaseballField/baseballfield_81.jpg", "BaseballField/baseballfield_149.jpg", "BaseballField/baseballfield_141.jpg", "BaseballField/baseballfield_22.jpg", "BaseballField/baseballfield_217.jpg", "BaseballField/baseballfield_84.jpg", "BaseballField/baseballfield_175.jpg", "BaseballField/baseballfield_172.jpg", "BaseballField/baseballfield_46.jpg", "BaseballField/baseballfield_69.jpg", "BaseballField/baseballfield_5.jpg", "BaseballField/baseballfield_165.jpg", "BaseballField/baseballfield_135.jpg", "BaseballField/baseballfield_134.jpg", "BaseballField/baseballfield_65.jpg", "BaseballField/baseballfield_123.jpg", "BaseballField/baseballfield_100.jpg", "BaseballField/baseballfield_15.jpg", "BaseballField/baseballfield_56.jpg", "BaseballField/baseballfield_83.jpg", "BaseballField/baseballfield_177.jpg", "BaseballField/baseballfield_1.jpg", "BaseballField/baseballfield_181.jpg", "BaseballField/baseballfield_49.jpg", "BaseballField/baseballfield_98.jpg", "BaseballField/baseballfield_208.jpg", "BaseballField/baseballfield_8.jpg", "BaseballField/baseballfield_170.jpg", "BaseballField/baseballfield_28.jpg", "BaseballField/baseballfield_152.jpg", "BaseballField/baseballfield_139.jpg", "BaseballField/baseballfield_167.jpg", "BaseballField/baseballfield_202.jpg", "BaseballField/baseballfield_55.jpg", "BaseballField/baseballfield_216.jpg", "BaseballField/baseballfield_219.jpg", "BaseballField/baseballfield_104.jpg", "BaseballField/baseballfield_213.jpg", "BaseballField/baseballfield_187.jpg", "BaseballField/baseballfield_143.jpg", "BaseballField/baseballfield_21.jpg", "BaseballField/baseballfield_164.jpg", "BaseballField/baseballfield_204.jpg", "BaseballField/baseballfield_24.jpg", "BaseballField/baseballfield_31.jpg", "BaseballField/baseballfield_77.jpg", "BaseballField/baseballfield_66.jpg", "BaseballField/baseballfield_190.jpg", "BaseballField/baseballfield_140.jpg", "BaseballField/baseballfield_115.jpg", "BaseballField/baseballfield_79.jpg", "BaseballField/baseballfield_195.jpg", "BaseballField/baseballfield_12.jpg", "BaseballField/baseballfield_74.jpg", "BaseballField/baseballfield_131.jpg", "BaseballField/baseballfield_75.jpg", "BaseballField/baseballfield_87.jpg", "BaseballField/baseballfield_105.jpg", "BaseballField/baseballfield_10.jpg", "BaseballField/baseballfield_38.jpg", "BaseballField/baseballfield_9.jpg", "BaseballField/baseballfield_161.jpg", "BaseballField/baseballfield_206.jpg", "BaseballField/baseballfield_6.jpg", "BaseballField/baseballfield_142.jpg", "BaseballField/baseballfield_44.jpg", "Church/church_66.jpg", "Church/church_101.jpg", "Church/church_95.jpg", "Church/church_93.jpg", "Church/church_157.jpg", "Church/church_177.jpg", "Church/church_90.jpg", "Church/church_22.jpg", "Church/church_6.jpg", "Church/church_103.jpg", "Church/church_40.jpg", "Church/church_97.jpg", "Church/church_180.jpg", "Church/church_87.jpg", "Church/church_77.jpg", "Church/church_230.jpg", "Church/church_107.jpg", "Church/church_144.jpg", "Church/church_122.jpg", "Church/church_165.jpg", "Church/church_205.jpg", "Church/church_152.jpg", "Church/church_34.jpg", "Church/church_113.jpg", "Church/church_211.jpg", "Church/church_142.jpg", "Church/church_50.jpg", "Church/church_110.jpg", "Church/church_88.jpg", "Church/church_117.jpg", "Church/church_121.jpg", "Church/church_124.jpg", "Church/church_233.jpg", "Church/church_70.jpg", "Church/church_149.jpg", "Church/church_2.jpg", "Church/church_18.jpg", "Church/church_202.jpg", "Church/church_164.jpg", "Church/church_57.jpg", "Church/church_38.jpg", "Church/church_234.jpg", "Church/church_218.jpg", "Church/church_163.jpg", "Church/church_76.jpg", "Church/church_35.jpg", "Church/church_82.jpg", "Church/church_52.jpg", "Church/church_5.jpg", "Church/church_138.jpg", "Church/church_161.jpg", "Church/church_185.jpg", "Church/church_196.jpg", "Church/church_100.jpg", "Church/church_215.jpg", "Church/church_123.jpg", "Church/church_158.jpg", "Church/church_98.jpg", "Church/church_61.jpg", "Church/church_15.jpg", "Church/church_89.jpg", "Church/church_36.jpg", "Church/church_105.jpg", "Church/church_187.jpg", "Church/church_78.jpg", "Church/church_68.jpg", "Church/church_170.jpg", "Church/church_227.jpg", "Church/church_65.jpg", "Church/church_136.jpg", "Church/church_188.jpg", "Church/church_207.jpg", "Church/church_186.jpg", "Church/church_173.jpg", "Church/church_232.jpg", "Church/church_238.jpg", "Church/church_191.jpg", "Church/church_14.jpg", "Church/church_171.jpg", "Church/church_60.jpg", "Church/church_118.jpg", "Church/church_169.jpg", "Church/church_212.jpg", "Church/church_72.jpg", "Church/church_224.jpg", "Church/church_106.jpg", "Church/church_195.jpg", "Church/church_203.jpg", "Church/church_176.jpg", "Church/church_168.jpg", "Church/church_237.jpg", "Church/church_17.jpg", "Church/church_86.jpg", "Church/church_49.jpg", "Church/church_64.jpg", "Church/church_213.jpg", "Church/church_99.jpg", "Church/church_140.jpg", "Church/church_75.jpg", "Church/church_231.jpg", "Church/church_204.jpg", "Church/church_183.jpg", "Church/church_13.jpg", "Church/church_19.jpg", "Church/church_154.jpg", "Church/church_189.jpg", "Church/church_4.jpg", "Church/church_37.jpg", "Church/church_94.jpg", "Church/church_133.jpg", "Church/church_10.jpg", "Church/church_179.jpg", "Church/church_226.jpg", "Church/church_208.jpg", "Church/church_42.jpg", "Church/church_67.jpg", "Church/church_239.jpg", "Church/church_175.jpg", "Church/church_46.jpg", "Church/church_240.jpg", "Church/church_132.jpg", "Church/church_126.jpg", "Church/church_29.jpg", "Church/church_153.jpg", "Church/church_41.jpg", "Church/church_214.jpg", "Church/church_135.jpg", "Church/church_166.jpg", "Church/church_125.jpg", "Church/church_199.jpg", "Church/church_114.jpg", "Church/church_172.jpg", "Church/church_108.jpg", "Church/church_190.jpg", "Church/church_32.jpg", "Church/church_53.jpg", "Church/church_128.jpg", "Church/church_81.jpg", "Church/church_16.jpg", "Church/church_79.jpg", "Church/church_228.jpg", "Church/church_162.jpg", "Church/church_58.jpg", "Church/church_92.jpg", "Church/church_119.jpg", "Church/church_8.jpg", "Church/church_129.jpg", "Church/church_210.jpg", "Church/church_59.jpg", "Church/church_26.jpg", "Church/church_104.jpg", "Church/church_74.jpg", "Church/church_127.jpg", "Church/church_178.jpg", "Church/church_167.jpg", "Church/church_91.jpg", "Church/church_134.jpg", "Church/church_147.jpg", "Church/church_45.jpg", "Church/church_145.jpg", "Church/church_9.jpg", "Church/church_137.jpg", "Church/church_174.jpg", "Church/church_51.jpg", "Church/church_229.jpg", "Church/church_206.jpg", "Church/church_11.jpg", "Church/church_21.jpg", "Church/church_69.jpg", "Church/church_155.jpg", "Church/church_12.jpg", "Church/church_235.jpg", "Church/church_222.jpg", "Church/church_1.jpg", "Church/church_146.jpg", "Church/church_143.jpg", "Church/church_112.jpg", "Church/church_63.jpg", "Church/church_221.jpg", "Church/church_55.jpg", "Church/church_193.jpg", "Church/church_217.jpg", "Farmland/farmland_262.jpg", "Farmland/farmland_73.jpg", "Farmland/farmland_340.jpg", "Farmland/farmland_52.jpg", "Farmland/farmland_320.jpg", "Farmland/farmland_348.jpg", "Farmland/farmland_142.jpg", "Farmland/farmland_269.jpg", "Farmland/farmland_94.jpg", "Farmland/farmland_240.jpg", "Farmland/farmland_153.jpg", "Farmland/farmland_188.jpg", "Farmland/farmland_364.jpg", "Farmland/farmland_335.jpg", "Farmland/farmland_62.jpg", "Farmland/farmland_257.jpg", "Farmland/farmland_209.jpg", "Farmland/farmland_247.jpg", "Farmland/farmland_87.jpg", "Farmland/farmland_330.jpg", "Farmland/farmland_146.jpg", "Farmland/farmland_321.jpg", "Farmland/farmland_215.jpg", "Farmland/farmland_282.jpg", "Farmland/farmland_191.jpg", "Farmland/farmland_318.jpg", "Farmland/farmland_82.jpg", "Farmland/farmland_3.jpg", "Farmland/farmland_322.jpg", "Farmland/farmland_316.jpg", "Farmland/farmland_67.jpg", "Farmland/farmland_173.jpg", "Farmland/farmland_80.jpg", "Farmland/farmland_114.jpg", "Farmland/farmland_167.jpg", "Farmland/farmland_76.jpg", "Farmland/farmland_158.jpg", "Farmland/farmland_11.jpg", "Farmland/farmland_280.jpg", "Farmland/farmland_89.jpg", "Farmland/farmland_326.jpg", "Farmland/farmland_206.jpg", "Farmland/farmland_127.jpg", "Farmland/farmland_39.jpg", "Farmland/farmland_349.jpg", "Farmland/farmland_251.jpg", "Farmland/farmland_149.jpg", "Farmland/farmland_132.jpg", "Farmland/farmland_288.jpg", "Farmland/farmland_214.jpg", "Farmland/farmland_234.jpg", "Farmland/farmland_281.jpg", "Farmland/farmland_174.jpg", "Farmland/farmland_14.jpg", "Farmland/farmland_144.jpg", "Farmland/farmland_210.jpg", "Farmland/farmland_306.jpg", "Farmland/farmland_63.jpg", "Farmland/farmland_358.jpg", "Farmland/farmland_254.jpg", "Farmland/farmland_102.jpg", "Farmland/farmland_48.jpg", "Farmland/farmland_361.jpg", "Farmland/farmland_42.jpg", "Farmland/farmland_266.jpg", "Farmland/farmland_192.jpg", "Farmland/farmland_323.jpg", "Farmland/farmland_186.jpg", "Farmland/farmland_261.jpg", "Farmland/farmland_111.jpg", "Farmland/farmland_298.jpg", "Farmland/farmland_224.jpg", "Farmland/farmland_152.jpg", "Farmland/farmland_296.jpg", "Farmland/farmland_228.jpg", "Farmland/farmland_342.jpg", "Farmland/farmland_185.jpg", "Farmland/farmland_150.jpg", "Farmland/farmland_106.jpg", "Farmland/farmland_28.jpg", "Farmland/farmland_357.jpg", "Farmland/farmland_154.jpg", "Farmland/farmland_278.jpg", "Farmland/farmland_264.jpg", "Farmland/farmland_212.jpg", "Farmland/farmland_295.jpg", "Farmland/farmland_31.jpg", "Farmland/farmland_325.jpg", "Farmland/farmland_6.jpg", "Farmland/farmland_97.jpg", "Farmland/farmland_130.jpg", "Farmland/farmland_166.jpg", "Farmland/farmland_75.jpg", "Farmland/farmland_201.jpg", "Farmland/farmland_69.jpg", "Farmland/farmland_217.jpg", "Farmland/farmland_300.jpg", "Farmland/farmland_277.jpg", "Farmland/farmland_199.jpg", "Farmland/farmland_200.jpg", "Farmland/farmland_7.jpg", "Farmland/farmland_344.jpg", "Farmland/farmland_216.jpg", "Farmland/farmland_22.jpg", "Farmland/farmland_92.jpg", "Farmland/farmland_311.jpg", "Farmland/farmland_55.jpg", "Farmland/farmland_338.jpg", "Farmland/farmland_123.jpg", "Farmland/farmland_160.jpg", "Farmland/farmland_36.jpg", "Farmland/farmland_353.jpg", "Farmland/farmland_169.jpg", "Farmland/farmland_227.jpg", "Farmland/farmland_88.jpg", "Farmland/farmland_159.jpg", "Farmland/farmland_41.jpg", "Farmland/farmland_260.jpg", "Farmland/farmland_139.jpg", "Farmland/farmland_310.jpg", "Farmland/farmland_222.jpg", "Farmland/farmland_163.jpg", "Farmland/farmland_331.jpg", "Farmland/farmland_45.jpg", "Farmland/farmland_85.jpg", "Farmland/farmland_155.jpg", "Farmland/farmland_229.jpg", "Farmland/farmland_221.jpg", "Farmland/farmland_250.jpg", "Farmland/farmland_252.jpg", "Farmland/farmland_263.jpg", "Farmland/farmland_308.jpg", "Farmland/farmland_148.jpg", "Farmland/farmland_181.jpg", "Farmland/farmland_197.jpg", "Farmland/farmland_120.jpg", "Farmland/farmland_193.jpg", "Farmland/farmland_18.jpg", "Farmland/farmland_213.jpg", "Farmland/farmland_189.jpg", "Farmland/farmland_232.jpg", "Farmland/farmland_38.jpg", "Farmland/farmland_346.jpg", "Farmland/farmland_313.jpg", "Farmland/farmland_1.jpg", "Farmland/farmland_286.jpg", "Farmland/farmland_354.jpg", "Farmland/farmland_368.jpg", "Farmland/farmland_312.jpg", "Farmland/farmland_43.jpg", "Farmland/farmland_202.jpg", "Farmland/farmland_116.jpg", "Farmland/farmland_182.jpg", "Farmland/farmland_109.jpg", "Farmland/farmland_272.jpg", "Farmland/farmland_370.jpg", "Farmland/farmland_233.jpg", "Farmland/farmland_35.jpg", "Farmland/farmland_187.jpg", "Farmland/farmland_34.jpg", "Farmland/farmland_180.jpg", "Farmland/farmland_207.jpg", "Farmland/farmland_242.jpg", "Farmland/farmland_79.jpg", "Farmland/farmland_304.jpg", "Farmland/farmland_91.jpg", "Farmland/farmland_57.jpg", "Farmland/farmland_2.jpg", "Farmland/farmland_44.jpg", "Farmland/farmland_126.jpg", "Farmland/farmland_13.jpg", "Farmland/farmland_256.jpg", "Farmland/farmland_208.jpg", "Farmland/farmland_226.jpg", "Farmland/farmland_365.jpg", "Farmland/farmland_115.jpg", "Farmland/farmland_168.jpg", "Farmland/farmland_86.jpg", "Farmland/farmland_273.jpg", "Farmland/farmland_356.jpg", "Farmland/farmland_294.jpg", "Farmland/farmland_284.jpg", "Farmland/farmland_84.jpg", "Farmland/farmland_183.jpg", "Farmland/farmland_175.jpg", "Farmland/farmland_333.jpg", "Farmland/farmland_136.jpg", "Farmland/farmland_293.jpg", "Farmland/farmland_110.jpg", "Farmland/farmland_303.jpg", "Farmland/farmland_231.jpg", "Farmland/farmland_172.jpg", "Farmland/farmland_367.jpg", "Farmland/farmland_12.jpg", "Farmland/farmland_59.jpg", "Farmland/farmland_100.jpg", "Farmland/farmland_83.jpg", "Farmland/farmland_315.jpg", "Farmland/farmland_245.jpg", "Farmland/farmland_274.jpg", "Farmland/farmland_345.jpg", "Farmland/farmland_297.jpg", "Farmland/farmland_302.jpg", "Farmland/farmland_125.jpg", "Farmland/farmland_366.jpg", "Farmland/farmland_68.jpg", "Farmland/farmland_58.jpg", "Farmland/farmland_53.jpg", "Farmland/farmland_141.jpg", "Farmland/farmland_243.jpg", "Farmland/farmland_23.jpg", "Farmland/farmland_65.jpg", "Farmland/farmland_30.jpg", "Farmland/farmland_156.jpg", "Farmland/farmland_289.jpg", "Farmland/farmland_314.jpg", "Farmland/farmland_134.jpg", "Farmland/farmland_151.jpg", "Farmland/farmland_49.jpg", "Farmland/farmland_329.jpg", "Farmland/farmland_279.jpg", "Farmland/farmland_25.jpg", "Farmland/farmland_61.jpg", "Farmland/farmland_95.jpg", "Farmland/farmland_171.jpg", "Farmland/farmland_108.jpg", "Farmland/farmland_56.jpg", "Farmland/farmland_218.jpg", "Farmland/farmland_143.jpg", "Farmland/farmland_301.jpg", "Farmland/farmland_249.jpg", "Farmland/farmland_195.jpg", "Farmland/farmland_129.jpg", "Farmland/farmland_176.jpg", "Farmland/farmland_341.jpg", "Farmland/farmland_99.jpg", "Farmland/farmland_96.jpg", "Farmland/farmland_319.jpg", "Farmland/farmland_147.jpg", "Farmland/farmland_190.jpg", "Farmland/farmland_307.jpg", "Farmland/farmland_128.jpg", "Farmland/farmland_60.jpg", "Farmland/farmland_37.jpg", "Farmland/farmland_347.jpg", "Farmland/farmland_369.jpg", "Farmland/farmland_337.jpg", "Farmland/farmland_10.jpg", "Farmland/farmland_113.jpg", "Farmland/farmland_259.jpg", "Farmland/farmland_51.jpg", "Farmland/farmland_5.jpg", "Farmland/farmland_205.jpg", "Farmland/farmland_350.jpg", "Farmland/farmland_64.jpg", "Farmland/farmland_332.jpg", "Farmland/farmland_137.jpg", "Farmland/farmland_90.jpg", "Farmland/farmland_121.jpg", "Farmland/farmland_291.jpg", "Farmland/farmland_359.jpg", "Farmland/farmland_184.jpg", "Farmland/farmland_241.jpg", "Farmland/farmland_81.jpg", "Farmland/farmland_19.jpg", "Farmland/farmland_47.jpg", "Farmland/farmland_15.jpg", "Farmland/farmland_32.jpg", "Farmland/farmland_117.jpg", "Farmland/farmland_162.jpg", "Farmland/farmland_336.jpg", "Farmland/farmland_74.jpg", "Farmland/farmland_4.jpg", "Farmland/farmland_324.jpg", "Farmland/farmland_54.jpg", "Farmland/farmland_24.jpg", "Farmland/farmland_219.jpg", "Farmland/farmland_157.jpg", "Farmland/farmland_16.jpg", "Farmland/farmland_26.jpg", "Farmland/farmland_133.jpg", "Farmland/farmland_98.jpg", "Farmland/farmland_225.jpg", "Farmland/farmland_138.jpg", "Farmland/farmland_170.jpg", "Farmland/farmland_165.jpg", "Stadium/stadium_89.jpg", "Stadium/stadium_247.jpg", "Stadium/stadium_185.jpg", "Stadium/stadium_290.jpg", "Stadium/stadium_54.jpg", "Stadium/stadium_214.jpg", "Stadium/stadium_38.jpg", "Stadium/stadium_277.jpg", "Stadium/stadium_166.jpg", "Stadium/stadium_270.jpg", "Stadium/stadium_207.jpg", "Stadium/stadium_22.jpg", "Stadium/stadium_230.jpg", "Stadium/stadium_59.jpg", "Stadium/stadium_110.jpg", "Stadium/stadium_202.jpg", "Stadium/stadium_107.jpg", "Stadium/stadium_199.jpg", "Stadium/stadium_281.jpg", "Stadium/stadium_215.jpg", "Stadium/stadium_113.jpg", "Stadium/stadium_238.jpg", "Stadium/stadium_197.jpg", "Stadium/stadium_258.jpg", "Stadium/stadium_156.jpg", "Stadium/stadium_251.jpg", "Stadium/stadium_149.jpg", "Stadium/stadium_143.jpg", "Stadium/stadium_147.jpg", "Stadium/stadium_90.jpg", "Stadium/stadium_140.jpg", "Stadium/stadium_60.jpg", "Stadium/stadium_71.jpg", "Stadium/stadium_198.jpg", "Stadium/stadium_91.jpg", "Stadium/stadium_36.jpg", "Stadium/stadium_144.jpg", "Stadium/stadium_99.jpg", "Stadium/stadium_117.jpg", "Stadium/stadium_271.jpg", "Stadium/stadium_170.jpg", "Stadium/stadium_77.jpg", "Stadium/stadium_104.jpg", "Stadium/stadium_96.jpg", "Stadium/stadium_1.jpg", "Stadium/stadium_57.jpg", "Stadium/stadium_273.jpg", "Stadium/stadium_233.jpg", "Stadium/stadium_284.jpg", "Stadium/stadium_46.jpg", "Stadium/stadium_206.jpg", "Stadium/stadium_73.jpg", "Stadium/stadium_229.jpg", "Stadium/stadium_64.jpg", "Stadium/stadium_130.jpg", "Stadium/stadium_41.jpg", "Stadium/stadium_188.jpg", "Stadium/stadium_4.jpg", "Stadium/stadium_26.jpg", "Stadium/stadium_44.jpg", "Stadium/stadium_28.jpg", "Stadium/stadium_169.jpg", "Stadium/stadium_9.jpg", "Stadium/stadium_227.jpg", "Stadium/stadium_265.jpg", "Stadium/stadium_42.jpg", "Stadium/stadium_98.jpg", "Stadium/stadium_55.jpg", "Stadium/stadium_253.jpg", "Stadium/stadium_129.jpg", "Stadium/stadium_231.jpg", "Stadium/stadium_208.jpg", "Stadium/stadium_47.jpg", "Stadium/stadium_108.jpg", "Stadium/stadium_30.jpg", "Stadium/stadium_121.jpg", "Stadium/stadium_285.jpg", "Stadium/stadium_181.jpg", "Stadium/stadium_103.jpg", "Stadium/stadium_190.jpg", "Stadium/stadium_20.jpg", "Stadium/stadium_146.jpg", "Stadium/stadium_126.jpg", "Stadium/stadium_210.jpg", "Stadium/stadium_288.jpg", "Stadium/stadium_35.jpg", "Stadium/stadium_242.jpg", "Stadium/stadium_17.jpg", "Stadium/stadium_50.jpg", "Stadium/stadium_3.jpg", "Stadium/stadium_33.jpg", "Stadium/stadium_134.jpg", "Stadium/stadium_123.jpg", "Stadium/stadium_221.jpg", "Stadium/stadium_193.jpg", "Stadium/stadium_239.jpg", "Stadium/stadium_7.jpg", "Stadium/stadium_79.jpg", "Stadium/stadium_240.jpg", "Stadium/stadium_172.jpg", "Stadium/stadium_76.jpg", "Stadium/stadium_173.jpg", "Stadium/stadium_23.jpg", "Stadium/stadium_155.jpg", "Stadium/stadium_67.jpg", "Stadium/stadium_160.jpg", "Stadium/stadium_32.jpg", "Stadium/stadium_268.jpg", "Stadium/stadium_211.jpg", "Stadium/stadium_49.jpg", "Stadium/stadium_226.jpg", "Stadium/stadium_88.jpg", "Stadium/stadium_195.jpg", "Stadium/stadium_74.jpg", "Stadium/stadium_53.jpg", "Stadium/stadium_256.jpg", "Stadium/stadium_21.jpg", "Stadium/stadium_85.jpg", "Stadium/stadium_261.jpg", "Stadium/stadium_241.jpg", "Stadium/stadium_94.jpg", "Stadium/stadium_18.jpg", "Stadium/stadium_14.jpg", "Stadium/stadium_152.jpg", "Stadium/stadium_161.jpg", "Stadium/stadium_62.jpg", "Stadium/stadium_141.jpg", "Stadium/stadium_133.jpg", "Stadium/stadium_34.jpg", "Stadium/stadium_192.jpg", "Stadium/stadium_267.jpg", "Stadium/stadium_266.jpg", "Stadium/stadium_217.jpg", "Stadium/stadium_196.jpg", "Stadium/stadium_249.jpg", "Stadium/stadium_52.jpg", "Stadium/stadium_216.jpg", "Stadium/stadium_136.jpg", "Stadium/stadium_82.jpg", "Stadium/stadium_150.jpg", "Stadium/stadium_224.jpg", "Stadium/stadium_72.jpg", "Stadium/stadium_116.jpg", "Stadium/stadium_218.jpg", "Stadium/stadium_56.jpg", "Stadium/stadium_287.jpg", "Stadium/stadium_102.jpg", "Stadium/stadium_178.jpg", "Stadium/stadium_228.jpg", "Stadium/stadium_25.jpg", "Stadium/stadium_235.jpg", "Stadium/stadium_222.jpg", "Stadium/stadium_262.jpg", "Stadium/stadium_106.jpg", "Stadium/stadium_27.jpg", "Stadium/stadium_109.jpg", "Stadium/stadium_274.jpg", "Stadium/stadium_177.jpg", "Stadium/stadium_10.jpg", "Stadium/stadium_86.jpg", "Stadium/stadium_254.jpg", "Stadium/stadium_154.jpg", "Stadium/stadium_15.jpg", "Stadium/stadium_184.jpg", "Stadium/stadium_171.jpg", "Stadium/stadium_220.jpg", "Stadium/stadium_289.jpg", "Stadium/stadium_5.jpg", "Stadium/stadium_6.jpg", "Stadium/stadium_269.jpg", "Stadium/stadium_275.jpg", "Stadium/stadium_135.jpg", "Stadium/stadium_223.jpg", "Stadium/stadium_245.jpg", "Stadium/stadium_8.jpg", "Stadium/stadium_194.jpg", "Stadium/stadium_118.jpg", "Stadium/stadium_66.jpg", "Stadium/stadium_252.jpg", "Stadium/stadium_128.jpg", "Stadium/stadium_159.jpg", "Stadium/stadium_153.jpg", "Stadium/stadium_40.jpg", "Stadium/stadium_31.jpg", "Stadium/stadium_232.jpg", "Stadium/stadium_92.jpg", "Stadium/stadium_204.jpg", "Stadium/stadium_70.jpg", "Stadium/stadium_81.jpg", "Stadium/stadium_24.jpg", "Stadium/stadium_145.jpg", "Stadium/stadium_186.jpg", "Stadium/stadium_260.jpg", "Stadium/stadium_137.jpg", "Stadium/stadium_257.jpg", "Stadium/stadium_120.jpg", "Stadium/stadium_97.jpg", "Stadium/stadium_209.jpg", "Stadium/stadium_248.jpg", "Stadium/stadium_174.jpg", "Stadium/stadium_65.jpg", "Stadium/stadium_151.jpg", "Stadium/stadium_19.jpg", "Stadium/stadium_183.jpg", "Stadium/stadium_244.jpg", "Stadium/stadium_219.jpg", "Stadium/stadium_203.jpg", "Stadium/stadium_200.jpg", "Stadium/stadium_101.jpg", "Stadium/stadium_165.jpg", "Stadium/stadium_225.jpg", "Stadium/stadium_127.jpg", "Stadium/stadium_205.jpg", "Stadium/stadium_246.jpg", "Stadium/stadium_201.jpg", "Stadium/stadium_272.jpg", "Stadium/stadium_132.jpg", "Stadium/stadium_63.jpg", "Stadium/stadium_164.jpg", "Stadium/stadium_16.jpg", "Stadium/stadium_80.jpg", "Stadium/stadium_87.jpg", "Viaduct/viaduct_17.jpg", "Viaduct/viaduct_182.jpg", "Viaduct/viaduct_278.jpg", "Viaduct/viaduct_245.jpg", "Viaduct/viaduct_219.jpg", "Viaduct/viaduct_391.jpg", "Viaduct/viaduct_24.jpg", "Viaduct/viaduct_167.jpg", "Viaduct/viaduct_361.jpg", "Viaduct/viaduct_6.jpg", "Viaduct/viaduct_135.jpg", "Viaduct/viaduct_98.jpg", "Viaduct/viaduct_191.jpg", "Viaduct/viaduct_420.jpg", "Viaduct/viaduct_272.jpg", "Viaduct/viaduct_247.jpg", "Viaduct/viaduct_298.jpg", "Viaduct/viaduct_302.jpg", "Viaduct/viaduct_123.jpg", "Viaduct/viaduct_88.jpg", "Viaduct/viaduct_31.jpg", "Viaduct/viaduct_368.jpg", "Viaduct/viaduct_408.jpg", "Viaduct/viaduct_283.jpg", "Viaduct/viaduct_122.jpg", "Viaduct/viaduct_33.jpg", "Viaduct/viaduct_262.jpg", "Viaduct/viaduct_119.jpg", "Viaduct/viaduct_200.jpg", "Viaduct/viaduct_224.jpg", "Viaduct/viaduct_326.jpg", "Viaduct/viaduct_96.jpg", "Viaduct/viaduct_44.jpg", "Viaduct/viaduct_294.jpg", "Viaduct/viaduct_390.jpg", "Viaduct/viaduct_331.jpg", "Viaduct/viaduct_388.jpg", "Viaduct/viaduct_270.jpg", "Viaduct/viaduct_71.jpg", "Viaduct/viaduct_393.jpg", "Viaduct/viaduct_378.jpg", "Viaduct/viaduct_226.jpg", "Viaduct/viaduct_192.jpg", "Viaduct/viaduct_90.jpg", "Viaduct/viaduct_394.jpg", "Viaduct/viaduct_217.jpg", "Viaduct/viaduct_363.jpg", "Viaduct/viaduct_333.jpg", "Viaduct/viaduct_43.jpg", "Viaduct/viaduct_196.jpg", "Viaduct/viaduct_261.jpg", "Viaduct/viaduct_53.jpg", "Viaduct/viaduct_385.jpg", "Viaduct/viaduct_38.jpg", "Viaduct/viaduct_412.jpg", "Viaduct/viaduct_163.jpg", "Viaduct/viaduct_76.jpg", "Viaduct/viaduct_372.jpg", "Viaduct/viaduct_162.jpg", "Viaduct/viaduct_174.jpg", "Viaduct/viaduct_231.jpg", "Viaduct/viaduct_300.jpg", "Viaduct/viaduct_237.jpg", "Viaduct/viaduct_114.jpg", "Viaduct/viaduct_48.jpg", "Viaduct/viaduct_290.jpg", "Viaduct/viaduct_343.jpg", "Viaduct/viaduct_206.jpg", "Viaduct/viaduct_301.jpg", "Viaduct/viaduct_345.jpg", "Viaduct/viaduct_332.jpg", "Viaduct/viaduct_400.jpg", "Viaduct/viaduct_315.jpg", "Viaduct/viaduct_336.jpg", "Viaduct/viaduct_84.jpg", "Viaduct/viaduct_133.jpg", "Viaduct/viaduct_20.jpg", "Viaduct/viaduct_156.jpg", "Viaduct/viaduct_26.jpg", "Viaduct/viaduct_387.jpg", "Viaduct/viaduct_41.jpg", "Viaduct/viaduct_74.jpg", "Viaduct/viaduct_397.jpg", "Viaduct/viaduct_106.jpg", "Viaduct/viaduct_225.jpg", "Viaduct/viaduct_46.jpg", "Viaduct/viaduct_287.jpg", "Viaduct/viaduct_319.jpg", "Viaduct/viaduct_316.jpg", "Viaduct/viaduct_342.jpg", "Viaduct/viaduct_127.jpg", "Viaduct/viaduct_354.jpg", "Viaduct/viaduct_329.jpg", "Viaduct/viaduct_306.jpg", "Viaduct/viaduct_165.jpg", "Viaduct/viaduct_149.jpg", "Viaduct/viaduct_155.jpg", "Viaduct/viaduct_255.jpg", "Viaduct/viaduct_64.jpg", "Viaduct/viaduct_54.jpg", "Viaduct/viaduct_61.jpg", "Viaduct/viaduct_252.jpg", "Viaduct/viaduct_9.jpg", "Viaduct/viaduct_323.jpg", "Viaduct/viaduct_328.jpg", "Viaduct/viaduct_19.jpg", "Viaduct/viaduct_414.jpg", "Viaduct/viaduct_317.jpg", "Viaduct/viaduct_78.jpg", "Viaduct/viaduct_281.jpg", "Viaduct/viaduct_350.jpg", "Viaduct/viaduct_45.jpg", "Viaduct/viaduct_395.jpg", "Viaduct/viaduct_384.jpg", "Viaduct/viaduct_335.jpg", "Viaduct/viaduct_67.jpg", "Viaduct/viaduct_279.jpg", "Viaduct/viaduct_389.jpg", "Viaduct/viaduct_72.jpg", "Viaduct/viaduct_140.jpg", "Viaduct/viaduct_92.jpg", "Viaduct/viaduct_15.jpg", "Viaduct/viaduct_266.jpg", "Viaduct/viaduct_190.jpg", "Viaduct/viaduct_105.jpg", "Viaduct/viaduct_267.jpg", "Viaduct/viaduct_95.jpg", "Viaduct/viaduct_352.jpg", "Viaduct/viaduct_5.jpg", "Viaduct/viaduct_413.jpg", "Viaduct/viaduct_171.jpg", "Viaduct/viaduct_296.jpg", "Viaduct/viaduct_359.jpg", "Viaduct/viaduct_417.jpg", "Viaduct/viaduct_94.jpg", "Viaduct/viaduct_419.jpg", "Viaduct/viaduct_35.jpg", "Viaduct/viaduct_314.jpg", "Viaduct/viaduct_12.jpg", "Viaduct/viaduct_259.jpg", "Viaduct/viaduct_97.jpg", "Viaduct/viaduct_382.jpg", "Viaduct/viaduct_362.jpg", "Viaduct/viaduct_131.jpg", "Viaduct/viaduct_212.jpg", "Viaduct/viaduct_222.jpg", "Viaduct/viaduct_295.jpg", "Viaduct/viaduct_183.jpg", "Viaduct/viaduct_312.jpg", "Viaduct/viaduct_318.jpg", "Viaduct/viaduct_77.jpg", "Viaduct/viaduct_124.jpg", "Viaduct/viaduct_402.jpg", "Viaduct/viaduct_392.jpg", "Viaduct/viaduct_25.jpg", "Viaduct/viaduct_80.jpg", "Viaduct/viaduct_291.jpg", "Viaduct/viaduct_32.jpg", "Viaduct/viaduct_68.jpg", "Viaduct/viaduct_185.jpg", "Viaduct/viaduct_349.jpg", "Viaduct/viaduct_110.jpg", "Viaduct/viaduct_405.jpg", "Viaduct/viaduct_103.jpg", "Viaduct/viaduct_303.jpg", "Viaduct/viaduct_398.jpg", "Viaduct/viaduct_409.jpg", "Viaduct/viaduct_415.jpg", "Viaduct/viaduct_309.jpg", "Viaduct/viaduct_341.jpg", "Viaduct/viaduct_73.jpg", "Viaduct/viaduct_56.jpg", "Viaduct/viaduct_81.jpg", "Viaduct/viaduct_347.jpg", "Viaduct/viaduct_381.jpg", "Viaduct/viaduct_101.jpg", "Viaduct/viaduct_18.jpg", "Viaduct/viaduct_180.jpg", "Viaduct/viaduct_87.jpg", "Viaduct/viaduct_355.jpg", "Viaduct/viaduct_274.jpg", "Viaduct/viaduct_86.jpg", "Viaduct/viaduct_407.jpg", "Viaduct/viaduct_66.jpg", "Viaduct/viaduct_230.jpg", "Viaduct/viaduct_160.jpg", "Viaduct/viaduct_223.jpg", "Viaduct/viaduct_85.jpg", "Viaduct/viaduct_275.jpg", "Viaduct/viaduct_288.jpg", "Viaduct/viaduct_208.jpg", "Viaduct/viaduct_159.jpg", "Viaduct/viaduct_168.jpg", "Viaduct/viaduct_148.jpg", "Viaduct/viaduct_356.jpg", "Viaduct/viaduct_265.jpg", "Viaduct/viaduct_151.jpg", "Viaduct/viaduct_179.jpg", "Viaduct/viaduct_221.jpg", "Viaduct/viaduct_141.jpg", "Viaduct/viaduct_346.jpg", "Viaduct/viaduct_357.jpg", "Viaduct/viaduct_337.jpg", "Viaduct/viaduct_194.jpg", "Viaduct/viaduct_313.jpg", "Viaduct/viaduct_353.jpg", "Viaduct/viaduct_129.jpg", "Viaduct/viaduct_169.jpg", "Viaduct/viaduct_344.jpg", "Viaduct/viaduct_348.jpg", "Viaduct/viaduct_396.jpg", "Viaduct/viaduct_249.jpg", "Viaduct/viaduct_2.jpg", "Viaduct/viaduct_178.jpg", "Viaduct/viaduct_254.jpg", "Viaduct/viaduct_220.jpg", "Viaduct/viaduct_107.jpg", "Viaduct/viaduct_14.jpg", "Viaduct/viaduct_201.jpg", "Viaduct/viaduct_104.jpg", "Viaduct/viaduct_218.jpg", "Viaduct/viaduct_93.jpg", "Viaduct/viaduct_11.jpg", "Viaduct/viaduct_181.jpg", "Viaduct/viaduct_375.jpg", "Viaduct/viaduct_282.jpg", "Viaduct/viaduct_215.jpg", "Viaduct/viaduct_42.jpg", "Viaduct/viaduct_13.jpg", "Viaduct/viaduct_380.jpg", "Viaduct/viaduct_34.jpg", "Viaduct/viaduct_339.jpg", "Viaduct/viaduct_8.jpg", "Viaduct/viaduct_244.jpg", "Viaduct/viaduct_289.jpg", "Viaduct/viaduct_358.jpg", "Viaduct/viaduct_198.jpg", "Viaduct/viaduct_293.jpg", "Viaduct/viaduct_147.jpg", "Viaduct/viaduct_154.jpg", "Viaduct/viaduct_134.jpg", "Viaduct/viaduct_327.jpg", "Viaduct/viaduct_284.jpg", "Viaduct/viaduct_22.jpg", "Viaduct/viaduct_203.jpg", "Viaduct/viaduct_257.jpg", "Viaduct/viaduct_116.jpg", "Viaduct/viaduct_210.jpg", "Viaduct/viaduct_324.jpg", "Viaduct/viaduct_111.jpg", "Viaduct/viaduct_65.jpg", "Viaduct/viaduct_205.jpg", "Viaduct/viaduct_128.jpg", "Viaduct/viaduct_242.jpg", "Viaduct/viaduct_89.jpg", "Viaduct/viaduct_117.jpg", "Viaduct/viaduct_263.jpg", "Viaduct/viaduct_82.jpg", "Viaduct/viaduct_83.jpg", "Viaduct/viaduct_227.jpg", "Viaduct/viaduct_143.jpg", "Viaduct/viaduct_248.jpg", "Viaduct/viaduct_152.jpg", "Viaduct/viaduct_406.jpg", "Viaduct/viaduct_351.jpg", "Viaduct/viaduct_330.jpg", "Viaduct/viaduct_60.jpg", "Viaduct/viaduct_322.jpg", "Viaduct/viaduct_144.jpg", "Viaduct/viaduct_3.jpg", "Viaduct/viaduct_79.jpg", "Viaduct/viaduct_176.jpg", "Viaduct/viaduct_320.jpg", "Viaduct/viaduct_40.jpg", "Viaduct/viaduct_321.jpg", "Viaduct/viaduct_91.jpg", "Viaduct/viaduct_188.jpg", "Viaduct/viaduct_258.jpg", "Viaduct/viaduct_115.jpg", "Viaduct/viaduct_166.jpg", "Viaduct/viaduct_386.jpg", "Viaduct/viaduct_253.jpg", "Viaduct/viaduct_374.jpg", "Viaduct/viaduct_113.jpg", "Viaduct/viaduct_139.jpg", "Viaduct/viaduct_214.jpg", "Viaduct/viaduct_260.jpg", "Viaduct/viaduct_268.jpg", "Viaduct/viaduct_193.jpg", "Viaduct/viaduct_233.jpg", "Viaduct/viaduct_308.jpg", "Viaduct/viaduct_273.jpg", "Viaduct/viaduct_70.jpg", "Viaduct/viaduct_28.jpg", "Viaduct/viaduct_199.jpg", "Viaduct/viaduct_251.jpg", "Viaduct/viaduct_404.jpg", "Viaduct/viaduct_109.jpg", "Viaduct/viaduct_209.jpg", "Viaduct/viaduct_369.jpg", "Viaduct/viaduct_150.jpg", "Viaduct/viaduct_30.jpg", "Viaduct/viaduct_121.jpg", "Viaduct/viaduct_256.jpg", "Viaduct/viaduct_146.jpg", "Viaduct/viaduct_27.jpg", "Viaduct/viaduct_292.jpg", "Viaduct/viaduct_132.jpg", "Viaduct/viaduct_204.jpg", "Viaduct/viaduct_142.jpg", "Viaduct/viaduct_23.jpg", "Viaduct/viaduct_120.jpg", "Viaduct/viaduct_186.jpg", "Viaduct/viaduct_58.jpg", "Viaduct/viaduct_158.jpg", "Viaduct/viaduct_232.jpg", "Viaduct/viaduct_112.jpg", "Viaduct/viaduct_57.jpg", "Viaduct/viaduct_370.jpg", "Viaduct/viaduct_286.jpg", "Viaduct/viaduct_403.jpg", "Viaduct/viaduct_338.jpg", "Viaduct/viaduct_236.jpg", "Viaduct/viaduct_418.jpg", "Viaduct/viaduct_130.jpg", "Viaduct/viaduct_299.jpg", "Commercial/commercial_148.jpg", "Commercial/commercial_188.jpg", "Commercial/commercial_135.jpg", "Commercial/commercial_145.jpg", "Commercial/commercial_219.jpg", "Commercial/commercial_84.jpg", "Commercial/commercial_185.jpg", "Commercial/commercial_152.jpg", "Commercial/commercial_16.jpg", "Commercial/commercial_11.jpg", "Commercial/commercial_101.jpg", "Commercial/commercial_124.jpg", "Commercial/commercial_272.jpg", "Commercial/commercial_129.jpg", "Commercial/commercial_194.jpg", "Commercial/commercial_98.jpg", "Commercial/commercial_298.jpg", "Commercial/commercial_15.jpg", "Commercial/commercial_107.jpg", "Commercial/commercial_238.jpg", "Commercial/commercial_193.jpg", "Commercial/commercial_342.jpg", "Commercial/commercial_58.jpg", "Commercial/commercial_321.jpg", "Commercial/commercial_186.jpg", "Commercial/commercial_278.jpg", "Commercial/commercial_100.jpg", "Commercial/commercial_262.jpg", "Commercial/commercial_151.jpg", "Commercial/commercial_138.jpg", "Commercial/commercial_159.jpg", "Commercial/commercial_243.jpg", "Commercial/commercial_126.jpg", "Commercial/commercial_172.jpg", "Commercial/commercial_79.jpg", "Commercial/commercial_336.jpg", "Commercial/commercial_320.jpg", "Commercial/commercial_274.jpg", "Commercial/commercial_10.jpg", "Commercial/commercial_284.jpg", "Commercial/commercial_91.jpg", "Commercial/commercial_337.jpg", "Commercial/commercial_2.jpg", "Commercial/commercial_63.jpg", "Commercial/commercial_154.jpg", "Commercial/commercial_190.jpg", "Commercial/commercial_122.jpg", "Commercial/commercial_47.jpg", "Commercial/commercial_184.jpg", "Commercial/commercial_257.jpg", "Commercial/commercial_111.jpg", "Commercial/commercial_200.jpg", "Commercial/commercial_204.jpg", "Commercial/commercial_289.jpg", "Commercial/commercial_296.jpg", "Commercial/commercial_286.jpg", "Commercial/commercial_318.jpg", "Commercial/commercial_349.jpg", "Commercial/commercial_323.jpg", "Commercial/commercial_297.jpg", "Commercial/commercial_127.jpg", "Commercial/commercial_165.jpg", "Commercial/commercial_215.jpg", "Commercial/commercial_211.jpg", "Commercial/commercial_157.jpg", "Commercial/commercial_234.jpg", "Commercial/commercial_46.jpg", "Commercial/commercial_299.jpg", "Commercial/commercial_189.jpg", "Commercial/commercial_226.jpg", "Commercial/commercial_70.jpg", "Commercial/commercial_72.jpg", "Commercial/commercial_241.jpg", "Commercial/commercial_205.jpg", "Commercial/commercial_345.jpg", "Commercial/commercial_210.jpg", "Commercial/commercial_250.jpg", "Commercial/commercial_235.jpg", "Commercial/commercial_120.jpg", "Commercial/commercial_121.jpg", "Commercial/commercial_162.jpg", "Commercial/commercial_171.jpg", "Commercial/commercial_317.jpg", "Commercial/commercial_156.jpg", "Commercial/commercial_288.jpg", "Commercial/commercial_94.jpg", "Commercial/commercial_115.jpg", "Commercial/commercial_325.jpg", "Commercial/commercial_130.jpg", "Commercial/commercial_116.jpg", "Commercial/commercial_197.jpg", "Commercial/commercial_39.jpg", "Commercial/commercial_269.jpg", "Commercial/commercial_216.jpg", "Commercial/commercial_277.jpg", "Commercial/commercial_304.jpg", "Commercial/commercial_316.jpg", "Commercial/commercial_8.jpg", "Commercial/commercial_201.jpg", "Commercial/commercial_60.jpg", "Commercial/commercial_256.jpg", "Commercial/commercial_202.jpg", "Commercial/commercial_248.jpg", "Commercial/commercial_64.jpg", "Commercial/commercial_112.jpg", "Commercial/commercial_319.jpg", "Commercial/commercial_236.jpg", "Commercial/commercial_50.jpg", "Commercial/commercial_196.jpg", "Commercial/commercial_183.jpg", "Commercial/commercial_155.jpg", "Commercial/commercial_34.jpg", "Commercial/commercial_114.jpg", "Commercial/commercial_187.jpg", "Commercial/commercial_141.jpg", "Commercial/commercial_276.jpg", "Commercial/commercial_80.jpg", "Commercial/commercial_173.jpg", "Commercial/commercial_53.jpg", "Commercial/commercial_231.jpg", "Commercial/commercial_329.jpg", "Commercial/commercial_48.jpg", "Commercial/commercial_77.jpg", "Commercial/commercial_59.jpg", "Commercial/commercial_207.jpg", "Commercial/commercial_273.jpg", "Commercial/commercial_251.jpg", "Commercial/commercial_5.jpg", "Commercial/commercial_240.jpg", "Commercial/commercial_22.jpg", "Commercial/commercial_140.jpg", "Commercial/commercial_55.jpg", "Commercial/commercial_128.jpg", "Commercial/commercial_44.jpg", "Commercial/commercial_246.jpg", "Commercial/commercial_166.jpg", "Commercial/commercial_71.jpg", "Commercial/commercial_244.jpg", "Commercial/commercial_179.jpg", "Commercial/commercial_346.jpg", "Commercial/commercial_308.jpg", "Commercial/commercial_338.jpg", "Commercial/commercial_175.jpg", "Commercial/commercial_164.jpg", "Commercial/commercial_23.jpg", "Commercial/commercial_295.jpg", "Commercial/commercial_73.jpg", "Commercial/commercial_198.jpg", "Commercial/commercial_182.jpg", "Commercial/commercial_160.jpg", "Commercial/commercial_328.jpg", "Commercial/commercial_83.jpg", "Commercial/commercial_90.jpg", "Commercial/commercial_212.jpg", "Commercial/commercial_261.jpg", "Commercial/commercial_312.jpg", "Commercial/commercial_134.jpg", "Commercial/commercial_253.jpg", "Commercial/commercial_233.jpg", "Commercial/commercial_178.jpg", "Commercial/commercial_43.jpg", "Commercial/commercial_31.jpg", "Commercial/commercial_52.jpg", "Commercial/commercial_275.jpg", "Commercial/commercial_332.jpg", "Commercial/commercial_334.jpg", "Commercial/commercial_82.jpg", "Commercial/commercial_142.jpg", "Commercial/commercial_314.jpg", "Commercial/commercial_300.jpg", "Commercial/commercial_291.jpg", "Commercial/commercial_56.jpg", "Commercial/commercial_85.jpg", "Commercial/commercial_191.jpg", "Commercial/commercial_118.jpg", "Commercial/commercial_9.jpg", "Commercial/commercial_324.jpg", "Commercial/commercial_68.jpg", "Commercial/commercial_104.jpg", "Commercial/commercial_195.jpg", "Commercial/commercial_40.jpg", "Commercial/commercial_259.jpg", "Commercial/commercial_206.jpg", "Commercial/commercial_61.jpg", "Commercial/commercial_37.jpg", "Commercial/commercial_285.jpg", "Commercial/commercial_302.jpg", "Commercial/commercial_224.jpg", "Commercial/commercial_12.jpg", "Commercial/commercial_252.jpg", "Commercial/commercial_327.jpg", "Commercial/commercial_311.jpg", "Commercial/commercial_19.jpg", "Commercial/commercial_163.jpg", "Commercial/commercial_287.jpg", "Commercial/commercial_24.jpg", "Commercial/commercial_347.jpg", "Commercial/commercial_214.jpg", "Commercial/commercial_208.jpg", "Commercial/commercial_7.jpg", "Commercial/commercial_18.jpg", "Commercial/commercial_102.jpg", "Commercial/commercial_146.jpg", "Commercial/commercial_245.jpg", "Commercial/commercial_143.jpg", "Commercial/commercial_279.jpg", "Commercial/commercial_335.jpg", "Commercial/commercial_131.jpg", "Commercial/commercial_139.jpg", "Commercial/commercial_280.jpg", "Commercial/commercial_268.jpg", "Commercial/commercial_254.jpg", "Commercial/commercial_25.jpg", "Commercial/commercial_330.jpg", "Commercial/commercial_153.jpg", "Commercial/commercial_313.jpg", "Commercial/commercial_30.jpg", "Commercial/commercial_217.jpg", "Commercial/commercial_6.jpg", "Commercial/commercial_33.jpg", "Commercial/commercial_35.jpg", "Commercial/commercial_263.jpg", "Commercial/commercial_158.jpg", "Commercial/commercial_344.jpg", "Commercial/commercial_41.jpg", "Commercial/commercial_150.jpg", "Commercial/commercial_293.jpg", "Commercial/commercial_281.jpg", "Commercial/commercial_54.jpg", "Commercial/commercial_267.jpg", "Commercial/commercial_242.jpg", "Commercial/commercial_66.jpg", "Commercial/commercial_109.jpg", "Commercial/commercial_14.jpg", "Commercial/commercial_310.jpg", "Commercial/commercial_309.jpg", "Commercial/commercial_1.jpg", "Commercial/commercial_110.jpg", "Commercial/commercial_203.jpg", "Commercial/commercial_26.jpg", "Commercial/commercial_42.jpg", "Commercial/commercial_149.jpg", "Commercial/commercial_174.jpg", "Commercial/commercial_133.jpg", "Commercial/commercial_209.jpg", "Commercial/commercial_283.jpg", "Commercial/commercial_169.jpg", "Commercial/commercial_220.jpg", "Commercial/commercial_20.jpg", "Commercial/commercial_294.jpg", "Commercial/commercial_331.jpg", "Commercial/commercial_227.jpg", "Commercial/commercial_57.jpg", "Commercial/commercial_45.jpg", "Commercial/commercial_161.jpg", "Commercial/commercial_232.jpg", "Commercial/commercial_78.jpg", "Commercial/commercial_265.jpg", "Commercial/commercial_222.jpg", "Commercial/commercial_75.jpg", "Commercial/commercial_237.jpg", "Commercial/commercial_17.jpg", "Commercial/commercial_348.jpg", "Commercial/commercial_270.jpg", "Commercial/commercial_62.jpg", "Commercial/commercial_213.jpg", "Commercial/commercial_3.jpg", "Commercial/commercial_307.jpg", "Commercial/commercial_181.jpg", "Commercial/commercial_343.jpg", "Industrial/industrial_136.jpg", "Industrial/industrial_66.jpg", "Industrial/industrial_213.jpg", "Industrial/industrial_72.jpg", "Industrial/industrial_190.jpg", "Industrial/industrial_151.jpg", "Industrial/industrial_259.jpg", "Industrial/industrial_303.jpg", "Industrial/industrial_205.jpg", "Industrial/industrial_287.jpg", "Industrial/industrial_311.jpg", "Industrial/industrial_11.jpg", "Industrial/industrial_253.jpg", "Industrial/industrial_27.jpg", "Industrial/industrial_385.jpg", "Industrial/industrial_161.jpg", "Industrial/industrial_203.jpg", "Industrial/industrial_200.jpg", "Industrial/industrial_32.jpg", "Industrial/industrial_168.jpg", "Industrial/industrial_54.jpg", "Industrial/industrial_351.jpg", "Industrial/industrial_255.jpg", "Industrial/industrial_44.jpg", "Industrial/industrial_163.jpg", "Industrial/industrial_331.jpg", "Industrial/industrial_78.jpg", "Industrial/industrial_15.jpg", "Industrial/industrial_19.jpg", "Industrial/industrial_388.jpg", "Industrial/industrial_360.jpg", "Industrial/industrial_296.jpg", "Industrial/industrial_288.jpg", "Industrial/industrial_64.jpg", "Industrial/industrial_186.jpg", "Industrial/industrial_52.jpg", "Industrial/industrial_137.jpg", "Industrial/industrial_380.jpg", "Industrial/industrial_178.jpg", "Industrial/industrial_211.jpg", "Industrial/industrial_274.jpg", "Industrial/industrial_62.jpg", "Industrial/industrial_110.jpg", "Industrial/industrial_378.jpg", "Industrial/industrial_291.jpg", "Industrial/industrial_82.jpg", "Industrial/industrial_216.jpg", "Industrial/industrial_270.jpg", "Industrial/industrial_297.jpg", "Industrial/industrial_322.jpg", "Industrial/industrial_45.jpg", "Industrial/industrial_292.jpg", "Industrial/industrial_275.jpg", "Industrial/industrial_231.jpg", "Industrial/industrial_112.jpg", "Industrial/industrial_208.jpg", "Industrial/industrial_363.jpg", "Industrial/industrial_276.jpg", "Industrial/industrial_12.jpg", "Industrial/industrial_362.jpg", "Industrial/industrial_354.jpg", "Industrial/industrial_60.jpg", "Industrial/industrial_141.jpg", "Industrial/industrial_80.jpg", "Industrial/industrial_240.jpg", "Industrial/industrial_75.jpg", "Industrial/industrial_358.jpg", "Industrial/industrial_102.jpg", "Industrial/industrial_153.jpg", "Industrial/industrial_36.jpg", "Industrial/industrial_117.jpg", "Industrial/industrial_122.jpg", "Industrial/industrial_218.jpg", "Industrial/industrial_63.jpg", "Industrial/industrial_56.jpg", "Industrial/industrial_98.jpg", "Industrial/industrial_258.jpg", "Industrial/industrial_356.jpg", "Industrial/industrial_17.jpg", "Industrial/industrial_299.jpg", "Industrial/industrial_339.jpg", "Industrial/industrial_34.jpg", "Industrial/industrial_67.jpg", "Industrial/industrial_238.jpg", "Industrial/industrial_350.jpg", "Industrial/industrial_90.jpg", "Industrial/industrial_59.jpg", "Industrial/industrial_384.jpg", "Industrial/industrial_97.jpg", "Industrial/industrial_160.jpg", "Industrial/industrial_13.jpg", "Industrial/industrial_91.jpg", "Industrial/industrial_83.jpg", "Industrial/industrial_43.jpg", "Industrial/industrial_261.jpg", "Industrial/industrial_70.jpg", "Industrial/industrial_126.jpg", "Industrial/industrial_305.jpg", "Industrial/industrial_120.jpg", "Industrial/industrial_81.jpg", "Industrial/industrial_158.jpg", "Industrial/industrial_49.jpg", "Industrial/industrial_92.jpg", "Industrial/industrial_99.jpg", "Industrial/industrial_390.jpg", "Industrial/industrial_323.jpg", "Industrial/industrial_2.jpg", "Industrial/industrial_31.jpg", "Industrial/industrial_272.jpg", "Industrial/industrial_235.jpg", "Industrial/industrial_150.jpg", "Industrial/industrial_192.jpg", "Industrial/industrial_234.jpg", "Industrial/industrial_277.jpg", "Industrial/industrial_119.jpg", "Industrial/industrial_30.jpg", "Industrial/industrial_225.jpg", "Industrial/industrial_379.jpg", "Industrial/industrial_298.jpg", "Industrial/industrial_40.jpg", "Industrial/industrial_237.jpg", "Industrial/industrial_377.jpg", "Industrial/industrial_271.jpg", "Industrial/industrial_61.jpg", "Industrial/industrial_374.jpg", "Industrial/industrial_169.jpg", "Industrial/industrial_252.jpg", "Industrial/industrial_48.jpg", "Industrial/industrial_193.jpg", "Industrial/industrial_353.jpg", "Industrial/industrial_144.jpg", "Industrial/industrial_386.jpg", "Industrial/industrial_105.jpg", "Industrial/industrial_333.jpg", "Industrial/industrial_215.jpg", "Industrial/industrial_348.jpg", "Industrial/industrial_124.jpg", "Industrial/industrial_228.jpg", "Industrial/industrial_89.jpg", "Industrial/industrial_108.jpg", "Industrial/industrial_174.jpg", "Industrial/industrial_209.jpg", "Industrial/industrial_366.jpg", "Industrial/industrial_196.jpg", "Industrial/industrial_175.jpg", "Industrial/industrial_273.jpg", "Industrial/industrial_58.jpg", "Industrial/industrial_181.jpg", "Industrial/industrial_243.jpg", "Industrial/industrial_69.jpg", "Industrial/industrial_301.jpg", "Industrial/industrial_101.jpg", "Industrial/industrial_355.jpg", "Industrial/industrial_232.jpg", "Industrial/industrial_295.jpg", "Industrial/industrial_371.jpg", "Industrial/industrial_342.jpg", "Industrial/industrial_76.jpg", "Industrial/industrial_100.jpg", "Industrial/industrial_123.jpg", "Industrial/industrial_266.jpg", "Industrial/industrial_21.jpg", "Industrial/industrial_347.jpg", "Industrial/industrial_191.jpg", "Industrial/industrial_14.jpg", "Industrial/industrial_383.jpg", "Industrial/industrial_256.jpg", "Industrial/industrial_223.jpg", "Industrial/industrial_222.jpg", "Industrial/industrial_221.jpg", "Industrial/industrial_206.jpg", "Industrial/industrial_65.jpg", "Industrial/industrial_302.jpg", "Industrial/industrial_230.jpg", "Industrial/industrial_189.jpg", "Industrial/industrial_133.jpg", "Industrial/industrial_164.jpg", "Industrial/industrial_184.jpg", "Industrial/industrial_130.jpg", "Industrial/industrial_201.jpg", "Industrial/industrial_47.jpg", "Industrial/industrial_324.jpg", "Industrial/industrial_212.jpg", "Industrial/industrial_167.jpg", "Industrial/industrial_29.jpg", "Industrial/industrial_38.jpg", "Industrial/industrial_166.jpg", "Industrial/industrial_148.jpg", "Industrial/industrial_139.jpg", "Industrial/industrial_16.jpg", "Industrial/industrial_199.jpg", "Industrial/industrial_381.jpg", "Industrial/industrial_265.jpg", "Industrial/industrial_172.jpg", "Industrial/industrial_226.jpg", "Industrial/industrial_372.jpg", "Industrial/industrial_279.jpg", "Industrial/industrial_154.jpg", "Industrial/industrial_335.jpg", "Industrial/industrial_306.jpg", "Industrial/industrial_315.jpg", "Industrial/industrial_219.jpg", "Industrial/industrial_1.jpg", "Industrial/industrial_227.jpg", "Industrial/industrial_95.jpg", "Industrial/industrial_118.jpg", "Industrial/industrial_229.jpg", "Industrial/industrial_114.jpg", "Industrial/industrial_369.jpg", "Industrial/industrial_343.jpg", "Industrial/industrial_74.jpg", "Industrial/industrial_285.jpg", "Industrial/industrial_202.jpg", "Industrial/industrial_93.jpg", "Industrial/industrial_247.jpg", "Industrial/industrial_300.jpg", "Industrial/industrial_94.jpg", "Industrial/industrial_179.jpg", "Industrial/industrial_6.jpg", "Industrial/industrial_244.jpg", "Industrial/industrial_280.jpg", "Industrial/industrial_359.jpg", "Industrial/industrial_41.jpg", "Industrial/industrial_68.jpg", "Industrial/industrial_340.jpg", "Industrial/industrial_194.jpg", "Industrial/industrial_142.jpg", "Industrial/industrial_111.jpg", "Industrial/industrial_182.jpg", "Industrial/industrial_245.jpg", "Industrial/industrial_121.jpg", "Industrial/industrial_313.jpg", "Industrial/industrial_236.jpg", "Industrial/industrial_286.jpg", "Industrial/industrial_293.jpg", "Industrial/industrial_224.jpg", "Industrial/industrial_7.jpg", "Industrial/industrial_264.jpg", "Industrial/industrial_109.jpg", "Industrial/industrial_176.jpg", "Industrial/industrial_361.jpg", "Industrial/industrial_282.jpg", "Industrial/industrial_375.jpg", "Industrial/industrial_382.jpg", "Industrial/industrial_71.jpg", "Industrial/industrial_370.jpg", "Industrial/industrial_187.jpg", "Industrial/industrial_177.jpg", "Industrial/industrial_85.jpg", "Industrial/industrial_214.jpg", "Industrial/industrial_317.jpg", "Industrial/industrial_140.jpg", "Industrial/industrial_106.jpg", "Industrial/industrial_50.jpg", "Industrial/industrial_389.jpg", "Industrial/industrial_129.jpg", "Industrial/industrial_88.jpg", "Industrial/industrial_157.jpg", "Industrial/industrial_309.jpg", "Industrial/industrial_156.jpg", "Industrial/industrial_42.jpg", "Industrial/industrial_329.jpg", "Industrial/industrial_46.jpg", "Industrial/industrial_53.jpg", "Industrial/industrial_257.jpg", "Industrial/industrial_233.jpg", "Industrial/industrial_310.jpg", "Industrial/industrial_345.jpg", "Industrial/industrial_3.jpg", "Industrial/industrial_170.jpg", "Industrial/industrial_116.jpg", "Industrial/industrial_308.jpg", "Industrial/industrial_183.jpg", "Industrial/industrial_57.jpg", "Industrial/industrial_79.jpg", "Industrial/industrial_328.jpg", "Industrial/industrial_37.jpg", "Industrial/industrial_195.jpg", "Industrial/industrial_104.jpg", "Industrial/industrial_24.jpg", "Industrial/industrial_268.jpg", "Industrial/industrial_263.jpg", "Industrial/industrial_127.jpg", "Industrial/industrial_334.jpg", "Industrial/industrial_33.jpg", "Industrial/industrial_368.jpg", "Industrial/industrial_159.jpg", "Industrial/industrial_314.jpg", "Industrial/industrial_204.jpg", "Industrial/industrial_165.jpg", "Industrial/industrial_147.jpg", "Industrial/industrial_312.jpg", "Industrial/industrial_316.jpg", "Industrial/industrial_103.jpg", "Industrial/industrial_248.jpg", "Industrial/industrial_84.jpg", "Industrial/industrial_260.jpg", "Industrial/industrial_87.jpg", "Industrial/industrial_267.jpg", "Industrial/industrial_387.jpg", "Industrial/industrial_73.jpg", "Industrial/industrial_185.jpg", "Airport/airport_89.jpg", "Airport/airport_165.jpg", "Airport/airport_19.jpg", "Airport/airport_136.jpg", "Airport/airport_88.jpg", "Airport/airport_77.jpg", "Airport/airport_295.jpg", "Airport/airport_319.jpg", "Airport/airport_179.jpg", "Airport/airport_274.jpg", "Airport/airport_337.jpg", "Airport/airport_300.jpg", "Airport/airport_237.jpg", "Airport/airport_272.jpg", "Airport/airport_260.jpg", "Airport/airport_10.jpg", "Airport/airport_355.jpg", "Airport/airport_287.jpg", "Airport/airport_23.jpg", "Airport/airport_228.jpg", "Airport/airport_66.jpg", "Airport/airport_200.jpg", "Airport/airport_205.jpg", "Airport/airport_299.jpg", "Airport/airport_174.jpg", "Airport/airport_90.jpg", "Airport/airport_27.jpg", "Airport/airport_150.jpg", "Airport/airport_60.jpg", "Airport/airport_285.jpg", "Airport/airport_186.jpg", "Airport/airport_251.jpg", "Airport/airport_32.jpg", "Airport/airport_142.jpg", "Airport/airport_93.jpg", "Airport/airport_308.jpg", "Airport/airport_171.jpg", "Airport/airport_323.jpg", "Airport/airport_229.jpg", "Airport/airport_76.jpg", "Airport/airport_310.jpg", "Airport/airport_155.jpg", "Airport/airport_216.jpg", "Airport/airport_28.jpg", "Airport/airport_322.jpg", "Airport/airport_65.jpg", "Airport/airport_45.jpg", "Airport/airport_240.jpg", "Airport/airport_75.jpg", "Airport/airport_236.jpg", "Airport/airport_266.jpg", "Airport/airport_55.jpg", "Airport/airport_80.jpg", "Airport/airport_282.jpg", "Airport/airport_108.jpg", "Airport/airport_82.jpg", "Airport/airport_62.jpg", "Airport/airport_357.jpg", "Airport/airport_316.jpg", "Airport/airport_197.jpg", "Airport/airport_208.jpg", "Airport/airport_202.jpg", "Airport/airport_175.jpg", "Airport/airport_149.jpg", "Airport/airport_15.jpg", "Airport/airport_25.jpg", "Airport/airport_144.jpg", "Airport/airport_257.jpg", "Airport/airport_291.jpg", "Airport/airport_223.jpg", "Airport/airport_158.jpg", "Airport/airport_261.jpg", "Airport/airport_315.jpg", "Airport/airport_198.jpg", "Airport/airport_18.jpg", "Airport/airport_42.jpg", "Airport/airport_333.jpg", "Airport/airport_184.jpg", "Airport/airport_40.jpg", "Airport/airport_135.jpg", "Airport/airport_128.jpg", "Airport/airport_157.jpg", "Airport/airport_30.jpg", "Airport/airport_152.jpg", "Airport/airport_348.jpg", "Airport/airport_1.jpg", "Airport/airport_134.jpg", "Airport/airport_219.jpg", "Airport/airport_303.jpg", "Airport/airport_73.jpg", "Airport/airport_161.jpg", "Airport/airport_132.jpg", "Airport/airport_192.jpg", "Airport/airport_246.jpg", "Airport/airport_334.jpg", "Airport/airport_107.jpg", "Airport/airport_163.jpg", "Airport/airport_199.jpg", "Airport/airport_354.jpg", "Airport/airport_47.jpg", "Airport/airport_250.jpg", "Airport/airport_159.jpg", "Airport/airport_347.jpg", "Airport/airport_258.jpg", "Airport/airport_113.jpg", "Airport/airport_86.jpg", "Airport/airport_281.jpg", "Airport/airport_225.jpg", "Airport/airport_168.jpg", "Airport/airport_269.jpg", "Airport/airport_326.jpg", "Airport/airport_7.jpg", "Airport/airport_317.jpg", "Airport/airport_137.jpg", "Airport/airport_343.jpg", "Airport/airport_48.jpg", "Airport/airport_131.jpg", "Airport/airport_305.jpg", "Airport/airport_349.jpg", "Airport/airport_293.jpg", "Airport/airport_24.jpg", "Airport/airport_262.jpg", "Airport/airport_224.jpg", "Airport/airport_283.jpg", "Airport/airport_124.jpg", "Airport/airport_105.jpg", "Airport/airport_146.jpg", "Airport/airport_95.jpg", "Airport/airport_358.jpg", "Airport/airport_239.jpg", "Airport/airport_176.jpg", "Airport/airport_173.jpg", "Airport/airport_252.jpg", "Airport/airport_342.jpg", "Airport/airport_183.jpg", "Airport/airport_307.jpg", "Airport/airport_273.jpg", "Airport/airport_94.jpg", "Airport/airport_133.jpg", "Airport/airport_164.jpg", "Airport/airport_110.jpg", "Airport/airport_332.jpg", "Airport/airport_189.jpg", "Airport/airport_206.jpg", "Airport/airport_256.jpg", "Airport/airport_233.jpg", "Airport/airport_255.jpg", "Airport/airport_327.jpg", "Airport/airport_341.jpg", "Airport/airport_2.jpg", "Airport/airport_271.jpg", "Airport/airport_254.jpg", "Airport/airport_235.jpg", "Airport/airport_78.jpg", "Airport/airport_215.jpg", "Airport/airport_264.jpg", "Airport/airport_194.jpg", "Airport/airport_217.jpg", "Airport/airport_16.jpg", "Airport/airport_221.jpg", "Airport/airport_268.jpg", "Airport/airport_26.jpg", "Airport/airport_280.jpg", "Airport/airport_339.jpg", "Airport/airport_270.jpg", "Airport/airport_83.jpg", "Airport/airport_5.jpg", "Airport/airport_130.jpg", "Airport/airport_289.jpg", "Airport/airport_57.jpg", "Airport/airport_129.jpg", "Airport/airport_58.jpg", "Airport/airport_335.jpg", "Airport/airport_9.jpg", "Airport/airport_4.jpg", "Airport/airport_220.jpg", "Airport/airport_50.jpg", "Airport/airport_242.jpg", "Airport/airport_36.jpg", "Airport/airport_244.jpg", "Airport/airport_328.jpg", "Airport/airport_359.jpg", "Airport/airport_52.jpg", "Airport/airport_195.jpg", "Airport/airport_321.jpg", "Airport/airport_167.jpg", "Airport/airport_344.jpg", "Airport/airport_6.jpg", "Airport/airport_79.jpg", "Airport/airport_301.jpg", "Airport/airport_234.jpg", "Airport/airport_148.jpg", "Airport/airport_71.jpg", "Airport/airport_279.jpg", "Airport/airport_218.jpg", "Airport/airport_191.jpg", "Airport/airport_309.jpg", "Airport/airport_101.jpg", "Airport/airport_64.jpg", "Airport/airport_312.jpg", "Airport/airport_143.jpg", "Airport/airport_85.jpg", "Airport/airport_306.jpg", "Airport/airport_231.jpg", "Airport/airport_190.jpg", "Airport/airport_187.jpg", "Airport/airport_14.jpg", "Airport/airport_277.jpg", "Airport/airport_54.jpg", "Airport/airport_21.jpg", "Airport/airport_276.jpg", "Airport/airport_17.jpg", "Airport/airport_121.jpg", "Airport/airport_193.jpg", "Airport/airport_126.jpg", "Airport/airport_100.jpg", "Airport/airport_33.jpg", "Airport/airport_350.jpg", "Airport/airport_61.jpg", "Airport/airport_345.jpg", "Airport/airport_118.jpg", "Airport/airport_288.jpg", "Airport/airport_278.jpg", "Airport/airport_154.jpg", "Airport/airport_98.jpg", "Airport/airport_67.jpg", "Airport/airport_84.jpg", "Airport/airport_29.jpg", "Airport/airport_265.jpg", "Airport/airport_331.jpg", "Airport/airport_170.jpg", "Airport/airport_360.jpg", "Airport/airport_138.jpg", "Airport/airport_209.jpg", "Airport/airport_13.jpg", "Airport/airport_211.jpg", "Airport/airport_330.jpg", "Airport/airport_297.jpg", "Airport/airport_185.jpg", "Airport/airport_329.jpg", "Airport/airport_267.jpg", "Airport/airport_178.jpg", "Airport/airport_37.jpg", "Airport/airport_59.jpg", "Airport/airport_153.jpg", "Airport/airport_353.jpg", "Airport/airport_222.jpg", "Airport/airport_290.jpg", "Airport/airport_111.jpg", "Airport/airport_97.jpg", "Airport/airport_275.jpg", "Airport/airport_249.jpg", "Airport/airport_314.jpg", "Airport/airport_201.jpg", "Airport/airport_112.jpg", "Airport/airport_117.jpg", "Airport/airport_259.jpg", "Airport/airport_226.jpg", "Airport/airport_182.jpg", "Airport/airport_104.jpg", "Airport/airport_12.jpg", "Airport/airport_72.jpg", "Airport/airport_243.jpg", "Airport/airport_180.jpg", "Airport/airport_351.jpg", "Airport/airport_99.jpg", "Airport/airport_302.jpg", "Airport/airport_324.jpg", "Airport/airport_169.jpg", "Airport/airport_115.jpg", "Airport/airport_102.jpg", "Airport/airport_122.jpg", "Airport/airport_8.jpg", "Airport/airport_96.jpg", "Airport/airport_49.jpg", "Airport/airport_156.jpg", "Airport/airport_188.jpg", "Airport/airport_340.jpg", "SparseResidential/sparseresidential_149.jpg", "SparseResidential/sparseresidential_274.jpg", "SparseResidential/sparseresidential_24.jpg", "SparseResidential/sparseresidential_106.jpg", "SparseResidential/sparseresidential_107.jpg", "SparseResidential/sparseresidential_194.jpg", "SparseResidential/sparseresidential_51.jpg", "SparseResidential/sparseresidential_133.jpg", "SparseResidential/sparseresidential_286.jpg", "SparseResidential/sparseresidential_259.jpg", "SparseResidential/sparseresidential_34.jpg", "SparseResidential/sparseresidential_226.jpg", "SparseResidential/sparseresidential_258.jpg", "SparseResidential/sparseresidential_272.jpg", "SparseResidential/sparseresidential_189.jpg", "SparseResidential/sparseresidential_228.jpg", "SparseResidential/sparseresidential_298.jpg", "SparseResidential/sparseresidential_84.jpg", "SparseResidential/sparseresidential_109.jpg", "SparseResidential/sparseresidential_263.jpg", "SparseResidential/sparseresidential_167.jpg", "SparseResidential/sparseresidential_92.jpg", "SparseResidential/sparseresidential_251.jpg", "SparseResidential/sparseresidential_282.jpg", "SparseResidential/sparseresidential_111.jpg", "SparseResidential/sparseresidential_26.jpg", "SparseResidential/sparseresidential_16.jpg", "SparseResidential/sparseresidential_85.jpg", "SparseResidential/sparseresidential_79.jpg", "SparseResidential/sparseresidential_21.jpg", "SparseResidential/sparseresidential_211.jpg", "SparseResidential/sparseresidential_87.jpg", "SparseResidential/sparseresidential_218.jpg", "SparseResidential/sparseresidential_137.jpg", "SparseResidential/sparseresidential_120.jpg", "SparseResidential/sparseresidential_233.jpg", "SparseResidential/sparseresidential_271.jpg", "SparseResidential/sparseresidential_250.jpg", "SparseResidential/sparseresidential_200.jpg", "SparseResidential/sparseresidential_267.jpg", "SparseResidential/sparseresidential_171.jpg", "SparseResidential/sparseresidential_163.jpg", "SparseResidential/sparseresidential_290.jpg", "SparseResidential/sparseresidential_231.jpg", "SparseResidential/sparseresidential_288.jpg", "SparseResidential/sparseresidential_234.jpg", "SparseResidential/sparseresidential_80.jpg", "SparseResidential/sparseresidential_66.jpg", "SparseResidential/sparseresidential_124.jpg", "SparseResidential/sparseresidential_141.jpg", "SparseResidential/sparseresidential_136.jpg", "SparseResidential/sparseresidential_195.jpg", "SparseResidential/sparseresidential_156.jpg", "SparseResidential/sparseresidential_101.jpg", "SparseResidential/sparseresidential_244.jpg", "SparseResidential/sparseresidential_297.jpg", "SparseResidential/sparseresidential_119.jpg", "SparseResidential/sparseresidential_122.jpg", "SparseResidential/sparseresidential_275.jpg", "SparseResidential/sparseresidential_168.jpg", "SparseResidential/sparseresidential_63.jpg", "SparseResidential/sparseresidential_247.jpg", "SparseResidential/sparseresidential_96.jpg", "SparseResidential/sparseresidential_3.jpg", "SparseResidential/sparseresidential_278.jpg", "SparseResidential/sparseresidential_147.jpg", "SparseResidential/sparseresidential_52.jpg", "SparseResidential/sparseresidential_151.jpg", "SparseResidential/sparseresidential_273.jpg", "SparseResidential/sparseresidential_277.jpg", "SparseResidential/sparseresidential_185.jpg", "SparseResidential/sparseresidential_115.jpg", "SparseResidential/sparseresidential_235.jpg", "SparseResidential/sparseresidential_261.jpg", "SparseResidential/sparseresidential_72.jpg", "SparseResidential/sparseresidential_126.jpg", "SparseResidential/sparseresidential_175.jpg", "SparseResidential/sparseresidential_214.jpg", "SparseResidential/sparseresidential_68.jpg", "SparseResidential/sparseresidential_219.jpg", "SparseResidential/sparseresidential_71.jpg", "SparseResidential/sparseresidential_215.jpg", "SparseResidential/sparseresidential_58.jpg", "SparseResidential/sparseresidential_41.jpg", "SparseResidential/sparseresidential_270.jpg", "SparseResidential/sparseresidential_14.jpg", "SparseResidential/sparseresidential_210.jpg", "SparseResidential/sparseresidential_178.jpg", "SparseResidential/sparseresidential_38.jpg", "SparseResidential/sparseresidential_112.jpg", "SparseResidential/sparseresidential_153.jpg", "SparseResidential/sparseresidential_158.jpg", "SparseResidential/sparseresidential_6.jpg", "SparseResidential/sparseresidential_213.jpg", "SparseResidential/sparseresidential_268.jpg", "SparseResidential/sparseresidential_30.jpg", "SparseResidential/sparseresidential_157.jpg", "SparseResidential/sparseresidential_67.jpg", "SparseResidential/sparseresidential_90.jpg", "SparseResidential/sparseresidential_150.jpg", "SparseResidential/sparseresidential_279.jpg", "SparseResidential/sparseresidential_35.jpg", "SparseResidential/sparseresidential_199.jpg", "SparseResidential/sparseresidential_161.jpg", "SparseResidential/sparseresidential_265.jpg", "SparseResidential/sparseresidential_55.jpg", "SparseResidential/sparseresidential_285.jpg", "SparseResidential/sparseresidential_180.jpg", "SparseResidential/sparseresidential_246.jpg", "SparseResidential/sparseresidential_127.jpg", "SparseResidential/sparseresidential_142.jpg", "SparseResidential/sparseresidential_45.jpg", "SparseResidential/sparseresidential_300.jpg", "SparseResidential/sparseresidential_227.jpg", "SparseResidential/sparseresidential_217.jpg", "SparseResidential/sparseresidential_75.jpg", "SparseResidential/sparseresidential_23.jpg", "SparseResidential/sparseresidential_89.jpg", "SparseResidential/sparseresidential_93.jpg", "SparseResidential/sparseresidential_183.jpg", "SparseResidential/sparseresidential_36.jpg", "SparseResidential/sparseresidential_187.jpg", "SparseResidential/sparseresidential_47.jpg", "SparseResidential/sparseresidential_289.jpg", "SparseResidential/sparseresidential_121.jpg", "SparseResidential/sparseresidential_191.jpg", "SparseResidential/sparseresidential_65.jpg", "SparseResidential/sparseresidential_57.jpg", "SparseResidential/sparseresidential_11.jpg", "SparseResidential/sparseresidential_184.jpg", "SparseResidential/sparseresidential_61.jpg", "SparseResidential/sparseresidential_241.jpg", "SparseResidential/sparseresidential_108.jpg", "SparseResidential/sparseresidential_145.jpg", "SparseResidential/sparseresidential_102.jpg", "SparseResidential/sparseresidential_12.jpg", "SparseResidential/sparseresidential_174.jpg", "SparseResidential/sparseresidential_253.jpg", "SparseResidential/sparseresidential_182.jpg", "SparseResidential/sparseresidential_237.jpg", "SparseResidential/sparseresidential_212.jpg", "SparseResidential/sparseresidential_222.jpg", "SparseResidential/sparseresidential_201.jpg", "SparseResidential/sparseresidential_94.jpg", "SparseResidential/sparseresidential_243.jpg", "SparseResidential/sparseresidential_103.jpg", "SparseResidential/sparseresidential_56.jpg", "SparseResidential/sparseresidential_129.jpg", "SparseResidential/sparseresidential_130.jpg", "SparseResidential/sparseresidential_242.jpg", "SparseResidential/sparseresidential_42.jpg", "SparseResidential/sparseresidential_88.jpg", "SparseResidential/sparseresidential_193.jpg", "SparseResidential/sparseresidential_17.jpg", "SparseResidential/sparseresidential_166.jpg", "SparseResidential/sparseresidential_266.jpg", "SparseResidential/sparseresidential_143.jpg", "SparseResidential/sparseresidential_95.jpg", "SparseResidential/sparseresidential_154.jpg", "SparseResidential/sparseresidential_134.jpg", "SparseResidential/sparseresidential_190.jpg", "SparseResidential/sparseresidential_205.jpg", "SparseResidential/sparseresidential_131.jpg", "SparseResidential/sparseresidential_256.jpg", "SparseResidential/sparseresidential_252.jpg", "SparseResidential/sparseresidential_54.jpg", "SparseResidential/sparseresidential_280.jpg", "SparseResidential/sparseresidential_294.jpg", "SparseResidential/sparseresidential_118.jpg", "SparseResidential/sparseresidential_99.jpg", "SparseResidential/sparseresidential_238.jpg", "SparseResidential/sparseresidential_78.jpg", "SparseResidential/sparseresidential_173.jpg", "SparseResidential/sparseresidential_225.jpg", "SparseResidential/sparseresidential_239.jpg", "SparseResidential/sparseresidential_255.jpg", "SparseResidential/sparseresidential_287.jpg", "SparseResidential/sparseresidential_152.jpg", "SparseResidential/sparseresidential_50.jpg", "SparseResidential/sparseresidential_176.jpg", "SparseResidential/sparseresidential_114.jpg", "SparseResidential/sparseresidential_40.jpg", "SparseResidential/sparseresidential_254.jpg", "SparseResidential/sparseresidential_110.jpg", "SparseResidential/sparseresidential_73.jpg", "SparseResidential/sparseresidential_179.jpg", "SparseResidential/sparseresidential_100.jpg", "SparseResidential/sparseresidential_123.jpg", "SparseResidential/sparseresidential_169.jpg", "SparseResidential/sparseresidential_39.jpg", "SparseResidential/sparseresidential_165.jpg", "SparseResidential/sparseresidential_117.jpg", "SparseResidential/sparseresidential_59.jpg", "SparseResidential/sparseresidential_283.jpg", "SparseResidential/sparseresidential_260.jpg", "SparseResidential/sparseresidential_19.jpg", "SparseResidential/sparseresidential_248.jpg", "SparseResidential/sparseresidential_91.jpg", "SparseResidential/sparseresidential_1.jpg", "SparseResidential/sparseresidential_240.jpg", "SparseResidential/sparseresidential_98.jpg", "SparseResidential/sparseresidential_292.jpg", "SparseResidential/sparseresidential_232.jpg", "SparseResidential/sparseresidential_33.jpg", "SparseResidential/sparseresidential_74.jpg", "SparseResidential/sparseresidential_135.jpg", "SparseResidential/sparseresidential_25.jpg", "SparseResidential/sparseresidential_198.jpg", "SparseResidential/sparseresidential_281.jpg", "SparseResidential/sparseresidential_5.jpg", "SparseResidential/sparseresidential_155.jpg", "SparseResidential/sparseresidential_97.jpg", "SparseResidential/sparseresidential_264.jpg", "SparseResidential/sparseresidential_140.jpg", "SparseResidential/sparseresidential_22.jpg", "SparseResidential/sparseresidential_144.jpg", "SparseResidential/sparseresidential_223.jpg", "SparseResidential/sparseresidential_159.jpg", "SparseResidential/sparseresidential_86.jpg", "SparseResidential/sparseresidential_295.jpg", "SparseResidential/sparseresidential_113.jpg", "SparseResidential/sparseresidential_186.jpg", "SparseResidential/sparseresidential_296.jpg", "SparseResidential/sparseresidential_104.jpg", "SparseResidential/sparseresidential_172.jpg", "SparseResidential/sparseresidential_77.jpg", "SparseResidential/sparseresidential_197.jpg", "SparseResidential/sparseresidential_70.jpg", "SparseResidential/sparseresidential_53.jpg", "SparseResidential/sparseresidential_284.jpg", "MediumResidential/mediumresidential_122.jpg", "MediumResidential/mediumresidential_160.jpg", "MediumResidential/mediumresidential_180.jpg", "MediumResidential/mediumresidential_18.jpg", "MediumResidential/mediumresidential_267.jpg", "MediumResidential/mediumresidential_27.jpg", "MediumResidential/mediumresidential_263.jpg", "MediumResidential/mediumresidential_173.jpg", "MediumResidential/mediumresidential_171.jpg", "MediumResidential/mediumresidential_126.jpg", "MediumResidential/mediumresidential_109.jpg", "MediumResidential/mediumresidential_117.jpg", "MediumResidential/mediumresidential_268.jpg", "MediumResidential/mediumresidential_67.jpg", "MediumResidential/mediumresidential_80.jpg", "MediumResidential/mediumresidential_139.jpg", "MediumResidential/mediumresidential_23.jpg", "MediumResidential/mediumresidential_249.jpg", "MediumResidential/mediumresidential_62.jpg", "MediumResidential/mediumresidential_206.jpg", "MediumResidential/mediumresidential_84.jpg", "MediumResidential/mediumresidential_248.jpg", "MediumResidential/mediumresidential_216.jpg", "MediumResidential/mediumresidential_43.jpg", "MediumResidential/mediumresidential_121.jpg", "MediumResidential/mediumresidential_37.jpg", "MediumResidential/mediumresidential_34.jpg", "MediumResidential/mediumresidential_282.jpg", "MediumResidential/mediumresidential_65.jpg", "MediumResidential/mediumresidential_133.jpg", "MediumResidential/mediumresidential_95.jpg", "MediumResidential/mediumresidential_153.jpg", "MediumResidential/mediumresidential_142.jpg", "MediumResidential/mediumresidential_83.jpg", "MediumResidential/mediumresidential_49.jpg", "MediumResidential/mediumresidential_22.jpg", "MediumResidential/mediumresidential_146.jpg", "MediumResidential/mediumresidential_162.jpg", "MediumResidential/mediumresidential_60.jpg", "MediumResidential/mediumresidential_136.jpg", "MediumResidential/mediumresidential_116.jpg", "MediumResidential/mediumresidential_58.jpg", "MediumResidential/mediumresidential_97.jpg", "MediumResidential/mediumresidential_128.jpg", "MediumResidential/mediumresidential_17.jpg", "MediumResidential/mediumresidential_158.jpg", "MediumResidential/mediumresidential_266.jpg", "MediumResidential/mediumresidential_52.jpg", "MediumResidential/mediumresidential_144.jpg", "MediumResidential/mediumresidential_285.jpg", "MediumResidential/mediumresidential_130.jpg", "MediumResidential/mediumresidential_290.jpg", "MediumResidential/mediumresidential_69.jpg", "MediumResidential/mediumresidential_238.jpg", "MediumResidential/mediumresidential_77.jpg", "MediumResidential/mediumresidential_47.jpg", "MediumResidential/mediumresidential_46.jpg", "MediumResidential/mediumresidential_210.jpg", "MediumResidential/mediumresidential_276.jpg", "MediumResidential/mediumresidential_194.jpg", "MediumResidential/mediumresidential_243.jpg", "MediumResidential/mediumresidential_89.jpg", "MediumResidential/mediumresidential_254.jpg", "MediumResidential/mediumresidential_1.jpg", "MediumResidential/mediumresidential_172.jpg", "MediumResidential/mediumresidential_99.jpg", "MediumResidential/mediumresidential_66.jpg", "MediumResidential/mediumresidential_251.jpg", "MediumResidential/mediumresidential_265.jpg", "MediumResidential/mediumresidential_129.jpg", "MediumResidential/mediumresidential_159.jpg", "MediumResidential/mediumresidential_170.jpg", "MediumResidential/mediumresidential_13.jpg", "MediumResidential/mediumresidential_227.jpg", "MediumResidential/mediumresidential_190.jpg", "MediumResidential/mediumresidential_197.jpg", "MediumResidential/mediumresidential_31.jpg", "MediumResidential/mediumresidential_209.jpg", "MediumResidential/mediumresidential_178.jpg", "MediumResidential/mediumresidential_224.jpg", "MediumResidential/mediumresidential_221.jpg", "MediumResidential/mediumresidential_278.jpg", "MediumResidential/mediumresidential_287.jpg", "MediumResidential/mediumresidential_118.jpg", "MediumResidential/mediumresidential_113.jpg", "MediumResidential/mediumresidential_154.jpg", "MediumResidential/mediumresidential_217.jpg", "MediumResidential/mediumresidential_104.jpg", "MediumResidential/mediumresidential_102.jpg", "MediumResidential/mediumresidential_71.jpg", "MediumResidential/mediumresidential_8.jpg", "MediumResidential/mediumresidential_147.jpg", "MediumResidential/mediumresidential_30.jpg", "MediumResidential/mediumresidential_78.jpg", "MediumResidential/mediumresidential_273.jpg", "MediumResidential/mediumresidential_115.jpg", "MediumResidential/mediumresidential_44.jpg", "MediumResidential/mediumresidential_274.jpg", "MediumResidential/mediumresidential_149.jpg", "MediumResidential/mediumresidential_114.jpg", "MediumResidential/mediumresidential_231.jpg", "MediumResidential/mediumresidential_253.jpg", "MediumResidential/mediumresidential_220.jpg", "MediumResidential/mediumresidential_9.jpg", "MediumResidential/mediumresidential_183.jpg", "MediumResidential/mediumresidential_167.jpg", "MediumResidential/mediumresidential_202.jpg", "MediumResidential/mediumresidential_252.jpg", "MediumResidential/mediumresidential_110.jpg", "MediumResidential/mediumresidential_272.jpg", "MediumResidential/mediumresidential_59.jpg", "MediumResidential/mediumresidential_213.jpg", "MediumResidential/mediumresidential_25.jpg", "MediumResidential/mediumresidential_247.jpg", "MediumResidential/mediumresidential_179.jpg", "MediumResidential/mediumresidential_169.jpg", "MediumResidential/mediumresidential_91.jpg", "MediumResidential/mediumresidential_219.jpg", "MediumResidential/mediumresidential_63.jpg", "MediumResidential/mediumresidential_86.jpg", "MediumResidential/mediumresidential_82.jpg", "MediumResidential/mediumresidential_229.jpg", "MediumResidential/mediumresidential_138.jpg", "MediumResidential/mediumresidential_225.jpg", "MediumResidential/mediumresidential_242.jpg", "MediumResidential/mediumresidential_120.jpg", "MediumResidential/mediumresidential_42.jpg", "MediumResidential/mediumresidential_177.jpg", "MediumResidential/mediumresidential_193.jpg", "MediumResidential/mediumresidential_57.jpg", "MediumResidential/mediumresidential_289.jpg", "MediumResidential/mediumresidential_156.jpg", "MediumResidential/mediumresidential_246.jpg", "MediumResidential/mediumresidential_4.jpg", "MediumResidential/mediumresidential_94.jpg", "MediumResidential/mediumresidential_181.jpg", "MediumResidential/mediumresidential_259.jpg", "MediumResidential/mediumresidential_184.jpg", "MediumResidential/mediumresidential_257.jpg", "MediumResidential/mediumresidential_134.jpg", "MediumResidential/mediumresidential_228.jpg", "MediumResidential/mediumresidential_286.jpg", "MediumResidential/mediumresidential_33.jpg", "MediumResidential/mediumresidential_161.jpg", "MediumResidential/mediumresidential_186.jpg", "MediumResidential/mediumresidential_241.jpg", "MediumResidential/mediumresidential_93.jpg", "MediumResidential/mediumresidential_106.jpg", "MediumResidential/mediumresidential_256.jpg", "MediumResidential/mediumresidential_214.jpg", "MediumResidential/mediumresidential_107.jpg", "MediumResidential/mediumresidential_244.jpg", "MediumResidential/mediumresidential_187.jpg", "MediumResidential/mediumresidential_166.jpg", "MediumResidential/mediumresidential_269.jpg", "MediumResidential/mediumresidential_40.jpg", "MediumResidential/mediumresidential_234.jpg", "MediumResidential/mediumresidential_16.jpg", "MediumResidential/mediumresidential_11.jpg", "MediumResidential/mediumresidential_39.jpg", "MediumResidential/mediumresidential_222.jpg", "MediumResidential/mediumresidential_218.jpg", "MediumResidential/mediumresidential_41.jpg", "MediumResidential/mediumresidential_264.jpg", "MediumResidential/mediumresidential_141.jpg", "MediumResidential/mediumresidential_207.jpg", "MediumResidential/mediumresidential_262.jpg", "MediumResidential/mediumresidential_176.jpg", "MediumResidential/mediumresidential_29.jpg", "MediumResidential/mediumresidential_10.jpg", "MediumResidential/mediumresidential_250.jpg", "MediumResidential/mediumresidential_7.jpg", "MediumResidential/mediumresidential_20.jpg", "MediumResidential/mediumresidential_201.jpg", "MediumResidential/mediumresidential_271.jpg", "MediumResidential/mediumresidential_275.jpg", "MediumResidential/mediumresidential_55.jpg", "MediumResidential/mediumresidential_226.jpg", "MediumResidential/mediumresidential_131.jpg", "MediumResidential/mediumresidential_101.jpg", "MediumResidential/mediumresidential_145.jpg", "MediumResidential/mediumresidential_61.jpg", "MediumResidential/mediumresidential_189.jpg", "MediumResidential/mediumresidential_12.jpg", "MediumResidential/mediumresidential_240.jpg", "MediumResidential/mediumresidential_211.jpg", "MediumResidential/mediumresidential_96.jpg", "MediumResidential/mediumresidential_45.jpg", "MediumResidential/mediumresidential_28.jpg", "MediumResidential/mediumresidential_235.jpg", "MediumResidential/mediumresidential_283.jpg", "MediumResidential/mediumresidential_119.jpg", "MediumResidential/mediumresidential_137.jpg", "MediumResidential/mediumresidential_280.jpg", "MediumResidential/mediumresidential_24.jpg", "MediumResidential/mediumresidential_3.jpg", "MediumResidential/mediumresidential_76.jpg", "MediumResidential/mediumresidential_19.jpg", "MediumResidential/mediumresidential_182.jpg", "MediumResidential/mediumresidential_50.jpg", "MediumResidential/mediumresidential_258.jpg", "MediumResidential/mediumresidential_261.jpg", "MediumResidential/mediumresidential_53.jpg", "MediumResidential/mediumresidential_279.jpg", "MediumResidential/mediumresidential_21.jpg", "MediumResidential/mediumresidential_164.jpg", "MediumResidential/mediumresidential_132.jpg", "MediumResidential/mediumresidential_38.jpg", "MediumResidential/mediumresidential_74.jpg", "MediumResidential/mediumresidential_125.jpg", "MediumResidential/mediumresidential_281.jpg", "MediumResidential/mediumresidential_205.jpg", "MediumResidential/mediumresidential_32.jpg", "MediumResidential/mediumresidential_143.jpg", "MediumResidential/mediumresidential_103.jpg", "MediumResidential/mediumresidential_233.jpg", "MediumResidential/mediumresidential_68.jpg", "MediumResidential/mediumresidential_200.jpg", "MediumResidential/mediumresidential_152.jpg", "MediumResidential/mediumresidential_288.jpg", "MediumResidential/mediumresidential_2.jpg", "MediumResidential/mediumresidential_100.jpg", "DenseResidential/denseresidential_261.jpg", "DenseResidential/denseresidential_1.jpg", "DenseResidential/denseresidential_366.jpg", "DenseResidential/denseresidential_350.jpg", "DenseResidential/denseresidential_115.jpg", "DenseResidential/denseresidential_57.jpg", "DenseResidential/denseresidential_150.jpg", "DenseResidential/denseresidential_222.jpg", "DenseResidential/denseresidential_58.jpg", "DenseResidential/denseresidential_183.jpg", "DenseResidential/denseresidential_337.jpg", "DenseResidential/denseresidential_16.jpg", "DenseResidential/denseresidential_170.jpg", "DenseResidential/denseresidential_343.jpg", "DenseResidential/denseresidential_8.jpg", "DenseResidential/denseresidential_53.jpg", "DenseResidential/denseresidential_320.jpg", "DenseResidential/denseresidential_119.jpg", "DenseResidential/denseresidential_264.jpg", "DenseResidential/denseresidential_25.jpg", "DenseResidential/denseresidential_68.jpg", "DenseResidential/denseresidential_256.jpg", "DenseResidential/denseresidential_78.jpg", "DenseResidential/denseresidential_241.jpg", "DenseResidential/denseresidential_296.jpg", "DenseResidential/denseresidential_374.jpg", "DenseResidential/denseresidential_104.jpg", "DenseResidential/denseresidential_43.jpg", "DenseResidential/denseresidential_234.jpg", "DenseResidential/denseresidential_171.jpg", "DenseResidential/denseresidential_169.jpg", "DenseResidential/denseresidential_190.jpg", "DenseResidential/denseresidential_152.jpg", "DenseResidential/denseresidential_10.jpg", "DenseResidential/denseresidential_250.jpg", "DenseResidential/denseresidential_126.jpg", "DenseResidential/denseresidential_407.jpg", "DenseResidential/denseresidential_228.jpg", "DenseResidential/denseresidential_80.jpg", "DenseResidential/denseresidential_371.jpg", "DenseResidential/denseresidential_132.jpg", "DenseResidential/denseresidential_279.jpg", "DenseResidential/denseresidential_397.jpg", "DenseResidential/denseresidential_201.jpg", "DenseResidential/denseresidential_349.jpg", "DenseResidential/denseresidential_208.jpg", "DenseResidential/denseresidential_361.jpg", "DenseResidential/denseresidential_11.jpg", "DenseResidential/denseresidential_329.jpg", "DenseResidential/denseresidential_30.jpg", "DenseResidential/denseresidential_293.jpg", "DenseResidential/denseresidential_294.jpg", "DenseResidential/denseresidential_373.jpg", "DenseResidential/denseresidential_123.jpg", "DenseResidential/denseresidential_136.jpg", "DenseResidential/denseresidential_113.jpg", "DenseResidential/denseresidential_236.jpg", "DenseResidential/denseresidential_124.jpg", "DenseResidential/denseresidential_130.jpg", "DenseResidential/denseresidential_22.jpg", "DenseResidential/denseresidential_82.jpg", "DenseResidential/denseresidential_351.jpg", "DenseResidential/denseresidential_106.jpg", "DenseResidential/denseresidential_9.jpg", "DenseResidential/denseresidential_197.jpg", "DenseResidential/denseresidential_154.jpg", "DenseResidential/denseresidential_134.jpg", "DenseResidential/denseresidential_377.jpg", "DenseResidential/denseresidential_180.jpg", "DenseResidential/denseresidential_103.jpg", "DenseResidential/denseresidential_332.jpg", "DenseResidential/denseresidential_135.jpg", "DenseResidential/denseresidential_269.jpg", "DenseResidential/denseresidential_40.jpg", "DenseResidential/denseresidential_110.jpg", "DenseResidential/denseresidential_275.jpg", "DenseResidential/denseresidential_144.jpg", "DenseResidential/denseresidential_26.jpg", "DenseResidential/denseresidential_89.jpg", "DenseResidential/denseresidential_406.jpg", "DenseResidential/denseresidential_191.jpg", "DenseResidential/denseresidential_153.jpg", "DenseResidential/denseresidential_151.jpg", "DenseResidential/denseresidential_128.jpg", "DenseResidential/denseresidential_399.jpg", "DenseResidential/denseresidential_384.jpg", "DenseResidential/denseresidential_408.jpg", "DenseResidential/denseresidential_363.jpg", "DenseResidential/denseresidential_105.jpg", "DenseResidential/denseresidential_273.jpg", "DenseResidential/denseresidential_93.jpg", "DenseResidential/denseresidential_393.jpg", "DenseResidential/denseresidential_347.jpg", "DenseResidential/denseresidential_102.jpg", "DenseResidential/denseresidential_248.jpg", "DenseResidential/denseresidential_187.jpg", "DenseResidential/denseresidential_317.jpg", "DenseResidential/denseresidential_304.jpg", "DenseResidential/denseresidential_381.jpg", "DenseResidential/denseresidential_405.jpg", "DenseResidential/denseresidential_370.jpg", "DenseResidential/denseresidential_246.jpg", "DenseResidential/denseresidential_94.jpg", "DenseResidential/denseresidential_367.jpg", "DenseResidential/denseresidential_64.jpg", "DenseResidential/denseresidential_220.jpg", "DenseResidential/denseresidential_267.jpg", "DenseResidential/denseresidential_28.jpg", "DenseResidential/denseresidential_87.jpg", "DenseResidential/denseresidential_360.jpg", "DenseResidential/denseresidential_258.jpg", "DenseResidential/denseresidential_194.jpg", "DenseResidential/denseresidential_193.jpg", "DenseResidential/denseresidential_88.jpg", "DenseResidential/denseresidential_18.jpg", "DenseResidential/denseresidential_237.jpg", "DenseResidential/denseresidential_402.jpg", "DenseResidential/denseresidential_23.jpg", "DenseResidential/denseresidential_129.jpg", "DenseResidential/denseresidential_319.jpg", "DenseResidential/denseresidential_355.jpg", "DenseResidential/denseresidential_140.jpg", "DenseResidential/denseresidential_305.jpg", "DenseResidential/denseresidential_61.jpg", "DenseResidential/denseresidential_131.jpg", "DenseResidential/denseresidential_146.jpg", "DenseResidential/denseresidential_240.jpg", "DenseResidential/denseresidential_278.jpg", "DenseResidential/denseresidential_161.jpg", "DenseResidential/denseresidential_108.jpg", "DenseResidential/denseresidential_156.jpg", "DenseResidential/denseresidential_354.jpg", "DenseResidential/denseresidential_182.jpg", "DenseResidential/denseresidential_168.jpg", "DenseResidential/denseresidential_142.jpg", "DenseResidential/denseresidential_383.jpg", "DenseResidential/denseresidential_27.jpg", "DenseResidential/denseresidential_342.jpg", "DenseResidential/denseresidential_382.jpg", "DenseResidential/denseresidential_212.jpg", "DenseResidential/denseresidential_218.jpg", "DenseResidential/denseresidential_271.jpg", "DenseResidential/denseresidential_357.jpg", "DenseResidential/denseresidential_398.jpg", "DenseResidential/denseresidential_62.jpg", "DenseResidential/denseresidential_29.jpg", "DenseResidential/denseresidential_36.jpg", "DenseResidential/denseresidential_285.jpg", "DenseResidential/denseresidential_51.jpg", "DenseResidential/denseresidential_260.jpg", "DenseResidential/denseresidential_215.jpg", "DenseResidential/denseresidential_125.jpg", "DenseResidential/denseresidential_292.jpg", "DenseResidential/denseresidential_318.jpg", "DenseResidential/denseresidential_380.jpg", "DenseResidential/denseresidential_45.jpg", "DenseResidential/denseresidential_174.jpg", "DenseResidential/denseresidential_159.jpg", "DenseResidential/denseresidential_336.jpg", "DenseResidential/denseresidential_157.jpg", "DenseResidential/denseresidential_306.jpg", "DenseResidential/denseresidential_247.jpg", "DenseResidential/denseresidential_391.jpg", "DenseResidential/denseresidential_213.jpg", "DenseResidential/denseresidential_202.jpg", "DenseResidential/denseresidential_2.jpg", "DenseResidential/denseresidential_203.jpg", "DenseResidential/denseresidential_67.jpg", "DenseResidential/denseresidential_244.jpg", "DenseResidential/denseresidential_15.jpg", "DenseResidential/denseresidential_195.jpg", "DenseResidential/denseresidential_300.jpg", "DenseResidential/denseresidential_73.jpg", "DenseResidential/denseresidential_79.jpg", "DenseResidential/denseresidential_60.jpg", "DenseResidential/denseresidential_99.jpg", "DenseResidential/denseresidential_369.jpg", "DenseResidential/denseresidential_12.jpg", "DenseResidential/denseresidential_276.jpg", "DenseResidential/denseresidential_359.jpg", "DenseResidential/denseresidential_364.jpg", "DenseResidential/denseresidential_19.jpg", "DenseResidential/denseresidential_316.jpg", "DenseResidential/denseresidential_251.jpg", "DenseResidential/denseresidential_172.jpg", "DenseResidential/denseresidential_245.jpg", "DenseResidential/denseresidential_387.jpg", "DenseResidential/denseresidential_311.jpg", "DenseResidential/denseresidential_196.jpg", "DenseResidential/denseresidential_143.jpg", "DenseResidential/denseresidential_310.jpg", "DenseResidential/denseresidential_37.jpg", "DenseResidential/denseresidential_344.jpg", "DenseResidential/denseresidential_330.jpg", "DenseResidential/denseresidential_252.jpg", "DenseResidential/denseresidential_372.jpg", "DenseResidential/denseresidential_35.jpg", "DenseResidential/denseresidential_185.jpg", "DenseResidential/denseresidential_179.jpg", "DenseResidential/denseresidential_331.jpg", "DenseResidential/denseresidential_379.jpg", "DenseResidential/denseresidential_325.jpg", "DenseResidential/denseresidential_55.jpg", "DenseResidential/denseresidential_173.jpg", "DenseResidential/denseresidential_200.jpg", "DenseResidential/denseresidential_313.jpg", "DenseResidential/denseresidential_326.jpg", "DenseResidential/denseresidential_291.jpg", "DenseResidential/denseresidential_257.jpg", "DenseResidential/denseresidential_335.jpg", "DenseResidential/denseresidential_229.jpg", "DenseResidential/denseresidential_5.jpg", "DenseResidential/denseresidential_230.jpg", "DenseResidential/denseresidential_109.jpg", "DenseResidential/denseresidential_281.jpg", "DenseResidential/denseresidential_299.jpg", "DenseResidential/denseresidential_216.jpg", "DenseResidential/denseresidential_346.jpg", "DenseResidential/denseresidential_39.jpg", "DenseResidential/denseresidential_107.jpg", "DenseResidential/denseresidential_165.jpg", "DenseResidential/denseresidential_69.jpg", "DenseResidential/denseresidential_86.jpg", "DenseResidential/denseresidential_259.jpg", "DenseResidential/denseresidential_388.jpg", "DenseResidential/denseresidential_376.jpg", "DenseResidential/denseresidential_225.jpg", "DenseResidential/denseresidential_70.jpg", "DenseResidential/denseresidential_138.jpg", "DenseResidential/denseresidential_145.jpg", "DenseResidential/denseresidential_206.jpg", "DenseResidential/denseresidential_98.jpg", "DenseResidential/denseresidential_34.jpg", "DenseResidential/denseresidential_400.jpg", "DenseResidential/denseresidential_385.jpg", "DenseResidential/denseresidential_307.jpg", "DenseResidential/denseresidential_48.jpg", "DenseResidential/denseresidential_198.jpg", "DenseResidential/denseresidential_50.jpg", "DenseResidential/denseresidential_378.jpg", "DenseResidential/denseresidential_266.jpg", "DenseResidential/denseresidential_254.jpg", "DenseResidential/denseresidential_32.jpg", "DenseResidential/denseresidential_338.jpg", "DenseResidential/denseresidential_297.jpg", "DenseResidential/denseresidential_147.jpg", "DenseResidential/denseresidential_358.jpg", "DenseResidential/denseresidential_403.jpg", "DenseResidential/denseresidential_231.jpg", "DenseResidential/denseresidential_178.jpg", "DenseResidential/denseresidential_288.jpg", "DenseResidential/denseresidential_160.jpg", "DenseResidential/denseresidential_158.jpg", "DenseResidential/denseresidential_221.jpg", "DenseResidential/denseresidential_114.jpg", "DenseResidential/denseresidential_186.jpg", "DenseResidential/denseresidential_83.jpg", "DenseResidential/denseresidential_72.jpg", "DenseResidential/denseresidential_176.jpg", "DenseResidential/denseresidential_321.jpg", "DenseResidential/denseresidential_280.jpg", "DenseResidential/denseresidential_81.jpg", "DenseResidential/denseresidential_207.jpg", "DenseResidential/denseresidential_211.jpg", "DenseResidential/denseresidential_352.jpg", "DenseResidential/denseresidential_356.jpg", "DenseResidential/denseresidential_166.jpg", "DenseResidential/denseresidential_263.jpg", "DenseResidential/denseresidential_122.jpg", "DenseResidential/denseresidential_249.jpg", "DenseResidential/denseresidential_287.jpg", "DenseResidential/denseresidential_315.jpg", "DenseResidential/denseresidential_46.jpg", "DenseResidential/denseresidential_148.jpg", "DenseResidential/denseresidential_410.jpg", "DenseResidential/denseresidential_328.jpg", "DenseResidential/denseresidential_324.jpg", "DenseResidential/denseresidential_277.jpg", "DenseResidential/denseresidential_226.jpg", "DenseResidential/denseresidential_52.jpg", "DenseResidential/denseresidential_243.jpg", "DenseResidential/denseresidential_38.jpg", "DenseResidential/denseresidential_121.jpg", "DenseResidential/denseresidential_409.jpg", "DenseResidential/denseresidential_209.jpg", "DenseResidential/denseresidential_92.jpg", "DenseResidential/denseresidential_192.jpg", "DenseResidential/denseresidential_401.jpg", "DenseResidential/denseresidential_327.jpg", "DenseResidential/denseresidential_353.jpg", "DenseResidential/denseresidential_322.jpg", "DenseResidential/denseresidential_3.jpg", "DenseResidential/denseresidential_217.jpg", "DenseResidential/denseresidential_100.jpg", "DenseResidential/denseresidential_127.jpg", "DenseResidential/denseresidential_97.jpg", "DenseResidential/denseresidential_390.jpg", "DenseResidential/denseresidential_141.jpg", "DenseResidential/denseresidential_289.jpg", "DenseResidential/denseresidential_404.jpg", "DenseResidential/denseresidential_6.jpg", "DenseResidential/denseresidential_284.jpg", "DenseResidential/denseresidential_181.jpg", "DenseResidential/denseresidential_386.jpg", "DenseResidential/denseresidential_199.jpg", "DenseResidential/denseresidential_290.jpg", "DenseResidential/denseresidential_24.jpg", "DenseResidential/denseresidential_392.jpg", "DenseResidential/denseresidential_21.jpg", "DenseResidential/denseresidential_205.jpg", "DenseResidential/denseresidential_163.jpg", "DenseResidential/denseresidential_85.jpg", "DenseResidential/denseresidential_375.jpg", "DenseResidential/denseresidential_232.jpg", "DenseResidential/denseresidential_303.jpg", "DenseResidential/denseresidential_155.jpg", "DenseResidential/denseresidential_334.jpg", "DenseResidential/denseresidential_340.jpg", "RailwayStation/railwaystation_181.jpg", "RailwayStation/railwaystation_96.jpg", "RailwayStation/railwaystation_7.jpg", "RailwayStation/railwaystation_152.jpg", "RailwayStation/railwaystation_224.jpg", "RailwayStation/railwaystation_67.jpg", "RailwayStation/railwaystation_129.jpg", "RailwayStation/railwaystation_177.jpg", "RailwayStation/railwaystation_213.jpg", "RailwayStation/railwaystation_41.jpg", "RailwayStation/railwaystation_218.jpg", "RailwayStation/railwaystation_113.jpg", "RailwayStation/railwaystation_25.jpg", "RailwayStation/railwaystation_66.jpg", "RailwayStation/railwaystation_219.jpg", "RailwayStation/railwaystation_70.jpg", "RailwayStation/railwaystation_199.jpg", "RailwayStation/railwaystation_1.jpg", "RailwayStation/railwaystation_232.jpg", "RailwayStation/railwaystation_43.jpg", "RailwayStation/railwaystation_97.jpg", "RailwayStation/railwaystation_5.jpg", "RailwayStation/railwaystation_26.jpg", "RailwayStation/railwaystation_206.jpg", "RailwayStation/railwaystation_73.jpg", "RailwayStation/railwaystation_39.jpg", "RailwayStation/railwaystation_151.jpg", "RailwayStation/railwaystation_259.jpg", "RailwayStation/railwaystation_172.jpg", "RailwayStation/railwaystation_72.jpg", "RailwayStation/railwaystation_133.jpg", "RailwayStation/railwaystation_49.jpg", "RailwayStation/railwaystation_155.jpg", "RailwayStation/railwaystation_226.jpg", "RailwayStation/railwaystation_27.jpg", "RailwayStation/railwaystation_235.jpg", "RailwayStation/railwaystation_157.jpg", "RailwayStation/railwaystation_109.jpg", "RailwayStation/railwaystation_21.jpg", "RailwayStation/railwaystation_94.jpg", "RailwayStation/railwaystation_38.jpg", "RailwayStation/railwaystation_142.jpg", "RailwayStation/railwaystation_101.jpg", "RailwayStation/railwaystation_203.jpg", "RailwayStation/railwaystation_215.jpg", "RailwayStation/railwaystation_24.jpg", "RailwayStation/railwaystation_28.jpg", "RailwayStation/railwaystation_40.jpg", "RailwayStation/railwaystation_118.jpg", "RailwayStation/railwaystation_33.jpg", "RailwayStation/railwaystation_82.jpg", "RailwayStation/railwaystation_254.jpg", "RailwayStation/railwaystation_205.jpg", "RailwayStation/railwaystation_83.jpg", "RailwayStation/railwaystation_85.jpg", "RailwayStation/railwaystation_193.jpg", "RailwayStation/railwaystation_156.jpg", "RailwayStation/railwaystation_36.jpg", "RailwayStation/railwaystation_122.jpg", "RailwayStation/railwaystation_173.jpg", "RailwayStation/railwaystation_186.jpg", "RailwayStation/railwaystation_170.jpg", "RailwayStation/railwaystation_207.jpg", "RailwayStation/railwaystation_171.jpg", "RailwayStation/railwaystation_182.jpg", "RailwayStation/railwaystation_187.jpg", "RailwayStation/railwaystation_35.jpg", "RailwayStation/railwaystation_198.jpg", "RailwayStation/railwaystation_30.jpg", "RailwayStation/railwaystation_22.jpg", "RailwayStation/railwaystation_37.jpg", "RailwayStation/railwaystation_249.jpg", "RailwayStation/railwaystation_74.jpg", "RailwayStation/railwaystation_149.jpg", "RailwayStation/railwaystation_20.jpg", "RailwayStation/railwaystation_244.jpg", "RailwayStation/railwaystation_223.jpg", "RailwayStation/railwaystation_111.jpg", "RailwayStation/railwaystation_8.jpg", "RailwayStation/railwaystation_214.jpg", "RailwayStation/railwaystation_48.jpg", "RailwayStation/railwaystation_84.jpg", "RailwayStation/railwaystation_163.jpg", "RailwayStation/railwaystation_93.jpg", "RailwayStation/railwaystation_192.jpg", "RailwayStation/railwaystation_189.jpg", "RailwayStation/railwaystation_131.jpg", "RailwayStation/railwaystation_95.jpg", "RailwayStation/railwaystation_123.jpg", "RailwayStation/railwaystation_46.jpg", "RailwayStation/railwaystation_86.jpg", "RailwayStation/railwaystation_248.jpg", "RailwayStation/railwaystation_183.jpg", "RailwayStation/railwaystation_110.jpg", "RailwayStation/railwaystation_81.jpg", "RailwayStation/railwaystation_102.jpg", "RailwayStation/railwaystation_167.jpg", "RailwayStation/railwaystation_212.jpg", "RailwayStation/railwaystation_191.jpg", "RailwayStation/railwaystation_146.jpg", "RailwayStation/railwaystation_188.jpg", "RailwayStation/railwaystation_13.jpg", "RailwayStation/railwaystation_153.jpg", "RailwayStation/railwaystation_100.jpg", "RailwayStation/railwaystation_34.jpg", "RailwayStation/railwaystation_217.jpg", "RailwayStation/railwaystation_202.jpg", "RailwayStation/railwaystation_17.jpg", "RailwayStation/railwaystation_12.jpg", "RailwayStation/railwaystation_75.jpg", "RailwayStation/railwaystation_121.jpg", "RailwayStation/railwaystation_228.jpg", "RailwayStation/railwaystation_18.jpg", "RailwayStation/railwaystation_147.jpg", "RailwayStation/railwaystation_180.jpg", "RailwayStation/railwaystation_150.jpg", "RailwayStation/railwaystation_47.jpg", "RailwayStation/railwaystation_138.jpg", "RailwayStation/railwaystation_245.jpg", "RailwayStation/railwaystation_141.jpg", "RailwayStation/railwaystation_143.jpg", "RailwayStation/railwaystation_4.jpg", "RailwayStation/railwaystation_58.jpg", "RailwayStation/railwaystation_29.jpg", "RailwayStation/railwaystation_119.jpg", "RailwayStation/railwaystation_105.jpg", "RailwayStation/railwaystation_221.jpg", "RailwayStation/railwaystation_256.jpg", "RailwayStation/railwaystation_88.jpg", "RailwayStation/railwaystation_89.jpg", "RailwayStation/railwaystation_124.jpg", "RailwayStation/railwaystation_242.jpg", "RailwayStation/railwaystation_68.jpg", "RailwayStation/railwaystation_11.jpg", "RailwayStation/railwaystation_238.jpg", "RailwayStation/railwaystation_128.jpg", "RailwayStation/railwaystation_132.jpg", "RailwayStation/railwaystation_53.jpg", "RailwayStation/railwaystation_148.jpg", "RailwayStation/railwaystation_134.jpg", "RailwayStation/railwaystation_222.jpg", "RailwayStation/railwaystation_54.jpg", "RailwayStation/railwaystation_241.jpg", "RailwayStation/railwaystation_2.jpg", "RailwayStation/railwaystation_16.jpg", "RailwayStation/railwaystation_135.jpg", "RailwayStation/railwaystation_23.jpg", "RailwayStation/railwaystation_3.jpg", "RailwayStation/railwaystation_231.jpg", "RailwayStation/railwaystation_230.jpg", "RailwayStation/railwaystation_115.jpg", "RailwayStation/railwaystation_201.jpg", "RailwayStation/railwaystation_194.jpg", "RailwayStation/railwaystation_103.jpg", "RailwayStation/railwaystation_90.jpg", "RailwayStation/railwaystation_56.jpg", "RailwayStation/railwaystation_107.jpg", "RailwayStation/railwaystation_168.jpg", "RailwayStation/railwaystation_161.jpg", "RailwayStation/railwaystation_120.jpg", "RailwayStation/railwaystation_255.jpg", "RailwayStation/railwaystation_139.jpg", "RailwayStation/railwaystation_116.jpg", "RailwayStation/railwaystation_234.jpg", "RailwayStation/railwaystation_237.jpg", "RailwayStation/railwaystation_195.jpg", "RailwayStation/railwaystation_176.jpg", "RailwayStation/railwaystation_52.jpg", "RailwayStation/railwaystation_126.jpg", "RailwayStation/railwaystation_136.jpg", "RailwayStation/railwaystation_251.jpg", "RailwayStation/railwaystation_55.jpg", "RailwayStation/railwaystation_137.jpg", "RailwayStation/railwaystation_162.jpg", "RailwayStation/railwaystation_225.jpg", "RailwayStation/railwaystation_45.jpg", "RailwayStation/railwaystation_50.jpg", "RailwayStation/railwaystation_63.jpg", "RailwayStation/railwaystation_76.jpg", "RailwayStation/railwaystation_165.jpg", "RailwayStation/railwaystation_166.jpg", "RailwayStation/railwaystation_250.jpg", "RailwayStation/railwaystation_31.jpg", "RailwayStation/railwaystation_200.jpg", "RailwayStation/railwaystation_227.jpg", "RailwayStation/railwaystation_80.jpg", "RailwayStation/railwaystation_51.jpg", "RailwayStation/railwaystation_247.jpg", "RailwayStation/railwaystation_87.jpg", "RailwayStation/railwaystation_253.jpg", "RailwayStation/railwaystation_91.jpg", "RailwayStation/railwaystation_106.jpg", "RailwayStation/railwaystation_59.jpg", "RailwayStation/railwaystation_130.jpg", "RailwayStation/railwaystation_64.jpg", "RailwayStation/railwaystation_9.jpg", "RailwayStation/railwaystation_190.jpg", "RailwayStation/railwaystation_158.jpg", "BareLand/bareland_198.jpg", "BareLand/bareland_272.jpg", "BareLand/bareland_175.jpg", "BareLand/bareland_261.jpg", "BareLand/bareland_150.jpg", "BareLand/bareland_18.jpg", "BareLand/bareland_283.jpg", "BareLand/bareland_9.jpg", "BareLand/bareland_291.jpg", "BareLand/bareland_301.jpg", "BareLand/bareland_220.jpg", "BareLand/bareland_262.jpg", "BareLand/bareland_44.jpg", "BareLand/bareland_29.jpg", "BareLand/bareland_30.jpg", "BareLand/bareland_182.jpg", "BareLand/bareland_240.jpg", "BareLand/bareland_249.jpg", "BareLand/bareland_268.jpg", "BareLand/bareland_108.jpg", "BareLand/bareland_64.jpg", "BareLand/bareland_213.jpg", "BareLand/bareland_253.jpg", "BareLand/bareland_190.jpg", "BareLand/bareland_149.jpg", "BareLand/bareland_157.jpg", "BareLand/bareland_303.jpg", "BareLand/bareland_274.jpg", "BareLand/bareland_24.jpg", "BareLand/bareland_91.jpg", "BareLand/bareland_221.jpg", "BareLand/bareland_115.jpg", "BareLand/bareland_192.jpg", "BareLand/bareland_19.jpg", "BareLand/bareland_285.jpg", "BareLand/bareland_6.jpg", "BareLand/bareland_235.jpg", "BareLand/bareland_256.jpg", "BareLand/bareland_88.jpg", "BareLand/bareland_98.jpg", "BareLand/bareland_141.jpg", "BareLand/bareland_89.jpg", "BareLand/bareland_73.jpg", "BareLand/bareland_139.jpg", "BareLand/bareland_191.jpg", "BareLand/bareland_144.jpg", "BareLand/bareland_145.jpg", "BareLand/bareland_112.jpg", "BareLand/bareland_275.jpg", "BareLand/bareland_178.jpg", "BareLand/bareland_109.jpg", "BareLand/bareland_87.jpg", "BareLand/bareland_126.jpg", "BareLand/bareland_211.jpg", "BareLand/bareland_50.jpg", "BareLand/bareland_57.jpg", "BareLand/bareland_210.jpg", "BareLand/bareland_237.jpg", "BareLand/bareland_279.jpg", "BareLand/bareland_169.jpg", "BareLand/bareland_184.jpg", "BareLand/bareland_53.jpg", "BareLand/bareland_223.jpg", "BareLand/bareland_199.jpg", "BareLand/bareland_143.jpg", "BareLand/bareland_202.jpg", "BareLand/bareland_257.jpg", "BareLand/bareland_80.jpg", "BareLand/bareland_214.jpg", "BareLand/bareland_207.jpg", "BareLand/bareland_58.jpg", "BareLand/bareland_180.jpg", "BareLand/bareland_203.jpg", "BareLand/bareland_142.jpg", "BareLand/bareland_172.jpg", "BareLand/bareland_242.jpg", "BareLand/bareland_34.jpg", "BareLand/bareland_119.jpg", "BareLand/bareland_14.jpg", "BareLand/bareland_302.jpg", "BareLand/bareland_74.jpg", "BareLand/bareland_85.jpg", "BareLand/bareland_290.jpg", "BareLand/bareland_212.jpg", "BareLand/bareland_27.jpg", "BareLand/bareland_75.jpg", "BareLand/bareland_5.jpg", "BareLand/bareland_270.jpg", "BareLand/bareland_72.jpg", "BareLand/bareland_48.jpg", "BareLand/bareland_129.jpg", "BareLand/bareland_196.jpg", "BareLand/bareland_13.jpg", "BareLand/bareland_124.jpg", "BareLand/bareland_254.jpg", "BareLand/bareland_63.jpg", "BareLand/bareland_56.jpg", "BareLand/bareland_239.jpg", "BareLand/bareland_52.jpg", "BareLand/bareland_82.jpg", "BareLand/bareland_171.jpg", "BareLand/bareland_148.jpg", "BareLand/bareland_259.jpg", "BareLand/bareland_21.jpg", "BareLand/bareland_105.jpg", "BareLand/bareland_45.jpg", "BareLand/bareland_133.jpg", "BareLand/bareland_33.jpg", "BareLand/bareland_118.jpg", "BareLand/bareland_100.jpg", "BareLand/bareland_4.jpg", "BareLand/bareland_307.jpg", "BareLand/bareland_277.jpg", "BareLand/bareland_151.jpg", "BareLand/bareland_216.jpg", "BareLand/bareland_116.jpg", "BareLand/bareland_70.jpg", "BareLand/bareland_248.jpg", "BareLand/bareland_170.jpg", "BareLand/bareland_69.jpg", "BareLand/bareland_296.jpg", "BareLand/bareland_209.jpg", "BareLand/bareland_41.jpg", "BareLand/bareland_76.jpg", "BareLand/bareland_65.jpg", "BareLand/bareland_111.jpg", "BareLand/bareland_174.jpg", "BareLand/bareland_97.jpg", "BareLand/bareland_246.jpg", "BareLand/bareland_2.jpg", "BareLand/bareland_12.jpg", "BareLand/bareland_265.jpg", "BareLand/bareland_222.jpg", "BareLand/bareland_218.jpg", "BareLand/bareland_35.jpg", "BareLand/bareland_90.jpg", "BareLand/bareland_25.jpg", "BareLand/bareland_123.jpg", "BareLand/bareland_289.jpg", "BareLand/bareland_208.jpg", "BareLand/bareland_281.jpg", "BareLand/bareland_20.jpg", "BareLand/bareland_197.jpg", "BareLand/bareland_67.jpg", "BareLand/bareland_194.jpg", "BareLand/bareland_176.jpg", "BareLand/bareland_138.jpg", "BareLand/bareland_225.jpg", "BareLand/bareland_160.jpg", "BareLand/bareland_224.jpg", "BareLand/bareland_181.jpg", "BareLand/bareland_264.jpg", "BareLand/bareland_134.jpg", "BareLand/bareland_36.jpg", "BareLand/bareland_37.jpg", "BareLand/bareland_309.jpg", "BareLand/bareland_17.jpg", "BareLand/bareland_162.jpg", "BareLand/bareland_179.jpg", "BareLand/bareland_110.jpg", "BareLand/bareland_54.jpg", "BareLand/bareland_59.jpg", "BareLand/bareland_231.jpg", "BareLand/bareland_229.jpg", "BareLand/bareland_255.jpg", "BareLand/bareland_113.jpg", "BareLand/bareland_55.jpg", "BareLand/bareland_288.jpg", "BareLand/bareland_278.jpg", "BareLand/bareland_96.jpg", "BareLand/bareland_299.jpg", "BareLand/bareland_201.jpg", "BareLand/bareland_28.jpg", "BareLand/bareland_1.jpg", "BareLand/bareland_39.jpg", "BareLand/bareland_10.jpg", "BareLand/bareland_244.jpg", "BareLand/bareland_68.jpg", "BareLand/bareland_16.jpg", "BareLand/bareland_252.jpg", "BareLand/bareland_166.jpg", "BareLand/bareland_297.jpg", "BareLand/bareland_163.jpg", "BareLand/bareland_156.jpg", "BareLand/bareland_267.jpg", "BareLand/bareland_106.jpg", "BareLand/bareland_204.jpg", "BareLand/bareland_292.jpg", "BareLand/bareland_251.jpg", "BareLand/bareland_146.jpg", "BareLand/bareland_152.jpg", "BareLand/bareland_263.jpg", "BareLand/bareland_186.jpg", "BareLand/bareland_293.jpg", "BareLand/bareland_93.jpg", "BareLand/bareland_114.jpg", "BareLand/bareland_232.jpg", "BareLand/bareland_140.jpg", "BareLand/bareland_230.jpg", "BareLand/bareland_61.jpg", "BareLand/bareland_135.jpg", "BareLand/bareland_284.jpg", "BareLand/bareland_60.jpg", "BareLand/bareland_217.jpg", "BareLand/bareland_310.jpg", "BareLand/bareland_136.jpg", "BareLand/bareland_99.jpg", "BareLand/bareland_280.jpg", "BareLand/bareland_47.jpg", "BareLand/bareland_269.jpg", "BareLand/bareland_266.jpg", "BareLand/bareland_23.jpg", "BareLand/bareland_121.jpg", "BareLand/bareland_117.jpg", "BareLand/bareland_128.jpg", "BareLand/bareland_195.jpg", "BareLand/bareland_130.jpg", "BareLand/bareland_92.jpg", "BareLand/bareland_260.jpg", "BareLand/bareland_219.jpg", "BareLand/bareland_77.jpg", "BareLand/bareland_305.jpg", "BareLand/bareland_250.jpg", "BareLand/bareland_51.jpg", "BareLand/bareland_295.jpg", "BareLand/bareland_287.jpg", "BareLand/bareland_155.jpg", "BareLand/bareland_46.jpg", "BareLand/bareland_300.jpg", "BareLand/bareland_94.jpg", "BareLand/bareland_273.jpg", "BareLand/bareland_38.jpg", "BareLand/bareland_62.jpg", "BareLand/bareland_177.jpg", "BareLand/bareland_258.jpg", "BareLand/bareland_79.jpg", "BareLand/bareland_122.jpg", "BareLand/bareland_215.jpg", "Beach/beach_242.jpg", "Beach/beach_54.jpg", "Beach/beach_341.jpg", "Beach/beach_209.jpg", "Beach/beach_28.jpg", "Beach/beach_395.jpg", "Beach/beach_96.jpg", "Beach/beach_188.jpg", "Beach/beach_114.jpg", "Beach/beach_36.jpg", "Beach/beach_189.jpg", "Beach/beach_154.jpg", "Beach/beach_159.jpg", "Beach/beach_296.jpg", "Beach/beach_164.jpg", "Beach/beach_30.jpg", "Beach/beach_399.jpg", "Beach/beach_156.jpg", "Beach/beach_161.jpg", "Beach/beach_85.jpg", "Beach/beach_19.jpg", "Beach/beach_89.jpg", "Beach/beach_101.jpg", "Beach/beach_142.jpg", "Beach/beach_246.jpg", "Beach/beach_178.jpg", "Beach/beach_104.jpg", "Beach/beach_210.jpg", "Beach/beach_262.jpg", "Beach/beach_32.jpg", "Beach/beach_360.jpg", "Beach/beach_211.jpg", "Beach/beach_295.jpg", "Beach/beach_128.jpg", "Beach/beach_108.jpg", "Beach/beach_270.jpg", "Beach/beach_167.jpg", "Beach/beach_226.jpg", "Beach/beach_234.jpg", "Beach/beach_162.jpg", "Beach/beach_371.jpg", "Beach/beach_113.jpg", "Beach/beach_177.jpg", "Beach/beach_368.jpg", "Beach/beach_2.jpg", "Beach/beach_75.jpg", "Beach/beach_317.jpg", "Beach/beach_245.jpg", "Beach/beach_46.jpg", "Beach/beach_147.jpg", "Beach/beach_259.jpg", "Beach/beach_348.jpg", "Beach/beach_318.jpg", "Beach/beach_173.jpg", "Beach/beach_134.jpg", "Beach/beach_284.jpg", "Beach/beach_355.jpg", "Beach/beach_280.jpg", "Beach/beach_353.jpg", "Beach/beach_191.jpg", "Beach/beach_337.jpg", "Beach/beach_283.jpg", "Beach/beach_207.jpg", "Beach/beach_42.jpg", "Beach/beach_229.jpg", "Beach/beach_157.jpg", "Beach/beach_269.jpg", "Beach/beach_343.jpg", "Beach/beach_272.jpg", "Beach/beach_119.jpg", "Beach/beach_364.jpg", "Beach/beach_291.jpg", "Beach/beach_238.jpg", "Beach/beach_386.jpg", "Beach/beach_278.jpg", "Beach/beach_299.jpg", "Beach/beach_381.jpg", "Beach/beach_344.jpg", "Beach/beach_349.jpg", "Beach/beach_206.jpg", "Beach/beach_80.jpg", "Beach/beach_168.jpg", "Beach/beach_172.jpg", "Beach/beach_65.jpg", "Beach/beach_193.jpg", "Beach/beach_116.jpg", "Beach/beach_184.jpg", "Beach/beach_117.jpg", "Beach/beach_350.jpg", "Beach/beach_347.jpg", "Beach/beach_391.jpg", "Beach/beach_18.jpg", "Beach/beach_155.jpg", "Beach/beach_255.jpg", "Beach/beach_235.jpg", "Beach/beach_33.jpg", "Beach/beach_267.jpg", "Beach/beach_133.jpg", "Beach/beach_123.jpg", "Beach/beach_76.jpg", "Beach/beach_285.jpg", "Beach/beach_79.jpg", "Beach/beach_199.jpg", "Beach/beach_394.jpg", "Beach/beach_289.jpg", "Beach/beach_39.jpg", "Beach/beach_130.jpg", "Beach/beach_385.jpg", "Beach/beach_362.jpg", "Beach/beach_236.jpg", "Beach/beach_141.jpg", "Beach/beach_83.jpg", "Beach/beach_8.jpg", "Beach/beach_249.jpg", "Beach/beach_166.jpg", "Beach/beach_383.jpg", "Beach/beach_214.jpg", "Beach/beach_97.jpg", "Beach/beach_220.jpg", "Beach/beach_273.jpg", "Beach/beach_163.jpg", "Beach/beach_77.jpg", "Beach/beach_219.jpg", "Beach/beach_325.jpg", "Beach/beach_132.jpg", "Beach/beach_316.jpg", "Beach/beach_212.jpg", "Beach/beach_16.jpg", "Beach/beach_37.jpg", "Beach/beach_331.jpg", "Beach/beach_15.jpg", "Beach/beach_179.jpg", "Beach/beach_56.jpg", "Beach/beach_365.jpg", "Beach/beach_61.jpg", "Beach/beach_112.jpg", "Beach/beach_90.jpg", "Beach/beach_388.jpg", "Beach/beach_58.jpg", "Beach/beach_152.jpg", "Beach/beach_303.jpg", "Beach/beach_95.jpg", "Beach/beach_22.jpg", "Beach/beach_136.jpg", "Beach/beach_300.jpg", "Beach/beach_29.jpg", "Beach/beach_86.jpg", "Beach/beach_69.jpg", "Beach/beach_87.jpg", "Beach/beach_376.jpg", "Beach/beach_372.jpg", "Beach/beach_335.jpg", "Beach/beach_68.jpg", "Beach/beach_287.jpg", "Beach/beach_92.jpg", "Beach/beach_183.jpg", "Beach/beach_14.jpg", "Beach/beach_139.jpg", "Beach/beach_271.jpg", "Beach/beach_327.jpg", "Beach/beach_377.jpg", "Beach/beach_306.jpg", "Beach/beach_23.jpg", "Beach/beach_91.jpg", "Beach/beach_369.jpg", "Beach/beach_334.jpg", "Beach/beach_124.jpg", "Beach/beach_387.jpg", "Beach/beach_354.jpg", "Beach/beach_247.jpg", "Beach/beach_64.jpg", "Beach/beach_146.jpg", "Beach/beach_88.jpg", "Beach/beach_263.jpg", "Beach/beach_366.jpg", "Beach/beach_328.jpg", "Beach/beach_342.jpg", "Beach/beach_213.jpg", "Beach/beach_351.jpg", "Beach/beach_382.jpg", "Beach/beach_126.jpg", "Beach/beach_181.jpg", "Beach/beach_332.jpg", "Beach/beach_248.jpg", "Beach/beach_121.jpg", "Beach/beach_384.jpg", "Beach/beach_281.jpg", "Beach/beach_329.jpg", "Beach/beach_165.jpg", "Beach/beach_149.jpg", "Beach/beach_127.jpg", "Beach/beach_373.jpg", "Beach/beach_363.jpg", "Beach/beach_314.jpg", "Beach/beach_367.jpg", "Beach/beach_208.jpg", "Beach/beach_244.jpg", "Beach/beach_171.jpg", "Beach/beach_265.jpg", "Beach/beach_160.jpg", "Beach/beach_305.jpg", "Beach/beach_228.jpg", "Beach/beach_138.jpg", "Beach/beach_254.jpg", "Beach/beach_105.jpg", "Beach/beach_374.jpg", "Beach/beach_192.jpg", "Beach/beach_308.jpg", "Beach/beach_224.jpg", "Beach/beach_55.jpg", "Beach/beach_140.jpg", "Beach/beach_106.jpg", "Beach/beach_84.jpg", "Beach/beach_3.jpg", "Beach/beach_276.jpg", "Beach/beach_10.jpg", "Beach/beach_227.jpg", "Beach/beach_74.jpg", "Beach/beach_216.jpg", "Beach/beach_297.jpg", "Beach/beach_137.jpg", "Beach/beach_218.jpg", "Beach/beach_73.jpg", "Beach/beach_129.jpg", "Beach/beach_13.jpg", "Beach/beach_169.jpg", "Beach/beach_389.jpg", "Beach/beach_264.jpg", "Beach/beach_298.jpg", "Beach/beach_145.jpg", "Beach/beach_100.jpg", "Beach/beach_40.jpg", "Beach/beach_202.jpg", "Beach/beach_397.jpg", "Beach/beach_57.jpg", "Beach/beach_174.jpg", "Beach/beach_21.jpg", "Beach/beach_44.jpg", "Beach/beach_339.jpg", "Beach/beach_322.jpg", "Beach/beach_72.jpg", "Beach/beach_148.jpg", "Beach/beach_118.jpg", "Beach/beach_251.jpg", "Beach/beach_41.jpg", "Beach/beach_222.jpg", "Beach/beach_203.jpg", "Beach/beach_307.jpg", "Beach/beach_268.jpg", "Beach/beach_24.jpg", "Beach/beach_358.jpg", "Beach/beach_109.jpg", "Beach/beach_230.jpg", "Beach/beach_266.jpg", "Beach/beach_217.jpg", "Beach/beach_243.jpg", "Beach/beach_175.jpg", "Beach/beach_313.jpg", "Beach/beach_338.jpg", "Beach/beach_231.jpg", "Beach/beach_195.jpg", "Beach/beach_240.jpg", "Beach/beach_107.jpg", "Beach/beach_288.jpg", "Beach/beach_17.jpg", "Beach/beach_221.jpg", "Beach/beach_336.jpg", "Beach/beach_323.jpg", "Beach/beach_340.jpg", "Beach/beach_78.jpg", "Beach/beach_320.jpg", "Beach/beach_81.jpg", "Beach/beach_143.jpg", "Beach/beach_304.jpg", "Beach/beach_319.jpg", "Beach/beach_359.jpg", "Beach/beach_151.jpg", "Beach/beach_294.jpg", "Beach/beach_170.jpg", "Beach/beach_98.jpg", "Beach/beach_380.jpg", "Beach/beach_180.jpg", "Beach/beach_144.jpg", "Beach/beach_237.jpg", "Beach/beach_25.jpg", "Beach/beach_34.jpg", "Beach/beach_20.jpg", "Beach/beach_53.jpg", "Beach/beach_330.jpg", "Beach/beach_187.jpg", "Beach/beach_60.jpg", "Beach/beach_311.jpg", "Beach/beach_333.jpg", "Beach/beach_9.jpg", "Beach/beach_115.jpg", "Beach/beach_253.jpg", "Beach/beach_261.jpg", "Beach/beach_198.jpg", "Beach/beach_48.jpg", "Beach/beach_205.jpg", "Beach/beach_392.jpg", "Beach/beach_241.jpg", "Beach/beach_67.jpg", "Beach/beach_223.jpg", "Beach/beach_125.jpg", "Beach/beach_186.jpg", "Beach/beach_135.jpg", "Beach/beach_158.jpg", "Beach/beach_352.jpg", "Beach/beach_176.jpg", "Port/port_113.jpg", "Port/port_295.jpg", "Port/port_20.jpg", "Port/port_183.jpg", "Port/port_261.jpg", "Port/port_351.jpg", "Port/port_103.jpg", "Port/port_8.jpg", "Port/port_139.jpg", "Port/port_44.jpg", "Port/port_340.jpg", "Port/port_209.jpg", "Port/port_33.jpg", "Port/port_174.jpg", "Port/port_6.jpg", "Port/port_84.jpg", "Port/port_326.jpg", "Port/port_145.jpg", "Port/port_191.jpg", "Port/port_320.jpg", "Port/port_159.jpg", "Port/port_197.jpg", "Port/port_63.jpg", "Port/port_213.jpg", "Port/port_11.jpg", "Port/port_50.jpg", "Port/port_284.jpg", "Port/port_282.jpg", "Port/port_31.jpg", "Port/port_164.jpg", "Port/port_165.jpg", "Port/port_77.jpg", "Port/port_9.jpg", "Port/port_329.jpg", "Port/port_264.jpg", "Port/port_266.jpg", "Port/port_370.jpg", "Port/port_193.jpg", "Port/port_227.jpg", "Port/port_246.jpg", "Port/port_359.jpg", "Port/port_60.jpg", "Port/port_133.jpg", "Port/port_349.jpg", "Port/port_13.jpg", "Port/port_222.jpg", "Port/port_99.jpg", "Port/port_231.jpg", "Port/port_181.jpg", "Port/port_343.jpg", "Port/port_255.jpg", "Port/port_163.jpg", "Port/port_35.jpg", "Port/port_71.jpg", "Port/port_28.jpg", "Port/port_292.jpg", "Port/port_263.jpg", "Port/port_307.jpg", "Port/port_240.jpg", "Port/port_251.jpg", "Port/port_294.jpg", "Port/port_357.jpg", "Port/port_65.jpg", "Port/port_243.jpg", "Port/port_41.jpg", "Port/port_226.jpg", "Port/port_45.jpg", "Port/port_334.jpg", "Port/port_220.jpg", "Port/port_269.jpg", "Port/port_75.jpg", "Port/port_87.jpg", "Port/port_364.jpg", "Port/port_180.jpg", "Port/port_36.jpg", "Port/port_40.jpg", "Port/port_52.jpg", "Port/port_64.jpg", "Port/port_162.jpg", "Port/port_148.jpg", "Port/port_252.jpg", "Port/port_115.jpg", "Port/port_373.jpg", "Port/port_39.jpg", "Port/port_375.jpg", "Port/port_176.jpg", "Port/port_328.jpg", "Port/port_313.jpg", "Port/port_49.jpg", "Port/port_225.jpg", "Port/port_128.jpg", "Port/port_111.jpg", "Port/port_166.jpg", "Port/port_106.jpg", "Port/port_260.jpg", "Port/port_283.jpg", "Port/port_194.jpg", "Port/port_317.jpg", "Port/port_341.jpg", "Port/port_68.jpg", "Port/port_29.jpg", "Port/port_237.jpg", "Port/port_355.jpg", "Port/port_144.jpg", "Port/port_101.jpg", "Port/port_122.jpg", "Port/port_130.jpg", "Port/port_21.jpg", "Port/port_157.jpg", "Port/port_57.jpg", "Port/port_338.jpg", "Port/port_198.jpg", "Port/port_211.jpg", "Port/port_287.jpg", "Port/port_265.jpg", "Port/port_312.jpg", "Port/port_85.jpg", "Port/port_62.jpg", "Port/port_322.jpg", "Port/port_100.jpg", "Port/port_272.jpg", "Port/port_314.jpg", "Port/port_367.jpg", "Port/port_146.jpg", "Port/port_319.jpg", "Port/port_171.jpg", "Port/port_16.jpg", "Port/port_156.jpg", "Port/port_318.jpg", "Port/port_331.jpg", "Port/port_304.jpg", "Port/port_203.jpg", "Port/port_371.jpg", "Port/port_336.jpg", "Port/port_248.jpg", "Port/port_150.jpg", "Port/port_38.jpg", "Port/port_376.jpg", "Port/port_247.jpg", "Port/port_362.jpg", "Port/port_192.jpg", "Port/port_271.jpg", "Port/port_315.jpg", "Port/port_34.jpg", "Port/port_143.jpg", "Port/port_147.jpg", "Port/port_342.jpg", "Port/port_114.jpg", "Port/port_274.jpg", "Port/port_202.jpg", "Port/port_250.jpg", "Port/port_190.jpg", "Port/port_7.jpg", "Port/port_98.jpg", "Port/port_61.jpg", "Port/port_344.jpg", "Port/port_333.jpg", "Port/port_221.jpg", "Port/port_257.jpg", "Port/port_152.jpg", "Port/port_234.jpg", "Port/port_94.jpg", "Port/port_368.jpg", "Port/port_81.jpg", "Port/port_132.jpg", "Port/port_112.jpg", "Port/port_3.jpg", "Port/port_123.jpg", "Port/port_290.jpg", "Port/port_188.jpg", "Port/port_24.jpg", "Port/port_233.jpg", "Port/port_127.jpg", "Port/port_242.jpg", "Port/port_327.jpg", "Port/port_279.jpg", "Port/port_330.jpg", "Port/port_305.jpg", "Port/port_185.jpg", "Port/port_311.jpg", "Port/port_177.jpg", "Port/port_126.jpg", "Port/port_189.jpg", "Port/port_125.jpg", "Port/port_58.jpg", "Port/port_358.jpg", "Port/port_182.jpg", "Port/port_219.jpg", "Port/port_303.jpg", "Port/port_244.jpg", "Port/port_79.jpg", "Port/port_378.jpg", "Port/port_10.jpg", "Port/port_298.jpg", "Port/port_32.jpg", "Port/port_350.jpg", "Port/port_360.jpg", "Port/port_214.jpg", "Port/port_348.jpg", "Port/port_324.jpg", "Port/port_73.jpg", "Port/port_141.jpg", "Port/port_299.jpg", "Port/port_55.jpg", "Port/port_301.jpg", "Port/port_102.jpg", "Port/port_270.jpg", "Port/port_204.jpg", "Port/port_195.jpg", "Port/port_25.jpg", "Port/port_186.jpg", "Port/port_121.jpg", "Port/port_241.jpg", "Port/port_239.jpg", "Port/port_278.jpg", "Port/port_346.jpg", "Port/port_224.jpg", "Port/port_117.jpg", "Port/port_5.jpg", "Port/port_19.jpg", "Port/port_95.jpg", "Port/port_69.jpg", "Port/port_74.jpg", "Port/port_179.jpg", "Port/port_325.jpg", "Port/port_138.jpg", "Port/port_217.jpg", "Port/port_135.jpg", "Port/port_169.jpg", "Port/port_280.jpg", "Port/port_332.jpg", "Port/port_253.jpg", "Port/port_377.jpg", "Port/port_78.jpg", "Port/port_199.jpg", "Port/port_59.jpg", "Port/port_369.jpg", "Port/port_254.jpg", "Port/port_374.jpg", "Port/port_306.jpg", "Port/port_172.jpg", "Port/port_262.jpg", "Port/port_245.jpg", "Port/port_206.jpg", "Port/port_372.jpg", "Port/port_109.jpg", "Port/port_82.jpg", "Port/port_361.jpg", "Port/port_90.jpg", "Port/port_238.jpg", "Port/port_230.jpg", "Port/port_17.jpg", "Port/port_116.jpg", "Port/port_285.jpg", "Port/port_356.jpg", "Port/port_48.jpg", "Port/port_380.jpg", "Port/port_67.jpg", "Port/port_107.jpg", "Port/port_200.jpg", "Port/port_18.jpg", "Port/port_120.jpg", "Port/port_80.jpg", "Port/port_96.jpg", "Port/port_178.jpg", "Port/port_118.jpg", "Port/port_167.jpg", "Port/port_339.jpg", "Port/port_142.jpg", "Port/port_366.jpg", "Port/port_119.jpg", "Port/port_302.jpg", "Port/port_46.jpg", "Port/port_208.jpg", "Port/port_323.jpg", "Port/port_104.jpg", "Port/port_321.jpg", "Port/port_92.jpg", "Port/port_273.jpg", "Port/port_300.jpg", "Port/port_42.jpg", "Port/port_154.jpg", "Port/port_212.jpg", "Port/port_216.jpg", "Port/port_289.jpg", "Port/port_187.jpg", "Port/port_51.jpg", "Port/port_149.jpg", "Port/port_277.jpg", "Port/port_310.jpg", "Port/port_89.jpg", "Port/port_201.jpg", "Port/port_210.jpg", "Port/port_229.jpg", "Mountain/mountain_205.jpg", "Mountain/mountain_289.jpg", "Mountain/mountain_335.jpg", "Mountain/mountain_82.jpg", "Mountain/mountain_329.jpg", "Mountain/mountain_138.jpg", "Mountain/mountain_236.jpg", "Mountain/mountain_316.jpg", "Mountain/mountain_87.jpg", "Mountain/mountain_15.jpg", "Mountain/mountain_140.jpg", "Mountain/mountain_25.jpg", "Mountain/mountain_43.jpg", "Mountain/mountain_17.jpg", "Mountain/mountain_53.jpg", "Mountain/mountain_229.jpg", "Mountain/mountain_107.jpg", "Mountain/mountain_295.jpg", "Mountain/mountain_5.jpg", "Mountain/mountain_149.jpg", "Mountain/mountain_203.jpg", "Mountain/mountain_16.jpg", "Mountain/mountain_293.jpg", "Mountain/mountain_238.jpg", "Mountain/mountain_272.jpg", "Mountain/mountain_337.jpg", "Mountain/mountain_75.jpg", "Mountain/mountain_148.jpg", "Mountain/mountain_22.jpg", "Mountain/mountain_327.jpg", "Mountain/mountain_170.jpg", "Mountain/mountain_210.jpg", "Mountain/mountain_214.jpg", "Mountain/mountain_125.jpg", "Mountain/mountain_144.jpg", "Mountain/mountain_322.jpg", "Mountain/mountain_300.jpg", "Mountain/mountain_63.jpg", "Mountain/mountain_291.jpg", "Mountain/mountain_258.jpg", "Mountain/mountain_24.jpg", "Mountain/mountain_267.jpg", "Mountain/mountain_242.jpg", "Mountain/mountain_263.jpg", "Mountain/mountain_241.jpg", "Mountain/mountain_121.jpg", "Mountain/mountain_135.jpg", "Mountain/mountain_128.jpg", "Mountain/mountain_253.jpg", "Mountain/mountain_301.jpg", "Mountain/mountain_129.jpg", "Mountain/mountain_191.jpg", "Mountain/mountain_168.jpg", "Mountain/mountain_109.jpg", "Mountain/mountain_223.jpg", "Mountain/mountain_33.jpg", "Mountain/mountain_224.jpg", "Mountain/mountain_324.jpg", "Mountain/mountain_137.jpg", "Mountain/mountain_188.jpg", "Mountain/mountain_298.jpg", "Mountain/mountain_21.jpg", "Mountain/mountain_197.jpg", "Mountain/mountain_246.jpg", "Mountain/mountain_81.jpg", "Mountain/mountain_215.jpg", "Mountain/mountain_9.jpg", "Mountain/mountain_28.jpg", "Mountain/mountain_254.jpg", "Mountain/mountain_96.jpg", "Mountain/mountain_299.jpg", "Mountain/mountain_330.jpg", "Mountain/mountain_315.jpg", "Mountain/mountain_319.jpg", "Mountain/mountain_150.jpg", "Mountain/mountain_158.jpg", "Mountain/mountain_310.jpg", "Mountain/mountain_89.jpg", "Mountain/mountain_118.jpg", "Mountain/mountain_126.jpg", "Mountain/mountain_117.jpg", "Mountain/mountain_127.jpg", "Mountain/mountain_30.jpg", "Mountain/mountain_1.jpg", "Mountain/mountain_304.jpg", "Mountain/mountain_110.jpg", "Mountain/mountain_44.jpg", "Mountain/mountain_8.jpg", "Mountain/mountain_95.jpg", "Mountain/mountain_169.jpg", "Mountain/mountain_196.jpg", "Mountain/mountain_122.jpg", "Mountain/mountain_132.jpg", "Mountain/mountain_45.jpg", "Mountain/mountain_172.jpg", "Mountain/mountain_179.jpg", "Mountain/mountain_47.jpg", "Mountain/mountain_146.jpg", "Mountain/mountain_154.jpg", "Mountain/mountain_192.jpg", "Mountain/mountain_155.jpg", "Mountain/mountain_106.jpg", "Mountain/mountain_91.jpg", "Mountain/mountain_27.jpg", "Mountain/mountain_216.jpg", "Mountain/mountain_92.jpg", "Mountain/mountain_269.jpg", "Mountain/mountain_220.jpg", "Mountain/mountain_323.jpg", "Mountain/mountain_180.jpg", "Mountain/mountain_206.jpg", "Mountain/mountain_52.jpg", "Mountain/mountain_51.jpg", "Mountain/mountain_256.jpg", "Mountain/mountain_235.jpg", "Mountain/mountain_270.jpg", "Mountain/mountain_328.jpg", "Mountain/mountain_57.jpg", "Mountain/mountain_72.jpg", "Mountain/mountain_177.jpg", "Mountain/mountain_338.jpg", "Mountain/mountain_98.jpg", "Mountain/mountain_68.jpg", "Mountain/mountain_251.jpg", "Mountain/mountain_273.jpg", "Mountain/mountain_101.jpg", "Mountain/mountain_173.jpg", "Mountain/mountain_166.jpg", "Mountain/mountain_325.jpg", "Mountain/mountain_174.jpg", "Mountain/mountain_243.jpg", "Mountain/mountain_219.jpg", "Mountain/mountain_257.jpg", "Mountain/mountain_23.jpg", "Mountain/mountain_103.jpg", "Mountain/mountain_244.jpg", "Mountain/mountain_19.jpg", "Mountain/mountain_208.jpg", "Mountain/mountain_321.jpg", "Mountain/mountain_274.jpg", "Mountain/mountain_90.jpg", "Mountain/mountain_14.jpg", "Mountain/mountain_311.jpg", "Mountain/mountain_194.jpg", "Mountain/mountain_143.jpg", "Mountain/mountain_162.jpg", "Mountain/mountain_185.jpg", "Mountain/mountain_333.jpg", "Mountain/mountain_259.jpg", "Mountain/mountain_209.jpg", "Mountain/mountain_297.jpg", "Mountain/mountain_232.jpg", "Mountain/mountain_59.jpg", "Mountain/mountain_313.jpg", "Mountain/mountain_250.jpg", "Mountain/mountain_266.jpg", "Mountain/mountain_136.jpg", "Mountain/mountain_252.jpg", "Mountain/mountain_260.jpg", "Mountain/mountain_183.jpg", "Mountain/mountain_124.jpg", "Mountain/mountain_13.jpg", "Mountain/mountain_71.jpg", "Mountain/mountain_306.jpg", "Mountain/mountain_264.jpg", "Mountain/mountain_160.jpg", "Mountain/mountain_240.jpg", "Mountain/mountain_20.jpg", "Mountain/mountain_326.jpg", "Mountain/mountain_271.jpg", "Mountain/mountain_111.jpg", "Mountain/mountain_239.jpg", "Mountain/mountain_58.jpg", "Mountain/mountain_86.jpg", "Mountain/mountain_277.jpg", "Mountain/mountain_187.jpg", "Mountain/mountain_248.jpg", "Mountain/mountain_131.jpg", "Mountain/mountain_56.jpg", "Mountain/mountain_204.jpg", "Mountain/mountain_225.jpg", "Mountain/mountain_217.jpg", "Mountain/mountain_70.jpg", "Mountain/mountain_94.jpg", "Mountain/mountain_79.jpg", "Mountain/mountain_83.jpg", "Mountain/mountain_200.jpg", "Mountain/mountain_163.jpg", "Mountain/mountain_255.jpg", "Mountain/mountain_97.jpg", "Mountain/mountain_41.jpg", "Mountain/mountain_60.jpg", "Mountain/mountain_227.jpg", "Mountain/mountain_54.jpg", "Mountain/mountain_29.jpg", "Mountain/mountain_100.jpg", "Mountain/mountain_38.jpg", "Mountain/mountain_305.jpg", "Mountain/mountain_190.jpg", "Mountain/mountain_152.jpg", "Mountain/mountain_116.jpg", "Mountain/mountain_69.jpg", "Mountain/mountain_309.jpg", "Mountain/mountain_11.jpg", "Mountain/mountain_105.jpg", "Mountain/mountain_287.jpg", "Mountain/mountain_119.jpg", "Mountain/mountain_113.jpg", "Mountain/mountain_133.jpg", "Mountain/mountain_281.jpg", "Mountain/mountain_99.jpg", "Mountain/mountain_120.jpg", "Mountain/mountain_268.jpg", "Mountain/mountain_212.jpg", "Mountain/mountain_93.jpg", "Mountain/mountain_76.jpg", "Mountain/mountain_74.jpg", "Mountain/mountain_292.jpg", "Mountain/mountain_247.jpg", "Mountain/mountain_202.jpg", "Mountain/mountain_303.jpg", "Mountain/mountain_283.jpg", "Mountain/mountain_245.jpg", "Mountain/mountain_262.jpg", "Mountain/mountain_317.jpg", "Mountain/mountain_40.jpg", "Mountain/mountain_159.jpg", "Mountain/mountain_12.jpg", "Mountain/mountain_231.jpg", "Mountain/mountain_279.jpg", "Mountain/mountain_32.jpg", "Mountain/mountain_157.jpg", "Mountain/mountain_175.jpg", "Mountain/mountain_134.jpg", "Mountain/mountain_67.jpg", "Mountain/mountain_3.jpg", "Mountain/mountain_10.jpg", "Mountain/mountain_66.jpg", "Mountain/mountain_46.jpg", "Mountain/mountain_184.jpg", "Mountain/mountain_164.jpg", "Mountain/mountain_218.jpg", "Mountain/mountain_39.jpg", "Mountain/mountain_199.jpg", "Mountain/mountain_213.jpg", "Mountain/mountain_141.jpg", "Mountain/mountain_222.jpg", "Mountain/mountain_334.jpg", "Mountain/mountain_130.jpg", "Mountain/mountain_171.jpg", "Mountain/mountain_230.jpg", "Mountain/mountain_234.jpg", "Mountain/mountain_318.jpg", "Mountain/mountain_42.jpg", "Mountain/mountain_339.jpg", "Mountain/mountain_84.jpg", "Mountain/mountain_233.jpg", "Mountain/mountain_55.jpg", "Mountain/mountain_104.jpg", "Mountain/mountain_285.jpg", "Mountain/mountain_147.jpg", "Mountain/mountain_49.jpg", "Desert/desert_156.jpg", "Desert/desert_45.jpg", "Desert/desert_127.jpg", "Desert/desert_297.jpg", "Desert/desert_222.jpg", "Desert/desert_280.jpg", "Desert/desert_198.jpg", "Desert/desert_144.jpg", "Desert/desert_39.jpg", "Desert/desert_185.jpg", "Desert/desert_252.jpg", "Desert/desert_81.jpg", "Desert/desert_241.jpg", "Desert/desert_264.jpg", "Desert/desert_89.jpg", "Desert/desert_126.jpg", "Desert/desert_283.jpg", "Desert/desert_169.jpg", "Desert/desert_20.jpg", "Desert/desert_248.jpg", "Desert/desert_16.jpg", "Desert/desert_55.jpg", "Desert/desert_167.jpg", "Desert/desert_136.jpg", "Desert/desert_236.jpg", "Desert/desert_165.jpg", "Desert/desert_272.jpg", "Desert/desert_191.jpg", "Desert/desert_114.jpg", "Desert/desert_219.jpg", "Desert/desert_277.jpg", "Desert/desert_62.jpg", "Desert/desert_188.jpg", "Desert/desert_19.jpg", "Desert/desert_86.jpg", "Desert/desert_15.jpg", "Desert/desert_251.jpg", "Desert/desert_71.jpg", "Desert/desert_262.jpg", "Desert/desert_146.jpg", "Desert/desert_145.jpg", "Desert/desert_118.jpg", "Desert/desert_92.jpg", "Desert/desert_259.jpg", "Desert/desert_105.jpg", "Desert/desert_162.jpg", "Desert/desert_268.jpg", "Desert/desert_21.jpg", "Desert/desert_34.jpg", "Desert/desert_87.jpg", "Desert/desert_130.jpg", "Desert/desert_29.jpg", "Desert/desert_24.jpg", "Desert/desert_276.jpg", "Desert/desert_54.jpg", "Desert/desert_206.jpg", "Desert/desert_63.jpg", "Desert/desert_95.jpg", "Desert/desert_285.jpg", "Desert/desert_137.jpg", "Desert/desert_56.jpg", "Desert/desert_93.jpg", "Desert/desert_278.jpg", "Desert/desert_187.jpg", "Desert/desert_234.jpg", "Desert/desert_59.jpg", "Desert/desert_174.jpg", "Desert/desert_32.jpg", "Desert/desert_237.jpg", "Desert/desert_38.jpg", "Desert/desert_170.jpg", "Desert/desert_121.jpg", "Desert/desert_247.jpg", "Desert/desert_255.jpg", "Desert/desert_182.jpg", "Desert/desert_150.jpg", "Desert/desert_200.jpg", "Desert/desert_10.jpg", "Desert/desert_67.jpg", "Desert/desert_267.jpg", "Desert/desert_41.jpg", "Desert/desert_226.jpg", "Desert/desert_192.jpg", "Desert/desert_73.jpg", "Desert/desert_238.jpg", "Desert/desert_176.jpg", "Desert/desert_298.jpg", "Desert/desert_194.jpg", "Desert/desert_129.jpg", "Desert/desert_123.jpg", "Desert/desert_175.jpg", "Desert/desert_148.jpg", "Desert/desert_261.jpg", "Desert/desert_112.jpg", "Desert/desert_230.jpg", "Desert/desert_18.jpg", "Desert/desert_184.jpg", "Desert/desert_49.jpg", "Desert/desert_157.jpg", "Desert/desert_48.jpg", "Desert/desert_190.jpg", "Desert/desert_239.jpg", "Desert/desert_189.jpg", "Desert/desert_163.jpg", "Desert/desert_201.jpg", "Desert/desert_100.jpg", "Desert/desert_88.jpg", "Desert/desert_299.jpg", "Desert/desert_125.jpg", "Desert/desert_106.jpg", "Desert/desert_223.jpg", "Desert/desert_288.jpg", "Desert/desert_186.jpg", "Desert/desert_196.jpg", "Desert/desert_11.jpg", "Desert/desert_258.jpg", "Desert/desert_171.jpg", "Desert/desert_168.jpg", "Desert/desert_208.jpg", "Desert/desert_141.jpg", "Desert/desert_51.jpg", "Desert/desert_292.jpg", "Desert/desert_30.jpg", "Desert/desert_216.jpg", "Desert/desert_178.jpg", "Desert/desert_42.jpg", "Desert/desert_108.jpg", "Desert/desert_147.jpg", "Desert/desert_229.jpg", "Desert/desert_160.jpg", "Desert/desert_151.jpg", "Desert/desert_179.jpg", "Desert/desert_138.jpg", "Desert/desert_183.jpg", "Desert/desert_221.jpg", "Desert/desert_7.jpg", "Desert/desert_300.jpg", "Desert/desert_246.jpg", "Desert/desert_117.jpg", "Desert/desert_164.jpg", "Desert/desert_2.jpg", "Desert/desert_12.jpg", "Desert/desert_233.jpg", "Desert/desert_61.jpg", "Desert/desert_287.jpg", "Desert/desert_78.jpg", "Desert/desert_291.jpg", "Desert/desert_53.jpg", "Desert/desert_82.jpg", "Desert/desert_195.jpg", "Desert/desert_79.jpg", "Desert/desert_270.jpg", "Desert/desert_153.jpg", "Desert/desert_214.jpg", "Desert/desert_6.jpg", "Desert/desert_269.jpg", "Desert/desert_107.jpg", "Desert/desert_209.jpg", "Desert/desert_202.jpg", "Desert/desert_282.jpg", "Desert/desert_215.jpg", "Desert/desert_17.jpg", "Desert/desert_173.jpg", "Desert/desert_57.jpg", "Desert/desert_68.jpg", "Desert/desert_37.jpg", "Desert/desert_289.jpg", "Desert/desert_120.jpg", "Desert/desert_177.jpg", "Desert/desert_199.jpg", "Desert/desert_274.jpg", "Desert/desert_279.jpg", "Desert/desert_69.jpg", "Desert/desert_210.jpg", "Desert/desert_5.jpg", "Desert/desert_47.jpg", "Desert/desert_72.jpg", "Desert/desert_260.jpg", "Desert/desert_133.jpg", "Desert/desert_58.jpg", "Desert/desert_8.jpg", "Desert/desert_44.jpg", "Desert/desert_250.jpg", "Desert/desert_135.jpg", "Desert/desert_110.jpg", "Desert/desert_46.jpg", "Desert/desert_109.jpg", "Desert/desert_111.jpg", "Desert/desert_245.jpg", "Desert/desert_124.jpg", "Desert/desert_242.jpg", "Desert/desert_207.jpg", "Desert/desert_4.jpg", "Desert/desert_159.jpg", "Desert/desert_75.jpg", "Desert/desert_155.jpg", "Desert/desert_128.jpg", "Desert/desert_286.jpg", "Desert/desert_265.jpg", "Desert/desert_83.jpg", "Desert/desert_96.jpg", "Desert/desert_228.jpg", "Desert/desert_36.jpg", "Desert/desert_224.jpg", "Desert/desert_294.jpg", "Desert/desert_104.jpg", "Desert/desert_249.jpg", "Desert/desert_203.jpg", "Desert/desert_166.jpg", "Desert/desert_76.jpg", "Desert/desert_70.jpg", "Desert/desert_293.jpg", "Desert/desert_43.jpg", "Desert/desert_232.jpg", "Desert/desert_161.jpg", "Desert/desert_257.jpg", "Desert/desert_132.jpg", "Desert/desert_220.jpg", "Desert/desert_28.jpg", "Desert/desert_85.jpg", "Desert/desert_197.jpg", "Desert/desert_99.jpg", "Desert/desert_84.jpg", "Desert/desert_35.jpg", "Desert/desert_60.jpg", "Desert/desert_94.jpg", "Desert/desert_143.jpg", "Desert/desert_22.jpg", "Desert/desert_152.jpg", "Desert/desert_253.jpg", "Meadow/meadow_214.jpg", "Meadow/meadow_146.jpg", "Meadow/meadow_137.jpg", "Meadow/meadow_25.jpg", "Meadow/meadow_123.jpg", "Meadow/meadow_244.jpg", "Meadow/meadow_52.jpg", "Meadow/meadow_55.jpg", "Meadow/meadow_6.jpg", "Meadow/meadow_264.jpg", "Meadow/meadow_279.jpg", "Meadow/meadow_160.jpg", "Meadow/meadow_77.jpg", "Meadow/meadow_115.jpg", "Meadow/meadow_69.jpg", "Meadow/meadow_144.jpg", "Meadow/meadow_60.jpg", "Meadow/meadow_17.jpg", "Meadow/meadow_78.jpg", "Meadow/meadow_268.jpg", "Meadow/meadow_201.jpg", "Meadow/meadow_22.jpg", "Meadow/meadow_40.jpg", "Meadow/meadow_168.jpg", "Meadow/meadow_107.jpg", "Meadow/meadow_256.jpg", "Meadow/meadow_142.jpg", "Meadow/meadow_11.jpg", "Meadow/meadow_80.jpg", "Meadow/meadow_89.jpg", "Meadow/meadow_223.jpg", "Meadow/meadow_189.jpg", "Meadow/meadow_39.jpg", "Meadow/meadow_48.jpg", "Meadow/meadow_132.jpg", "Meadow/meadow_10.jpg", "Meadow/meadow_245.jpg", "Meadow/meadow_158.jpg", "Meadow/meadow_50.jpg", "Meadow/meadow_204.jpg", "Meadow/meadow_135.jpg", "Meadow/meadow_200.jpg", "Meadow/meadow_174.jpg", "Meadow/meadow_95.jpg", "Meadow/meadow_183.jpg", "Meadow/meadow_206.jpg", "Meadow/meadow_198.jpg", "Meadow/meadow_23.jpg", "Meadow/meadow_266.jpg", "Meadow/meadow_9.jpg", "Meadow/meadow_34.jpg", "Meadow/meadow_219.jpg", "Meadow/meadow_62.jpg", "Meadow/meadow_260.jpg", "Meadow/meadow_239.jpg", "Meadow/meadow_99.jpg", "Meadow/meadow_117.jpg", "Meadow/meadow_67.jpg", "Meadow/meadow_126.jpg", "Meadow/meadow_143.jpg", "Meadow/meadow_175.jpg", "Meadow/meadow_147.jpg", "Meadow/meadow_249.jpg", "Meadow/meadow_87.jpg", "Meadow/meadow_229.jpg", "Meadow/meadow_269.jpg", "Meadow/meadow_100.jpg", "Meadow/meadow_280.jpg", "Meadow/meadow_29.jpg", "Meadow/meadow_114.jpg", "Meadow/meadow_235.jpg", "Meadow/meadow_2.jpg", "Meadow/meadow_18.jpg", "Meadow/meadow_191.jpg", "Meadow/meadow_184.jpg", "Meadow/meadow_65.jpg", "Meadow/meadow_152.jpg", "Meadow/meadow_41.jpg", "Meadow/meadow_46.jpg", "Meadow/meadow_180.jpg", "Meadow/meadow_129.jpg", "Meadow/meadow_90.jpg", "Meadow/meadow_97.jpg", "Meadow/meadow_122.jpg", "Meadow/meadow_252.jpg", "Meadow/meadow_38.jpg", "Meadow/meadow_131.jpg", "Meadow/meadow_161.jpg", "Meadow/meadow_27.jpg", "Meadow/meadow_54.jpg", "Meadow/meadow_253.jpg", "Meadow/meadow_118.jpg", "Meadow/meadow_208.jpg", "Meadow/meadow_213.jpg", "Meadow/meadow_42.jpg", "Meadow/meadow_156.jpg", "Meadow/meadow_79.jpg", "Meadow/meadow_58.jpg", "Meadow/meadow_136.jpg", "Meadow/meadow_45.jpg", "Meadow/meadow_177.jpg", "Meadow/meadow_207.jpg", "Meadow/meadow_110.jpg", "Meadow/meadow_15.jpg", "Meadow/meadow_258.jpg", "Meadow/meadow_194.jpg", "Meadow/meadow_138.jpg", "Meadow/meadow_274.jpg", "Meadow/meadow_82.jpg", "Meadow/meadow_272.jpg", "Meadow/meadow_150.jpg", "Meadow/meadow_1.jpg", "Meadow/meadow_217.jpg", "Meadow/meadow_86.jpg", "Meadow/meadow_231.jpg", "Meadow/meadow_83.jpg", "Meadow/meadow_139.jpg", "Meadow/meadow_157.jpg", "Meadow/meadow_182.jpg", "Meadow/meadow_81.jpg", "Meadow/meadow_140.jpg", "Meadow/meadow_35.jpg", "Meadow/meadow_262.jpg", "Meadow/meadow_237.jpg", "Meadow/meadow_236.jpg", "Meadow/meadow_232.jpg", "Meadow/meadow_165.jpg", "Meadow/meadow_16.jpg", "Meadow/meadow_205.jpg", "Meadow/meadow_36.jpg", "Meadow/meadow_215.jpg", "Meadow/meadow_222.jpg", "Meadow/meadow_169.jpg", "Meadow/meadow_19.jpg", "Meadow/meadow_128.jpg", "Meadow/meadow_93.jpg", "Meadow/meadow_91.jpg", "Meadow/meadow_210.jpg", "Meadow/meadow_151.jpg", "Meadow/meadow_134.jpg", "Meadow/meadow_163.jpg", "Meadow/meadow_199.jpg", "Meadow/meadow_43.jpg", "Meadow/meadow_270.jpg", "Meadow/meadow_247.jpg", "Meadow/meadow_121.jpg", "Meadow/meadow_255.jpg", "Meadow/meadow_190.jpg", "Meadow/meadow_53.jpg", "Meadow/meadow_59.jpg", "Meadow/meadow_176.jpg", "Meadow/meadow_20.jpg", "Meadow/meadow_278.jpg", "Meadow/meadow_5.jpg", "Meadow/meadow_238.jpg", "Meadow/meadow_242.jpg", "Meadow/meadow_233.jpg", "Meadow/meadow_84.jpg", "Meadow/meadow_7.jpg", "Meadow/meadow_265.jpg", "Meadow/meadow_155.jpg", "Meadow/meadow_103.jpg", "Meadow/meadow_3.jpg", "Meadow/meadow_85.jpg", "Meadow/meadow_246.jpg", "Meadow/meadow_92.jpg", "Meadow/meadow_101.jpg", "Meadow/meadow_209.jpg", "Meadow/meadow_178.jpg", "Meadow/meadow_276.jpg", "Meadow/meadow_259.jpg", "Meadow/meadow_72.jpg", "Meadow/meadow_188.jpg", "Meadow/meadow_171.jpg", "Meadow/meadow_227.jpg", "Meadow/meadow_225.jpg", "Meadow/meadow_257.jpg", "Meadow/meadow_125.jpg", "Meadow/meadow_243.jpg", "Meadow/meadow_37.jpg", "Meadow/meadow_221.jpg", "Meadow/meadow_74.jpg", "Meadow/meadow_70.jpg", "Meadow/meadow_94.jpg", "Meadow/meadow_47.jpg", "Meadow/meadow_218.jpg", "Meadow/meadow_241.jpg", "Meadow/meadow_112.jpg", "Meadow/meadow_187.jpg", "Meadow/meadow_75.jpg", "Meadow/meadow_105.jpg", "Meadow/meadow_185.jpg", "Meadow/meadow_149.jpg", "Meadow/meadow_133.jpg", "Meadow/meadow_195.jpg", "Meadow/meadow_173.jpg", "Meadow/meadow_181.jpg", "Meadow/meadow_108.jpg", "Meadow/meadow_96.jpg", "Meadow/meadow_267.jpg", "Meadow/meadow_32.jpg", "Meadow/meadow_192.jpg", "Meadow/meadow_111.jpg", "Meadow/meadow_119.jpg", "Meadow/meadow_14.jpg", "Meadow/meadow_211.jpg", "Meadow/meadow_106.jpg", "Meadow/meadow_164.jpg", "Meadow/meadow_154.jpg", "Meadow/meadow_21.jpg", "Meadow/meadow_8.jpg", "Meadow/meadow_162.jpg", "Meadow/meadow_116.jpg", "Meadow/meadow_167.jpg", "Parking/parking_157.jpg", "Parking/parking_102.jpg", "Parking/parking_208.jpg", "Parking/parking_363.jpg", "Parking/parking_247.jpg", "Parking/parking_87.jpg", "Parking/parking_117.jpg", "Parking/parking_331.jpg", "Parking/parking_138.jpg", "Parking/parking_254.jpg", "Parking/parking_97.jpg", "Parking/parking_160.jpg", "Parking/parking_34.jpg", "Parking/parking_218.jpg", "Parking/parking_231.jpg", "Parking/parking_347.jpg", "Parking/parking_111.jpg", "Parking/parking_42.jpg", "Parking/parking_271.jpg", "Parking/parking_265.jpg", "Parking/parking_320.jpg", "Parking/parking_80.jpg", "Parking/parking_244.jpg", "Parking/parking_301.jpg", "Parking/parking_294.jpg", "Parking/parking_371.jpg", "Parking/parking_52.jpg", "Parking/parking_326.jpg", "Parking/parking_194.jpg", "Parking/parking_7.jpg", "Parking/parking_240.jpg", "Parking/parking_24.jpg", "Parking/parking_84.jpg", "Parking/parking_233.jpg", "Parking/parking_330.jpg", "Parking/parking_107.jpg", "Parking/parking_119.jpg", "Parking/parking_381.jpg", "Parking/parking_337.jpg", "Parking/parking_193.jpg", "Parking/parking_161.jpg", "Parking/parking_289.jpg", "Parking/parking_346.jpg", "Parking/parking_369.jpg", "Parking/parking_63.jpg", "Parking/parking_269.jpg", "Parking/parking_176.jpg", "Parking/parking_321.jpg", "Parking/parking_306.jpg", "Parking/parking_217.jpg", "Parking/parking_221.jpg", "Parking/parking_127.jpg", "Parking/parking_298.jpg", "Parking/parking_61.jpg", "Parking/parking_251.jpg", "Parking/parking_262.jpg", "Parking/parking_48.jpg", "Parking/parking_59.jpg", "Parking/parking_304.jpg", "Parking/parking_162.jpg", "Parking/parking_224.jpg", "Parking/parking_222.jpg", "Parking/parking_33.jpg", "Parking/parking_203.jpg", "Parking/parking_357.jpg", "Parking/parking_358.jpg", "Parking/parking_368.jpg", "Parking/parking_54.jpg", "Parking/parking_323.jpg", "Parking/parking_237.jpg", "Parking/parking_315.jpg", "Parking/parking_17.jpg", "Parking/parking_1.jpg", "Parking/parking_153.jpg", "Parking/parking_329.jpg", "Parking/parking_280.jpg", "Parking/parking_252.jpg", "Parking/parking_114.jpg", "Parking/parking_266.jpg", "Parking/parking_180.jpg", "Parking/parking_378.jpg", "Parking/parking_113.jpg", "Parking/parking_390.jpg", "Parking/parking_14.jpg", "Parking/parking_334.jpg", "Parking/parking_386.jpg", "Parking/parking_292.jpg", "Parking/parking_19.jpg", "Parking/parking_379.jpg", "Parking/parking_72.jpg", "Parking/parking_69.jpg", "Parking/parking_121.jpg", "Parking/parking_198.jpg", "Parking/parking_101.jpg", "Parking/parking_295.jpg", "Parking/parking_58.jpg", "Parking/parking_279.jpg", "Parking/parking_277.jpg", "Parking/parking_204.jpg", "Parking/parking_341.jpg", "Parking/parking_303.jpg", "Parking/parking_335.jpg", "Parking/parking_359.jpg", "Parking/parking_125.jpg", "Parking/parking_118.jpg", "Parking/parking_336.jpg", "Parking/parking_109.jpg", "Parking/parking_229.jpg", "Parking/parking_322.jpg", "Parking/parking_249.jpg", "Parking/parking_318.jpg", "Parking/parking_106.jpg", "Parking/parking_189.jpg", "Parking/parking_228.jpg", "Parking/parking_328.jpg", "Parking/parking_186.jpg", "Parking/parking_345.jpg", "Parking/parking_255.jpg", "Parking/parking_150.jpg", "Parking/parking_15.jpg", "Parking/parking_313.jpg", "Parking/parking_70.jpg", "Parking/parking_389.jpg", "Parking/parking_12.jpg", "Parking/parking_85.jpg", "Parking/parking_51.jpg", "Parking/parking_317.jpg", "Parking/parking_165.jpg", "Parking/parking_45.jpg", "Parking/parking_22.jpg", "Parking/parking_4.jpg", "Parking/parking_152.jpg", "Parking/parking_88.jpg", "Parking/parking_91.jpg", "Parking/parking_126.jpg", "Parking/parking_50.jpg", "Parking/parking_171.jpg", "Parking/parking_211.jpg", "Parking/parking_65.jpg", "Parking/parking_168.jpg", "Parking/parking_339.jpg", "Parking/parking_256.jpg", "Parking/parking_263.jpg", "Parking/parking_232.jpg", "Parking/parking_130.jpg", "Parking/parking_202.jpg", "Parking/parking_302.jpg", "Parking/parking_116.jpg", "Parking/parking_319.jpg", "Parking/parking_164.jpg", "Parking/parking_296.jpg", "Parking/parking_166.jpg", "Parking/parking_62.jpg", "Parking/parking_140.jpg", "Parking/parking_76.jpg", "Parking/parking_375.jpg", "Parking/parking_374.jpg", "Parking/parking_344.jpg", "Parking/parking_136.jpg", "Parking/parking_338.jpg", "Parking/parking_8.jpg", "Parking/parking_355.jpg", "Parking/parking_201.jpg", "Parking/parking_230.jpg", "Parking/parking_154.jpg", "Parking/parking_56.jpg", "Parking/parking_185.jpg", "Parking/parking_282.jpg", "Parking/parking_272.jpg", "Parking/parking_312.jpg", "Parking/parking_75.jpg", "Parking/parking_365.jpg", "Parking/parking_170.jpg", "Parking/parking_305.jpg", "Parking/parking_370.jpg", "Parking/parking_105.jpg", "Parking/parking_367.jpg", "Parking/parking_219.jpg", "Parking/parking_36.jpg", "Parking/parking_169.jpg", "Parking/parking_324.jpg", "Parking/parking_241.jpg", "Parking/parking_131.jpg", "Parking/parking_26.jpg", "Parking/parking_273.jpg", "Parking/parking_100.jpg", "Parking/parking_86.jpg", "Parking/parking_184.jpg", "Parking/parking_120.jpg", "Parking/parking_275.jpg", "Parking/parking_181.jpg", "Parking/parking_376.jpg", "Parking/parking_352.jpg", "Parking/parking_286.jpg", "Parking/parking_172.jpg", "Parking/parking_112.jpg", "Parking/parking_234.jpg", "Parking/parking_96.jpg", "Parking/parking_239.jpg", "Parking/parking_123.jpg", "Parking/parking_115.jpg", "Parking/parking_245.jpg", "Parking/parking_356.jpg", "Parking/parking_214.jpg", "Parking/parking_40.jpg", "Parking/parking_20.jpg", "Parking/parking_253.jpg", "Parking/parking_21.jpg", "Parking/parking_209.jpg", "Parking/parking_353.jpg", "Parking/parking_2.jpg", "Parking/parking_236.jpg", "Parking/parking_155.jpg", "Parking/parking_372.jpg", "Parking/parking_134.jpg", "Parking/parking_311.jpg", "Parking/parking_37.jpg", "Parking/parking_373.jpg", "Parking/parking_205.jpg", "Parking/parking_43.jpg", "Parking/parking_257.jpg", "Parking/parking_89.jpg", "Parking/parking_124.jpg", "Parking/parking_175.jpg", "Parking/parking_92.jpg", "Parking/parking_53.jpg", "Parking/parking_284.jpg", "Parking/parking_287.jpg", "Parking/parking_291.jpg", "Parking/parking_278.jpg", "Parking/parking_173.jpg", "Parking/parking_297.jpg", "Parking/parking_325.jpg", "Parking/parking_6.jpg", "Parking/parking_73.jpg", "Parking/parking_95.jpg", "Parking/parking_187.jpg", "Parking/parking_307.jpg", "Parking/parking_11.jpg", "Parking/parking_235.jpg", "Parking/parking_77.jpg", "Parking/parking_178.jpg", "Parking/parking_270.jpg", "Parking/parking_18.jpg", "Parking/parking_49.jpg", "Parking/parking_67.jpg", "Parking/parking_99.jpg", "Parking/parking_250.jpg", "Parking/parking_3.jpg", "Parking/parking_276.jpg", "Parking/parking_195.jpg", "Parking/parking_385.jpg", "Parking/parking_342.jpg", "Parking/parking_143.jpg", "Parking/parking_310.jpg", "Parking/parking_361.jpg", "Parking/parking_300.jpg", "Parking/parking_13.jpg", "Parking/parking_227.jpg", "Parking/parking_64.jpg", "Parking/parking_191.jpg", "Parking/parking_281.jpg", "Parking/parking_29.jpg", "Parking/parking_216.jpg", "Parking/parking_183.jpg", "Parking/parking_10.jpg", "Parking/parking_243.jpg", "Parking/parking_182.jpg", "Parking/parking_215.jpg", "Parking/parking_383.jpg", "Parking/parking_9.jpg", "Parking/parking_103.jpg", "Parking/parking_149.jpg", "Parking/parking_177.jpg", "Parking/parking_148.jpg", "Parking/parking_206.jpg", "Parking/parking_110.jpg", "Parking/parking_147.jpg", "Parking/parking_79.jpg", "Parking/parking_81.jpg", "Parking/parking_192.jpg", "Parking/parking_159.jpg", "Parking/parking_174.jpg", "Parking/parking_74.jpg", "Parking/parking_210.jpg", "Parking/parking_141.jpg", "Parking/parking_366.jpg", "Parking/parking_82.jpg", "Parking/parking_200.jpg", "Parking/parking_128.jpg", "Parking/parking_108.jpg", "Parking/parking_98.jpg", "Parking/parking_259.jpg", "Parking/parking_349.jpg", "Parking/parking_288.jpg", "Parking/parking_293.jpg", "Parking/parking_27.jpg", "Parking/parking_188.jpg", "Parking/parking_207.jpg", "Parking/parking_90.jpg", "Parking/parking_274.jpg", "Parking/parking_139.jpg", "School/school_253.jpg", "School/school_152.jpg", "School/school_281.jpg", "School/school_208.jpg", "School/school_233.jpg", "School/school_236.jpg", "School/school_25.jpg", "School/school_211.jpg", "School/school_81.jpg", "School/school_184.jpg", "School/school_158.jpg", "School/school_161.jpg", "School/school_276.jpg", "School/school_261.jpg", "School/school_22.jpg", "School/school_247.jpg", "School/school_138.jpg", "School/school_218.jpg", "School/school_202.jpg", "School/school_21.jpg", "School/school_153.jpg", "School/school_133.jpg", "School/school_121.jpg", "School/school_150.jpg", "School/school_32.jpg", "School/school_35.jpg", "School/school_6.jpg", "School/school_33.jpg", "School/school_252.jpg", "School/school_227.jpg", "School/school_175.jpg", "School/school_9.jpg", "School/school_244.jpg", "School/school_251.jpg", "School/school_223.jpg", "School/school_39.jpg", "School/school_182.jpg", "School/school_171.jpg", "School/school_123.jpg", "School/school_40.jpg", "School/school_101.jpg", "School/school_189.jpg", "School/school_29.jpg", "School/school_86.jpg", "School/school_278.jpg", "School/school_242.jpg", "School/school_286.jpg", "School/school_178.jpg", "School/school_129.jpg", "School/school_34.jpg", "School/school_162.jpg", "School/school_277.jpg", "School/school_246.jpg", "School/school_72.jpg", "School/school_119.jpg", "School/school_8.jpg", "School/school_148.jpg", "School/school_13.jpg", "School/school_108.jpg", "School/school_290.jpg", "School/school_4.jpg", "School/school_90.jpg", "School/school_254.jpg", "School/school_170.jpg", "School/school_53.jpg", "School/school_298.jpg", "School/school_110.jpg", "School/school_265.jpg", "School/school_174.jpg", "School/school_297.jpg", "School/school_212.jpg", "School/school_191.jpg", "School/school_27.jpg", "School/school_54.jpg", "School/school_282.jpg", "School/school_258.jpg", "School/school_187.jpg", "School/school_167.jpg", "School/school_285.jpg", "School/school_3.jpg", "School/school_163.jpg", "School/school_74.jpg", "School/school_190.jpg", "School/school_96.jpg", "School/school_159.jpg", "School/school_275.jpg", "School/school_209.jpg", "School/school_48.jpg", "School/school_113.jpg", "School/school_23.jpg", "School/school_217.jpg", "School/school_67.jpg", "School/school_125.jpg", "School/school_157.jpg", "School/school_128.jpg", "School/school_168.jpg", "School/school_78.jpg", "School/school_147.jpg", "School/school_264.jpg", "School/school_98.jpg", "School/school_28.jpg", "School/school_231.jpg", "School/school_16.jpg", "School/school_44.jpg", "School/school_112.jpg", "School/school_160.jpg", "School/school_41.jpg", "School/school_228.jpg", "School/school_132.jpg", "School/school_266.jpg", "School/school_84.jpg", "School/school_294.jpg", "School/school_106.jpg", "School/school_139.jpg", "School/school_271.jpg", "School/school_284.jpg", "School/school_30.jpg", "School/school_71.jpg", "School/school_52.jpg", "School/school_26.jpg", "School/school_103.jpg", "School/school_154.jpg", "School/school_289.jpg", "School/school_2.jpg", "School/school_293.jpg", "School/school_183.jpg", "School/school_288.jpg", "School/school_292.jpg", "School/school_97.jpg", "School/school_181.jpg", "School/school_180.jpg", "School/school_239.jpg", "School/school_62.jpg", "School/school_238.jpg", "School/school_219.jpg", "School/school_60.jpg", "School/school_70.jpg", "School/school_179.jpg", "School/school_262.jpg", "School/school_82.jpg", "School/school_12.jpg", "School/school_197.jpg", "School/school_221.jpg", "School/school_259.jpg", "School/school_95.jpg", "School/school_73.jpg", "School/school_140.jpg", "School/school_230.jpg", "School/school_117.jpg", "School/school_20.jpg", "School/school_186.jpg", "School/school_85.jpg", "School/school_19.jpg", "School/school_88.jpg", "School/school_260.jpg", "School/school_166.jpg", "School/school_143.jpg", "School/school_255.jpg", "School/school_115.jpg", "School/school_109.jpg", "School/school_169.jpg", "School/school_65.jpg", "School/school_256.jpg", "School/school_5.jpg", "School/school_43.jpg", "School/school_177.jpg", "School/school_15.jpg", "School/school_222.jpg", "School/school_235.jpg", "School/school_120.jpg", "School/school_42.jpg", "School/school_135.jpg", "School/school_206.jpg", "School/school_199.jpg", "School/school_240.jpg", "School/school_145.jpg", "School/school_104.jpg", "School/school_126.jpg", "School/school_75.jpg", "School/school_58.jpg", "School/school_36.jpg", "School/school_198.jpg", "School/school_66.jpg", "School/school_185.jpg", "School/school_273.jpg", "School/school_37.jpg", "School/school_137.jpg", "School/school_100.jpg", "School/school_105.jpg", "School/school_224.jpg", "School/school_237.jpg", "School/school_176.jpg", "School/school_57.jpg", "School/school_91.jpg", "School/school_268.jpg", "School/school_64.jpg", "School/school_17.jpg", "School/school_215.jpg", "School/school_164.jpg", "School/school_207.jpg", "School/school_130.jpg", "School/school_229.jpg", "School/school_295.jpg", "School/school_156.jpg", "School/school_200.jpg", "School/school_267.jpg", "School/school_193.jpg", "School/school_77.jpg", "School/school_232.jpg", "School/school_141.jpg", "School/school_274.jpg", "School/school_213.jpg", "School/school_79.jpg", "School/school_144.jpg", "School/school_214.jpg", "School/school_50.jpg", "School/school_102.jpg", "School/school_49.jpg", "School/school_296.jpg", "School/school_279.jpg", "School/school_7.jpg", "School/school_76.jpg", "School/school_99.jpg", "School/school_14.jpg", "School/school_24.jpg", "School/school_142.jpg", "School/school_291.jpg", "School/school_234.jpg", "School/school_18.jpg", "School/school_94.jpg", "StorageTanks/storagetanks_2.jpg", "StorageTanks/storagetanks_129.jpg", "StorageTanks/storagetanks_175.jpg", "StorageTanks/storagetanks_238.jpg", "StorageTanks/storagetanks_266.jpg", "StorageTanks/storagetanks_264.jpg", "StorageTanks/storagetanks_199.jpg", "StorageTanks/storagetanks_121.jpg", "StorageTanks/storagetanks_334.jpg", "StorageTanks/storagetanks_296.jpg", "StorageTanks/storagetanks_346.jpg", "StorageTanks/storagetanks_10.jpg", "StorageTanks/storagetanks_297.jpg", "StorageTanks/storagetanks_63.jpg", "StorageTanks/storagetanks_349.jpg", "StorageTanks/storagetanks_299.jpg", "StorageTanks/storagetanks_180.jpg", "StorageTanks/storagetanks_269.jpg", "StorageTanks/storagetanks_214.jpg", "StorageTanks/storagetanks_106.jpg", "StorageTanks/storagetanks_143.jpg", "StorageTanks/storagetanks_104.jpg", "StorageTanks/storagetanks_324.jpg", "StorageTanks/storagetanks_302.jpg", "StorageTanks/storagetanks_277.jpg", "StorageTanks/storagetanks_71.jpg", "StorageTanks/storagetanks_274.jpg", "StorageTanks/storagetanks_279.jpg", "StorageTanks/storagetanks_312.jpg", "StorageTanks/storagetanks_212.jpg", "StorageTanks/storagetanks_137.jpg", "StorageTanks/storagetanks_8.jpg", "StorageTanks/storagetanks_12.jpg", "StorageTanks/storagetanks_115.jpg", "StorageTanks/storagetanks_232.jpg", "StorageTanks/storagetanks_183.jpg", "StorageTanks/storagetanks_93.jpg", "StorageTanks/storagetanks_85.jpg", "StorageTanks/storagetanks_82.jpg", "StorageTanks/storagetanks_147.jpg", "StorageTanks/storagetanks_188.jpg", "StorageTanks/storagetanks_243.jpg", "StorageTanks/storagetanks_30.jpg", "StorageTanks/storagetanks_347.jpg", "StorageTanks/storagetanks_314.jpg", "StorageTanks/storagetanks_356.jpg", "StorageTanks/storagetanks_131.jpg", "StorageTanks/storagetanks_42.jpg", "StorageTanks/storagetanks_210.jpg", "StorageTanks/storagetanks_333.jpg", "StorageTanks/storagetanks_326.jpg", "StorageTanks/storagetanks_136.jpg", "StorageTanks/storagetanks_278.jpg", "StorageTanks/storagetanks_215.jpg", "StorageTanks/storagetanks_228.jpg", "StorageTanks/storagetanks_31.jpg", "StorageTanks/storagetanks_68.jpg", "StorageTanks/storagetanks_117.jpg", "StorageTanks/storagetanks_196.jpg", "StorageTanks/storagetanks_300.jpg", "StorageTanks/storagetanks_345.jpg", "StorageTanks/storagetanks_258.jpg", "StorageTanks/storagetanks_40.jpg", "StorageTanks/storagetanks_78.jpg", "StorageTanks/storagetanks_306.jpg", "StorageTanks/storagetanks_275.jpg", "StorageTanks/storagetanks_186.jpg", "StorageTanks/storagetanks_285.jpg", "StorageTanks/storagetanks_139.jpg", "StorageTanks/storagetanks_154.jpg", "StorageTanks/storagetanks_255.jpg", "StorageTanks/storagetanks_251.jpg", "StorageTanks/storagetanks_27.jpg", "StorageTanks/storagetanks_148.jpg", "StorageTanks/storagetanks_98.jpg", "StorageTanks/storagetanks_53.jpg", "StorageTanks/storagetanks_48.jpg", "StorageTanks/storagetanks_130.jpg", "StorageTanks/storagetanks_216.jpg", "StorageTanks/storagetanks_103.jpg", "StorageTanks/storagetanks_25.jpg", "StorageTanks/storagetanks_293.jpg", "StorageTanks/storagetanks_91.jpg", "StorageTanks/storagetanks_99.jpg", "StorageTanks/storagetanks_335.jpg", "StorageTanks/storagetanks_145.jpg", "StorageTanks/storagetanks_37.jpg", "StorageTanks/storagetanks_283.jpg", "StorageTanks/storagetanks_123.jpg", "StorageTanks/storagetanks_55.jpg", "StorageTanks/storagetanks_163.jpg", "StorageTanks/storagetanks_241.jpg", "StorageTanks/storagetanks_261.jpg", "StorageTanks/storagetanks_268.jpg", "StorageTanks/storagetanks_280.jpg", "StorageTanks/storagetanks_342.jpg", "StorageTanks/storagetanks_72.jpg", "StorageTanks/storagetanks_70.jpg", "StorageTanks/storagetanks_239.jpg", "StorageTanks/storagetanks_144.jpg", "StorageTanks/storagetanks_26.jpg", "StorageTanks/storagetanks_110.jpg", "StorageTanks/storagetanks_134.jpg", "StorageTanks/storagetanks_273.jpg", "StorageTanks/storagetanks_86.jpg", "StorageTanks/storagetanks_5.jpg", "StorageTanks/storagetanks_164.jpg", "StorageTanks/storagetanks_242.jpg", "StorageTanks/storagetanks_168.jpg", "StorageTanks/storagetanks_120.jpg", "StorageTanks/storagetanks_185.jpg", "StorageTanks/storagetanks_174.jpg", "StorageTanks/storagetanks_177.jpg", "StorageTanks/storagetanks_79.jpg", "StorageTanks/storagetanks_253.jpg", "StorageTanks/storagetanks_184.jpg", "StorageTanks/storagetanks_50.jpg", "StorageTanks/storagetanks_358.jpg", "StorageTanks/storagetanks_15.jpg", "StorageTanks/storagetanks_52.jpg", "StorageTanks/storagetanks_124.jpg", "StorageTanks/storagetanks_221.jpg", "StorageTanks/storagetanks_65.jpg", "StorageTanks/storagetanks_66.jpg", "StorageTanks/storagetanks_213.jpg", "StorageTanks/storagetanks_357.jpg", "StorageTanks/storagetanks_286.jpg", "StorageTanks/storagetanks_219.jpg", "StorageTanks/storagetanks_33.jpg", "StorageTanks/storagetanks_205.jpg", "StorageTanks/storagetanks_292.jpg", "StorageTanks/storagetanks_39.jpg", "StorageTanks/storagetanks_142.jpg", "StorageTanks/storagetanks_331.jpg", "StorageTanks/storagetanks_325.jpg", "StorageTanks/storagetanks_167.jpg", "StorageTanks/storagetanks_155.jpg", "StorageTanks/storagetanks_126.jpg", "StorageTanks/storagetanks_51.jpg", "StorageTanks/storagetanks_250.jpg", "StorageTanks/storagetanks_4.jpg", "StorageTanks/storagetanks_13.jpg", "StorageTanks/storagetanks_208.jpg", "StorageTanks/storagetanks_182.jpg", "StorageTanks/storagetanks_128.jpg", "StorageTanks/storagetanks_204.jpg", "StorageTanks/storagetanks_207.jpg", "StorageTanks/storagetanks_29.jpg", "StorageTanks/storagetanks_192.jpg", "StorageTanks/storagetanks_75.jpg", "StorageTanks/storagetanks_327.jpg", "StorageTanks/storagetanks_7.jpg", "StorageTanks/storagetanks_267.jpg", "StorageTanks/storagetanks_156.jpg", "StorageTanks/storagetanks_247.jpg", "StorageTanks/storagetanks_310.jpg", "StorageTanks/storagetanks_341.jpg", "StorageTanks/storagetanks_101.jpg", "StorageTanks/storagetanks_102.jpg", "StorageTanks/storagetanks_240.jpg", "StorageTanks/storagetanks_263.jpg", "StorageTanks/storagetanks_291.jpg", "StorageTanks/storagetanks_47.jpg", "StorageTanks/storagetanks_227.jpg", "StorageTanks/storagetanks_322.jpg", "StorageTanks/storagetanks_56.jpg", "StorageTanks/storagetanks_271.jpg", "StorageTanks/storagetanks_105.jpg", "StorageTanks/storagetanks_127.jpg", "StorageTanks/storagetanks_201.jpg", "StorageTanks/storagetanks_35.jpg", "StorageTanks/storagetanks_16.jpg", "StorageTanks/storagetanks_100.jpg", "StorageTanks/storagetanks_262.jpg", "StorageTanks/storagetanks_77.jpg", "StorageTanks/storagetanks_323.jpg", "StorageTanks/storagetanks_114.jpg", "StorageTanks/storagetanks_233.jpg", "StorageTanks/storagetanks_315.jpg", "StorageTanks/storagetanks_80.jpg", "StorageTanks/storagetanks_132.jpg", "StorageTanks/storagetanks_46.jpg", "StorageTanks/storagetanks_23.jpg", "StorageTanks/storagetanks_260.jpg", "StorageTanks/storagetanks_84.jpg", "StorageTanks/storagetanks_229.jpg", "StorageTanks/storagetanks_190.jpg", "StorageTanks/storagetanks_290.jpg", "StorageTanks/storagetanks_352.jpg", "StorageTanks/storagetanks_197.jpg", "StorageTanks/storagetanks_359.jpg", "StorageTanks/storagetanks_360.jpg", "StorageTanks/storagetanks_161.jpg", "StorageTanks/storagetanks_211.jpg", "StorageTanks/storagetanks_353.jpg", "StorageTanks/storagetanks_294.jpg", "StorageTanks/storagetanks_135.jpg", "StorageTanks/storagetanks_330.jpg", "StorageTanks/storagetanks_218.jpg", "StorageTanks/storagetanks_152.jpg", "StorageTanks/storagetanks_62.jpg", "StorageTanks/storagetanks_316.jpg", "StorageTanks/storagetanks_328.jpg", "StorageTanks/storagetanks_74.jpg", "StorageTanks/storagetanks_76.jpg", "StorageTanks/storagetanks_321.jpg", "StorageTanks/storagetanks_224.jpg", "StorageTanks/storagetanks_138.jpg", "StorageTanks/storagetanks_244.jpg", "StorageTanks/storagetanks_230.jpg", "StorageTanks/storagetanks_111.jpg", "StorageTanks/storagetanks_284.jpg", "StorageTanks/storagetanks_119.jpg", "StorageTanks/storagetanks_140.jpg", "StorageTanks/storagetanks_9.jpg", "StorageTanks/storagetanks_166.jpg", "StorageTanks/storagetanks_67.jpg", "StorageTanks/storagetanks_169.jpg", "StorageTanks/storagetanks_231.jpg", "StorageTanks/storagetanks_237.jpg", "StorageTanks/storagetanks_319.jpg", "StorageTanks/storagetanks_22.jpg", "StorageTanks/storagetanks_344.jpg", "StorageTanks/storagetanks_88.jpg", "StorageTanks/storagetanks_305.jpg", "StorageTanks/storagetanks_252.jpg", "StorageTanks/storagetanks_60.jpg", "StorageTanks/storagetanks_298.jpg", "StorageTanks/storagetanks_248.jpg", "StorageTanks/storagetanks_236.jpg", "StorageTanks/storagetanks_288.jpg", "StorageTanks/storagetanks_223.jpg", "StorageTanks/storagetanks_194.jpg", "StorageTanks/storagetanks_200.jpg", "StorageTanks/storagetanks_171.jpg", "StorageTanks/storagetanks_97.jpg", "StorageTanks/storagetanks_94.jpg", "StorageTanks/storagetanks_337.jpg", "StorageTanks/storagetanks_20.jpg", "StorageTanks/storagetanks_18.jpg", "StorageTanks/storagetanks_109.jpg", "StorageTanks/storagetanks_176.jpg", "StorageTanks/storagetanks_61.jpg", "StorageTanks/storagetanks_301.jpg", "StorageTanks/storagetanks_308.jpg", "StorageTanks/storagetanks_149.jpg", "StorageTanks/storagetanks_162.jpg", "StorageTanks/storagetanks_38.jpg", "StorageTanks/storagetanks_21.jpg", "StorageTanks/storagetanks_170.jpg", "StorageTanks/storagetanks_313.jpg", "StorageTanks/storagetanks_57.jpg", "StorageTanks/storagetanks_217.jpg", "StorageTanks/storagetanks_95.jpg", "StorageTanks/storagetanks_257.jpg", "StorageTanks/storagetanks_332.jpg", "StorageTanks/storagetanks_45.jpg", "StorageTanks/storagetanks_343.jpg", "StorageTanks/storagetanks_287.jpg", "StorageTanks/storagetanks_118.jpg", "StorageTanks/storagetanks_141.jpg", "StorageTanks/storagetanks_339.jpg", "StorageTanks/storagetanks_311.jpg", "StorageTanks/storagetanks_256.jpg", "StorageTanks/storagetanks_151.jpg", "StorageTanks/storagetanks_113.jpg", "StorageTanks/storagetanks_281.jpg", "StorageTanks/storagetanks_181.jpg", "StorageTanks/storagetanks_19.jpg", "StorageTanks/storagetanks_89.jpg", "StorageTanks/storagetanks_203.jpg", "StorageTanks/storagetanks_202.jpg", "StorageTanks/storagetanks_318.jpg", "StorageTanks/storagetanks_165.jpg", "StorageTanks/storagetanks_49.jpg", "StorageTanks/storagetanks_198.jpg", "StorageTanks/storagetanks_150.jpg", "StorageTanks/storagetanks_153.jpg"], "val": ["Pond/pond_366.jpg", "Pond/pond_125.jpg", "Pond/pond_61.jpg", "Pond/pond_364.jpg", "Pond/pond_34.jpg", "Pond/pond_90.jpg", "Pond/pond_104.jpg", "Pond/pond_56.jpg", "Pond/pond_124.jpg", "Pond/pond_220.jpg", "Forest/forest_163.jpg", "Forest/forest_161.jpg", "Forest/forest_67.jpg", "Forest/forest_42.jpg", "Forest/forest_191.jpg", "Forest/forest_87.jpg", "Forest/forest_17.jpg", "Forest/forest_61.jpg", "Forest/forest_69.jpg", "Forest/forest_234.jpg", "River/river_390.jpg", "River/river_384.jpg", "River/river_280.jpg", "River/river_17.jpg", "River/river_144.jpg", "River/river_179.jpg", "River/river_175.jpg", "River/river_298.jpg", "River/river_122.jpg", "River/river_385.jpg", "Resort/resort_203.jpg", "Resort/resort_84.jpg", "Resort/resort_10.jpg", "Resort/resort_228.jpg", "Resort/resort_212.jpg", "Resort/resort_135.jpg", "Resort/resort_50.jpg", "Resort/resort_171.jpg", "Resort/resort_108.jpg", "Resort/resort_245.jpg", "Playground/playground_214.jpg", "Playground/playground_274.jpg", "Playground/playground_343.jpg", "Playground/playground_270.jpg", "Playground/playground_129.jpg", "Playground/playground_2.jpg", "Playground/playground_194.jpg", "Playground/playground_47.jpg", "Playground/playground_340.jpg", "Playground/playground_160.jpg", "Bridge/bridge_258.jpg", "Bridge/bridge_262.jpg", "Bridge/bridge_18.jpg", "Bridge/bridge_228.jpg", "Bridge/bridge_241.jpg", "Bridge/bridge_199.jpg", "Bridge/bridge_309.jpg", "Bridge/bridge_156.jpg", "Bridge/bridge_86.jpg", "Bridge/bridge_134.jpg", "Park/park_95.jpg", "Park/park_67.jpg", "Park/park_86.jpg", "Park/park_333.jpg", "Park/park_204.jpg", "Park/park_55.jpg", "Park/park_280.jpg", "Park/park_116.jpg", "Park/park_328.jpg", "Park/park_93.jpg", "Center/center_99.jpg", "Center/center_239.jpg", "Center/center_214.jpg", "Center/center_220.jpg", "Center/center_91.jpg", "Center/center_98.jpg", "Center/center_244.jpg", "Center/center_90.jpg", "Center/center_86.jpg", "Center/center_1.jpg", "Square/square_22.jpg", "Square/square_130.jpg", "Square/square_134.jpg", "Square/square_217.jpg", "Square/square_25.jpg", "Square/square_14.jpg", "Square/square_247.jpg", "Square/square_289.jpg", "Square/square_87.jpg", "Square/square_240.jpg", "BaseballField/baseballfield_93.jpg", "BaseballField/baseballfield_210.jpg", "BaseballField/baseballfield_163.jpg", "BaseballField/baseballfield_62.jpg", "BaseballField/baseballfield_162.jpg", "BaseballField/baseballfield_132.jpg", "BaseballField/baseballfield_215.jpg", "BaseballField/baseballfield_112.jpg", "BaseballField/baseballfield_4.jpg", "BaseballField/baseballfield_192.jpg", "Church/church_120.jpg", "Church/church_24.jpg", "Church/church_182.jpg", "Church/church_225.jpg", "Church/church_184.jpg", "Church/church_23.jpg", "Church/church_198.jpg", "Church/church_20.jpg", "Church/church_216.jpg", "Church/church_159.jpg", "Farmland/farmland_161.jpg", "Farmland/farmland_179.jpg", "Farmland/farmland_8.jpg", "Farmland/farmland_140.jpg", "Farmland/farmland_118.jpg", "Farmland/farmland_237.jpg", "Farmland/farmland_178.jpg", "Farmland/farmland_17.jpg", "Farmland/farmland_253.jpg", "Farmland/farmland_352.jpg", "Stadium/stadium_69.jpg", "Stadium/stadium_131.jpg", "Stadium/stadium_213.jpg", "Stadium/stadium_162.jpg", "Stadium/stadium_114.jpg", "Stadium/stadium_2.jpg", "Stadium/stadium_278.jpg", "Stadium/stadium_286.jpg", "Stadium/stadium_51.jpg", "Stadium/stadium_105.jpg", "Viaduct/viaduct_211.jpg", "Viaduct/viaduct_285.jpg", "Viaduct/viaduct_243.jpg", "Viaduct/viaduct_367.jpg", "Viaduct/viaduct_411.jpg", "Viaduct/viaduct_69.jpg", "Viaduct/viaduct_264.jpg", "Viaduct/viaduct_307.jpg", "Viaduct/viaduct_126.jpg", "Viaduct/viaduct_137.jpg", "Commercial/commercial_136.jpg", "Commercial/commercial_339.jpg", "Commercial/commercial_89.jpg", "Commercial/commercial_167.jpg", "Commercial/commercial_223.jpg", "Commercial/commercial_168.jpg", "Commercial/commercial_117.jpg", "Commercial/commercial_176.jpg", "Commercial/commercial_27.jpg", "Commercial/commercial_315.jpg", "Industrial/industrial_20.jpg", "Industrial/industrial_210.jpg", "Industrial/industrial_197.jpg", "Industrial/industrial_246.jpg", "Industrial/industrial_321.jpg", "Industrial/industrial_125.jpg", "Industrial/industrial_349.jpg", "Industrial/industrial_173.jpg", "Industrial/industrial_262.jpg", "Industrial/industrial_35.jpg", "Airport/airport_35.jpg", "Airport/airport_39.jpg", "Airport/airport_320.jpg", "Airport/airport_22.jpg", "Airport/airport_294.jpg", "Airport/airport_356.jpg", "Airport/airport_230.jpg", "Airport/airport_53.jpg", "Airport/airport_139.jpg", "Airport/airport_114.jpg", "SparseResidential/sparseresidential_43.jpg", "SparseResidential/sparseresidential_230.jpg", "SparseResidential/sparseresidential_9.jpg", "SparseResidential/sparseresidential_116.jpg", "SparseResidential/sparseresidential_82.jpg", "SparseResidential/sparseresidential_207.jpg", "SparseResidential/sparseresidential_245.jpg", "SparseResidential/sparseresidential_208.jpg", "SparseResidential/sparseresidential_202.jpg", "SparseResidential/sparseresidential_138.jpg", "MediumResidential/mediumresidential_105.jpg", "MediumResidential/mediumresidential_215.jpg", "MediumResidential/mediumresidential_255.jpg", "MediumResidential/mediumresidential_208.jpg", "MediumResidential/mediumresidential_175.jpg", "MediumResidential/mediumresidential_192.jpg", "MediumResidential/mediumresidential_35.jpg", "MediumResidential/mediumresidential_237.jpg", "MediumResidential/mediumresidential_51.jpg", "MediumResidential/mediumresidential_163.jpg", "DenseResidential/denseresidential_162.jpg", "DenseResidential/denseresidential_90.jpg", "DenseResidential/denseresidential_54.jpg", "DenseResidential/denseresidential_44.jpg", "DenseResidential/denseresidential_223.jpg", "DenseResidential/denseresidential_214.jpg", "DenseResidential/denseresidential_389.jpg", "DenseResidential/denseresidential_268.jpg", "DenseResidential/denseresidential_111.jpg", "DenseResidential/denseresidential_286.jpg", "RailwayStation/railwaystation_243.jpg", "RailwayStation/railwaystation_61.jpg", "RailwayStation/railwaystation_210.jpg", "RailwayStation/railwaystation_252.jpg", "RailwayStation/railwaystation_6.jpg", "RailwayStation/railwaystation_220.jpg", "RailwayStation/railwaystation_98.jpg", "RailwayStation/railwaystation_15.jpg", "RailwayStation/railwaystation_260.jpg", "RailwayStation/railwaystation_164.jpg", "BareLand/bareland_298.jpg", "BareLand/bareland_168.jpg", "BareLand/bareland_241.jpg", "BareLand/bareland_154.jpg", "BareLand/bareland_161.jpg", "BareLand/bareland_282.jpg", "BareLand/bareland_78.jpg", "BareLand/bareland_26.jpg", "BareLand/bareland_236.jpg", "BareLand/bareland_167.jpg", "Beach/beach_62.jpg", "Beach/beach_225.jpg", "Beach/beach_310.jpg", "Beach/beach_309.jpg", "Beach/beach_111.jpg", "Beach/beach_31.jpg", "Beach/beach_293.jpg", "Beach/beach_257.jpg", "Beach/beach_6.jpg", "Beach/beach_122.jpg", "Port/port_308.jpg", "Port/port_4.jpg", "Port/port_288.jpg", "Port/port_158.jpg", "Port/port_105.jpg", "Port/port_347.jpg", "Port/port_14.jpg", "Port/port_291.jpg", "Port/port_173.jpg", "Port/port_140.jpg", "Mountain/mountain_7.jpg", "Mountain/mountain_18.jpg", "Mountain/mountain_37.jpg", "Mountain/mountain_34.jpg", "Mountain/mountain_36.jpg", "Mountain/mountain_145.jpg", "Mountain/mountain_288.jpg", "Mountain/mountain_167.jpg", "Mountain/mountain_65.jpg", "Mountain/mountain_286.jpg", "Desert/desert_139.jpg", "Desert/desert_26.jpg", "Desert/desert_225.jpg", "Desert/desert_256.jpg", "Desert/desert_227.jpg", "Desert/desert_103.jpg", "Desert/desert_284.jpg", "Desert/desert_23.jpg", "Desert/desert_243.jpg", "Desert/desert_102.jpg", "Meadow/meadow_273.jpg", "Meadow/meadow_148.jpg", "Meadow/meadow_76.jpg", "Meadow/meadow_26.jpg", "Meadow/meadow_216.jpg", "Meadow/meadow_261.jpg", "Meadow/meadow_104.jpg", "Meadow/meadow_113.jpg", "Meadow/meadow_234.jpg", "Meadow/meadow_66.jpg", "Parking/parking_388.jpg", "Parking/parking_197.jpg", "Parking/parking_333.jpg", "Parking/parking_343.jpg", "Parking/parking_163.jpg", "Parking/parking_264.jpg", "Parking/parking_35.jpg", "Parking/parking_380.jpg", "Parking/parking_146.jpg", "Parking/parking_31.jpg", "School/school_45.jpg", "School/school_155.jpg", "School/school_280.jpg", "School/school_172.jpg", "School/school_10.jpg", "School/school_122.jpg", "School/school_146.jpg", "School/school_204.jpg", "School/school_68.jpg", "School/school_46.jpg", "StorageTanks/storagetanks_191.jpg", "StorageTanks/storagetanks_59.jpg", "StorageTanks/storagetanks_340.jpg", "StorageTanks/storagetanks_24.jpg", "StorageTanks/storagetanks_348.jpg", "StorageTanks/storagetanks_87.jpg", "StorageTanks/storagetanks_272.jpg", "StorageTanks/storagetanks_189.jpg", "StorageTanks/storagetanks_270.jpg", "StorageTanks/storagetanks_112.jpg"], "test": ["Pond/pond_126.jpg", "Pond/pond_99.jpg", "Pond/pond_66.jpg", "Pond/pond_405.jpg", "Pond/pond_4.jpg", "Pond/pond_332.jpg", "Pond/pond_355.jpg", "Pond/pond_360.jpg", "Pond/pond_120.jpg", "Pond/pond_270.jpg", "Pond/pond_119.jpg", "Pond/pond_335.jpg", "Pond/pond_274.jpg", "Pond/pond_322.jpg", "Pond/pond_369.jpg", "Pond/pond_201.jpg", "Pond/pond_28.jpg", "Pond/pond_406.jpg", "Pond/pond_180.jpg", "Pond/pond_26.jpg", "Pond/pond_325.jpg", "Pond/pond_257.jpg", "Pond/pond_323.jpg", "Pond/pond_141.jpg", "Pond/pond_82.jpg", "Pond/pond_376.jpg", "Pond/pond_373.jpg", "Pond/pond_175.jpg", "Pond/pond_219.jpg", "Pond/pond_379.jpg", "Pond/pond_186.jpg", "Pond/pond_51.jpg", "Pond/pond_263.jpg", "Pond/pond_209.jpg", "Pond/pond_103.jpg", "Pond/pond_327.jpg", "Pond/pond_413.jpg", "Pond/pond_404.jpg", "Pond/pond_154.jpg", "Pond/pond_271.jpg", "Pond/pond_291.jpg", "Pond/pond_81.jpg", "Pond/pond_374.jpg", "Pond/pond_135.jpg", "Pond/pond_375.jpg", "Pond/pond_344.jpg", "Pond/pond_199.jpg", "Pond/pond_80.jpg", "Pond/pond_388.jpg", "Pond/pond_88.jpg", "Pond/pond_3.jpg", "Pond/pond_312.jpg", "Pond/pond_400.jpg", "Pond/pond_411.jpg", "Pond/pond_239.jpg", "Pond/pond_276.jpg", "Pond/pond_13.jpg", "Pond/pond_338.jpg", "Pond/pond_96.jpg", "Pond/pond_224.jpg", "Pond/pond_342.jpg", "Pond/pond_147.jpg", "Pond/pond_144.jpg", "Pond/pond_288.jpg", "Pond/pond_171.jpg", "Pond/pond_295.jpg", "Pond/pond_160.jpg", "Pond/pond_100.jpg", "Pond/pond_177.jpg", "Pond/pond_68.jpg", "Pond/pond_197.jpg", "Pond/pond_136.jpg", "Pond/pond_22.jpg", "Pond/pond_279.jpg", "Pond/pond_352.jpg", "Pond/pond_235.jpg", "Pond/pond_148.jpg", "Pond/pond_151.jpg", "Pond/pond_164.jpg", "Pond/pond_194.jpg", "Pond/pond_299.jpg", "Pond/pond_200.jpg", "Pond/pond_251.jpg", "Pond/pond_227.jpg", "Forest/forest_149.jpg", "Forest/forest_11.jpg", "Forest/forest_49.jpg", "Forest/forest_63.jpg", "Forest/forest_21.jpg", "Forest/forest_101.jpg", "Forest/forest_38.jpg", "Forest/forest_40.jpg", "Forest/forest_165.jpg", "Forest/forest_53.jpg", "Forest/forest_104.jpg", "Forest/forest_83.jpg", "Forest/forest_233.jpg", "Forest/forest_141.jpg", "Forest/forest_227.jpg", "Forest/forest_39.jpg", "Forest/forest_15.jpg", "Forest/forest_120.jpg", "Forest/forest_174.jpg", "Forest/forest_4.jpg", "Forest/forest_240.jpg", "Forest/forest_185.jpg", "Forest/forest_99.jpg", "Forest/forest_247.jpg", "Forest/forest_167.jpg", "Forest/forest_59.jpg", "Forest/forest_201.jpg", "Forest/forest_237.jpg", "Forest/forest_192.jpg", "Forest/forest_194.jpg", "Forest/forest_213.jpg", "Forest/forest_47.jpg", "Forest/forest_212.jpg", "Forest/forest_181.jpg", "Forest/forest_92.jpg", "Forest/forest_102.jpg", "Forest/forest_145.jpg", "Forest/forest_239.jpg", "Forest/forest_221.jpg", "Forest/forest_226.jpg", "Forest/forest_236.jpg", "Forest/forest_134.jpg", "Forest/forest_225.jpg", "Forest/forest_250.jpg", "Forest/forest_197.jpg", "Forest/forest_18.jpg", "Forest/forest_220.jpg", "Forest/forest_231.jpg", "Forest/forest_71.jpg", "Forest/forest_109.jpg", "River/river_254.jpg", "River/river_263.jpg", "River/river_281.jpg", "River/river_331.jpg", "River/river_95.jpg", "River/river_68.jpg", "River/river_211.jpg", "River/river_38.jpg", "River/river_305.jpg", "River/river_153.jpg", "River/river_293.jpg", "River/river_338.jpg", "River/river_296.jpg", "River/river_336.jpg", "River/river_351.jpg", "River/river_19.jpg", "River/river_3.jpg", "River/river_272.jpg", "River/river_41.jpg", "River/river_242.jpg", "River/river_396.jpg", "River/river_195.jpg", "River/river_72.jpg", "River/river_193.jpg", "River/river_387.jpg", "River/river_74.jpg", "River/river_31.jpg", "River/river_361.jpg", "River/river_225.jpg", "River/river_73.jpg", "River/river_49.jpg", "River/river_326.jpg", "River/river_52.jpg", "River/river_233.jpg", "River/river_340.jpg", "River/river_25.jpg", "River/river_383.jpg", "River/river_67.jpg", "River/river_127.jpg", "River/river_278.jpg", "River/river_275.jpg", "River/river_286.jpg", "River/river_90.jpg", "River/river_327.jpg", "River/river_291.jpg", "River/river_371.jpg", "River/river_404.jpg", "River/river_165.jpg", "River/river_181.jpg", "River/river_230.jpg", "River/river_268.jpg", "River/river_366.jpg", "River/river_70.jpg", "River/river_348.jpg", "River/river_308.jpg", "River/river_350.jpg", "River/river_221.jpg", "River/river_59.jpg", "River/river_133.jpg", "River/river_60.jpg", "River/river_44.jpg", "River/river_64.jpg", "River/river_203.jpg", "River/river_325.jpg", "River/river_295.jpg", "River/river_243.jpg", "River/river_98.jpg", "River/river_300.jpg", "River/river_261.jpg", "River/river_53.jpg", "River/river_80.jpg", "River/river_407.jpg", "River/river_121.jpg", "River/river_328.jpg", "River/river_216.jpg", "River/river_302.jpg", "River/river_63.jpg", "River/river_12.jpg", "River/river_257.jpg", "River/river_284.jpg", "River/river_147.jpg", "River/river_51.jpg", "Resort/resort_86.jpg", "Resort/resort_136.jpg", "Resort/resort_124.jpg", "Resort/resort_278.jpg", "Resort/resort_200.jpg", "Resort/resort_97.jpg", "Resort/resort_161.jpg", "Resort/resort_257.jpg", "Resort/resort_26.jpg", "Resort/resort_134.jpg", "Resort/resort_178.jpg", "Resort/resort_240.jpg", "Resort/resort_76.jpg", "Resort/resort_44.jpg", "Resort/resort_188.jpg", "Resort/resort_72.jpg", "Resort/resort_184.jpg", "Resort/resort_154.jpg", "Resort/resort_9.jpg", "Resort/resort_167.jpg", "Resort/resort_102.jpg", "Resort/resort_118.jpg", "Resort/resort_232.jpg", "Resort/resort_127.jpg", "Resort/resort_281.jpg", "Resort/resort_6.jpg", "Resort/resort_40.jpg", "Resort/resort_122.jpg", "Resort/resort_275.jpg", "Resort/resort_284.jpg", "Resort/resort_158.jpg", "Resort/resort_131.jpg", "Resort/resort_206.jpg", "Resort/resort_279.jpg", "Resort/resort_290.jpg", "Resort/resort_87.jpg", "Resort/resort_121.jpg", "Resort/resort_28.jpg", "Resort/resort_31.jpg", "Resort/resort_78.jpg", "Resort/resort_151.jpg", "Resort/resort_246.jpg", "Resort/resort_195.jpg", "Resort/resort_137.jpg", "Resort/resort_123.jpg", "Resort/resort_235.jpg", "Resort/resort_112.jpg", "Resort/resort_62.jpg", "Resort/resort_168.jpg", "Resort/resort_2.jpg", "Resort/resort_146.jpg", "Resort/resort_288.jpg", "Resort/resort_162.jpg", "Resort/resort_185.jpg", "Resort/resort_237.jpg", "Resort/resort_224.jpg", "Resort/resort_176.jpg", "Resort/resort_125.jpg", "Playground/playground_311.jpg", "Playground/playground_238.jpg", "Playground/playground_169.jpg", "Playground/playground_26.jpg", "Playground/playground_353.jpg", "Playground/playground_104.jpg", "Playground/playground_370.jpg", "Playground/playground_90.jpg", "Playground/playground_122.jpg", "Playground/playground_181.jpg", "Playground/playground_197.jpg", "Playground/playground_14.jpg", "Playground/playground_121.jpg", "Playground/playground_273.jpg", "Playground/playground_103.jpg", "Playground/playground_218.jpg", "Playground/playground_308.jpg", "Playground/playground_285.jpg", "Playground/playground_320.jpg", "Playground/playground_303.jpg", "Playground/playground_166.jpg", "Playground/playground_257.jpg", "Playground/playground_221.jpg", "Playground/playground_96.jpg", "Playground/playground_227.jpg", "Playground/playground_154.jpg", "Playground/playground_253.jpg", "Playground/playground_363.jpg", "Playground/playground_50.jpg", "Playground/playground_360.jpg", "Playground/playground_1.jpg", "Playground/playground_331.jpg", "Playground/playground_235.jpg", "Playground/playground_62.jpg", "Playground/playground_35.jpg", "Playground/playground_163.jpg", "Playground/playground_88.jpg", "Playground/playground_317.jpg", "Playground/playground_239.jpg", "Playground/playground_126.jpg", "Playground/playground_299.jpg", "Playground/playground_282.jpg", "Playground/playground_204.jpg", "Playground/playground_184.jpg", "Playground/playground_119.jpg", "Playground/playground_196.jpg", "Playground/playground_262.jpg", "Playground/playground_155.jpg", "Playground/playground_21.jpg", "Playground/playground_321.jpg", "Playground/playground_143.jpg", "Playground/playground_183.jpg", "Playground/playground_107.jpg", "Playground/playground_177.jpg", "Playground/playground_284.jpg", "Playground/playground_82.jpg", "Playground/playground_179.jpg", "Playground/playground_326.jpg", "Playground/playground_309.jpg", "Playground/playground_85.jpg", "Playground/playground_140.jpg", "Playground/playground_296.jpg", "Playground/playground_128.jpg", "Playground/playground_192.jpg", "Playground/playground_193.jpg", "Playground/playground_81.jpg", "Playground/playground_216.jpg", "Playground/playground_159.jpg", "Playground/playground_108.jpg", "Playground/playground_187.jpg", "Playground/playground_132.jpg", "Playground/playground_73.jpg", "Playground/playground_142.jpg", "Playground/playground_265.jpg", "Bridge/bridge_147.jpg", "Bridge/bridge_111.jpg", "Bridge/bridge_304.jpg", "Bridge/bridge_295.jpg", "Bridge/bridge_358.jpg", "Bridge/bridge_167.jpg", "Bridge/bridge_275.jpg", "Bridge/bridge_154.jpg", "Bridge/bridge_280.jpg", "Bridge/bridge_146.jpg", "Bridge/bridge_68.jpg", "Bridge/bridge_29.jpg", "Bridge/bridge_55.jpg", "Bridge/bridge_229.jpg", "Bridge/bridge_357.jpg", "Bridge/bridge_6.jpg", "Bridge/bridge_169.jpg", "Bridge/bridge_27.jpg", "Bridge/bridge_223.jpg", "Bridge/bridge_346.jpg", "Bridge/bridge_155.jpg", "Bridge/bridge_248.jpg", "Bridge/bridge_319.jpg", "Bridge/bridge_91.jpg", "Bridge/bridge_230.jpg", "Bridge/bridge_272.jpg", "Bridge/bridge_28.jpg", "Bridge/bridge_177.jpg", "Bridge/bridge_69.jpg", "Bridge/bridge_58.jpg", "Bridge/bridge_347.jpg", "Bridge/bridge_324.jpg", "Bridge/bridge_250.jpg", "Bridge/bridge_208.jpg", "Bridge/bridge_201.jpg", "Bridge/bridge_19.jpg", "Bridge/bridge_329.jpg", "Bridge/bridge_259.jpg", "Bridge/bridge_53.jpg", "Bridge/bridge_66.jpg", "Bridge/bridge_278.jpg", "Bridge/bridge_337.jpg", "Bridge/bridge_108.jpg", "Bridge/bridge_213.jpg", "Bridge/bridge_274.jpg", "Bridge/bridge_107.jpg", "Bridge/bridge_269.jpg", "Bridge/bridge_80.jpg", "Bridge/bridge_98.jpg", "Bridge/bridge_174.jpg", "Bridge/bridge_287.jpg", "Bridge/bridge_164.jpg", "Bridge/bridge_245.jpg", "Bridge/bridge_273.jpg", "Bridge/bridge_180.jpg", "Bridge/bridge_312.jpg", "Bridge/bridge_65.jpg", "Bridge/bridge_89.jpg", "Bridge/bridge_149.jpg", "Bridge/bridge_221.jpg", "Bridge/bridge_51.jpg", "Bridge/bridge_233.jpg", "Bridge/bridge_76.jpg", "Bridge/bridge_34.jpg", "Bridge/bridge_41.jpg", "Bridge/bridge_235.jpg", "Bridge/bridge_253.jpg", "Bridge/bridge_353.jpg", "Bridge/bridge_4.jpg", "Bridge/bridge_196.jpg", "Bridge/bridge_17.jpg", "Bridge/bridge_202.jpg", "Park/park_255.jpg", "Park/park_24.jpg", "Park/park_61.jpg", "Park/park_182.jpg", "Park/park_121.jpg", "Park/park_310.jpg", "Park/park_26.jpg", "Park/park_23.jpg", "Park/park_114.jpg", "Park/park_272.jpg", "Park/park_31.jpg", "Park/park_5.jpg", "Park/park_297.jpg", "Park/park_47.jpg", "Park/park_265.jpg", "Park/park_256.jpg", "Park/park_206.jpg", "Park/park_78.jpg", "Park/park_66.jpg", "Park/park_305.jpg", "Park/park_153.jpg", "Park/park_141.jpg", "Park/park_292.jpg", "Park/park_217.jpg", "Park/park_169.jpg", "Park/park_73.jpg", "Park/park_338.jpg", "Park/park_327.jpg", "Park/park_213.jpg", "Park/park_42.jpg", "Park/park_96.jpg", "Park/park_194.jpg", "Park/park_250.jpg", "Park/park_325.jpg", "Park/park_115.jpg", "Park/park_45.jpg", "Park/park_259.jpg", "Park/park_148.jpg", "Park/park_150.jpg", "Park/park_136.jpg", "Park/park_215.jpg", "Park/park_30.jpg", "Park/park_228.jpg", "Park/park_246.jpg", "Park/park_92.jpg", "Park/park_224.jpg", "Park/park_339.jpg", "Park/park_83.jpg", "Park/park_108.jpg", "Park/park_25.jpg", "Park/park_39.jpg", "Park/park_266.jpg", "Park/park_203.jpg", "Park/park_321.jpg", "Park/park_110.jpg", "Park/park_274.jpg", "Park/park_270.jpg", "Park/park_319.jpg", "Park/park_227.jpg", "Park/park_145.jpg", "Park/park_51.jpg", "Park/park_258.jpg", "Park/park_157.jpg", "Park/park_12.jpg", "Park/park_13.jpg", "Park/park_301.jpg", "Park/park_210.jpg", "Park/park_33.jpg", "Park/park_167.jpg", "Park/park_140.jpg", "Center/center_79.jpg", "Center/center_44.jpg", "Center/center_224.jpg", "Center/center_20.jpg", "Center/center_165.jpg", "Center/center_197.jpg", "Center/center_45.jpg", "Center/center_73.jpg", "Center/center_16.jpg", "Center/center_24.jpg", "Center/center_58.jpg", "Center/center_215.jpg", "Center/center_100.jpg", "Center/center_77.jpg", "Center/center_160.jpg", "Center/center_260.jpg", "Center/center_179.jpg", "Center/center_93.jpg", "Center/center_84.jpg", "Center/center_137.jpg", "Center/center_206.jpg", "Center/center_49.jpg", "Center/center_78.jpg", "Center/center_249.jpg", "Center/center_213.jpg", "Center/center_196.jpg", "Center/center_181.jpg", "Center/center_43.jpg", "Center/center_255.jpg", "Center/center_108.jpg", "Center/center_218.jpg", "Center/center_235.jpg", "Center/center_134.jpg", "Center/center_231.jpg", "Center/center_246.jpg", "Center/center_80.jpg", "Center/center_115.jpg", "Center/center_150.jpg", "Center/center_254.jpg", "Center/center_105.jpg", "Center/center_139.jpg", "Center/center_141.jpg", "Center/center_226.jpg", "Center/center_15.jpg", "Center/center_222.jpg", "Center/center_46.jpg", "Center/center_95.jpg", "Center/center_258.jpg", "Center/center_13.jpg", "Center/center_107.jpg", "Center/center_102.jpg", "Center/center_69.jpg", "Square/square_59.jpg", "Square/square_221.jpg", "Square/square_118.jpg", "Square/square_320.jpg", "Square/square_116.jpg", "Square/square_1.jpg", "Square/square_115.jpg", "Square/square_260.jpg", "Square/square_68.jpg", "Square/square_187.jpg", "Square/square_170.jpg", "Square/square_92.jpg", "Square/square_173.jpg", "Square/square_282.jpg", "Square/square_195.jpg", "Square/square_226.jpg", "Square/square_263.jpg", "Square/square_10.jpg", "Square/square_61.jpg", "Square/square_305.jpg", "Square/square_243.jpg", "Square/square_72.jpg", "Square/square_313.jpg", "Square/square_121.jpg", "Square/square_211.jpg", "Square/square_302.jpg", "Square/square_5.jpg", "Square/square_100.jpg", "Square/square_146.jpg", "Square/square_107.jpg", "Square/square_126.jpg", "Square/square_20.jpg", "Square/square_234.jpg", "Square/square_325.jpg", "Square/square_39.jpg", "Square/square_83.jpg", "Square/square_34.jpg", "Square/square_241.jpg", "Square/square_326.jpg", "Square/square_179.jpg", "Square/square_244.jpg", "Square/square_36.jpg", "Square/square_283.jpg", "Square/square_330.jpg", "Square/square_123.jpg", "Square/square_298.jpg", "Square/square_64.jpg", "Square/square_258.jpg", "Square/square_319.jpg", "Square/square_109.jpg", "Square/square_216.jpg", "Square/square_108.jpg", "Square/square_67.jpg", "Square/square_45.jpg", "Square/square_101.jpg", "Square/square_98.jpg", "Square/square_158.jpg", "Square/square_132.jpg", "Square/square_310.jpg", "Square/square_79.jpg", "Square/square_26.jpg", "Square/square_62.jpg", "Square/square_119.jpg", "Square/square_266.jpg", "Square/square_206.jpg", "Square/square_80.jpg", "BaseballField/baseballfield_60.jpg", "BaseballField/baseballfield_19.jpg", "BaseballField/baseballfield_137.jpg", "BaseballField/baseballfield_89.jpg", "BaseballField/baseballfield_2.jpg", "BaseballField/baseballfield_35.jpg", "BaseballField/baseballfield_27.jpg", "BaseballField/baseballfield_30.jpg", "BaseballField/baseballfield_194.jpg", "BaseballField/baseballfield_133.jpg", "BaseballField/baseballfield_159.jpg", "BaseballField/baseballfield_7.jpg", "BaseballField/baseballfield_61.jpg", "BaseballField/baseballfield_128.jpg", "BaseballField/baseballfield_94.jpg", "BaseballField/baseballfield_70.jpg", "BaseballField/baseballfield_179.jpg", "BaseballField/baseballfield_136.jpg", "BaseballField/baseballfield_207.jpg", "BaseballField/baseballfield_155.jpg", "BaseballField/baseballfield_199.jpg", "BaseballField/baseballfield_106.jpg", "BaseballField/baseballfield_205.jpg", "BaseballField/baseballfield_54.jpg", "BaseballField/baseballfield_220.jpg", "BaseballField/baseballfield_102.jpg", "BaseballField/baseballfield_116.jpg", "BaseballField/baseballfield_180.jpg", "BaseballField/baseballfield_117.jpg", "BaseballField/baseballfield_37.jpg", "BaseballField/baseballfield_184.jpg", "BaseballField/baseballfield_25.jpg", "BaseballField/baseballfield_200.jpg", "BaseballField/baseballfield_108.jpg", "BaseballField/baseballfield_182.jpg", "BaseballField/baseballfield_124.jpg", "BaseballField/baseballfield_110.jpg", "BaseballField/baseballfield_26.jpg", "BaseballField/baseballfield_212.jpg", "BaseballField/baseballfield_32.jpg", "BaseballField/baseballfield_64.jpg", "BaseballField/baseballfield_76.jpg", "BaseballField/baseballfield_42.jpg", "BaseballField/baseballfield_138.jpg", "Church/church_200.jpg", "Church/church_47.jpg", "Church/church_28.jpg", "Church/church_181.jpg", "Church/church_27.jpg", "Church/church_150.jpg", "Church/church_151.jpg", "Church/church_71.jpg", "Church/church_83.jpg", "Church/church_139.jpg", "Church/church_25.jpg", "Church/church_194.jpg", "Church/church_7.jpg", "Church/church_192.jpg", "Church/church_31.jpg", "Church/church_39.jpg", "Church/church_80.jpg", "Church/church_219.jpg", "Church/church_148.jpg", "Church/church_109.jpg", "Church/church_201.jpg", "Church/church_116.jpg", "Church/church_236.jpg", "Church/church_3.jpg", "Church/church_43.jpg", "Church/church_54.jpg", "Church/church_141.jpg", "Church/church_197.jpg", "Church/church_44.jpg", "Church/church_48.jpg", "Church/church_102.jpg", "Church/church_33.jpg", "Church/church_156.jpg", "Church/church_56.jpg", "Church/church_111.jpg", "Church/church_96.jpg", "Church/church_62.jpg", "Church/church_30.jpg", "Church/church_85.jpg", "Church/church_223.jpg", "Church/church_131.jpg", "Church/church_73.jpg", "Church/church_160.jpg", "Church/church_84.jpg", "Church/church_115.jpg", "Church/church_220.jpg", "Church/church_209.jpg", "Church/church_130.jpg", "Farmland/farmland_77.jpg", "Farmland/farmland_103.jpg", "Farmland/farmland_230.jpg", "Farmland/farmland_287.jpg", "Farmland/farmland_334.jpg", "Farmland/farmland_112.jpg", "Farmland/farmland_267.jpg", "Farmland/farmland_164.jpg", "Farmland/farmland_135.jpg", "Farmland/farmland_283.jpg", "Farmland/farmland_211.jpg", "Farmland/farmland_309.jpg", "Farmland/farmland_271.jpg", "Farmland/farmland_145.jpg", "Farmland/farmland_223.jpg", "Farmland/farmland_220.jpg", "Farmland/farmland_363.jpg", "Farmland/farmland_265.jpg", "Farmland/farmland_327.jpg", "Farmland/farmland_78.jpg", "Farmland/farmland_305.jpg", "Farmland/farmland_246.jpg", "Farmland/farmland_236.jpg", "Farmland/farmland_204.jpg", "Farmland/farmland_27.jpg", "Farmland/farmland_20.jpg", "Farmland/farmland_194.jpg", "Farmland/farmland_93.jpg", "Farmland/farmland_107.jpg", "Farmland/farmland_258.jpg", "Farmland/farmland_119.jpg", "Farmland/farmland_362.jpg", "Farmland/farmland_270.jpg", "Farmland/farmland_290.jpg", "Farmland/farmland_275.jpg", "Farmland/farmland_9.jpg", "Farmland/farmland_101.jpg", "Farmland/farmland_104.jpg", "Farmland/farmland_70.jpg", "Farmland/farmland_50.jpg", "Farmland/farmland_72.jpg", "Farmland/farmland_177.jpg", "Farmland/farmland_66.jpg", "Farmland/farmland_339.jpg", "Farmland/farmland_299.jpg", "Farmland/farmland_248.jpg", "Farmland/farmland_328.jpg", "Farmland/farmland_198.jpg", "Farmland/farmland_360.jpg", "Farmland/farmland_122.jpg", "Farmland/farmland_71.jpg", "Farmland/farmland_276.jpg", "Farmland/farmland_355.jpg", "Farmland/farmland_124.jpg", "Farmland/farmland_244.jpg", "Farmland/farmland_239.jpg", "Farmland/farmland_131.jpg", "Farmland/farmland_235.jpg", "Farmland/farmland_351.jpg", "Farmland/farmland_238.jpg", "Farmland/farmland_292.jpg", "Farmland/farmland_255.jpg", "Farmland/farmland_317.jpg", "Farmland/farmland_285.jpg", "Farmland/farmland_33.jpg", "Farmland/farmland_203.jpg", "Farmland/farmland_268.jpg", "Farmland/farmland_196.jpg", "Farmland/farmland_343.jpg", "Farmland/farmland_40.jpg", "Farmland/farmland_105.jpg", "Farmland/farmland_29.jpg", "Farmland/farmland_21.jpg", "Farmland/farmland_46.jpg", "Stadium/stadium_255.jpg", "Stadium/stadium_157.jpg", "Stadium/stadium_125.jpg", "Stadium/stadium_84.jpg", "Stadium/stadium_280.jpg", "Stadium/stadium_39.jpg", "Stadium/stadium_45.jpg", "Stadium/stadium_29.jpg", "Stadium/stadium_119.jpg", "Stadium/stadium_176.jpg", "Stadium/stadium_179.jpg", "Stadium/stadium_237.jpg", "Stadium/stadium_264.jpg", "Stadium/stadium_158.jpg", "Stadium/stadium_43.jpg", "Stadium/stadium_189.jpg", "Stadium/stadium_93.jpg", "Stadium/stadium_112.jpg", "Stadium/stadium_122.jpg", "Stadium/stadium_259.jpg", "Stadium/stadium_182.jpg", "Stadium/stadium_48.jpg", "Stadium/stadium_191.jpg", "Stadium/stadium_111.jpg", "Stadium/stadium_168.jpg", "Stadium/stadium_95.jpg", "Stadium/stadium_83.jpg", "Stadium/stadium_283.jpg", "Stadium/stadium_263.jpg", "Stadium/stadium_142.jpg", "Stadium/stadium_11.jpg", "Stadium/stadium_61.jpg", "Stadium/stadium_243.jpg", "Stadium/stadium_75.jpg", "Stadium/stadium_58.jpg", "Stadium/stadium_148.jpg", "Stadium/stadium_279.jpg", "Stadium/stadium_187.jpg", "Stadium/stadium_37.jpg", "Stadium/stadium_115.jpg", "Stadium/stadium_180.jpg", "Stadium/stadium_12.jpg", "Stadium/stadium_175.jpg", "Stadium/stadium_139.jpg", "Stadium/stadium_13.jpg", "Stadium/stadium_78.jpg", "Stadium/stadium_100.jpg", "Stadium/stadium_167.jpg", "Stadium/stadium_68.jpg", "Stadium/stadium_236.jpg", "Stadium/stadium_138.jpg", "Stadium/stadium_234.jpg", "Stadium/stadium_276.jpg", "Stadium/stadium_282.jpg", "Stadium/stadium_212.jpg", "Stadium/stadium_163.jpg", "Stadium/stadium_250.jpg", "Stadium/stadium_124.jpg", "Viaduct/viaduct_277.jpg", "Viaduct/viaduct_63.jpg", "Viaduct/viaduct_51.jpg", "Viaduct/viaduct_213.jpg", "Viaduct/viaduct_229.jpg", "Viaduct/viaduct_164.jpg", "Viaduct/viaduct_207.jpg", "Viaduct/viaduct_365.jpg", "Viaduct/viaduct_376.jpg", "Viaduct/viaduct_184.jpg", "Viaduct/viaduct_177.jpg", "Viaduct/viaduct_7.jpg", "Viaduct/viaduct_189.jpg", "Viaduct/viaduct_401.jpg", "Viaduct/viaduct_410.jpg", "Viaduct/viaduct_334.jpg", "Viaduct/viaduct_416.jpg", "Viaduct/viaduct_228.jpg", "Viaduct/viaduct_47.jpg", "Viaduct/viaduct_59.jpg", "Viaduct/viaduct_173.jpg", "Viaduct/viaduct_4.jpg", "Viaduct/viaduct_271.jpg", "Viaduct/viaduct_161.jpg", "Viaduct/viaduct_373.jpg", "Viaduct/viaduct_246.jpg", "Viaduct/viaduct_39.jpg", "Viaduct/viaduct_241.jpg", "Viaduct/viaduct_100.jpg", "Viaduct/viaduct_234.jpg", "Viaduct/viaduct_197.jpg", "Viaduct/viaduct_37.jpg", "Viaduct/viaduct_325.jpg", "Viaduct/viaduct_153.jpg", "Viaduct/viaduct_235.jpg", "Viaduct/viaduct_102.jpg", "Viaduct/viaduct_55.jpg", "Viaduct/viaduct_125.jpg", "Viaduct/viaduct_29.jpg", "Viaduct/viaduct_157.jpg", "Viaduct/viaduct_138.jpg", "Viaduct/viaduct_250.jpg", "Viaduct/viaduct_239.jpg", "Viaduct/viaduct_366.jpg", "Viaduct/viaduct_240.jpg", "Viaduct/viaduct_280.jpg", "Viaduct/viaduct_276.jpg", "Viaduct/viaduct_187.jpg", "Viaduct/viaduct_16.jpg", "Viaduct/viaduct_108.jpg", "Viaduct/viaduct_379.jpg", "Viaduct/viaduct_383.jpg", "Viaduct/viaduct_238.jpg", "Viaduct/viaduct_52.jpg", "Viaduct/viaduct_340.jpg", "Viaduct/viaduct_297.jpg", "Viaduct/viaduct_195.jpg", "Viaduct/viaduct_269.jpg", "Viaduct/viaduct_21.jpg", "Viaduct/viaduct_145.jpg", "Viaduct/viaduct_172.jpg", "Viaduct/viaduct_136.jpg", "Viaduct/viaduct_399.jpg", "Viaduct/viaduct_311.jpg", "Viaduct/viaduct_364.jpg", "Viaduct/viaduct_62.jpg", "Viaduct/viaduct_36.jpg", "Viaduct/viaduct_10.jpg", "Viaduct/viaduct_305.jpg", "Viaduct/viaduct_371.jpg", "Viaduct/viaduct_50.jpg", "Viaduct/viaduct_75.jpg", "Viaduct/viaduct_310.jpg", "Viaduct/viaduct_304.jpg", "Viaduct/viaduct_49.jpg", "Viaduct/viaduct_118.jpg", "Viaduct/viaduct_170.jpg", "Viaduct/viaduct_99.jpg", "Viaduct/viaduct_1.jpg", "Viaduct/viaduct_175.jpg", "Viaduct/viaduct_202.jpg", "Viaduct/viaduct_360.jpg", "Viaduct/viaduct_216.jpg", "Viaduct/viaduct_377.jpg", "Commercial/commercial_95.jpg", "Commercial/commercial_340.jpg", "Commercial/commercial_177.jpg", "Commercial/commercial_86.jpg", "Commercial/commercial_221.jpg", "Commercial/commercial_264.jpg", "Commercial/commercial_239.jpg", "Commercial/commercial_106.jpg", "Commercial/commercial_38.jpg", "Commercial/commercial_92.jpg", "Commercial/commercial_260.jpg", "Commercial/commercial_4.jpg", "Commercial/commercial_333.jpg", "Commercial/commercial_49.jpg", "Commercial/commercial_87.jpg", "Commercial/commercial_350.jpg", "Commercial/commercial_282.jpg", "Commercial/commercial_341.jpg", "Commercial/commercial_99.jpg", "Commercial/commercial_228.jpg", "Commercial/commercial_67.jpg", "Commercial/commercial_290.jpg", "Commercial/commercial_81.jpg", "Commercial/commercial_180.jpg", "Commercial/commercial_97.jpg", "Commercial/commercial_32.jpg", "Commercial/commercial_225.jpg", "Commercial/commercial_76.jpg", "Commercial/commercial_74.jpg", "Commercial/commercial_93.jpg", "Commercial/commercial_96.jpg", "Commercial/commercial_147.jpg", "Commercial/commercial_322.jpg", "Commercial/commercial_199.jpg", "Commercial/commercial_292.jpg", "Commercial/commercial_258.jpg", "Commercial/commercial_249.jpg", "Commercial/commercial_218.jpg", "Commercial/commercial_113.jpg", "Commercial/commercial_229.jpg", "Commercial/commercial_271.jpg", "Commercial/commercial_192.jpg", "Commercial/commercial_88.jpg", "Commercial/commercial_144.jpg", "Commercial/commercial_266.jpg", "Commercial/commercial_137.jpg", "Commercial/commercial_108.jpg", "Commercial/commercial_306.jpg", "Commercial/commercial_69.jpg", "Commercial/commercial_36.jpg", "Commercial/commercial_170.jpg", "Commercial/commercial_123.jpg", "Commercial/commercial_103.jpg", "Commercial/commercial_119.jpg", "Commercial/commercial_132.jpg", "Commercial/commercial_28.jpg", "Commercial/commercial_301.jpg", "Commercial/commercial_255.jpg", "Commercial/commercial_125.jpg", "Commercial/commercial_13.jpg", "Commercial/commercial_51.jpg", "Commercial/commercial_105.jpg", "Commercial/commercial_230.jpg", "Commercial/commercial_303.jpg", "Commercial/commercial_65.jpg", "Commercial/commercial_305.jpg", "Commercial/commercial_326.jpg", "Commercial/commercial_21.jpg", "Commercial/commercial_29.jpg", "Commercial/commercial_247.jpg", "Industrial/industrial_281.jpg", "Industrial/industrial_180.jpg", "Industrial/industrial_107.jpg", "Industrial/industrial_77.jpg", "Industrial/industrial_135.jpg", "Industrial/industrial_341.jpg", "Industrial/industrial_326.jpg", "Industrial/industrial_289.jpg", "Industrial/industrial_241.jpg", "Industrial/industrial_249.jpg", "Industrial/industrial_269.jpg", "Industrial/industrial_338.jpg", "Industrial/industrial_28.jpg", "Industrial/industrial_22.jpg", "Industrial/industrial_51.jpg", "Industrial/industrial_86.jpg", "Industrial/industrial_138.jpg", "Industrial/industrial_373.jpg", "Industrial/industrial_18.jpg", "Industrial/industrial_242.jpg", "Industrial/industrial_278.jpg", "Industrial/industrial_149.jpg", "Industrial/industrial_9.jpg", "Industrial/industrial_146.jpg", "Industrial/industrial_39.jpg", "Industrial/industrial_134.jpg", "Industrial/industrial_327.jpg", "Industrial/industrial_55.jpg", "Industrial/industrial_318.jpg", "Industrial/industrial_364.jpg", "Industrial/industrial_330.jpg", "Industrial/industrial_155.jpg", "Industrial/industrial_346.jpg", "Industrial/industrial_367.jpg", "Industrial/industrial_365.jpg", "Industrial/industrial_325.jpg", "Industrial/industrial_198.jpg", "Industrial/industrial_188.jpg", "Industrial/industrial_336.jpg", "Industrial/industrial_250.jpg", "Industrial/industrial_96.jpg", "Industrial/industrial_251.jpg", "Industrial/industrial_357.jpg", "Industrial/industrial_26.jpg", "Industrial/industrial_332.jpg", "Industrial/industrial_304.jpg", "Industrial/industrial_376.jpg", "Industrial/industrial_113.jpg", "Industrial/industrial_290.jpg", "Industrial/industrial_10.jpg", "Industrial/industrial_131.jpg", "Industrial/industrial_307.jpg", "Industrial/industrial_115.jpg", "Industrial/industrial_5.jpg", "Industrial/industrial_283.jpg", "Industrial/industrial_319.jpg", "Industrial/industrial_220.jpg", "Industrial/industrial_352.jpg", "Industrial/industrial_152.jpg", "Industrial/industrial_128.jpg", "Industrial/industrial_337.jpg", "Industrial/industrial_217.jpg", "Industrial/industrial_284.jpg", "Industrial/industrial_207.jpg", "Industrial/industrial_344.jpg", "Industrial/industrial_23.jpg", "Industrial/industrial_25.jpg", "Industrial/industrial_239.jpg", "Industrial/industrial_162.jpg", "Industrial/industrial_143.jpg", "Industrial/industrial_294.jpg", "Industrial/industrial_4.jpg", "Industrial/industrial_171.jpg", "Industrial/industrial_320.jpg", "Industrial/industrial_145.jpg", "Industrial/industrial_8.jpg", "Industrial/industrial_254.jpg", "Industrial/industrial_132.jpg", "Airport/airport_213.jpg", "Airport/airport_304.jpg", "Airport/airport_43.jpg", "Airport/airport_241.jpg", "Airport/airport_68.jpg", "Airport/airport_81.jpg", "Airport/airport_286.jpg", "Airport/airport_245.jpg", "Airport/airport_31.jpg", "Airport/airport_318.jpg", "Airport/airport_151.jpg", "Airport/airport_120.jpg", "Airport/airport_87.jpg", "Airport/airport_91.jpg", "Airport/airport_125.jpg", "Airport/airport_106.jpg", "Airport/airport_46.jpg", "Airport/airport_103.jpg", "Airport/airport_210.jpg", "Airport/airport_177.jpg", "Airport/airport_204.jpg", "Airport/airport_336.jpg", "Airport/airport_3.jpg", "Airport/airport_145.jpg", "Airport/airport_284.jpg", "Airport/airport_162.jpg", "Airport/airport_338.jpg", "Airport/airport_203.jpg", "Airport/airport_92.jpg", "Airport/airport_247.jpg", "Airport/airport_313.jpg", "Airport/airport_123.jpg", "Airport/airport_196.jpg", "Airport/airport_227.jpg", "Airport/airport_63.jpg", "Airport/airport_346.jpg", "Airport/airport_147.jpg", "Airport/airport_311.jpg", "Airport/airport_232.jpg", "Airport/airport_116.jpg", "Airport/airport_325.jpg", "Airport/airport_141.jpg", "Airport/airport_109.jpg", "Airport/airport_119.jpg", "Airport/airport_166.jpg", "Airport/airport_238.jpg", "Airport/airport_127.jpg", "Airport/airport_69.jpg", "Airport/airport_38.jpg", "Airport/airport_74.jpg", "Airport/airport_11.jpg", "Airport/airport_298.jpg", "Airport/airport_214.jpg", "Airport/airport_181.jpg", "Airport/airport_51.jpg", "Airport/airport_253.jpg", "Airport/airport_34.jpg", "Airport/airport_263.jpg", "Airport/airport_352.jpg", "Airport/airport_41.jpg", "Airport/airport_70.jpg", "Airport/airport_212.jpg", "Airport/airport_20.jpg", "Airport/airport_140.jpg", "Airport/airport_56.jpg", "Airport/airport_44.jpg", "Airport/airport_160.jpg", "Airport/airport_296.jpg", "Airport/airport_248.jpg", "Airport/airport_292.jpg", "Airport/airport_172.jpg", "Airport/airport_207.jpg", "SparseResidential/sparseresidential_62.jpg", "SparseResidential/sparseresidential_81.jpg", "SparseResidential/sparseresidential_44.jpg", "SparseResidential/sparseresidential_2.jpg", "SparseResidential/sparseresidential_32.jpg", "SparseResidential/sparseresidential_139.jpg", "SparseResidential/sparseresidential_125.jpg", "SparseResidential/sparseresidential_13.jpg", "SparseResidential/sparseresidential_203.jpg", "SparseResidential/sparseresidential_209.jpg", "SparseResidential/sparseresidential_160.jpg", "SparseResidential/sparseresidential_132.jpg", "SparseResidential/sparseresidential_188.jpg", "SparseResidential/sparseresidential_192.jpg", "SparseResidential/sparseresidential_15.jpg", "SparseResidential/sparseresidential_8.jpg", "SparseResidential/sparseresidential_46.jpg", "SparseResidential/sparseresidential_170.jpg", "SparseResidential/sparseresidential_206.jpg", "SparseResidential/sparseresidential_269.jpg", "SparseResidential/sparseresidential_291.jpg", "SparseResidential/sparseresidential_177.jpg", "SparseResidential/sparseresidential_146.jpg", "SparseResidential/sparseresidential_276.jpg", "SparseResidential/sparseresidential_69.jpg", "SparseResidential/sparseresidential_229.jpg", "SparseResidential/sparseresidential_164.jpg", "SparseResidential/sparseresidential_76.jpg", "SparseResidential/sparseresidential_236.jpg", "SparseResidential/sparseresidential_60.jpg", "SparseResidential/sparseresidential_18.jpg", "SparseResidential/sparseresidential_29.jpg", "SparseResidential/sparseresidential_49.jpg", "SparseResidential/sparseresidential_7.jpg", "SparseResidential/sparseresidential_220.jpg", "SparseResidential/sparseresidential_48.jpg", "SparseResidential/sparseresidential_148.jpg", "SparseResidential/sparseresidential_162.jpg", "SparseResidential/sparseresidential_105.jpg", "SparseResidential/sparseresidential_31.jpg", "SparseResidential/sparseresidential_37.jpg", "SparseResidential/sparseresidential_64.jpg", "SparseResidential/sparseresidential_216.jpg", "SparseResidential/sparseresidential_28.jpg", "SparseResidential/sparseresidential_224.jpg", "SparseResidential/sparseresidential_257.jpg", "SparseResidential/sparseresidential_293.jpg", "SparseResidential/sparseresidential_299.jpg", "SparseResidential/sparseresidential_249.jpg", "SparseResidential/sparseresidential_10.jpg", "SparseResidential/sparseresidential_27.jpg", "SparseResidential/sparseresidential_128.jpg", "SparseResidential/sparseresidential_262.jpg", "SparseResidential/sparseresidential_204.jpg", "SparseResidential/sparseresidential_20.jpg", "SparseResidential/sparseresidential_4.jpg", "SparseResidential/sparseresidential_181.jpg", "SparseResidential/sparseresidential_221.jpg", "SparseResidential/sparseresidential_196.jpg", "SparseResidential/sparseresidential_83.jpg", "MediumResidential/mediumresidential_168.jpg", "MediumResidential/mediumresidential_112.jpg", "MediumResidential/mediumresidential_123.jpg", "MediumResidential/mediumresidential_204.jpg", "MediumResidential/mediumresidential_148.jpg", "MediumResidential/mediumresidential_239.jpg", "MediumResidential/mediumresidential_195.jpg", "MediumResidential/mediumresidential_203.jpg", "MediumResidential/mediumresidential_73.jpg", "MediumResidential/mediumresidential_260.jpg", "MediumResidential/mediumresidential_151.jpg", "MediumResidential/mediumresidential_188.jpg", "MediumResidential/mediumresidential_191.jpg", "MediumResidential/mediumresidential_185.jpg", "MediumResidential/mediumresidential_88.jpg", "MediumResidential/mediumresidential_212.jpg", "MediumResidential/mediumresidential_72.jpg", "MediumResidential/mediumresidential_75.jpg", "MediumResidential/mediumresidential_196.jpg", "MediumResidential/mediumresidential_124.jpg", "MediumResidential/mediumresidential_165.jpg", "MediumResidential/mediumresidential_127.jpg", "MediumResidential/mediumresidential_54.jpg", "MediumResidential/mediumresidential_70.jpg", "MediumResidential/mediumresidential_64.jpg", "MediumResidential/mediumresidential_79.jpg", "MediumResidential/mediumresidential_157.jpg", "MediumResidential/mediumresidential_277.jpg", "MediumResidential/mediumresidential_15.jpg", "MediumResidential/mediumresidential_140.jpg", "MediumResidential/mediumresidential_98.jpg", "MediumResidential/mediumresidential_174.jpg", "MediumResidential/mediumresidential_135.jpg", "MediumResidential/mediumresidential_5.jpg", "MediumResidential/mediumresidential_270.jpg", "MediumResidential/mediumresidential_26.jpg", "MediumResidential/mediumresidential_48.jpg", "MediumResidential/mediumresidential_36.jpg", "MediumResidential/mediumresidential_230.jpg", "MediumResidential/mediumresidential_85.jpg", "MediumResidential/mediumresidential_14.jpg", "MediumResidential/mediumresidential_223.jpg", "MediumResidential/mediumresidential_92.jpg", "MediumResidential/mediumresidential_6.jpg", "MediumResidential/mediumresidential_56.jpg", "MediumResidential/mediumresidential_111.jpg", "MediumResidential/mediumresidential_245.jpg", "MediumResidential/mediumresidential_108.jpg", "MediumResidential/mediumresidential_155.jpg", "MediumResidential/mediumresidential_236.jpg", "MediumResidential/mediumresidential_87.jpg", "MediumResidential/mediumresidential_232.jpg", "MediumResidential/mediumresidential_90.jpg", "MediumResidential/mediumresidential_199.jpg", "MediumResidential/mediumresidential_198.jpg", "MediumResidential/mediumresidential_81.jpg", "MediumResidential/mediumresidential_284.jpg", "MediumResidential/mediumresidential_150.jpg", "DenseResidential/denseresidential_59.jpg", "DenseResidential/denseresidential_283.jpg", "DenseResidential/denseresidential_368.jpg", "DenseResidential/denseresidential_63.jpg", "DenseResidential/denseresidential_396.jpg", "DenseResidential/denseresidential_312.jpg", "DenseResidential/denseresidential_17.jpg", "DenseResidential/denseresidential_274.jpg", "DenseResidential/denseresidential_139.jpg", "DenseResidential/denseresidential_265.jpg", "DenseResidential/denseresidential_282.jpg", "DenseResidential/denseresidential_298.jpg", "DenseResidential/denseresidential_295.jpg", "DenseResidential/denseresidential_42.jpg", "DenseResidential/denseresidential_71.jpg", "DenseResidential/denseresidential_238.jpg", "DenseResidential/denseresidential_339.jpg", "DenseResidential/denseresidential_301.jpg", "DenseResidential/denseresidential_31.jpg", "DenseResidential/denseresidential_309.jpg", "DenseResidential/denseresidential_84.jpg", "DenseResidential/denseresidential_333.jpg", "DenseResidential/denseresidential_188.jpg", "DenseResidential/denseresidential_175.jpg", "DenseResidential/denseresidential_348.jpg", "DenseResidential/denseresidential_149.jpg", "DenseResidential/denseresidential_75.jpg", "DenseResidential/denseresidential_210.jpg", "DenseResidential/denseresidential_272.jpg", "DenseResidential/denseresidential_219.jpg", "DenseResidential/denseresidential_133.jpg", "DenseResidential/denseresidential_177.jpg", "DenseResidential/denseresidential_308.jpg", "DenseResidential/denseresidential_365.jpg", "DenseResidential/denseresidential_233.jpg", "DenseResidential/denseresidential_164.jpg", "DenseResidential/denseresidential_323.jpg", "DenseResidential/denseresidential_33.jpg", "DenseResidential/denseresidential_20.jpg", "DenseResidential/denseresidential_255.jpg", "DenseResidential/denseresidential_95.jpg", "DenseResidential/denseresidential_137.jpg", "DenseResidential/denseresidential_101.jpg", "DenseResidential/denseresidential_394.jpg", "DenseResidential/denseresidential_116.jpg", "DenseResidential/denseresidential_118.jpg", "DenseResidential/denseresidential_74.jpg", "DenseResidential/denseresidential_66.jpg", "DenseResidential/denseresidential_302.jpg", "DenseResidential/denseresidential_184.jpg", "DenseResidential/denseresidential_362.jpg", "DenseResidential/denseresidential_395.jpg", "DenseResidential/denseresidential_239.jpg", "DenseResidential/denseresidential_96.jpg", "DenseResidential/denseresidential_204.jpg", "DenseResidential/denseresidential_270.jpg", "DenseResidential/denseresidential_112.jpg", "DenseResidential/denseresidential_227.jpg", "DenseResidential/denseresidential_189.jpg", "DenseResidential/denseresidential_65.jpg", "DenseResidential/denseresidential_41.jpg", "DenseResidential/denseresidential_76.jpg", "DenseResidential/denseresidential_14.jpg", "DenseResidential/denseresidential_7.jpg", "DenseResidential/denseresidential_4.jpg", "DenseResidential/denseresidential_47.jpg", "DenseResidential/denseresidential_167.jpg", "DenseResidential/denseresidential_91.jpg", "DenseResidential/denseresidential_49.jpg", "DenseResidential/denseresidential_314.jpg", "DenseResidential/denseresidential_262.jpg", "DenseResidential/denseresidential_345.jpg", "DenseResidential/denseresidential_120.jpg", "DenseResidential/denseresidential_13.jpg", "DenseResidential/denseresidential_242.jpg", "DenseResidential/denseresidential_235.jpg", "DenseResidential/denseresidential_224.jpg", "DenseResidential/denseresidential_77.jpg", "DenseResidential/denseresidential_117.jpg", "DenseResidential/denseresidential_56.jpg", "DenseResidential/denseresidential_341.jpg", "DenseResidential/denseresidential_253.jpg", "RailwayStation/railwaystation_204.jpg", "RailwayStation/railwaystation_32.jpg", "RailwayStation/railwaystation_108.jpg", "RailwayStation/railwaystation_236.jpg", "RailwayStation/railwaystation_69.jpg", "RailwayStation/railwaystation_57.jpg", "RailwayStation/railwaystation_246.jpg", "RailwayStation/railwaystation_185.jpg", "RailwayStation/railwaystation_112.jpg", "RailwayStation/railwaystation_184.jpg", "RailwayStation/railwaystation_169.jpg", "RailwayStation/railwaystation_160.jpg", "RailwayStation/railwaystation_117.jpg", "RailwayStation/railwaystation_240.jpg", "RailwayStation/railwaystation_233.jpg", "RailwayStation/railwaystation_239.jpg", "RailwayStation/railwaystation_79.jpg", "RailwayStation/railwaystation_92.jpg", "RailwayStation/railwaystation_211.jpg", "RailwayStation/railwaystation_154.jpg", "RailwayStation/railwaystation_258.jpg", "RailwayStation/railwaystation_10.jpg", "RailwayStation/railwaystation_175.jpg", "RailwayStation/railwaystation_125.jpg", "RailwayStation/railwaystation_65.jpg", "RailwayStation/railwaystation_99.jpg", "RailwayStation/railwaystation_178.jpg", "RailwayStation/railwaystation_114.jpg", "RailwayStation/railwaystation_104.jpg", "RailwayStation/railwaystation_42.jpg", "RailwayStation/railwaystation_77.jpg", "RailwayStation/railwaystation_62.jpg", "RailwayStation/railwaystation_127.jpg", "RailwayStation/railwaystation_197.jpg", "RailwayStation/railwaystation_216.jpg", "RailwayStation/railwaystation_174.jpg", "RailwayStation/railwaystation_78.jpg", "RailwayStation/railwaystation_196.jpg", "RailwayStation/railwaystation_159.jpg", "RailwayStation/railwaystation_229.jpg", "RailwayStation/railwaystation_145.jpg", "RailwayStation/railwaystation_60.jpg", "RailwayStation/railwaystation_257.jpg", "RailwayStation/railwaystation_19.jpg", "RailwayStation/railwaystation_71.jpg", "RailwayStation/railwaystation_144.jpg", "RailwayStation/railwaystation_140.jpg", "RailwayStation/railwaystation_44.jpg", "RailwayStation/railwaystation_208.jpg", "RailwayStation/railwaystation_209.jpg", "RailwayStation/railwaystation_14.jpg", "RailwayStation/railwaystation_179.jpg", "BareLand/bareland_3.jpg", "BareLand/bareland_200.jpg", "BareLand/bareland_188.jpg", "BareLand/bareland_120.jpg", "BareLand/bareland_131.jpg", "BareLand/bareland_183.jpg", "BareLand/bareland_185.jpg", "BareLand/bareland_243.jpg", "BareLand/bareland_189.jpg", "BareLand/bareland_95.jpg", "BareLand/bareland_233.jpg", "BareLand/bareland_245.jpg", "BareLand/bareland_153.jpg", "BareLand/bareland_7.jpg", "BareLand/bareland_11.jpg", "BareLand/bareland_107.jpg", "BareLand/bareland_286.jpg", "BareLand/bareland_206.jpg", "BareLand/bareland_31.jpg", "BareLand/bareland_234.jpg", "BareLand/bareland_304.jpg", "BareLand/bareland_276.jpg", "BareLand/bareland_127.jpg", "BareLand/bareland_238.jpg", "BareLand/bareland_193.jpg", "BareLand/bareland_81.jpg", "BareLand/bareland_8.jpg", "BareLand/bareland_104.jpg", "BareLand/bareland_22.jpg", "BareLand/bareland_226.jpg", "BareLand/bareland_102.jpg", "BareLand/bareland_101.jpg", "BareLand/bareland_15.jpg", "BareLand/bareland_165.jpg", "BareLand/bareland_132.jpg", "BareLand/bareland_137.jpg", "BareLand/bareland_86.jpg", "BareLand/bareland_83.jpg", "BareLand/bareland_227.jpg", "BareLand/bareland_158.jpg", "BareLand/bareland_228.jpg", "BareLand/bareland_40.jpg", "BareLand/bareland_71.jpg", "BareLand/bareland_43.jpg", "BareLand/bareland_159.jpg", "BareLand/bareland_306.jpg", "BareLand/bareland_103.jpg", "BareLand/bareland_247.jpg", "BareLand/bareland_49.jpg", "BareLand/bareland_187.jpg", "BareLand/bareland_66.jpg", "BareLand/bareland_125.jpg", "BareLand/bareland_32.jpg", "BareLand/bareland_84.jpg", "BareLand/bareland_164.jpg", "BareLand/bareland_147.jpg", "BareLand/bareland_173.jpg", "BareLand/bareland_294.jpg", "BareLand/bareland_42.jpg", "BareLand/bareland_205.jpg", "BareLand/bareland_308.jpg", "BareLand/bareland_271.jpg", "Beach/beach_215.jpg", "Beach/beach_375.jpg", "Beach/beach_356.jpg", "Beach/beach_370.jpg", "Beach/beach_312.jpg", "Beach/beach_190.jpg", "Beach/beach_361.jpg", "Beach/beach_275.jpg", "Beach/beach_301.jpg", "Beach/beach_378.jpg", "Beach/beach_4.jpg", "Beach/beach_59.jpg", "Beach/beach_393.jpg", "Beach/beach_50.jpg", "Beach/beach_47.jpg", "Beach/beach_120.jpg", "Beach/beach_250.jpg", "Beach/beach_277.jpg", "Beach/beach_256.jpg", "Beach/beach_346.jpg", "Beach/beach_153.jpg", "Beach/beach_182.jpg", "Beach/beach_196.jpg", "Beach/beach_315.jpg", "Beach/beach_282.jpg", "Beach/beach_326.jpg", "Beach/beach_102.jpg", "Beach/beach_200.jpg", "Beach/beach_70.jpg", "Beach/beach_150.jpg", "Beach/beach_201.jpg", "Beach/beach_94.jpg", "Beach/beach_197.jpg", "Beach/beach_1.jpg", "Beach/beach_51.jpg", "Beach/beach_292.jpg", "Beach/beach_260.jpg", "Beach/beach_290.jpg", "Beach/beach_390.jpg", "Beach/beach_12.jpg", "Beach/beach_7.jpg", "Beach/beach_45.jpg", "Beach/beach_233.jpg", "Beach/beach_38.jpg", "Beach/beach_232.jpg", "Beach/beach_345.jpg", "Beach/beach_204.jpg", "Beach/beach_379.jpg", "Beach/beach_63.jpg", "Beach/beach_321.jpg", "Beach/beach_93.jpg", "Beach/beach_35.jpg", "Beach/beach_52.jpg", "Beach/beach_43.jpg", "Beach/beach_258.jpg", "Beach/beach_357.jpg", "Beach/beach_286.jpg", "Beach/beach_398.jpg", "Beach/beach_194.jpg", "Beach/beach_71.jpg", "Beach/beach_66.jpg", "Beach/beach_5.jpg", "Beach/beach_131.jpg", "Beach/beach_26.jpg", "Beach/beach_279.jpg", "Beach/beach_27.jpg", "Beach/beach_396.jpg", "Beach/beach_302.jpg", "Beach/beach_239.jpg", "Beach/beach_400.jpg", "Beach/beach_252.jpg", "Beach/beach_185.jpg", "Beach/beach_11.jpg", "Beach/beach_99.jpg", "Beach/beach_103.jpg", "Beach/beach_82.jpg", "Beach/beach_324.jpg", "Beach/beach_49.jpg", "Beach/beach_274.jpg", "Beach/beach_110.jpg", "Port/port_232.jpg", "Port/port_37.jpg", "Port/port_161.jpg", "Port/port_345.jpg", "Port/port_93.jpg", "Port/port_88.jpg", "Port/port_293.jpg", "Port/port_236.jpg", "Port/port_363.jpg", "Port/port_275.jpg", "Port/port_124.jpg", "Port/port_223.jpg", "Port/port_258.jpg", "Port/port_43.jpg", "Port/port_205.jpg", "Port/port_26.jpg", "Port/port_168.jpg", "Port/port_297.jpg", "Port/port_30.jpg", "Port/port_72.jpg", "Port/port_170.jpg", "Port/port_53.jpg", "Port/port_129.jpg", "Port/port_235.jpg", "Port/port_276.jpg", "Port/port_70.jpg", "Port/port_23.jpg", "Port/port_256.jpg", "Port/port_354.jpg", "Port/port_228.jpg", "Port/port_267.jpg", "Port/port_335.jpg", "Port/port_137.jpg", "Port/port_155.jpg", "Port/port_281.jpg", "Port/port_76.jpg", "Port/port_1.jpg", "Port/port_286.jpg", "Port/port_259.jpg", "Port/port_97.jpg", "Port/port_56.jpg", "Port/port_134.jpg", "Port/port_365.jpg", "Port/port_86.jpg", "Port/port_175.jpg", "Port/port_27.jpg", "Port/port_207.jpg", "Port/port_268.jpg", "Port/port_15.jpg", "Port/port_215.jpg", "Port/port_2.jpg", "Port/port_108.jpg", "Port/port_184.jpg", "Port/port_151.jpg", "Port/port_296.jpg", "Port/port_353.jpg", "Port/port_12.jpg", "Port/port_218.jpg", "Port/port_379.jpg", "Port/port_131.jpg", "Port/port_153.jpg", "Port/port_309.jpg", "Port/port_160.jpg", "Port/port_22.jpg", "Port/port_196.jpg", "Port/port_110.jpg", "Port/port_337.jpg", "Port/port_249.jpg", "Port/port_352.jpg", "Port/port_47.jpg", "Port/port_316.jpg", "Port/port_54.jpg", "Port/port_136.jpg", "Port/port_66.jpg", "Port/port_91.jpg", "Port/port_83.jpg", "Mountain/mountain_228.jpg", "Mountain/mountain_26.jpg", "Mountain/mountain_226.jpg", "Mountain/mountain_88.jpg", "Mountain/mountain_320.jpg", "Mountain/mountain_331.jpg", "Mountain/mountain_294.jpg", "Mountain/mountain_178.jpg", "Mountain/mountain_115.jpg", "Mountain/mountain_151.jpg", "Mountain/mountain_153.jpg", "Mountain/mountain_261.jpg", "Mountain/mountain_31.jpg", "Mountain/mountain_276.jpg", "Mountain/mountain_142.jpg", "Mountain/mountain_186.jpg", "Mountain/mountain_61.jpg", "Mountain/mountain_2.jpg", "Mountain/mountain_282.jpg", "Mountain/mountain_35.jpg", "Mountain/mountain_6.jpg", "Mountain/mountain_314.jpg", "Mountain/mountain_201.jpg", "Mountain/mountain_302.jpg", "Mountain/mountain_275.jpg", "Mountain/mountain_62.jpg", "Mountain/mountain_77.jpg", "Mountain/mountain_198.jpg", "Mountain/mountain_48.jpg", "Mountain/mountain_249.jpg", "Mountain/mountain_280.jpg", "Mountain/mountain_181.jpg", "Mountain/mountain_85.jpg", "Mountain/mountain_112.jpg", "Mountain/mountain_312.jpg", "Mountain/mountain_296.jpg", "Mountain/mountain_73.jpg", "Mountain/mountain_290.jpg", "Mountain/mountain_284.jpg", "Mountain/mountain_336.jpg", "Mountain/mountain_50.jpg", "Mountain/mountain_308.jpg", "Mountain/mountain_4.jpg", "Mountain/mountain_108.jpg", "Mountain/mountain_207.jpg", "Mountain/mountain_189.jpg", "Mountain/mountain_176.jpg", "Mountain/mountain_64.jpg", "Mountain/mountain_123.jpg", "Mountain/mountain_78.jpg", "Mountain/mountain_237.jpg", "Mountain/mountain_102.jpg", "Mountain/mountain_165.jpg", "Mountain/mountain_265.jpg", "Mountain/mountain_182.jpg", "Mountain/mountain_161.jpg", "Mountain/mountain_156.jpg", "Mountain/mountain_114.jpg", "Mountain/mountain_221.jpg", "Mountain/mountain_193.jpg", "Mountain/mountain_211.jpg", "Mountain/mountain_278.jpg", "Mountain/mountain_340.jpg", "Mountain/mountain_332.jpg", "Mountain/mountain_139.jpg", "Mountain/mountain_195.jpg", "Mountain/mountain_307.jpg", "Mountain/mountain_80.jpg", "Desert/desert_131.jpg", "Desert/desert_80.jpg", "Desert/desert_149.jpg", "Desert/desert_218.jpg", "Desert/desert_254.jpg", "Desert/desert_116.jpg", "Desert/desert_205.jpg", "Desert/desert_212.jpg", "Desert/desert_40.jpg", "Desert/desert_240.jpg", "Desert/desert_115.jpg", "Desert/desert_275.jpg", "Desert/desert_27.jpg", "Desert/desert_204.jpg", "Desert/desert_113.jpg", "Desert/desert_154.jpg", "Desert/desert_158.jpg", "Desert/desert_98.jpg", "Desert/desert_266.jpg", "Desert/desert_211.jpg", "Desert/desert_244.jpg", "Desert/desert_74.jpg", "Desert/desert_217.jpg", "Desert/desert_77.jpg", "Desert/desert_172.jpg", "Desert/desert_296.jpg", "Desert/desert_181.jpg", "Desert/desert_50.jpg", "Desert/desert_90.jpg", "Desert/desert_235.jpg", "Desert/desert_271.jpg", "Desert/desert_295.jpg", "Desert/desert_231.jpg", "Desert/desert_263.jpg", "Desert/desert_281.jpg", "Desert/desert_97.jpg", "Desert/desert_140.jpg", "Desert/desert_9.jpg", "Desert/desert_3.jpg", "Desert/desert_52.jpg", "Desert/desert_101.jpg", "Desert/desert_13.jpg", "Desert/desert_122.jpg", "Desert/desert_119.jpg", "Desert/desert_14.jpg", "Desert/desert_273.jpg", "Desert/desert_180.jpg", "Desert/desert_25.jpg", "Desert/desert_134.jpg", "Desert/desert_64.jpg", "Desert/desert_290.jpg", "Desert/desert_142.jpg", "Desert/desert_65.jpg", "Desert/desert_66.jpg", "Desert/desert_91.jpg", "Desert/desert_1.jpg", "Desert/desert_213.jpg", "Desert/desert_31.jpg", "Desert/desert_193.jpg", "Desert/desert_33.jpg", "Meadow/meadow_254.jpg", "Meadow/meadow_24.jpg", "Meadow/meadow_275.jpg", "Meadow/meadow_251.jpg", "Meadow/meadow_49.jpg", "Meadow/meadow_130.jpg", "Meadow/meadow_170.jpg", "Meadow/meadow_197.jpg", "Meadow/meadow_226.jpg", "Meadow/meadow_196.jpg", "Meadow/meadow_141.jpg", "Meadow/meadow_263.jpg", "Meadow/meadow_57.jpg", "Meadow/meadow_68.jpg", "Meadow/meadow_193.jpg", "Meadow/meadow_203.jpg", "Meadow/meadow_73.jpg", "Meadow/meadow_172.jpg", "Meadow/meadow_61.jpg", "Meadow/meadow_271.jpg", "Meadow/meadow_220.jpg", "Meadow/meadow_56.jpg", "Meadow/meadow_63.jpg", "Meadow/meadow_186.jpg", "Meadow/meadow_153.jpg", "Meadow/meadow_145.jpg", "Meadow/meadow_88.jpg", "Meadow/meadow_33.jpg", "Meadow/meadow_51.jpg", "Meadow/meadow_28.jpg", "Meadow/meadow_159.jpg", "Meadow/meadow_127.jpg", "Meadow/meadow_250.jpg", "Meadow/meadow_4.jpg", "Meadow/meadow_71.jpg", "Meadow/meadow_179.jpg", "Meadow/meadow_248.jpg", "Meadow/meadow_202.jpg", "Meadow/meadow_124.jpg", "Meadow/meadow_240.jpg", "Meadow/meadow_212.jpg", "Meadow/meadow_228.jpg", "Meadow/meadow_230.jpg", "Meadow/meadow_98.jpg", "Meadow/meadow_12.jpg", "Meadow/meadow_277.jpg", "Meadow/meadow_13.jpg", "Meadow/meadow_44.jpg", "Meadow/meadow_102.jpg", "Meadow/meadow_31.jpg", "Meadow/meadow_64.jpg", "Meadow/meadow_166.jpg", "Meadow/meadow_109.jpg", "Meadow/meadow_120.jpg", "Meadow/meadow_30.jpg", "Meadow/meadow_224.jpg", "Parking/parking_223.jpg", "Parking/parking_382.jpg", "Parking/parking_196.jpg", "Parking/parking_377.jpg", "Parking/parking_362.jpg", "Parking/parking_47.jpg", "Parking/parking_55.jpg", "Parking/parking_32.jpg", "Parking/parking_144.jpg", "Parking/parking_137.jpg", "Parking/parking_364.jpg", "Parking/parking_199.jpg", "Parking/parking_387.jpg", "Parking/parking_16.jpg", "Parking/parking_23.jpg", "Parking/parking_83.jpg", "Parking/parking_268.jpg", "Parking/parking_242.jpg", "Parking/parking_260.jpg", "Parking/parking_41.jpg", "Parking/parking_226.jpg", "Parking/parking_267.jpg", "Parking/parking_220.jpg", "Parking/parking_332.jpg", "Parking/parking_213.jpg", "Parking/parking_68.jpg", "Parking/parking_283.jpg", "Parking/parking_238.jpg", "Parking/parking_142.jpg", "Parking/parking_44.jpg", "Parking/parking_225.jpg", "Parking/parking_25.jpg", "Parking/parking_133.jpg", "Parking/parking_71.jpg", "Parking/parking_104.jpg", "Parking/parking_167.jpg", "Parking/parking_60.jpg", "Parking/parking_384.jpg", "Parking/parking_78.jpg", "Parking/parking_28.jpg", "Parking/parking_145.jpg", "Parking/parking_314.jpg", "Parking/parking_38.jpg", "Parking/parking_190.jpg", "Parking/parking_93.jpg", "Parking/parking_129.jpg", "Parking/parking_327.jpg", "Parking/parking_30.jpg", "Parking/parking_290.jpg", "Parking/parking_132.jpg", "Parking/parking_258.jpg", "Parking/parking_360.jpg", "Parking/parking_285.jpg", "Parking/parking_135.jpg", "Parking/parking_212.jpg", "Parking/parking_261.jpg", "Parking/parking_94.jpg", "Parking/parking_351.jpg", "Parking/parking_248.jpg", "Parking/parking_299.jpg", "Parking/parking_340.jpg", "Parking/parking_179.jpg", "Parking/parking_66.jpg", "Parking/parking_308.jpg", "Parking/parking_57.jpg", "Parking/parking_151.jpg", "Parking/parking_156.jpg", "Parking/parking_122.jpg", "Parking/parking_5.jpg", "Parking/parking_354.jpg", "Parking/parking_350.jpg", "Parking/parking_46.jpg", "Parking/parking_348.jpg", "Parking/parking_316.jpg", "Parking/parking_246.jpg", "Parking/parking_39.jpg", "Parking/parking_158.jpg", "Parking/parking_309.jpg", "School/school_249.jpg", "School/school_116.jpg", "School/school_263.jpg", "School/school_287.jpg", "School/school_31.jpg", "School/school_38.jpg", "School/school_114.jpg", "School/school_299.jpg", "School/school_1.jpg", "School/school_257.jpg", "School/school_11.jpg", "School/school_300.jpg", "School/school_272.jpg", "School/school_245.jpg", "School/school_51.jpg", "School/school_241.jpg", "School/school_196.jpg", "School/school_201.jpg", "School/school_205.jpg", "School/school_61.jpg", "School/school_248.jpg", "School/school_131.jpg", "School/school_173.jpg", "School/school_192.jpg", "School/school_269.jpg", "School/school_250.jpg", "School/school_80.jpg", "School/school_194.jpg", "School/school_59.jpg", "School/school_283.jpg", "School/school_69.jpg", "School/school_93.jpg", "School/school_225.jpg", "School/school_243.jpg", "School/school_124.jpg", "School/school_270.jpg", "School/school_216.jpg", "School/school_149.jpg", "School/school_92.jpg", "School/school_134.jpg", "School/school_195.jpg", "School/school_56.jpg", "School/school_63.jpg", "School/school_136.jpg", "School/school_87.jpg", "School/school_83.jpg", "School/school_111.jpg", "School/school_55.jpg", "School/school_127.jpg", "School/school_118.jpg", "School/school_107.jpg", "School/school_210.jpg", "School/school_89.jpg", "School/school_151.jpg", "School/school_188.jpg", "School/school_220.jpg", "School/school_47.jpg", "School/school_203.jpg", "School/school_226.jpg", "School/school_165.jpg", "StorageTanks/storagetanks_235.jpg", "StorageTanks/storagetanks_179.jpg", "StorageTanks/storagetanks_125.jpg", "StorageTanks/storagetanks_338.jpg", "StorageTanks/storagetanks_234.jpg", "StorageTanks/storagetanks_225.jpg", "StorageTanks/storagetanks_350.jpg", "StorageTanks/storagetanks_336.jpg", "StorageTanks/storagetanks_289.jpg", "StorageTanks/storagetanks_43.jpg", "StorageTanks/storagetanks_41.jpg", "StorageTanks/storagetanks_90.jpg", "StorageTanks/storagetanks_133.jpg", "StorageTanks/storagetanks_28.jpg", "StorageTanks/storagetanks_108.jpg", "StorageTanks/storagetanks_220.jpg", "StorageTanks/storagetanks_6.jpg", "StorageTanks/storagetanks_81.jpg", "StorageTanks/storagetanks_173.jpg", "StorageTanks/storagetanks_309.jpg", "StorageTanks/storagetanks_317.jpg", "StorageTanks/storagetanks_259.jpg", "StorageTanks/storagetanks_159.jpg", "StorageTanks/storagetanks_295.jpg", "StorageTanks/storagetanks_36.jpg", "StorageTanks/storagetanks_172.jpg", "StorageTanks/storagetanks_265.jpg", "StorageTanks/storagetanks_14.jpg", "StorageTanks/storagetanks_351.jpg", "StorageTanks/storagetanks_92.jpg", "StorageTanks/storagetanks_116.jpg", "StorageTanks/storagetanks_187.jpg", "StorageTanks/storagetanks_206.jpg", "StorageTanks/storagetanks_178.jpg", "StorageTanks/storagetanks_122.jpg", "StorageTanks/storagetanks_17.jpg", "StorageTanks/storagetanks_249.jpg", "StorageTanks/storagetanks_354.jpg", "StorageTanks/storagetanks_246.jpg", "StorageTanks/storagetanks_146.jpg", "StorageTanks/storagetanks_254.jpg", "StorageTanks/storagetanks_276.jpg", "StorageTanks/storagetanks_34.jpg", "StorageTanks/storagetanks_73.jpg", "StorageTanks/storagetanks_193.jpg", "StorageTanks/storagetanks_107.jpg", "StorageTanks/storagetanks_320.jpg", "StorageTanks/storagetanks_69.jpg", "StorageTanks/storagetanks_96.jpg", "StorageTanks/storagetanks_32.jpg", "StorageTanks/storagetanks_304.jpg", "StorageTanks/storagetanks_303.jpg", "StorageTanks/storagetanks_1.jpg", "StorageTanks/storagetanks_158.jpg", "StorageTanks/storagetanks_245.jpg", "StorageTanks/storagetanks_11.jpg", "StorageTanks/storagetanks_83.jpg", "StorageTanks/storagetanks_3.jpg", "StorageTanks/storagetanks_209.jpg", "StorageTanks/storagetanks_54.jpg", "StorageTanks/storagetanks_226.jpg", "StorageTanks/storagetanks_58.jpg", "StorageTanks/storagetanks_195.jpg", "StorageTanks/storagetanks_329.jpg", "StorageTanks/storagetanks_160.jpg", "StorageTanks/storagetanks_157.jpg", "StorageTanks/storagetanks_222.jpg", "StorageTanks/storagetanks_44.jpg", "StorageTanks/storagetanks_64.jpg", "StorageTanks/storagetanks_355.jpg", "StorageTanks/storagetanks_282.jpg", "StorageTanks/storagetanks_307.jpg"]} \ No newline at end of file diff --git a/data_split/UC_split.json b/data_split/UC_split.json new file mode 100644 index 0000000000000000000000000000000000000000..28df9d0df4af87e67329520b18799127e7beae26 --- /dev/null +++ b/data_split/UC_split.json @@ -0,0 +1 @@ +{"train": ["agricultural/agricultural49.tif", "agricultural/agricultural58.tif", "agricultural/agricultural24.tif", "agricultural/agricultural44.tif", "agricultural/agricultural17.tif", "agricultural/agricultural21.tif", "agricultural/agricultural94.tif", "agricultural/agricultural50.tif", "agricultural/agricultural34.tif", "agricultural/agricultural16.tif", "agricultural/agricultural92.tif", "agricultural/agricultural62.tif", "agricultural/agricultural59.tif", "agricultural/agricultural87.tif", "agricultural/agricultural28.tif", "agricultural/agricultural79.tif", "agricultural/agricultural05.tif", "agricultural/agricultural43.tif", "agricultural/agricultural55.tif", "agricultural/agricultural51.tif", "agricultural/agricultural75.tif", "agricultural/agricultural57.tif", "agricultural/agricultural99.tif", "agricultural/agricultural83.tif", "agricultural/agricultural73.tif", "agricultural/agricultural04.tif", "agricultural/agricultural69.tif", "agricultural/agricultural42.tif", "agricultural/agricultural70.tif", "agricultural/agricultural78.tif", "agricultural/agricultural71.tif", "agricultural/agricultural54.tif", "agricultural/agricultural77.tif", "agricultural/agricultural39.tif", "agricultural/agricultural32.tif", "agricultural/agricultural81.tif", "agricultural/agricultural33.tif", "agricultural/agricultural84.tif", "agricultural/agricultural89.tif", "agricultural/agricultural13.tif", "agricultural/agricultural61.tif", "agricultural/agricultural41.tif", "agricultural/agricultural31.tif", "agricultural/agricultural65.tif", "agricultural/agricultural18.tif", "agricultural/agricultural80.tif", "agricultural/agricultural12.tif", "agricultural/agricultural37.tif", "agricultural/agricultural82.tif", "agricultural/agricultural06.tif", "agricultural/agricultural85.tif", "agricultural/agricultural95.tif", "agricultural/agricultural52.tif", "agricultural/agricultural14.tif", "agricultural/agricultural72.tif", "agricultural/agricultural86.tif", "agricultural/agricultural10.tif", "agricultural/agricultural56.tif", "agricultural/agricultural90.tif", "agricultural/agricultural63.tif", "airplane/airplane53.tif", "airplane/airplane22.tif", "airplane/airplane00.tif", "airplane/airplane99.tif", "airplane/airplane10.tif", "airplane/airplane31.tif", "airplane/airplane32.tif", "airplane/airplane90.tif", "airplane/airplane51.tif", "airplane/airplane07.tif", "airplane/airplane82.tif", "airplane/airplane48.tif", "airplane/airplane93.tif", "airplane/airplane39.tif", "airplane/airplane52.tif", "airplane/airplane49.tif", "airplane/airplane84.tif", "airplane/airplane73.tif", "airplane/airplane05.tif", "airplane/airplane01.tif", "airplane/airplane14.tif", "airplane/airplane50.tif", "airplane/airplane59.tif", "airplane/airplane57.tif", "airplane/airplane68.tif", "airplane/airplane72.tif", "airplane/airplane04.tif", "airplane/airplane78.tif", "airplane/airplane28.tif", "airplane/airplane26.tif", "airplane/airplane83.tif", "airplane/airplane55.tif", "airplane/airplane66.tif", "airplane/airplane92.tif", "airplane/airplane60.tif", "airplane/airplane58.tif", "airplane/airplane63.tif", "airplane/airplane81.tif", "airplane/airplane21.tif", "airplane/airplane69.tif", "airplane/airplane18.tif", "airplane/airplane54.tif", "airplane/airplane44.tif", "airplane/airplane87.tif", "airplane/airplane62.tif", "airplane/airplane30.tif", "airplane/airplane76.tif", "airplane/airplane24.tif", "airplane/airplane36.tif", "airplane/airplane56.tif", "airplane/airplane38.tif", "airplane/airplane75.tif", "airplane/airplane70.tif", "airplane/airplane79.tif", "airplane/airplane41.tif", "airplane/airplane89.tif", "airplane/airplane06.tif", "airplane/airplane67.tif", "airplane/airplane02.tif", "airplane/airplane45.tif", "baseballdiamond/baseballdiamond63.tif", "baseballdiamond/baseballdiamond39.tif", "baseballdiamond/baseballdiamond67.tif", "baseballdiamond/baseballdiamond10.tif", "baseballdiamond/baseballdiamond80.tif", "baseballdiamond/baseballdiamond11.tif", "baseballdiamond/baseballdiamond46.tif", "baseballdiamond/baseballdiamond77.tif", "baseballdiamond/baseballdiamond33.tif", "baseballdiamond/baseballdiamond76.tif", "baseballdiamond/baseballdiamond78.tif", "baseballdiamond/baseballdiamond96.tif", "baseballdiamond/baseballdiamond84.tif", "baseballdiamond/baseballdiamond42.tif", "baseballdiamond/baseballdiamond40.tif", "baseballdiamond/baseballdiamond02.tif", "baseballdiamond/baseballdiamond45.tif", "baseballdiamond/baseballdiamond86.tif", "baseballdiamond/baseballdiamond49.tif", "baseballdiamond/baseballdiamond43.tif", "baseballdiamond/baseballdiamond59.tif", "baseballdiamond/baseballdiamond03.tif", "baseballdiamond/baseballdiamond01.tif", "baseballdiamond/baseballdiamond26.tif", "baseballdiamond/baseballdiamond69.tif", "baseballdiamond/baseballdiamond18.tif", "baseballdiamond/baseballdiamond44.tif", "baseballdiamond/baseballdiamond68.tif", "baseballdiamond/baseballdiamond14.tif", "baseballdiamond/baseballdiamond94.tif", "baseballdiamond/baseballdiamond22.tif", "baseballdiamond/baseballdiamond00.tif", "baseballdiamond/baseballdiamond05.tif", "baseballdiamond/baseballdiamond60.tif", "baseballdiamond/baseballdiamond57.tif", "baseballdiamond/baseballdiamond51.tif", "baseballdiamond/baseballdiamond65.tif", "baseballdiamond/baseballdiamond06.tif", "baseballdiamond/baseballdiamond28.tif", "baseballdiamond/baseballdiamond20.tif", "baseballdiamond/baseballdiamond23.tif", "baseballdiamond/baseballdiamond97.tif", "baseballdiamond/baseballdiamond13.tif", "baseballdiamond/baseballdiamond87.tif", "baseballdiamond/baseballdiamond70.tif", "baseballdiamond/baseballdiamond66.tif", "baseballdiamond/baseballdiamond09.tif", "baseballdiamond/baseballdiamond19.tif", "baseballdiamond/baseballdiamond95.tif", "baseballdiamond/baseballdiamond12.tif", "baseballdiamond/baseballdiamond75.tif", "baseballdiamond/baseballdiamond07.tif", "baseballdiamond/baseballdiamond15.tif", "baseballdiamond/baseballdiamond54.tif", "baseballdiamond/baseballdiamond32.tif", "baseballdiamond/baseballdiamond48.tif", "baseballdiamond/baseballdiamond61.tif", "baseballdiamond/baseballdiamond16.tif", "baseballdiamond/baseballdiamond29.tif", "baseballdiamond/baseballdiamond47.tif", "beach/beach16.tif", "beach/beach73.tif", "beach/beach43.tif", "beach/beach64.tif", "beach/beach84.tif", "beach/beach34.tif", "beach/beach01.tif", "beach/beach44.tif", "beach/beach49.tif", "beach/beach21.tif", "beach/beach52.tif", "beach/beach86.tif", "beach/beach40.tif", "beach/beach00.tif", "beach/beach90.tif", "beach/beach57.tif", "beach/beach91.tif", "beach/beach22.tif", "beach/beach23.tif", "beach/beach28.tif", "beach/beach30.tif", "beach/beach26.tif", "beach/beach25.tif", "beach/beach09.tif", "beach/beach79.tif", "beach/beach48.tif", "beach/beach87.tif", "beach/beach03.tif", "beach/beach17.tif", "beach/beach60.tif", "beach/beach19.tif", "beach/beach78.tif", "beach/beach80.tif", "beach/beach37.tif", "beach/beach72.tif", "beach/beach24.tif", "beach/beach85.tif", "beach/beach59.tif", "beach/beach54.tif", "beach/beach07.tif", "beach/beach33.tif", "beach/beach71.tif", "beach/beach18.tif", "beach/beach65.tif", "beach/beach67.tif", "beach/beach38.tif", "beach/beach89.tif", "beach/beach74.tif", "beach/beach15.tif", "beach/beach20.tif", "beach/beach50.tif", "beach/beach76.tif", "beach/beach99.tif", "beach/beach69.tif", "beach/beach93.tif", "beach/beach06.tif", "beach/beach27.tif", "beach/beach83.tif", "beach/beach63.tif", "beach/beach62.tif", "buildings/buildings06.tif", "buildings/buildings94.tif", "buildings/buildings37.tif", "buildings/buildings08.tif", "buildings/buildings18.tif", "buildings/buildings33.tif", "buildings/buildings58.tif", "buildings/buildings95.tif", "buildings/buildings56.tif", "buildings/buildings29.tif", "buildings/buildings89.tif", "buildings/buildings20.tif", "buildings/buildings90.tif", "buildings/buildings83.tif", "buildings/buildings13.tif", "buildings/buildings03.tif", "buildings/buildings39.tif", "buildings/buildings31.tif", "buildings/buildings64.tif", "buildings/buildings05.tif", "buildings/buildings24.tif", "buildings/buildings71.tif", "buildings/buildings78.tif", "buildings/buildings76.tif", "buildings/buildings88.tif", "buildings/buildings02.tif", "buildings/buildings72.tif", "buildings/buildings92.tif", "buildings/buildings82.tif", "buildings/buildings07.tif", "buildings/buildings77.tif", "buildings/buildings87.tif", "buildings/buildings53.tif", "buildings/buildings17.tif", "buildings/buildings66.tif", "buildings/buildings81.tif", "buildings/buildings65.tif", "buildings/buildings68.tif", "buildings/buildings99.tif", "buildings/buildings42.tif", "buildings/buildings16.tif", "buildings/buildings85.tif", "buildings/buildings55.tif", "buildings/buildings14.tif", "buildings/buildings48.tif", "buildings/buildings69.tif", "buildings/buildings32.tif", "buildings/buildings67.tif", "buildings/buildings70.tif", "buildings/buildings40.tif", "buildings/buildings00.tif", "buildings/buildings57.tif", "buildings/buildings26.tif", "buildings/buildings04.tif", "buildings/buildings75.tif", "buildings/buildings80.tif", "buildings/buildings52.tif", "buildings/buildings10.tif", "buildings/buildings35.tif", "buildings/buildings30.tif", "chaparral/chaparral80.tif", "chaparral/chaparral16.tif", "chaparral/chaparral10.tif", "chaparral/chaparral33.tif", "chaparral/chaparral28.tif", "chaparral/chaparral32.tif", "chaparral/chaparral71.tif", "chaparral/chaparral97.tif", "chaparral/chaparral88.tif", "chaparral/chaparral17.tif", "chaparral/chaparral05.tif", "chaparral/chaparral09.tif", "chaparral/chaparral46.tif", "chaparral/chaparral49.tif", "chaparral/chaparral91.tif", "chaparral/chaparral92.tif", "chaparral/chaparral02.tif", "chaparral/chaparral68.tif", "chaparral/chaparral18.tif", "chaparral/chaparral25.tif", "chaparral/chaparral00.tif", "chaparral/chaparral11.tif", "chaparral/chaparral50.tif", "chaparral/chaparral24.tif", "chaparral/chaparral54.tif", "chaparral/chaparral81.tif", "chaparral/chaparral58.tif", "chaparral/chaparral85.tif", "chaparral/chaparral75.tif", "chaparral/chaparral41.tif", "chaparral/chaparral90.tif", "chaparral/chaparral62.tif", "chaparral/chaparral22.tif", "chaparral/chaparral76.tif", "chaparral/chaparral48.tif", "chaparral/chaparral65.tif", "chaparral/chaparral08.tif", "chaparral/chaparral53.tif", "chaparral/chaparral45.tif", "chaparral/chaparral01.tif", "chaparral/chaparral21.tif", "chaparral/chaparral63.tif", "chaparral/chaparral26.tif", "chaparral/chaparral64.tif", "chaparral/chaparral03.tif", "chaparral/chaparral31.tif", "chaparral/chaparral59.tif", "chaparral/chaparral82.tif", "chaparral/chaparral19.tif", "chaparral/chaparral51.tif", "chaparral/chaparral23.tif", "chaparral/chaparral07.tif", "chaparral/chaparral56.tif", "chaparral/chaparral39.tif", "chaparral/chaparral34.tif", "chaparral/chaparral36.tif", "chaparral/chaparral79.tif", "chaparral/chaparral94.tif", "chaparral/chaparral42.tif", "chaparral/chaparral35.tif", "denseresidential/denseresidential07.tif", "denseresidential/denseresidential01.tif", "denseresidential/denseresidential16.tif", "denseresidential/denseresidential30.tif", "denseresidential/denseresidential80.tif", "denseresidential/denseresidential56.tif", "denseresidential/denseresidential08.tif", "denseresidential/denseresidential95.tif", "denseresidential/denseresidential61.tif", "denseresidential/denseresidential77.tif", "denseresidential/denseresidential93.tif", "denseresidential/denseresidential04.tif", "denseresidential/denseresidential99.tif", "denseresidential/denseresidential86.tif", "denseresidential/denseresidential97.tif", "denseresidential/denseresidential82.tif", "denseresidential/denseresidential96.tif", "denseresidential/denseresidential87.tif", "denseresidential/denseresidential84.tif", "denseresidential/denseresidential90.tif", "denseresidential/denseresidential41.tif", "denseresidential/denseresidential53.tif", "denseresidential/denseresidential67.tif", "denseresidential/denseresidential21.tif", "denseresidential/denseresidential11.tif", "denseresidential/denseresidential15.tif", "denseresidential/denseresidential68.tif", "denseresidential/denseresidential00.tif", "denseresidential/denseresidential13.tif", "denseresidential/denseresidential49.tif", "denseresidential/denseresidential76.tif", "denseresidential/denseresidential06.tif", "denseresidential/denseresidential24.tif", "denseresidential/denseresidential55.tif", "denseresidential/denseresidential71.tif", "denseresidential/denseresidential34.tif", "denseresidential/denseresidential62.tif", "denseresidential/denseresidential37.tif", "denseresidential/denseresidential20.tif", "denseresidential/denseresidential81.tif", "denseresidential/denseresidential85.tif", "denseresidential/denseresidential02.tif", "denseresidential/denseresidential92.tif", "denseresidential/denseresidential27.tif", "denseresidential/denseresidential26.tif", "denseresidential/denseresidential05.tif", "denseresidential/denseresidential12.tif", "denseresidential/denseresidential66.tif", "denseresidential/denseresidential44.tif", "denseresidential/denseresidential83.tif", "denseresidential/denseresidential33.tif", "denseresidential/denseresidential74.tif", "denseresidential/denseresidential17.tif", "denseresidential/denseresidential60.tif", "denseresidential/denseresidential75.tif", "denseresidential/denseresidential39.tif", "denseresidential/denseresidential73.tif", "denseresidential/denseresidential38.tif", "denseresidential/denseresidential10.tif", "denseresidential/denseresidential19.tif", "forest/forest87.tif", "forest/forest05.tif", "forest/forest13.tif", "forest/forest37.tif", "forest/forest07.tif", "forest/forest34.tif", "forest/forest30.tif", "forest/forest26.tif", "forest/forest80.tif", "forest/forest79.tif", "forest/forest70.tif", "forest/forest16.tif", "forest/forest20.tif", "forest/forest18.tif", "forest/forest90.tif", "forest/forest94.tif", "forest/forest33.tif", "forest/forest78.tif", "forest/forest76.tif", "forest/forest41.tif", "forest/forest48.tif", "forest/forest23.tif", "forest/forest43.tif", "forest/forest61.tif", "forest/forest72.tif", "forest/forest10.tif", "forest/forest49.tif", "forest/forest86.tif", "forest/forest82.tif", "forest/forest65.tif", "forest/forest46.tif", "forest/forest66.tif", "forest/forest97.tif", "forest/forest50.tif", "forest/forest59.tif", "forest/forest08.tif", "forest/forest98.tif", "forest/forest19.tif", "forest/forest14.tif", "forest/forest75.tif", "forest/forest77.tif", "forest/forest15.tif", "forest/forest44.tif", "forest/forest91.tif", "forest/forest57.tif", "forest/forest21.tif", "forest/forest99.tif", "forest/forest47.tif", "forest/forest60.tif", "forest/forest56.tif", "forest/forest84.tif", "forest/forest95.tif", "forest/forest63.tif", "forest/forest71.tif", "forest/forest83.tif", "forest/forest51.tif", "forest/forest58.tif", "forest/forest73.tif", "forest/forest28.tif", "forest/forest27.tif", "freeway/freeway15.tif", "freeway/freeway66.tif", "freeway/freeway58.tif", "freeway/freeway53.tif", "freeway/freeway82.tif", "freeway/freeway27.tif", "freeway/freeway41.tif", "freeway/freeway16.tif", "freeway/freeway22.tif", "freeway/freeway86.tif", "freeway/freeway48.tif", "freeway/freeway63.tif", "freeway/freeway39.tif", "freeway/freeway00.tif", "freeway/freeway31.tif", "freeway/freeway29.tif", "freeway/freeway62.tif", "freeway/freeway02.tif", "freeway/freeway78.tif", "freeway/freeway19.tif", "freeway/freeway94.tif", "freeway/freeway08.tif", "freeway/freeway59.tif", "freeway/freeway13.tif", "freeway/freeway99.tif", "freeway/freeway49.tif", "freeway/freeway50.tif", "freeway/freeway95.tif", "freeway/freeway51.tif", "freeway/freeway89.tif", "freeway/freeway37.tif", "freeway/freeway11.tif", "freeway/freeway91.tif", "freeway/freeway77.tif", "freeway/freeway85.tif", "freeway/freeway10.tif", "freeway/freeway60.tif", "freeway/freeway40.tif", "freeway/freeway23.tif", "freeway/freeway72.tif", "freeway/freeway38.tif", "freeway/freeway09.tif", "freeway/freeway30.tif", "freeway/freeway18.tif", "freeway/freeway12.tif", "freeway/freeway75.tif", "freeway/freeway42.tif", "freeway/freeway92.tif", "freeway/freeway34.tif", "freeway/freeway88.tif", "freeway/freeway43.tif", "freeway/freeway24.tif", "freeway/freeway79.tif", "freeway/freeway69.tif", "freeway/freeway81.tif", "freeway/freeway64.tif", "freeway/freeway32.tif", "freeway/freeway44.tif", "freeway/freeway90.tif", "freeway/freeway76.tif", "golfcourse/golfcourse68.tif", "golfcourse/golfcourse62.tif", "golfcourse/golfcourse17.tif", "golfcourse/golfcourse43.tif", "golfcourse/golfcourse79.tif", "golfcourse/golfcourse40.tif", "golfcourse/golfcourse13.tif", "golfcourse/golfcourse19.tif", "golfcourse/golfcourse22.tif", "golfcourse/golfcourse82.tif", "golfcourse/golfcourse05.tif", "golfcourse/golfcourse37.tif", "golfcourse/golfcourse06.tif", "golfcourse/golfcourse50.tif", "golfcourse/golfcourse00.tif", "golfcourse/golfcourse30.tif", "golfcourse/golfcourse89.tif", "golfcourse/golfcourse46.tif", "golfcourse/golfcourse86.tif", "golfcourse/golfcourse49.tif", "golfcourse/golfcourse01.tif", "golfcourse/golfcourse56.tif", "golfcourse/golfcourse41.tif", "golfcourse/golfcourse61.tif", "golfcourse/golfcourse81.tif", "golfcourse/golfcourse20.tif", "golfcourse/golfcourse31.tif", "golfcourse/golfcourse09.tif", "golfcourse/golfcourse42.tif", "golfcourse/golfcourse12.tif", "golfcourse/golfcourse32.tif", "golfcourse/golfcourse70.tif", "golfcourse/golfcourse80.tif", "golfcourse/golfcourse39.tif", "golfcourse/golfcourse63.tif", "golfcourse/golfcourse07.tif", "golfcourse/golfcourse18.tif", "golfcourse/golfcourse75.tif", "golfcourse/golfcourse28.tif", "golfcourse/golfcourse72.tif", "golfcourse/golfcourse29.tif", "golfcourse/golfcourse52.tif", "golfcourse/golfcourse57.tif", "golfcourse/golfcourse48.tif", "golfcourse/golfcourse38.tif", "golfcourse/golfcourse71.tif", "golfcourse/golfcourse92.tif", "golfcourse/golfcourse47.tif", "golfcourse/golfcourse96.tif", "golfcourse/golfcourse83.tif", "golfcourse/golfcourse76.tif", "golfcourse/golfcourse98.tif", "golfcourse/golfcourse73.tif", "golfcourse/golfcourse78.tif", "golfcourse/golfcourse53.tif", "golfcourse/golfcourse94.tif", "golfcourse/golfcourse33.tif", "golfcourse/golfcourse51.tif", "golfcourse/golfcourse54.tif", "golfcourse/golfcourse44.tif", "harbor/harbor11.tif", "harbor/harbor98.tif", "harbor/harbor33.tif", "harbor/harbor06.tif", "harbor/harbor27.tif", "harbor/harbor46.tif", "harbor/harbor23.tif", "harbor/harbor50.tif", "harbor/harbor18.tif", "harbor/harbor48.tif", "harbor/harbor03.tif", "harbor/harbor70.tif", "harbor/harbor82.tif", "harbor/harbor85.tif", "harbor/harbor04.tif", "harbor/harbor65.tif", "harbor/harbor64.tif", "harbor/harbor67.tif", "harbor/harbor51.tif", "harbor/harbor29.tif", "harbor/harbor78.tif", "harbor/harbor07.tif", "harbor/harbor10.tif", "harbor/harbor09.tif", "harbor/harbor16.tif", "harbor/harbor45.tif", "harbor/harbor19.tif", "harbor/harbor92.tif", "harbor/harbor53.tif", "harbor/harbor47.tif", "harbor/harbor08.tif", "harbor/harbor22.tif", "harbor/harbor57.tif", "harbor/harbor69.tif", "harbor/harbor61.tif", "harbor/harbor74.tif", "harbor/harbor68.tif", "harbor/harbor13.tif", "harbor/harbor56.tif", "harbor/harbor37.tif", "harbor/harbor90.tif", "harbor/harbor43.tif", "harbor/harbor54.tif", "harbor/harbor55.tif", "harbor/harbor26.tif", "harbor/harbor35.tif", "harbor/harbor81.tif", "harbor/harbor71.tif", "harbor/harbor02.tif", "harbor/harbor80.tif", "harbor/harbor41.tif", "harbor/harbor99.tif", "harbor/harbor75.tif", "harbor/harbor79.tif", "harbor/harbor25.tif", "harbor/harbor84.tif", "harbor/harbor89.tif", "harbor/harbor58.tif", "harbor/harbor77.tif", "harbor/harbor72.tif", "intersection/intersection75.tif", "intersection/intersection10.tif", "intersection/intersection23.tif", "intersection/intersection41.tif", "intersection/intersection65.tif", "intersection/intersection15.tif", "intersection/intersection38.tif", "intersection/intersection77.tif", "intersection/intersection50.tif", "intersection/intersection13.tif", "intersection/intersection55.tif", "intersection/intersection96.tif", "intersection/intersection99.tif", "intersection/intersection90.tif", "intersection/intersection60.tif", "intersection/intersection30.tif", "intersection/intersection62.tif", "intersection/intersection95.tif", "intersection/intersection92.tif", "intersection/intersection28.tif", "intersection/intersection46.tif", "intersection/intersection49.tif", "intersection/intersection40.tif", "intersection/intersection24.tif", "intersection/intersection45.tif", "intersection/intersection53.tif", "intersection/intersection12.tif", "intersection/intersection36.tif", "intersection/intersection27.tif", "intersection/intersection80.tif", "intersection/intersection34.tif", "intersection/intersection21.tif", "intersection/intersection05.tif", "intersection/intersection54.tif", "intersection/intersection98.tif", "intersection/intersection37.tif", "intersection/intersection33.tif", "intersection/intersection59.tif", "intersection/intersection64.tif", "intersection/intersection47.tif", "intersection/intersection70.tif", "intersection/intersection02.tif", "intersection/intersection89.tif", "intersection/intersection20.tif", "intersection/intersection04.tif", "intersection/intersection32.tif", "intersection/intersection63.tif", "intersection/intersection17.tif", "intersection/intersection42.tif", "intersection/intersection57.tif", "intersection/intersection67.tif", "intersection/intersection11.tif", "intersection/intersection08.tif", "intersection/intersection71.tif", "intersection/intersection83.tif", "intersection/intersection51.tif", "intersection/intersection58.tif", "intersection/intersection06.tif", "intersection/intersection19.tif", "intersection/intersection69.tif", "mediumresidential/mediumresidential52.tif", "mediumresidential/mediumresidential17.tif", "mediumresidential/mediumresidential06.tif", "mediumresidential/mediumresidential47.tif", "mediumresidential/mediumresidential27.tif", "mediumresidential/mediumresidential21.tif", "mediumresidential/mediumresidential48.tif", "mediumresidential/mediumresidential45.tif", "mediumresidential/mediumresidential10.tif", "mediumresidential/mediumresidential07.tif", "mediumresidential/mediumresidential36.tif", "mediumresidential/mediumresidential65.tif", "mediumresidential/mediumresidential53.tif", "mediumresidential/mediumresidential38.tif", "mediumresidential/mediumresidential33.tif", "mediumresidential/mediumresidential42.tif", "mediumresidential/mediumresidential16.tif", "mediumresidential/mediumresidential78.tif", "mediumresidential/mediumresidential88.tif", "mediumresidential/mediumresidential03.tif", "mediumresidential/mediumresidential35.tif", "mediumresidential/mediumresidential01.tif", "mediumresidential/mediumresidential14.tif", "mediumresidential/mediumresidential19.tif", "mediumresidential/mediumresidential73.tif", "mediumresidential/mediumresidential79.tif", "mediumresidential/mediumresidential37.tif", "mediumresidential/mediumresidential44.tif", "mediumresidential/mediumresidential54.tif", "mediumresidential/mediumresidential28.tif", "mediumresidential/mediumresidential22.tif", "mediumresidential/mediumresidential39.tif", "mediumresidential/mediumresidential51.tif", "mediumresidential/mediumresidential97.tif", "mediumresidential/mediumresidential59.tif", "mediumresidential/mediumresidential77.tif", "mediumresidential/mediumresidential25.tif", "mediumresidential/mediumresidential82.tif", "mediumresidential/mediumresidential12.tif", "mediumresidential/mediumresidential13.tif", "mediumresidential/mediumresidential02.tif", "mediumresidential/mediumresidential89.tif", "mediumresidential/mediumresidential15.tif", "mediumresidential/mediumresidential49.tif", "mediumresidential/mediumresidential75.tif", "mediumresidential/mediumresidential95.tif", "mediumresidential/mediumresidential96.tif", "mediumresidential/mediumresidential63.tif", "mediumresidential/mediumresidential58.tif", "mediumresidential/mediumresidential87.tif", "mediumresidential/mediumresidential11.tif", "mediumresidential/mediumresidential55.tif", "mediumresidential/mediumresidential80.tif", "mediumresidential/mediumresidential64.tif", "mediumresidential/mediumresidential66.tif", "mediumresidential/mediumresidential57.tif", "mediumresidential/mediumresidential94.tif", "mediumresidential/mediumresidential81.tif", "mediumresidential/mediumresidential91.tif", "mediumresidential/mediumresidential70.tif", "mobilehomepark/mobilehomepark05.tif", "mobilehomepark/mobilehomepark37.tif", "mobilehomepark/mobilehomepark27.tif", "mobilehomepark/mobilehomepark26.tif", "mobilehomepark/mobilehomepark72.tif", "mobilehomepark/mobilehomepark33.tif", "mobilehomepark/mobilehomepark62.tif", "mobilehomepark/mobilehomepark22.tif", "mobilehomepark/mobilehomepark25.tif", "mobilehomepark/mobilehomepark06.tif", "mobilehomepark/mobilehomepark46.tif", "mobilehomepark/mobilehomepark00.tif", "mobilehomepark/mobilehomepark56.tif", "mobilehomepark/mobilehomepark03.tif", "mobilehomepark/mobilehomepark60.tif", "mobilehomepark/mobilehomepark98.tif", "mobilehomepark/mobilehomepark77.tif", "mobilehomepark/mobilehomepark13.tif", "mobilehomepark/mobilehomepark95.tif", "mobilehomepark/mobilehomepark45.tif", "mobilehomepark/mobilehomepark88.tif", "mobilehomepark/mobilehomepark04.tif", "mobilehomepark/mobilehomepark87.tif", "mobilehomepark/mobilehomepark50.tif", "mobilehomepark/mobilehomepark09.tif", "mobilehomepark/mobilehomepark71.tif", "mobilehomepark/mobilehomepark31.tif", "mobilehomepark/mobilehomepark99.tif", "mobilehomepark/mobilehomepark97.tif", "mobilehomepark/mobilehomepark23.tif", "mobilehomepark/mobilehomepark81.tif", "mobilehomepark/mobilehomepark70.tif", "mobilehomepark/mobilehomepark02.tif", "mobilehomepark/mobilehomepark85.tif", "mobilehomepark/mobilehomepark54.tif", "mobilehomepark/mobilehomepark69.tif", "mobilehomepark/mobilehomepark55.tif", "mobilehomepark/mobilehomepark49.tif", "mobilehomepark/mobilehomepark74.tif", "mobilehomepark/mobilehomepark53.tif", "mobilehomepark/mobilehomepark14.tif", "mobilehomepark/mobilehomepark57.tif", "mobilehomepark/mobilehomepark82.tif", "mobilehomepark/mobilehomepark92.tif", "mobilehomepark/mobilehomepark80.tif", "mobilehomepark/mobilehomepark16.tif", "mobilehomepark/mobilehomepark19.tif", "mobilehomepark/mobilehomepark91.tif", "mobilehomepark/mobilehomepark86.tif", "mobilehomepark/mobilehomepark39.tif", "mobilehomepark/mobilehomepark30.tif", "mobilehomepark/mobilehomepark61.tif", "mobilehomepark/mobilehomepark90.tif", "mobilehomepark/mobilehomepark20.tif", "mobilehomepark/mobilehomepark76.tif", "mobilehomepark/mobilehomepark83.tif", "mobilehomepark/mobilehomepark01.tif", "mobilehomepark/mobilehomepark17.tif", "mobilehomepark/mobilehomepark15.tif", "mobilehomepark/mobilehomepark67.tif", "overpass/overpass16.tif", "overpass/overpass43.tif", "overpass/overpass51.tif", "overpass/overpass52.tif", "overpass/overpass93.tif", "overpass/overpass61.tif", "overpass/overpass27.tif", "overpass/overpass91.tif", "overpass/overpass03.tif", "overpass/overpass40.tif", "overpass/overpass80.tif", "overpass/overpass11.tif", "overpass/overpass54.tif", "overpass/overpass00.tif", "overpass/overpass30.tif", "overpass/overpass83.tif", "overpass/overpass53.tif", "overpass/overpass02.tif", "overpass/overpass48.tif", "overpass/overpass74.tif", "overpass/overpass77.tif", "overpass/overpass95.tif", "overpass/overpass45.tif", "overpass/overpass86.tif", "overpass/overpass36.tif", "overpass/overpass89.tif", "overpass/overpass50.tif", "overpass/overpass01.tif", "overpass/overpass81.tif", "overpass/overpass04.tif", "overpass/overpass19.tif", "overpass/overpass49.tif", "overpass/overpass34.tif", "overpass/overpass14.tif", "overpass/overpass67.tif", "overpass/overpass79.tif", "overpass/overpass96.tif", "overpass/overpass10.tif", "overpass/overpass99.tif", "overpass/overpass44.tif", "overpass/overpass47.tif", "overpass/overpass90.tif", "overpass/overpass94.tif", "overpass/overpass70.tif", "overpass/overpass57.tif", "overpass/overpass58.tif", "overpass/overpass65.tif", "overpass/overpass56.tif", "overpass/overpass24.tif", "overpass/overpass06.tif", "overpass/overpass71.tif", "overpass/overpass66.tif", "overpass/overpass39.tif", "overpass/overpass37.tif", "overpass/overpass41.tif", "overpass/overpass07.tif", "overpass/overpass12.tif", "overpass/overpass29.tif", "overpass/overpass60.tif", "overpass/overpass88.tif", "parkinglot/parkinglot44.tif", "parkinglot/parkinglot71.tif", "parkinglot/parkinglot86.tif", "parkinglot/parkinglot41.tif", "parkinglot/parkinglot48.tif", "parkinglot/parkinglot22.tif", "parkinglot/parkinglot24.tif", "parkinglot/parkinglot59.tif", "parkinglot/parkinglot11.tif", "parkinglot/parkinglot05.tif", "parkinglot/parkinglot21.tif", "parkinglot/parkinglot75.tif", "parkinglot/parkinglot94.tif", "parkinglot/parkinglot69.tif", "parkinglot/parkinglot46.tif", "parkinglot/parkinglot53.tif", "parkinglot/parkinglot52.tif", "parkinglot/parkinglot08.tif", "parkinglot/parkinglot58.tif", "parkinglot/parkinglot97.tif", "parkinglot/parkinglot62.tif", "parkinglot/parkinglot98.tif", "parkinglot/parkinglot87.tif", "parkinglot/parkinglot57.tif", "parkinglot/parkinglot72.tif", "parkinglot/parkinglot02.tif", "parkinglot/parkinglot63.tif", "parkinglot/parkinglot27.tif", "parkinglot/parkinglot92.tif", "parkinglot/parkinglot73.tif", "parkinglot/parkinglot60.tif", "parkinglot/parkinglot54.tif", "parkinglot/parkinglot20.tif", "parkinglot/parkinglot80.tif", "parkinglot/parkinglot64.tif", "parkinglot/parkinglot18.tif", "parkinglot/parkinglot45.tif", "parkinglot/parkinglot32.tif", "parkinglot/parkinglot61.tif", "parkinglot/parkinglot49.tif", "parkinglot/parkinglot51.tif", "parkinglot/parkinglot15.tif", "parkinglot/parkinglot16.tif", "parkinglot/parkinglot96.tif", "parkinglot/parkinglot39.tif", "parkinglot/parkinglot25.tif", "parkinglot/parkinglot43.tif", "parkinglot/parkinglot40.tif", "parkinglot/parkinglot78.tif", "parkinglot/parkinglot34.tif", "parkinglot/parkinglot06.tif", "parkinglot/parkinglot07.tif", "parkinglot/parkinglot68.tif", "parkinglot/parkinglot95.tif", "parkinglot/parkinglot47.tif", "parkinglot/parkinglot12.tif", "parkinglot/parkinglot36.tif", "parkinglot/parkinglot37.tif", "parkinglot/parkinglot01.tif", "parkinglot/parkinglot81.tif", "river/river91.tif", "river/river90.tif", "river/river21.tif", "river/river25.tif", "river/river82.tif", "river/river69.tif", "river/river45.tif", "river/river79.tif", "river/river86.tif", "river/river31.tif", "river/river02.tif", "river/river41.tif", "river/river83.tif", "river/river03.tif", "river/river84.tif", "river/river59.tif", "river/river63.tif", "river/river30.tif", "river/river71.tif", "river/river22.tif", "river/river12.tif", "river/river10.tif", "river/river87.tif", "river/river27.tif", "river/river46.tif", "river/river37.tif", "river/river65.tif", "river/river74.tif", "river/river28.tif", "river/river77.tif", "river/river05.tif", "river/river42.tif", "river/river06.tif", "river/river50.tif", "river/river29.tif", "river/river66.tif", "river/river51.tif", "river/river19.tif", "river/river73.tif", "river/river64.tif", "river/river34.tif", "river/river24.tif", "river/river94.tif", "river/river57.tif", "river/river92.tif", "river/river98.tif", "river/river11.tif", "river/river09.tif", "river/river76.tif", "river/river68.tif", "river/river95.tif", "river/river01.tif", "river/river58.tif", "river/river16.tif", "river/river55.tif", "river/river04.tif", "river/river81.tif", "river/river33.tif", "river/river61.tif", "river/river60.tif", "runway/runway89.tif", "runway/runway09.tif", "runway/runway65.tif", "runway/runway49.tif", "runway/runway05.tif", "runway/runway01.tif", "runway/runway63.tif", "runway/runway43.tif", "runway/runway18.tif", "runway/runway96.tif", "runway/runway30.tif", "runway/runway83.tif", "runway/runway37.tif", "runway/runway71.tif", "runway/runway50.tif", "runway/runway54.tif", "runway/runway23.tif", "runway/runway72.tif", "runway/runway34.tif", "runway/runway56.tif", "runway/runway53.tif", "runway/runway20.tif", "runway/runway44.tif", "runway/runway60.tif", "runway/runway91.tif", "runway/runway00.tif", "runway/runway74.tif", "runway/runway16.tif", "runway/runway29.tif", "runway/runway84.tif", "runway/runway06.tif", "runway/runway07.tif", "runway/runway27.tif", "runway/runway03.tif", "runway/runway68.tif", "runway/runway85.tif", "runway/runway98.tif", "runway/runway25.tif", "runway/runway17.tif", "runway/runway28.tif", "runway/runway90.tif", "runway/runway04.tif", "runway/runway19.tif", "runway/runway70.tif", "runway/runway81.tif", "runway/runway55.tif", "runway/runway22.tif", "runway/runway94.tif", "runway/runway99.tif", "runway/runway39.tif", "runway/runway32.tif", "runway/runway80.tif", "runway/runway61.tif", "runway/runway41.tif", "runway/runway36.tif", "runway/runway10.tif", "runway/runway52.tif", "runway/runway62.tif", "runway/runway35.tif", "runway/runway86.tif", "sparseresidential/sparseresidential47.tif", "sparseresidential/sparseresidential72.tif", "sparseresidential/sparseresidential36.tif", "sparseresidential/sparseresidential15.tif", "sparseresidential/sparseresidential03.tif", "sparseresidential/sparseresidential21.tif", "sparseresidential/sparseresidential06.tif", "sparseresidential/sparseresidential88.tif", "sparseresidential/sparseresidential09.tif", "sparseresidential/sparseresidential83.tif", "sparseresidential/sparseresidential70.tif", "sparseresidential/sparseresidential44.tif", "sparseresidential/sparseresidential00.tif", "sparseresidential/sparseresidential82.tif", "sparseresidential/sparseresidential74.tif", "sparseresidential/sparseresidential90.tif", "sparseresidential/sparseresidential89.tif", "sparseresidential/sparseresidential58.tif", "sparseresidential/sparseresidential68.tif", "sparseresidential/sparseresidential45.tif", "sparseresidential/sparseresidential10.tif", "sparseresidential/sparseresidential30.tif", "sparseresidential/sparseresidential94.tif", "sparseresidential/sparseresidential16.tif", "sparseresidential/sparseresidential14.tif", "sparseresidential/sparseresidential96.tif", "sparseresidential/sparseresidential34.tif", "sparseresidential/sparseresidential61.tif", "sparseresidential/sparseresidential85.tif", "sparseresidential/sparseresidential86.tif", "sparseresidential/sparseresidential78.tif", "sparseresidential/sparseresidential28.tif", "sparseresidential/sparseresidential48.tif", "sparseresidential/sparseresidential79.tif", "sparseresidential/sparseresidential67.tif", "sparseresidential/sparseresidential73.tif", "sparseresidential/sparseresidential50.tif", "sparseresidential/sparseresidential77.tif", "sparseresidential/sparseresidential64.tif", "sparseresidential/sparseresidential43.tif", "sparseresidential/sparseresidential71.tif", "sparseresidential/sparseresidential52.tif", "sparseresidential/sparseresidential51.tif", "sparseresidential/sparseresidential93.tif", "sparseresidential/sparseresidential84.tif", "sparseresidential/sparseresidential39.tif", "sparseresidential/sparseresidential65.tif", "sparseresidential/sparseresidential37.tif", "sparseresidential/sparseresidential01.tif", "sparseresidential/sparseresidential91.tif", "sparseresidential/sparseresidential17.tif", "sparseresidential/sparseresidential33.tif", "sparseresidential/sparseresidential32.tif", "sparseresidential/sparseresidential80.tif", "sparseresidential/sparseresidential81.tif", "sparseresidential/sparseresidential75.tif", "sparseresidential/sparseresidential56.tif", "sparseresidential/sparseresidential13.tif", "sparseresidential/sparseresidential63.tif", "sparseresidential/sparseresidential98.tif", "storagetanks/storagetanks54.tif", "storagetanks/storagetanks20.tif", "storagetanks/storagetanks36.tif", "storagetanks/storagetanks49.tif", "storagetanks/storagetanks85.tif", "storagetanks/storagetanks84.tif", "storagetanks/storagetanks33.tif", "storagetanks/storagetanks15.tif", "storagetanks/storagetanks30.tif", "storagetanks/storagetanks43.tif", "storagetanks/storagetanks45.tif", "storagetanks/storagetanks73.tif", "storagetanks/storagetanks00.tif", "storagetanks/storagetanks95.tif", "storagetanks/storagetanks18.tif", "storagetanks/storagetanks76.tif", "storagetanks/storagetanks01.tif", "storagetanks/storagetanks03.tif", "storagetanks/storagetanks55.tif", "storagetanks/storagetanks26.tif", "storagetanks/storagetanks32.tif", "storagetanks/storagetanks08.tif", "storagetanks/storagetanks52.tif", "storagetanks/storagetanks53.tif", "storagetanks/storagetanks56.tif", "storagetanks/storagetanks78.tif", "storagetanks/storagetanks14.tif", "storagetanks/storagetanks27.tif", "storagetanks/storagetanks75.tif", "storagetanks/storagetanks66.tif", "storagetanks/storagetanks98.tif", "storagetanks/storagetanks40.tif", "storagetanks/storagetanks37.tif", "storagetanks/storagetanks86.tif", "storagetanks/storagetanks06.tif", "storagetanks/storagetanks67.tif", "storagetanks/storagetanks05.tif", "storagetanks/storagetanks48.tif", "storagetanks/storagetanks35.tif", "storagetanks/storagetanks28.tif", "storagetanks/storagetanks44.tif", "storagetanks/storagetanks60.tif", "storagetanks/storagetanks61.tif", "storagetanks/storagetanks99.tif", "storagetanks/storagetanks91.tif", "storagetanks/storagetanks88.tif", "storagetanks/storagetanks82.tif", "storagetanks/storagetanks71.tif", "storagetanks/storagetanks38.tif", "storagetanks/storagetanks11.tif", "storagetanks/storagetanks46.tif", "storagetanks/storagetanks34.tif", "storagetanks/storagetanks07.tif", "storagetanks/storagetanks41.tif", "storagetanks/storagetanks58.tif", "storagetanks/storagetanks90.tif", "storagetanks/storagetanks65.tif", "storagetanks/storagetanks72.tif", "storagetanks/storagetanks25.tif", "storagetanks/storagetanks57.tif", "tenniscourt/tenniscourt52.tif", "tenniscourt/tenniscourt58.tif", "tenniscourt/tenniscourt14.tif", "tenniscourt/tenniscourt63.tif", "tenniscourt/tenniscourt22.tif", "tenniscourt/tenniscourt02.tif", "tenniscourt/tenniscourt11.tif", "tenniscourt/tenniscourt36.tif", "tenniscourt/tenniscourt57.tif", "tenniscourt/tenniscourt15.tif", "tenniscourt/tenniscourt66.tif", "tenniscourt/tenniscourt93.tif", "tenniscourt/tenniscourt35.tif", "tenniscourt/tenniscourt17.tif", "tenniscourt/tenniscourt43.tif", "tenniscourt/tenniscourt92.tif", "tenniscourt/tenniscourt67.tif", "tenniscourt/tenniscourt60.tif", "tenniscourt/tenniscourt10.tif", "tenniscourt/tenniscourt24.tif", "tenniscourt/tenniscourt33.tif", "tenniscourt/tenniscourt48.tif", "tenniscourt/tenniscourt23.tif", "tenniscourt/tenniscourt07.tif", "tenniscourt/tenniscourt05.tif", "tenniscourt/tenniscourt72.tif", "tenniscourt/tenniscourt27.tif", "tenniscourt/tenniscourt54.tif", "tenniscourt/tenniscourt77.tif", "tenniscourt/tenniscourt04.tif", "tenniscourt/tenniscourt84.tif", "tenniscourt/tenniscourt65.tif", "tenniscourt/tenniscourt47.tif", "tenniscourt/tenniscourt28.tif", "tenniscourt/tenniscourt73.tif", "tenniscourt/tenniscourt00.tif", "tenniscourt/tenniscourt46.tif", "tenniscourt/tenniscourt62.tif", "tenniscourt/tenniscourt26.tif", "tenniscourt/tenniscourt90.tif", "tenniscourt/tenniscourt82.tif", "tenniscourt/tenniscourt50.tif", "tenniscourt/tenniscourt56.tif", "tenniscourt/tenniscourt85.tif", "tenniscourt/tenniscourt96.tif", "tenniscourt/tenniscourt09.tif", "tenniscourt/tenniscourt01.tif", "tenniscourt/tenniscourt03.tif", "tenniscourt/tenniscourt80.tif", "tenniscourt/tenniscourt79.tif", "tenniscourt/tenniscourt16.tif", "tenniscourt/tenniscourt89.tif", "tenniscourt/tenniscourt38.tif", "tenniscourt/tenniscourt37.tif", "tenniscourt/tenniscourt08.tif", "tenniscourt/tenniscourt51.tif", "tenniscourt/tenniscourt34.tif", "tenniscourt/tenniscourt78.tif", "tenniscourt/tenniscourt64.tif", "tenniscourt/tenniscourt55.tif"], "val": ["agricultural/agricultural15.tif", "agricultural/agricultural66.tif", "agricultural/agricultural08.tif", "agricultural/agricultural38.tif", "agricultural/agricultural96.tif", "agricultural/agricultural64.tif", "agricultural/agricultural68.tif", "agricultural/agricultural29.tif", "agricultural/agricultural22.tif", "agricultural/agricultural74.tif", "agricultural/agricultural40.tif", "agricultural/agricultural36.tif", "agricultural/agricultural19.tif", "agricultural/agricultural00.tif", "agricultural/agricultural60.tif", "agricultural/agricultural53.tif", "agricultural/agricultural46.tif", "agricultural/agricultural26.tif", "agricultural/agricultural93.tif", "agricultural/agricultural03.tif", "airplane/airplane80.tif", "airplane/airplane03.tif", "airplane/airplane74.tif", "airplane/airplane96.tif", "airplane/airplane16.tif", "airplane/airplane27.tif", "airplane/airplane94.tif", "airplane/airplane65.tif", "airplane/airplane12.tif", "airplane/airplane08.tif", "airplane/airplane29.tif", "airplane/airplane46.tif", "airplane/airplane42.tif", "airplane/airplane19.tif", "airplane/airplane43.tif", "airplane/airplane85.tif", "airplane/airplane20.tif", "airplane/airplane13.tif", "airplane/airplane40.tif", "airplane/airplane47.tif", "baseballdiamond/baseballdiamond27.tif", "baseballdiamond/baseballdiamond37.tif", "baseballdiamond/baseballdiamond30.tif", "baseballdiamond/baseballdiamond53.tif", "baseballdiamond/baseballdiamond58.tif", "baseballdiamond/baseballdiamond55.tif", "baseballdiamond/baseballdiamond85.tif", "baseballdiamond/baseballdiamond90.tif", "baseballdiamond/baseballdiamond98.tif", "baseballdiamond/baseballdiamond82.tif", "baseballdiamond/baseballdiamond21.tif", "baseballdiamond/baseballdiamond41.tif", "baseballdiamond/baseballdiamond72.tif", "baseballdiamond/baseballdiamond79.tif", "baseballdiamond/baseballdiamond83.tif", "baseballdiamond/baseballdiamond50.tif", "baseballdiamond/baseballdiamond81.tif", "baseballdiamond/baseballdiamond52.tif", "baseballdiamond/baseballdiamond56.tif", "baseballdiamond/baseballdiamond38.tif", "beach/beach32.tif", "beach/beach82.tif", "beach/beach96.tif", "beach/beach11.tif", "beach/beach29.tif", "beach/beach97.tif", "beach/beach53.tif", "beach/beach98.tif", "beach/beach51.tif", "beach/beach58.tif", "beach/beach92.tif", "beach/beach68.tif", "beach/beach56.tif", "beach/beach41.tif", "beach/beach42.tif", "beach/beach36.tif", "beach/beach61.tif", "beach/beach02.tif", "beach/beach81.tif", "beach/beach04.tif", "buildings/buildings27.tif", "buildings/buildings44.tif", "buildings/buildings63.tif", "buildings/buildings46.tif", "buildings/buildings73.tif", "buildings/buildings54.tif", "buildings/buildings79.tif", "buildings/buildings11.tif", "buildings/buildings86.tif", "buildings/buildings61.tif", "buildings/buildings91.tif", "buildings/buildings98.tif", "buildings/buildings84.tif", "buildings/buildings36.tif", "buildings/buildings59.tif", "buildings/buildings60.tif", "buildings/buildings45.tif", "buildings/buildings49.tif", "buildings/buildings43.tif", "buildings/buildings12.tif", "chaparral/chaparral93.tif", "chaparral/chaparral57.tif", "chaparral/chaparral20.tif", "chaparral/chaparral69.tif", "chaparral/chaparral78.tif", "chaparral/chaparral96.tif", "chaparral/chaparral52.tif", "chaparral/chaparral38.tif", "chaparral/chaparral83.tif", "chaparral/chaparral61.tif", "chaparral/chaparral40.tif", "chaparral/chaparral13.tif", "chaparral/chaparral66.tif", "chaparral/chaparral77.tif", "chaparral/chaparral89.tif", "chaparral/chaparral27.tif", "chaparral/chaparral60.tif", "chaparral/chaparral74.tif", "chaparral/chaparral70.tif", "chaparral/chaparral86.tif", "denseresidential/denseresidential09.tif", "denseresidential/denseresidential65.tif", "denseresidential/denseresidential45.tif", "denseresidential/denseresidential59.tif", "denseresidential/denseresidential31.tif", "denseresidential/denseresidential98.tif", "denseresidential/denseresidential14.tif", "denseresidential/denseresidential28.tif", "denseresidential/denseresidential89.tif", "denseresidential/denseresidential47.tif", "denseresidential/denseresidential88.tif", "denseresidential/denseresidential64.tif", "denseresidential/denseresidential25.tif", "denseresidential/denseresidential03.tif", "denseresidential/denseresidential40.tif", "denseresidential/denseresidential78.tif", "denseresidential/denseresidential36.tif", "denseresidential/denseresidential91.tif", "denseresidential/denseresidential63.tif", "denseresidential/denseresidential43.tif", "forest/forest93.tif", "forest/forest04.tif", "forest/forest85.tif", "forest/forest89.tif", "forest/forest09.tif", "forest/forest40.tif", "forest/forest17.tif", "forest/forest54.tif", "forest/forest11.tif", "forest/forest68.tif", "forest/forest35.tif", "forest/forest52.tif", "forest/forest36.tif", "forest/forest67.tif", "forest/forest31.tif", "forest/forest55.tif", "forest/forest06.tif", "forest/forest92.tif", "forest/forest22.tif", "forest/forest12.tif", "freeway/freeway35.tif", "freeway/freeway46.tif", "freeway/freeway67.tif", "freeway/freeway36.tif", "freeway/freeway97.tif", "freeway/freeway17.tif", "freeway/freeway96.tif", "freeway/freeway03.tif", "freeway/freeway84.tif", "freeway/freeway56.tif", "freeway/freeway04.tif", "freeway/freeway01.tif", "freeway/freeway68.tif", "freeway/freeway98.tif", "freeway/freeway87.tif", "freeway/freeway52.tif", "freeway/freeway70.tif", "freeway/freeway14.tif", "freeway/freeway57.tif", "freeway/freeway25.tif", "golfcourse/golfcourse91.tif", "golfcourse/golfcourse88.tif", "golfcourse/golfcourse34.tif", "golfcourse/golfcourse95.tif", "golfcourse/golfcourse87.tif", "golfcourse/golfcourse60.tif", "golfcourse/golfcourse74.tif", "golfcourse/golfcourse58.tif", "golfcourse/golfcourse99.tif", "golfcourse/golfcourse21.tif", "golfcourse/golfcourse77.tif", "golfcourse/golfcourse84.tif", "golfcourse/golfcourse65.tif", "golfcourse/golfcourse97.tif", "golfcourse/golfcourse14.tif", "golfcourse/golfcourse11.tif", "golfcourse/golfcourse25.tif", "golfcourse/golfcourse85.tif", "golfcourse/golfcourse26.tif", "golfcourse/golfcourse36.tif", "harbor/harbor20.tif", "harbor/harbor12.tif", "harbor/harbor73.tif", "harbor/harbor36.tif", "harbor/harbor00.tif", "harbor/harbor42.tif", "harbor/harbor49.tif", "harbor/harbor52.tif", "harbor/harbor01.tif", "harbor/harbor87.tif", "harbor/harbor66.tif", "harbor/harbor93.tif", "harbor/harbor44.tif", "harbor/harbor59.tif", "harbor/harbor28.tif", "harbor/harbor97.tif", "harbor/harbor39.tif", "harbor/harbor60.tif", "harbor/harbor05.tif", "harbor/harbor83.tif", "intersection/intersection43.tif", "intersection/intersection87.tif", "intersection/intersection16.tif", "intersection/intersection78.tif", "intersection/intersection44.tif", "intersection/intersection72.tif", "intersection/intersection07.tif", "intersection/intersection84.tif", "intersection/intersection01.tif", "intersection/intersection09.tif", "intersection/intersection73.tif", "intersection/intersection48.tif", "intersection/intersection74.tif", "intersection/intersection52.tif", "intersection/intersection91.tif", "intersection/intersection79.tif", "intersection/intersection18.tif", "intersection/intersection85.tif", "intersection/intersection81.tif", "intersection/intersection31.tif", "mediumresidential/mediumresidential84.tif", "mediumresidential/mediumresidential29.tif", "mediumresidential/mediumresidential61.tif", "mediumresidential/mediumresidential56.tif", "mediumresidential/mediumresidential85.tif", "mediumresidential/mediumresidential41.tif", "mediumresidential/mediumresidential98.tif", "mediumresidential/mediumresidential93.tif", "mediumresidential/mediumresidential43.tif", "mediumresidential/mediumresidential86.tif", "mediumresidential/mediumresidential24.tif", "mediumresidential/mediumresidential68.tif", "mediumresidential/mediumresidential62.tif", "mediumresidential/mediumresidential90.tif", "mediumresidential/mediumresidential71.tif", "mediumresidential/mediumresidential60.tif", "mediumresidential/mediumresidential99.tif", "mediumresidential/mediumresidential26.tif", "mediumresidential/mediumresidential30.tif", "mediumresidential/mediumresidential46.tif", "mobilehomepark/mobilehomepark75.tif", "mobilehomepark/mobilehomepark21.tif", "mobilehomepark/mobilehomepark36.tif", "mobilehomepark/mobilehomepark94.tif", "mobilehomepark/mobilehomepark44.tif", "mobilehomepark/mobilehomepark18.tif", "mobilehomepark/mobilehomepark73.tif", "mobilehomepark/mobilehomepark32.tif", "mobilehomepark/mobilehomepark47.tif", "mobilehomepark/mobilehomepark12.tif", "mobilehomepark/mobilehomepark42.tif", "mobilehomepark/mobilehomepark79.tif", "mobilehomepark/mobilehomepark89.tif", "mobilehomepark/mobilehomepark78.tif", "mobilehomepark/mobilehomepark64.tif", "mobilehomepark/mobilehomepark10.tif", "mobilehomepark/mobilehomepark84.tif", "mobilehomepark/mobilehomepark65.tif", "mobilehomepark/mobilehomepark11.tif", "mobilehomepark/mobilehomepark40.tif", "overpass/overpass76.tif", "overpass/overpass64.tif", "overpass/overpass98.tif", "overpass/overpass72.tif", "overpass/overpass35.tif", "overpass/overpass68.tif", "overpass/overpass73.tif", "overpass/overpass26.tif", "overpass/overpass42.tif", "overpass/overpass75.tif", "overpass/overpass38.tif", "overpass/overpass31.tif", "overpass/overpass63.tif", "overpass/overpass78.tif", "overpass/overpass18.tif", "overpass/overpass92.tif", "overpass/overpass22.tif", "overpass/overpass82.tif", "overpass/overpass09.tif", "overpass/overpass05.tif", "parkinglot/parkinglot89.tif", "parkinglot/parkinglot10.tif", "parkinglot/parkinglot83.tif", "parkinglot/parkinglot00.tif", "parkinglot/parkinglot33.tif", "parkinglot/parkinglot35.tif", "parkinglot/parkinglot04.tif", "parkinglot/parkinglot50.tif", "parkinglot/parkinglot79.tif", "parkinglot/parkinglot19.tif", "parkinglot/parkinglot84.tif", "parkinglot/parkinglot85.tif", "parkinglot/parkinglot13.tif", "parkinglot/parkinglot29.tif", "parkinglot/parkinglot55.tif", "parkinglot/parkinglot14.tif", "parkinglot/parkinglot31.tif", "parkinglot/parkinglot93.tif", "parkinglot/parkinglot30.tif", "parkinglot/parkinglot74.tif", "river/river18.tif", "river/river39.tif", "river/river08.tif", "river/river38.tif", "river/river47.tif", "river/river56.tif", "river/river62.tif", "river/river17.tif", "river/river35.tif", "river/river48.tif", "river/river75.tif", "river/river80.tif", "river/river96.tif", "river/river13.tif", "river/river70.tif", "river/river15.tif", "river/river52.tif", "river/river32.tif", "river/river49.tif", "river/river23.tif", "runway/runway12.tif", "runway/runway75.tif", "runway/runway24.tif", "runway/runway48.tif", "runway/runway33.tif", "runway/runway26.tif", "runway/runway57.tif", "runway/runway87.tif", "runway/runway67.tif", "runway/runway77.tif", "runway/runway73.tif", "runway/runway13.tif", "runway/runway82.tif", "runway/runway88.tif", "runway/runway79.tif", "runway/runway46.tif", "runway/runway15.tif", "runway/runway45.tif", "runway/runway40.tif", "runway/runway31.tif", "sparseresidential/sparseresidential11.tif", "sparseresidential/sparseresidential97.tif", "sparseresidential/sparseresidential07.tif", "sparseresidential/sparseresidential24.tif", "sparseresidential/sparseresidential23.tif", "sparseresidential/sparseresidential99.tif", "sparseresidential/sparseresidential29.tif", "sparseresidential/sparseresidential59.tif", "sparseresidential/sparseresidential57.tif", "sparseresidential/sparseresidential69.tif", "sparseresidential/sparseresidential53.tif", "sparseresidential/sparseresidential66.tif", "sparseresidential/sparseresidential55.tif", "sparseresidential/sparseresidential62.tif", "sparseresidential/sparseresidential18.tif", "sparseresidential/sparseresidential41.tif", "sparseresidential/sparseresidential05.tif", "sparseresidential/sparseresidential54.tif", "sparseresidential/sparseresidential22.tif", "sparseresidential/sparseresidential60.tif", "storagetanks/storagetanks42.tif", "storagetanks/storagetanks17.tif", "storagetanks/storagetanks93.tif", "storagetanks/storagetanks83.tif", "storagetanks/storagetanks12.tif", "storagetanks/storagetanks39.tif", "storagetanks/storagetanks24.tif", "storagetanks/storagetanks31.tif", "storagetanks/storagetanks51.tif", "storagetanks/storagetanks81.tif", "storagetanks/storagetanks92.tif", "storagetanks/storagetanks23.tif", "storagetanks/storagetanks19.tif", "storagetanks/storagetanks16.tif", "storagetanks/storagetanks80.tif", "storagetanks/storagetanks21.tif", "storagetanks/storagetanks97.tif", "storagetanks/storagetanks68.tif", "storagetanks/storagetanks89.tif", "storagetanks/storagetanks13.tif", "tenniscourt/tenniscourt75.tif", "tenniscourt/tenniscourt39.tif", "tenniscourt/tenniscourt20.tif", "tenniscourt/tenniscourt41.tif", "tenniscourt/tenniscourt59.tif", "tenniscourt/tenniscourt25.tif", "tenniscourt/tenniscourt30.tif", "tenniscourt/tenniscourt83.tif", "tenniscourt/tenniscourt74.tif", "tenniscourt/tenniscourt49.tif", "tenniscourt/tenniscourt18.tif", "tenniscourt/tenniscourt71.tif", "tenniscourt/tenniscourt31.tif", "tenniscourt/tenniscourt40.tif", "tenniscourt/tenniscourt42.tif", "tenniscourt/tenniscourt61.tif", "tenniscourt/tenniscourt95.tif", "tenniscourt/tenniscourt97.tif", "tenniscourt/tenniscourt06.tif", "tenniscourt/tenniscourt29.tif"], "test": ["agricultural/agricultural11.tif", "agricultural/agricultural23.tif", "agricultural/agricultural35.tif", "agricultural/agricultural09.tif", "agricultural/agricultural91.tif", "agricultural/agricultural88.tif", "agricultural/agricultural02.tif", "agricultural/agricultural20.tif", "agricultural/agricultural97.tif", "agricultural/agricultural76.tif", "agricultural/agricultural30.tif", "agricultural/agricultural47.tif", "agricultural/agricultural27.tif", "agricultural/agricultural07.tif", "agricultural/agricultural01.tif", "agricultural/agricultural45.tif", "agricultural/agricultural48.tif", "agricultural/agricultural98.tif", "agricultural/agricultural67.tif", "agricultural/agricultural25.tif", "airplane/airplane34.tif", "airplane/airplane09.tif", "airplane/airplane37.tif", "airplane/airplane11.tif", "airplane/airplane15.tif", "airplane/airplane61.tif", "airplane/airplane23.tif", "airplane/airplane33.tif", "airplane/airplane98.tif", "airplane/airplane64.tif", "airplane/airplane71.tif", "airplane/airplane91.tif", "airplane/airplane97.tif", "airplane/airplane17.tif", "airplane/airplane88.tif", "airplane/airplane35.tif", "airplane/airplane77.tif", "airplane/airplane86.tif", "airplane/airplane95.tif", "airplane/airplane25.tif", "baseballdiamond/baseballdiamond08.tif", "baseballdiamond/baseballdiamond71.tif", "baseballdiamond/baseballdiamond35.tif", "baseballdiamond/baseballdiamond62.tif", "baseballdiamond/baseballdiamond24.tif", "baseballdiamond/baseballdiamond73.tif", "baseballdiamond/baseballdiamond04.tif", "baseballdiamond/baseballdiamond64.tif", "baseballdiamond/baseballdiamond31.tif", "baseballdiamond/baseballdiamond36.tif", "baseballdiamond/baseballdiamond91.tif", "baseballdiamond/baseballdiamond34.tif", "baseballdiamond/baseballdiamond17.tif", "baseballdiamond/baseballdiamond93.tif", "baseballdiamond/baseballdiamond25.tif", "baseballdiamond/baseballdiamond99.tif", "baseballdiamond/baseballdiamond92.tif", "baseballdiamond/baseballdiamond88.tif", "baseballdiamond/baseballdiamond74.tif", "baseballdiamond/baseballdiamond89.tif", "beach/beach75.tif", "beach/beach95.tif", "beach/beach66.tif", "beach/beach55.tif", "beach/beach05.tif", "beach/beach70.tif", "beach/beach12.tif", "beach/beach94.tif", "beach/beach08.tif", "beach/beach47.tif", "beach/beach39.tif", "beach/beach77.tif", "beach/beach45.tif", "beach/beach88.tif", "beach/beach35.tif", "beach/beach10.tif", "beach/beach31.tif", "beach/beach46.tif", "beach/beach13.tif", "beach/beach14.tif", "buildings/buildings21.tif", "buildings/buildings51.tif", "buildings/buildings47.tif", "buildings/buildings96.tif", "buildings/buildings23.tif", "buildings/buildings97.tif", "buildings/buildings19.tif", "buildings/buildings38.tif", "buildings/buildings28.tif", "buildings/buildings25.tif", "buildings/buildings62.tif", "buildings/buildings50.tif", "buildings/buildings01.tif", "buildings/buildings34.tif", "buildings/buildings22.tif", "buildings/buildings09.tif", "buildings/buildings41.tif", "buildings/buildings15.tif", "buildings/buildings93.tif", "buildings/buildings74.tif", "chaparral/chaparral55.tif", "chaparral/chaparral29.tif", "chaparral/chaparral95.tif", "chaparral/chaparral99.tif", "chaparral/chaparral30.tif", "chaparral/chaparral72.tif", "chaparral/chaparral15.tif", "chaparral/chaparral37.tif", "chaparral/chaparral44.tif", "chaparral/chaparral06.tif", "chaparral/chaparral12.tif", "chaparral/chaparral04.tif", "chaparral/chaparral14.tif", "chaparral/chaparral43.tif", "chaparral/chaparral98.tif", "chaparral/chaparral67.tif", "chaparral/chaparral87.tif", "chaparral/chaparral47.tif", "chaparral/chaparral84.tif", "chaparral/chaparral73.tif", "denseresidential/denseresidential72.tif", "denseresidential/denseresidential50.tif", "denseresidential/denseresidential18.tif", "denseresidential/denseresidential42.tif", "denseresidential/denseresidential32.tif", "denseresidential/denseresidential35.tif", "denseresidential/denseresidential79.tif", "denseresidential/denseresidential58.tif", "denseresidential/denseresidential46.tif", "denseresidential/denseresidential94.tif", "denseresidential/denseresidential51.tif", "denseresidential/denseresidential48.tif", "denseresidential/denseresidential23.tif", "denseresidential/denseresidential57.tif", "denseresidential/denseresidential22.tif", "denseresidential/denseresidential52.tif", "denseresidential/denseresidential54.tif", "denseresidential/denseresidential70.tif", "denseresidential/denseresidential69.tif", "denseresidential/denseresidential29.tif", "forest/forest69.tif", "forest/forest45.tif", "forest/forest25.tif", "forest/forest64.tif", "forest/forest53.tif", "forest/forest62.tif", "forest/forest42.tif", "forest/forest32.tif", "forest/forest02.tif", "forest/forest96.tif", "forest/forest29.tif", "forest/forest81.tif", "forest/forest01.tif", "forest/forest24.tif", "forest/forest03.tif", "forest/forest00.tif", "forest/forest39.tif", "forest/forest88.tif", "forest/forest74.tif", "forest/forest38.tif", "freeway/freeway65.tif", "freeway/freeway73.tif", "freeway/freeway61.tif", "freeway/freeway71.tif", "freeway/freeway07.tif", "freeway/freeway33.tif", "freeway/freeway05.tif", "freeway/freeway28.tif", "freeway/freeway55.tif", "freeway/freeway26.tif", "freeway/freeway93.tif", "freeway/freeway06.tif", "freeway/freeway80.tif", "freeway/freeway74.tif", "freeway/freeway47.tif", "freeway/freeway45.tif", "freeway/freeway54.tif", "freeway/freeway20.tif", "freeway/freeway21.tif", "freeway/freeway83.tif", "golfcourse/golfcourse10.tif", "golfcourse/golfcourse66.tif", "golfcourse/golfcourse02.tif", "golfcourse/golfcourse35.tif", "golfcourse/golfcourse69.tif", "golfcourse/golfcourse45.tif", "golfcourse/golfcourse24.tif", "golfcourse/golfcourse23.tif", "golfcourse/golfcourse55.tif", "golfcourse/golfcourse08.tif", "golfcourse/golfcourse93.tif", "golfcourse/golfcourse67.tif", "golfcourse/golfcourse64.tif", "golfcourse/golfcourse16.tif", "golfcourse/golfcourse59.tif", "golfcourse/golfcourse03.tif", "golfcourse/golfcourse04.tif", "golfcourse/golfcourse27.tif", "golfcourse/golfcourse90.tif", "golfcourse/golfcourse15.tif", "harbor/harbor15.tif", "harbor/harbor88.tif", "harbor/harbor14.tif", "harbor/harbor31.tif", "harbor/harbor95.tif", "harbor/harbor96.tif", "harbor/harbor24.tif", "harbor/harbor91.tif", "harbor/harbor94.tif", "harbor/harbor63.tif", "harbor/harbor34.tif", "harbor/harbor62.tif", "harbor/harbor32.tif", "harbor/harbor76.tif", "harbor/harbor40.tif", "harbor/harbor86.tif", "harbor/harbor17.tif", "harbor/harbor30.tif", "harbor/harbor38.tif", "harbor/harbor21.tif", "intersection/intersection82.tif", "intersection/intersection88.tif", "intersection/intersection35.tif", "intersection/intersection56.tif", "intersection/intersection03.tif", "intersection/intersection00.tif", "intersection/intersection29.tif", "intersection/intersection68.tif", "intersection/intersection25.tif", "intersection/intersection66.tif", "intersection/intersection61.tif", "intersection/intersection86.tif", "intersection/intersection93.tif", "intersection/intersection39.tif", "intersection/intersection76.tif", "intersection/intersection14.tif", "intersection/intersection26.tif", "intersection/intersection22.tif", "intersection/intersection97.tif", "intersection/intersection94.tif", "mediumresidential/mediumresidential32.tif", "mediumresidential/mediumresidential31.tif", "mediumresidential/mediumresidential92.tif", "mediumresidential/mediumresidential23.tif", "mediumresidential/mediumresidential08.tif", "mediumresidential/mediumresidential74.tif", "mediumresidential/mediumresidential18.tif", "mediumresidential/mediumresidential00.tif", "mediumresidential/mediumresidential50.tif", "mediumresidential/mediumresidential67.tif", "mediumresidential/mediumresidential72.tif", "mediumresidential/mediumresidential04.tif", "mediumresidential/mediumresidential40.tif", "mediumresidential/mediumresidential09.tif", "mediumresidential/mediumresidential69.tif", "mediumresidential/mediumresidential76.tif", "mediumresidential/mediumresidential34.tif", "mediumresidential/mediumresidential20.tif", "mediumresidential/mediumresidential83.tif", "mediumresidential/mediumresidential05.tif", "mobilehomepark/mobilehomepark52.tif", "mobilehomepark/mobilehomepark59.tif", "mobilehomepark/mobilehomepark28.tif", "mobilehomepark/mobilehomepark38.tif", "mobilehomepark/mobilehomepark29.tif", "mobilehomepark/mobilehomepark43.tif", "mobilehomepark/mobilehomepark68.tif", "mobilehomepark/mobilehomepark93.tif", "mobilehomepark/mobilehomepark66.tif", "mobilehomepark/mobilehomepark35.tif", "mobilehomepark/mobilehomepark51.tif", "mobilehomepark/mobilehomepark48.tif", "mobilehomepark/mobilehomepark07.tif", "mobilehomepark/mobilehomepark96.tif", "mobilehomepark/mobilehomepark24.tif", "mobilehomepark/mobilehomepark58.tif", "mobilehomepark/mobilehomepark63.tif", "mobilehomepark/mobilehomepark34.tif", "mobilehomepark/mobilehomepark08.tif", "mobilehomepark/mobilehomepark41.tif", "overpass/overpass23.tif", "overpass/overpass85.tif", "overpass/overpass25.tif", "overpass/overpass84.tif", "overpass/overpass46.tif", "overpass/overpass15.tif", "overpass/overpass87.tif", "overpass/overpass20.tif", "overpass/overpass32.tif", "overpass/overpass59.tif", "overpass/overpass13.tif", "overpass/overpass62.tif", "overpass/overpass55.tif", "overpass/overpass28.tif", "overpass/overpass17.tif", "overpass/overpass33.tif", "overpass/overpass69.tif", "overpass/overpass08.tif", "overpass/overpass21.tif", "overpass/overpass97.tif", "parkinglot/parkinglot28.tif", "parkinglot/parkinglot65.tif", "parkinglot/parkinglot09.tif", "parkinglot/parkinglot70.tif", "parkinglot/parkinglot82.tif", "parkinglot/parkinglot91.tif", "parkinglot/parkinglot88.tif", "parkinglot/parkinglot56.tif", "parkinglot/parkinglot38.tif", "parkinglot/parkinglot03.tif", "parkinglot/parkinglot66.tif", "parkinglot/parkinglot99.tif", "parkinglot/parkinglot77.tif", "parkinglot/parkinglot42.tif", "parkinglot/parkinglot17.tif", "parkinglot/parkinglot76.tif", "parkinglot/parkinglot23.tif", "parkinglot/parkinglot26.tif", "parkinglot/parkinglot90.tif", "parkinglot/parkinglot67.tif", "river/river14.tif", "river/river40.tif", "river/river67.tif", "river/river36.tif", "river/river53.tif", "river/river72.tif", "river/river89.tif", "river/river00.tif", "river/river97.tif", "river/river99.tif", "river/river93.tif", "river/river44.tif", "river/river20.tif", "river/river78.tif", "river/river43.tif", "river/river26.tif", "river/river07.tif", "river/river54.tif", "river/river85.tif", "river/river88.tif", "runway/runway08.tif", "runway/runway02.tif", "runway/runway97.tif", "runway/runway11.tif", "runway/runway66.tif", "runway/runway51.tif", "runway/runway58.tif", "runway/runway78.tif", "runway/runway95.tif", "runway/runway21.tif", "runway/runway38.tif", "runway/runway92.tif", "runway/runway47.tif", "runway/runway64.tif", "runway/runway69.tif", "runway/runway14.tif", "runway/runway76.tif", "runway/runway59.tif", "runway/runway42.tif", "runway/runway93.tif", "sparseresidential/sparseresidential25.tif", "sparseresidential/sparseresidential27.tif", "sparseresidential/sparseresidential87.tif", "sparseresidential/sparseresidential95.tif", "sparseresidential/sparseresidential35.tif", "sparseresidential/sparseresidential20.tif", "sparseresidential/sparseresidential46.tif", "sparseresidential/sparseresidential19.tif", "sparseresidential/sparseresidential40.tif", "sparseresidential/sparseresidential31.tif", "sparseresidential/sparseresidential49.tif", "sparseresidential/sparseresidential42.tif", "sparseresidential/sparseresidential08.tif", "sparseresidential/sparseresidential02.tif", "sparseresidential/sparseresidential12.tif", "sparseresidential/sparseresidential04.tif", "sparseresidential/sparseresidential92.tif", "sparseresidential/sparseresidential38.tif", "sparseresidential/sparseresidential26.tif", "sparseresidential/sparseresidential76.tif", "storagetanks/storagetanks79.tif", "storagetanks/storagetanks62.tif", "storagetanks/storagetanks63.tif", "storagetanks/storagetanks29.tif", "storagetanks/storagetanks87.tif", "storagetanks/storagetanks74.tif", "storagetanks/storagetanks50.tif", "storagetanks/storagetanks64.tif", "storagetanks/storagetanks10.tif", "storagetanks/storagetanks94.tif", "storagetanks/storagetanks22.tif", "storagetanks/storagetanks59.tif", "storagetanks/storagetanks47.tif", "storagetanks/storagetanks77.tif", "storagetanks/storagetanks04.tif", "storagetanks/storagetanks70.tif", "storagetanks/storagetanks02.tif", "storagetanks/storagetanks96.tif", "storagetanks/storagetanks09.tif", "storagetanks/storagetanks69.tif", "tenniscourt/tenniscourt81.tif", "tenniscourt/tenniscourt88.tif", "tenniscourt/tenniscourt32.tif", "tenniscourt/tenniscourt45.tif", "tenniscourt/tenniscourt87.tif", "tenniscourt/tenniscourt53.tif", "tenniscourt/tenniscourt86.tif", "tenniscourt/tenniscourt76.tif", "tenniscourt/tenniscourt99.tif", "tenniscourt/tenniscourt94.tif", "tenniscourt/tenniscourt12.tif", "tenniscourt/tenniscourt21.tif", "tenniscourt/tenniscourt98.tif", "tenniscourt/tenniscourt19.tif", "tenniscourt/tenniscourt44.tif", "tenniscourt/tenniscourt70.tif", "tenniscourt/tenniscourt13.tif", "tenniscourt/tenniscourt69.tif", "tenniscourt/tenniscourt91.tif", "tenniscourt/tenniscourt68.tif"]} \ No newline at end of file diff --git a/datasets/__init__.py b/datasets/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..856abee9d7922e4ec3b9837b3ca9f64c37cd2cd1 --- /dev/null +++ b/datasets/__init__.py @@ -0,0 +1,9 @@ +from .datasets import register, make +from . import image_folder +from . import wrappers +from . import rs_super_warp +from . import cnn_sr_wrappers +from . import inr_sr_wrappers +from . import datasets_loader + +from .inr_diinn_sr_wrappers import INRSelectScaleSRWarp diff --git a/datasets/cnn_sr_wrappers.py b/datasets/cnn_sr_wrappers.py new file mode 100644 index 0000000000000000000000000000000000000000..f604e2d1566dd609d11e62898f4bef1dc7e8e1d8 --- /dev/null +++ b/datasets/cnn_sr_wrappers.py @@ -0,0 +1,75 @@ +import functools +import os.path +import random +import math + +import torchvision.transforms +from PIL import Image +import numpy as np +import torch +from einops import rearrange +from torch.utils.data import Dataset +from torchvision import transforms +from torchvision.transforms import InterpolationMode + +from datasets import register +import torchvision.transforms +from utils import to_pixel_samples, to_coordinates + + + +def resize_fn(img, size): + return transforms.ToTensor()( + transforms.Resize(size, Image.BICUBIC)( + transforms.ToPILImage()(img))) + + +@register('cnn_fixed_scale_sr_warp') +class CNNFixedScaleSRWarp(Dataset): + def __init__(self, dataset, scale_ratio, patch_size=48, + augment=False, val_mode=False, test_mode=False, + vis_continuous=False): + self.dataset = dataset + self.augment = augment + self.scale_ratio = scale_ratio + self.hr_size = int(patch_size * scale_ratio) + self.test_mode = test_mode + self.val_mode = val_mode + self.patch_size = patch_size + self.vis_continuous = vis_continuous + + def __len__(self): + return len(self.dataset) + + def __getitem__(self, idx): + img_hr, file_name = self.dataset[idx] + class_name = os.path.basename(os.path.dirname(file_name)) + file_name = os.path.basename(file_name).split('.')[0] + + if self.vis_continuous: + img_lr = transforms.Resize(self.patch_size, InterpolationMode.BICUBIC)( + transforms.CenterCrop(4*self.patch_size)(img_hr)) + + # img_hr: 3xHxW + if self.test_mode: + img_hr = transforms.CenterCrop(self.hr_size)(img_hr) + else: + img_hr = transforms.RandomCrop(self.hr_size)(img_hr) + + if not self.vis_continuous: + img_lr = transforms.Resize(self.patch_size, InterpolationMode.BICUBIC)(img_hr) + + if self.augment and not self.test_mode: + if random.random() < 0.5: + img_lr = img_lr.flip(-1) + img_hr = img_hr.flip(-1) + if random.random() < 0.5: + img_lr = img_lr.flip(-2) + img_hr = img_hr.flip(-2) + + return { + 'img': img_lr, + 'gt': img_hr, + 'class_name': class_name, + 'filename': file_name + } diff --git a/datasets/datasets.py b/datasets/datasets.py new file mode 100644 index 0000000000000000000000000000000000000000..30b8cd98a710186d7a2e6693554ee6719e3a502b --- /dev/null +++ b/datasets/datasets.py @@ -0,0 +1,21 @@ +import copy + + +datasets = {} + + +def register(name): + def decorator(cls): + datasets[name] = cls + return cls + return decorator + + +def make(dataset_spec, args=None): + if args is not None: + dataset_args = copy.deepcopy(dataset_spec['args']) + dataset_args.update(args) + else: + dataset_args = dataset_spec['args'] + dataset = datasets[dataset_spec['name']](**dataset_args) + return dataset diff --git a/datasets/datasets_loader.py b/datasets/datasets_loader.py new file mode 100644 index 0000000000000000000000000000000000000000..9b61dbeee997a129e0b48e7f884bc6a1478683d9 --- /dev/null +++ b/datasets/datasets_loader.py @@ -0,0 +1,69 @@ +import os +import json +from PIL import Image + +import pickle +import imageio +import numpy as np +import torch +from torch.utils.data import Dataset +from torchvision import transforms + +from datasets import register + + +@register('hr_data_loader') +class HRImgLoader(Dataset): + def __init__(self, root_path, split_file, split_key, first_k=None, cache='none'): + self.cache = cache + with open(split_file, 'r') as f: + filenames = json.load(f)[split_key] + if first_k is not None: + filenames = filenames[:first_k] + + self.files = [] + for filename in filenames: + file = os.path.join(root_path, filename) + + if cache == 'none': + self.files.append(file) + + elif cache == 'bin': + bin_root = os.path.join(os.path.dirname(root_path), + '_bin_' + os.path.basename(root_path)) + if not os.path.exists(bin_root): + os.mkdir(bin_root) + print('mkdir', bin_root) + bin_file = os.path.join( + bin_root, filename.split('.')[0] + '.pkl') + if not os.path.exists(bin_file): + with open(bin_file, 'wb') as f: + pickle.dump(imageio.imread(file), f) + print('dump', bin_file) + self.files.append(bin_file) + + elif cache == 'in_memory': + self.files.append(transforms.ToTensor()( + Image.open(file).convert('RGB'))) + + def __len__(self): + return len(self.files) + + def __getitem__(self, idx): + x = self.files[idx] + file_name = x + + if self.cache == 'none': + return transforms.ToTensor()(Image.open(x).convert('RGB')), file_name + + elif self.cache == 'bin': + with open(x, 'rb') as f: + x = pickle.load(f) + x = np.ascontiguousarray(x.transpose(2, 0, 1)) + x = torch.from_numpy(x).float() / 255 + return x, file_name + + elif self.cache == 'in_memory': + return x, file_name + + diff --git a/datasets/image_folder.py b/datasets/image_folder.py new file mode 100644 index 0000000000000000000000000000000000000000..0e7d87dd772fa5de03fc70ee775f9123bb7ee1da --- /dev/null +++ b/datasets/image_folder.py @@ -0,0 +1,87 @@ +import os +import json +from PIL import Image + +import pickle +import imageio +import numpy as np +import torch +from torch.utils.data import Dataset +from torchvision import transforms + +from datasets import register + + +@register('image-folder') +class ImageFolder(Dataset): + + def __init__(self, root_path, split_file=None, split_key=None, first_k=None, + repeat=1, cache='none'): + self.repeat = repeat + self.cache = cache + + if split_file is None: + filenames = sorted(os.listdir(root_path)) + else: + with open(split_file, 'r') as f: + filenames = json.load(f)[split_key] + if first_k is not None: + filenames = filenames[:first_k] + + self.files = [] + for filename in filenames: + file = os.path.join(root_path, filename) + + if cache == 'none': + self.files.append(file) + + elif cache == 'bin': + bin_root = os.path.join(os.path.dirname(root_path), + '_bin_' + os.path.basename(root_path)) + if not os.path.exists(bin_root): + os.mkdir(bin_root) + print('mkdir', bin_root) + bin_file = os.path.join( + bin_root, filename.split('.')[0] + '.pkl') + if not os.path.exists(bin_file): + with open(bin_file, 'wb') as f: + pickle.dump(imageio.imread(file), f) + print('dump', bin_file) + self.files.append(bin_file) + + elif cache == 'in_memory': + self.files.append(transforms.ToTensor()( + Image.open(file).convert('RGB'))) + + def __len__(self): + return len(self.files) * self.repeat + + def __getitem__(self, idx): + x = self.files[idx % len(self.files)] + + if self.cache == 'none': + return transforms.ToTensor()(Image.open(x).convert('RGB')) + + elif self.cache == 'bin': + with open(x, 'rb') as f: + x = pickle.load(f) + x = np.ascontiguousarray(x.transpose(2, 0, 1)) + x = torch.from_numpy(x).float() / 255 + return x + + elif self.cache == 'in_memory': + return x + + +@register('paired-image-folders') +class PairedImageFolders(Dataset): + + def __init__(self, root_path_1, root_path_2, **kwargs): + self.dataset_1 = ImageFolder(root_path_1, **kwargs) + self.dataset_2 = ImageFolder(root_path_2, **kwargs) + + def __len__(self): + return len(self.dataset_1) + + def __getitem__(self, idx): + return self.dataset_1[idx], self.dataset_2[idx] diff --git a/datasets/inr_diinn_sr_wrappers.py b/datasets/inr_diinn_sr_wrappers.py new file mode 100644 index 0000000000000000000000000000000000000000..776896a5c03576a5a5b625539c2ca265cf877107 --- /dev/null +++ b/datasets/inr_diinn_sr_wrappers.py @@ -0,0 +1,76 @@ +import copy +import functools +import os +import random +import math +from PIL import Image + +import numpy as np +import torch +from einops import rearrange +from torch.utils.data import Dataset +from torchvision import transforms + +from datasets import register +from utils import to_pixel_samples, to_coordinates + +import torchvision.transforms.functional as TF +import random +from typing import Sequence + + +class MyRotateTransform: + def __init__(self, angles: Sequence[int], p=0.5): + self.angles = angles + self.p = p + + def __call__(self, x): + if torch.rand(1) < self.p: + return x + angle = random.choice(self.angles) + return TF.rotate(x, angle) + + +@register('inr_diinn_select_scale_sr_warp') +class INRSelectScaleSRWarp(Dataset): + def __init__(self, + dataset, scales, patch_size=48, + augment=False, + val_mode=False, test_mode=False + ): + super(INRSelectScaleSRWarp, self).__init__() + self.dataset = dataset + self.scales = scales + self.patch_size = patch_size + self.augment = augment + self.test_mode = test_mode + self.val_mode = val_mode + + def __len__(self): + return len(self.dataset) + + def __getitem__(self, idx): + # import pdb + # pdb.set_trace() + img_hr_ori, file_name = self.dataset[idx] + class_name = os.path.basename(os.path.dirname(file_name)) + + sample = {} + for scale in self.scales: + hr_size = self.patch_size * scale + hr_size = int(hr_size) + + if self.test_mode or self.val_mode: + hr_size = int(self.patch_size * max(self.scales)) + img_hr = transforms.CenterCrop(hr_size)(img_hr_ori) + else: + img_hr = transforms.RandomCrop(hr_size)(copy.deepcopy(img_hr_ori)) + if self.augment: + img_hr = transforms.RandomHorizontalFlip(p=0.5)(img_hr) + img_hr = transforms.RandomVerticalFlip(p=0.5)(img_hr) + img_hr = MyRotateTransform([90, 180, 270], p=0.5)(img_hr) + + img_lr = transforms.Resize(self.patch_size, TF.InterpolationMode.BICUBIC)(img_hr) + sample[scale] = {'img': img_lr, 'gt': img_hr, 'class_name': class_name} + + return sample \ No newline at end of file diff --git a/datasets/inr_sr_wrappers.py b/datasets/inr_sr_wrappers.py new file mode 100644 index 0000000000000000000000000000000000000000..9cd3be7d2f1255eb0cd1788883414550c0ce4298 --- /dev/null +++ b/datasets/inr_sr_wrappers.py @@ -0,0 +1,177 @@ +import functools +import os +import random +import math +from PIL import Image + +import numpy as np +import torch +from einops import rearrange +from torch.utils.data import Dataset +from torchvision import transforms + +from datasets import register +from utils import to_pixel_samples, to_coordinates + +import torchvision.transforms.functional as TF +import random +from typing import Sequence + + +class MyRotateTransform: + def __init__(self, angles: Sequence[int], p=0.5): + self.angles = angles + self.p = p + + def __call__(self, x): + if torch.rand(1) < self.p: + return x + angle = random.choice(self.angles) + return TF.rotate(x, angle) + +@register('inr_fixed_scale_sr_warp') +class INRFixedScaleSRWarp(Dataset): + def __init__(self, + dataset, scale_ratio, patch_size=48, + augment=False, sample_q=None, + val_mode=False, test_mode=False, + encode_scale_ratio=False, + return_cell=False, # for liff + ): + super(INRFixedScaleSRWarp, self).__init__() + self.dataset = dataset + self.scale_ratio = scale_ratio + self.patch_size = patch_size + self.hr_size = int(patch_size * scale_ratio) + self.augment = augment + self.sample_q = sample_q + self.test_mode = test_mode + self.val_mode = val_mode + self.encode_scale_ratio = encode_scale_ratio + self.return_cell = return_cell + + def __len__(self): + return len(self.dataset) + + def __getitem__(self, idx): + # import pdb + # pdb.set_trace() + img_hr, file_name = self.dataset[idx] + class_name = os.path.basename(os.path.dirname(file_name)) + file_name = os.path.basename(file_name).split('.')[0] + # img_hr: 3xHxW + h, w = img_hr.shape[-2:] + # if h < 256 or w < 256: + # img_hr = transforms.Resize(256, Image.BICUBIC)(img_hr) + + if self.test_mode or self.val_mode: + img_hr = transforms.CenterCrop(self.hr_size)(img_hr) + else: + img_hr = transforms.RandomCrop(self.hr_size)(img_hr) + if self.augment: + img_hr = transforms.RandomHorizontalFlip(p=0.5)(img_hr) + img_hr = transforms.RandomVerticalFlip(p=0.5)(img_hr) + img_hr = MyRotateTransform([90, 180, 270], p=0.5)(img_hr) + + img_lr = transforms.Resize(self.patch_size, Image.BICUBIC)(img_hr) + + hr_coord = to_coordinates(size=img_hr.shape[-2:], return_map=False) + hr_rgb = rearrange(img_hr, 'C H W -> (H W) C') + + if self.sample_q is not None and not self.test_mode: + sample_lst = np.random.choice( + len(hr_coord), self.sample_q, replace=False) + hr_coord = hr_coord[sample_lst] + hr_rgb = hr_rgb[sample_lst] + return_dict = { + 'inp': img_lr, + 'coord': hr_coord, + 'gt': hr_rgb, + 'class_name': class_name, + 'filename': file_name + } + + if self.encode_scale_ratio: + scale_ratio = torch.ones_like(hr_coord) * self.patch_size / self.hr_size + return_dict['scale_ratio'] = scale_ratio + + if self.return_cell: + cell = torch.ones_like(hr_coord) + cell[:, 0] *= 2 / img_hr.shape[-2] + cell[:, 1] *= 2 / img_hr.shape[-1] + return_dict['cell'] = cell + + return return_dict + + +@register('inr_range_scale_sr_warp') +class INRRangeScaleSRWarp(Dataset): + def __init__(self, + dataset, max_scale_ratio, patch_size=48, + augment=False, sample_q=None, + val_mode=False, test_mode=False, + encode_scale_ratio=False, + return_cell=False, # for liff + ): + super(INRRangeScaleSRWarp, self).__init__() + self.dataset = dataset + self.max_scale_ratio = max_scale_ratio + self.patch_size = patch_size + assert max_scale_ratio <= 8 + self.augment = augment + self.sample_q = sample_q + self.test_mode = test_mode + self.val_mode = val_mode + self.encode_scale_ratio = encode_scale_ratio + self.return_cell = return_cell + + def __len__(self): + return len(self.dataset) + + def __getitem__(self, idx): + img_hr, file_name = self.dataset[idx] + class_name = os.path.basename(os.path.dirname(file_name)) + h, w = img_hr.shape[-2:] + # if h < 256 or w < 256: + # img_hr = transforms.Resize(256, Image.BICUBIC)(img_hr) + + hr_size = self.patch_size + self.patch_size * torch.rand([]) * (self.max_scale_ratio - 1) + hr_size = int(hr_size) + + if self.test_mode or self.val_mode: + hr_size = int(self.patch_size * self.max_scale_ratio) + img_hr = transforms.CenterCrop(hr_size)(img_hr) + else: + img_hr = transforms.RandomCrop(hr_size)(img_hr) + if self.augment: + img_hr = transforms.RandomHorizontalFlip(p=0.5)(img_hr) + img_hr = transforms.RandomVerticalFlip(p=0.5)(img_hr) + img_hr = MyRotateTransform([90, 180, 270], p=0.5)(img_hr) + + img_lr = transforms.Resize(self.patch_size, Image.BICUBIC)(img_hr) + + hr_coord = to_coordinates(size=img_hr.shape[-2:], return_map=False) + hr_rgb = rearrange(img_hr, 'C H W -> (H W) C') + + if self.sample_q is not None and not self.test_mode: + sample_lst = np.random.choice( + len(hr_coord), self.sample_q, replace=False) + hr_coord = hr_coord[sample_lst] + hr_rgb = hr_rgb[sample_lst] + return_dict = { + 'inp': img_lr, + 'coord': hr_coord, + 'gt': hr_rgb, + 'class_name': class_name + } + if self.encode_scale_ratio: + scale_ratio = torch.ones_like(hr_coord) * self.patch_size / hr_size + return_dict['scale_ratio'] = scale_ratio + + if self.return_cell: + cell = torch.ones_like(hr_coord) + cell[:, 0] *= 2 / img_hr.shape[-2] + cell[:, 1] *= 2 / img_hr.shape[-1] + return_dict['cell'] = cell + + return return_dict diff --git a/datasets/rs_super_warp.py b/datasets/rs_super_warp.py new file mode 100644 index 0000000000000000000000000000000000000000..7b56bd0272dadccc49f211d30358cd98490807bc --- /dev/null +++ b/datasets/rs_super_warp.py @@ -0,0 +1,75 @@ +import functools +import random +import math +from PIL import Image +import numpy as np +import torch +from einops import rearrange +from torch.utils.data import Dataset +from torchvision import transforms +from datasets import register +from utils import to_pixel_samples, to_coordinates + + +def resize_fn(img, size): + return transforms.ToTensor()( + transforms.Resize(size, Image.BICUBIC)( + transforms.ToPILImage()(img))) + + +@register('rs_sr_warp') +class RSSRWarp(Dataset): + def __init__(self, dataset, size_min=None, size_max=None, + augment=False, gt_resize=None, sample_q=None, val_mode=False): + self.dataset = dataset + self.size_min = size_min + if size_max is None: + size_max = size_min + self.size_max = size_max + self.augment = augment + self.gt_resize = gt_resize + self.sample_q = sample_q + self.val_mode = val_mode + + def __len__(self): + return len(self.dataset) + + def __getitem__(self, idx): + img_lr, img_hr = self.dataset[idx] + # p = idx / (len(self.dataset) - 1) + if not self.val_mode: + p = random.random() + w_hr = round(self.size_min + (self.size_max - self.size_min) * p) + img_hr = resize_fn(img_hr, w_hr) + else: + img_hr = resize_fn(img_hr, self.size_max) + + + if self.augment and not self.val_mode: + if random.random() < 0.5: + img_lr = img_lr.flip(-1) + img_hr = img_hr.flip(-1) + if random.random() < 0.5: + img_lr = img_lr.flip(-2) + img_hr = img_hr.flip(-2) + + if self.gt_resize is not None: + img_hr = resize_fn(img_hr, self.gt_resize) + + hr_coord = to_coordinates(size=img_hr.shape[-2:], return_map=False) + hr_rgb = rearrange(img_hr, 'C H W -> (H W) C') + + if self.sample_q is not None: + sample_lst = np.random.choice(len(hr_coord), self.sample_q, replace=False) + hr_coord = hr_coord[sample_lst] + hr_rgb = hr_rgb[sample_lst] + + # cell = torch.ones_like(hr_coord) + # cell[:, 0] *= 2 / img_hr.shape[-2] + # cell[:, 1] *= 2 / img_hr.shape[-1] + + return { + 'inp': img_lr, + 'coord': hr_coord, + 'gt': hr_rgb + } diff --git a/datasets/wrappers.py b/datasets/wrappers.py new file mode 100644 index 0000000000000000000000000000000000000000..8537fefdadb842b21f28eafa3359870136b3f09b --- /dev/null +++ b/datasets/wrappers.py @@ -0,0 +1,248 @@ +import functools +import random +import math +from PIL import Image + +import numpy as np +import torch +from torch.utils.data import Dataset +from torchvision import transforms + +from datasets import register +from utils import to_pixel_samples + + +@register('liff_test_warp') +class LIIFTestWarp(Dataset): + def __init__(self, dataset, scale_ratio, val_mode=False, sample_q=None): + self.dataset = dataset + self.scale_ratio = scale_ratio + self.val_mode = val_mode + self.sample_q = sample_q + print('hr_scale: ', int(scale_ratio*32)) + + def __len__(self): + return len(self.dataset) + + def __getitem__(self, idx): + img_lr, img_hr = self.dataset[idx] + if img_hr.shape[-1] < 256: + img_hr = transforms.Resize([256, 256])(img_hr) + + img_hr = transforms.Resize([self.scale_ratio*32, self.scale_ratio*32])(img_hr) + + hr_coord, hr_rgb = to_pixel_samples(img_hr.contiguous()) + + if self.sample_q is not None: + sample_lst = np.random.choice(len(hr_coord), self.sample_q, replace=False) + hr_coord = hr_coord[sample_lst] + hr_rgb = hr_rgb[sample_lst] + + cell = torch.ones_like(hr_coord) + cell[:, 0] *= 2 / img_hr.shape[-2] + cell[:, 1] *= 2 / img_hr.shape[-1] + + return { + 'inp': img_lr, + 'coord': hr_coord, + 'cell': cell, + 'gt': hr_rgb + } + +@register('sr-implicit-paired') +class SRImplicitPaired(Dataset): + + def __init__(self, dataset, inp_size=None, augment=False, sample_q=None): + self.dataset = dataset + self.inp_size = inp_size + self.augment = augment + self.sample_q = sample_q + + def __len__(self): + return len(self.dataset) + + def __getitem__(self, idx): + img_lr, img_hr = self.dataset[idx] + if img_hr.shape[-1] < 256: + img_hr = transforms.Resize([256, 256])(img_hr) + + s = img_hr.shape[-2] // img_lr.shape[-2] # assume int scale + if self.inp_size is None: + h_lr, w_lr = img_lr.shape[-2:] + img_hr = img_hr[:, :h_lr * s, :w_lr * s] + crop_lr, crop_hr = img_lr, img_hr + else: + w_lr = self.inp_size + x0 = random.randint(0, img_lr.shape[-2] - w_lr) + y0 = random.randint(0, img_lr.shape[-1] - w_lr) + crop_lr = img_lr[:, x0: x0 + w_lr, y0: y0 + w_lr] + w_hr = w_lr * s + x1 = x0 * s + y1 = y0 * s + crop_hr = img_hr[:, x1: x1 + w_hr, y1: y1 + w_hr] + + if self.augment: + hflip = random.random() < 0.5 + vflip = random.random() < 0.5 + dflip = random.random() < 0.5 + + def augment(x): + if hflip: + x = x.flip(-2) + if vflip: + x = x.flip(-1) + if dflip: + x = x.transpose(-2, -1) + return x + + crop_lr = augment(crop_lr) + crop_hr = augment(crop_hr) + + hr_coord, hr_rgb = to_pixel_samples(crop_hr.contiguous()) + + if self.sample_q is not None: + sample_lst = np.random.choice( + len(hr_coord), self.sample_q, replace=False) + hr_coord = hr_coord[sample_lst] + hr_rgb = hr_rgb[sample_lst] + + cell = torch.ones_like(hr_coord) + cell[:, 0] *= 2 / crop_hr.shape[-2] + cell[:, 1] *= 2 / crop_hr.shape[-1] + + return { + 'inp': crop_lr, + 'coord': hr_coord, + 'cell': cell, + 'gt': hr_rgb + } + + +def resize_fn(img, size): + return transforms.ToTensor()( + transforms.Resize(size, Image.BICUBIC)( + transforms.ToPILImage()(img))) + + +@register('sr-implicit-downsampled') +class SRImplicitDownsampled(Dataset): + + def __init__(self, dataset, inp_size=None, scale_min=1, scale_max=None, + augment=False, sample_q=None): + self.dataset = dataset + self.inp_size = inp_size + self.scale_min = scale_min + if scale_max is None: + scale_max = scale_min + self.scale_max = scale_max + self.augment = augment + self.sample_q = sample_q + + def __len__(self): + return len(self.dataset) + + def __getitem__(self, idx): + img = self.dataset[idx] + s = random.uniform(self.scale_min, self.scale_max) + + if self.inp_size is None: + h_lr = math.floor(img.shape[-2] / s + 1e-9) + w_lr = math.floor(img.shape[-1] / s + 1e-9) + img = img[:, :round(h_lr * s), :round(w_lr * s)] # assume round int + img_down = resize_fn(img, (h_lr, w_lr)) + crop_lr, crop_hr = img_down, img + else: + w_lr = self.inp_size + w_hr = round(w_lr * s) + x0 = random.randint(0, img.shape[-2] - w_hr) + y0 = random.randint(0, img.shape[-1] - w_hr) + crop_hr = img[:, x0: x0 + w_hr, y0: y0 + w_hr] + crop_lr = resize_fn(crop_hr, w_lr) + + if self.augment: + hflip = random.random() < 0.5 + vflip = random.random() < 0.5 + dflip = random.random() < 0.5 + + def augment(x): + if hflip: + x = x.flip(-2) + if vflip: + x = x.flip(-1) + if dflip: + x = x.transpose(-2, -1) + return x + + crop_lr = augment(crop_lr) + crop_hr = augment(crop_hr) + + hr_coord, hr_rgb = to_pixel_samples(crop_hr.contiguous()) + + if self.sample_q is not None: + sample_lst = np.random.choice( + len(hr_coord), self.sample_q, replace=False) + hr_coord = hr_coord[sample_lst] + hr_rgb = hr_rgb[sample_lst] + + cell = torch.ones_like(hr_coord) + cell[:, 0] *= 2 / crop_hr.shape[-2] + cell[:, 1] *= 2 / crop_hr.shape[-1] + + return { + 'inp': crop_lr, + 'coord': hr_coord, + 'cell': cell, + 'gt': hr_rgb + } + + +@register('sr-implicit-uniform-varied') +class SRImplicitUniformVaried(Dataset): + + def __init__(self, dataset, size_min, size_max=None, + augment=False, gt_resize=None, sample_q=None): + self.dataset = dataset + self.size_min = size_min + if size_max is None: + size_max = size_min + self.size_max = size_max + self.augment = augment + self.gt_resize = gt_resize + self.sample_q = sample_q + + def __len__(self): + return len(self.dataset) + + def __getitem__(self, idx): + img_lr, img_hr = self.dataset[idx] + # p = idx / (len(self.dataset) - 1) + p = random.random() + w_hr = round(self.size_min + (self.size_max - self.size_min) * p) + img_hr = resize_fn(img_hr, w_hr) + + if self.augment: + if random.random() < 0.5: + img_lr = img_lr.flip(-1) + img_hr = img_hr.flip(-1) + + if self.gt_resize is not None: + img_hr = resize_fn(img_hr, self.gt_resize) + + hr_coord, hr_rgb = to_pixel_samples(img_hr) + + if self.sample_q is not None: + sample_lst = np.random.choice( + len(hr_coord), self.sample_q, replace=False) + hr_coord = hr_coord[sample_lst] + hr_rgb = hr_rgb[sample_lst] + + cell = torch.ones_like(hr_coord) + cell[:, 0] *= 2 / img_hr.shape[-2] + cell[:, 1] *= 2 / img_hr.shape[-1] + + return { + 'inp': img_lr, + 'coord': hr_coord, + 'cell': cell, + 'gt': hr_rgb + } diff --git a/examples/AID_bridge_19_HR.png b/examples/AID_bridge_19_HR.png new file mode 100644 index 0000000000000000000000000000000000000000..62f8683c49b28b3bff3dd31bcb94f8b77011028b Binary files /dev/null and b/examples/AID_bridge_19_HR.png differ diff --git a/examples/AID_bridge_19_LR.png b/examples/AID_bridge_19_LR.png new file mode 100644 index 0000000000000000000000000000000000000000..7a4fc2cc2e982d972337f908ade30b1c89642f96 Binary files /dev/null and b/examples/AID_bridge_19_LR.png differ diff --git a/examples/AID_commercial_32_HR.png b/examples/AID_commercial_32_HR.png new file mode 100644 index 0000000000000000000000000000000000000000..d39af09ba8fa1372662378faf5edb59951d81de5 Binary files /dev/null and b/examples/AID_commercial_32_HR.png differ diff --git a/examples/AID_commercial_32_LR.png b/examples/AID_commercial_32_LR.png new file mode 100644 index 0000000000000000000000000000000000000000..a8c7378fbf18d265e9564f89446513bd684b78cd Binary files /dev/null and b/examples/AID_commercial_32_LR.png differ diff --git a/examples/AID_parking_60_HR.png b/examples/AID_parking_60_HR.png new file mode 100644 index 0000000000000000000000000000000000000000..81df55dccb9aab0880e9b746e97299e3c8881d60 Binary files /dev/null and b/examples/AID_parking_60_HR.png differ diff --git a/examples/AID_parking_60_LR.png b/examples/AID_parking_60_LR.png new file mode 100644 index 0000000000000000000000000000000000000000..c7860b6aa9f1763d143a097b7a4d810e8f449621 Binary files /dev/null and b/examples/AID_parking_60_LR.png differ diff --git a/examples/AID_school_161_HR.png b/examples/AID_school_161_HR.png new file mode 100644 index 0000000000000000000000000000000000000000..b81a87566d9bd34a0ff68aa723d2326e49737829 Binary files /dev/null and b/examples/AID_school_161_HR.png differ diff --git a/examples/AID_school_161_LR.png b/examples/AID_school_161_LR.png new file mode 100644 index 0000000000000000000000000000000000000000..a0a7d6044ecc7d049393ecec22dd70d1b5e9dafc Binary files /dev/null and b/examples/AID_school_161_LR.png differ diff --git a/examples/UC_airplane00_HR.png b/examples/UC_airplane00_HR.png new file mode 100644 index 0000000000000000000000000000000000000000..a483bb69dfdcdfc24ce7724feb5af502eb649d07 Binary files /dev/null and b/examples/UC_airplane00_HR.png differ diff --git a/examples/UC_airplane00_LR.png b/examples/UC_airplane00_LR.png new file mode 100644 index 0000000000000000000000000000000000000000..447ef6c237575751b91c38bb411846690bef9c2f Binary files /dev/null and b/examples/UC_airplane00_LR.png differ diff --git a/examples/UC_airplane95_HR.png b/examples/UC_airplane95_HR.png new file mode 100644 index 0000000000000000000000000000000000000000..1576e4462ebb66bd6158e9a252fcf50282a97220 Binary files /dev/null and b/examples/UC_airplane95_HR.png differ diff --git a/examples/UC_airplane95_LR.png b/examples/UC_airplane95_LR.png new file mode 100644 index 0000000000000000000000000000000000000000..584fd26b813c1c88b1969798adb426ce9e9f8dc9 Binary files /dev/null and b/examples/UC_airplane95_LR.png differ diff --git a/examples/UC_freeway35_HR.png b/examples/UC_freeway35_HR.png new file mode 100644 index 0000000000000000000000000000000000000000..462c0d87d8e046d8e1c3f82792579be9b4a8bf38 Binary files /dev/null and b/examples/UC_freeway35_HR.png differ diff --git a/examples/UC_freeway35_LR.png b/examples/UC_freeway35_LR.png new file mode 100644 index 0000000000000000000000000000000000000000..3bdd2fcd710f3942e45546f7f1a33a1246303986 Binary files /dev/null and b/examples/UC_freeway35_LR.png differ diff --git a/examples/UC_storagetanks54_HR.png b/examples/UC_storagetanks54_HR.png new file mode 100644 index 0000000000000000000000000000000000000000..d69f247c37a732d83b8fdbee7857c8e08eceaade Binary files /dev/null and b/examples/UC_storagetanks54_HR.png differ diff --git a/examples/UC_storagetanks54_LR.png b/examples/UC_storagetanks54_LR.png new file mode 100644 index 0000000000000000000000000000000000000000..15eee80f2bb043d67c7600b7cc8f7d18424d6351 Binary files /dev/null and b/examples/UC_storagetanks54_LR.png differ diff --git a/examples/airplane00.tif b/examples/airplane00.tif new file mode 100644 index 0000000000000000000000000000000000000000..d22d89794ee8b7bf5e6548ff4f96c5d2034fecad Binary files /dev/null and b/examples/airplane00.tif differ diff --git a/examples/airplane95.tif b/examples/airplane95.tif new file mode 100644 index 0000000000000000000000000000000000000000..12f265f3f76308bf6b9d7e6b59b95a42cebf0307 Binary files /dev/null and b/examples/airplane95.tif differ diff --git a/examples/bridge_19.jpg b/examples/bridge_19.jpg new file mode 100644 index 0000000000000000000000000000000000000000..480a14831237d22d1b1e0a917f15c5855050ee98 --- /dev/null +++ b/examples/bridge_19.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aa22040d7926585bbd934f153d22f124f0df705bbec64d4239ce6da5aa5133b7 +size 149159 diff --git a/examples/commercial_32.jpg b/examples/commercial_32.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f2b6d4d47b38f1e30c8b0a55806828990d405355 --- /dev/null +++ b/examples/commercial_32.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6fa7839cd5ebe88109e0045d654228fadddd57ce83b835f6adf2e2440db0b645 +size 247588 diff --git a/examples/freeway35.tif b/examples/freeway35.tif new file mode 100644 index 0000000000000000000000000000000000000000..4f142908db180210036e0600549430ba249256c1 Binary files /dev/null and b/examples/freeway35.tif differ diff --git a/examples/parking_60.jpg b/examples/parking_60.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f8dfd94ee8c37b45b9bf1673a4edccda0583bfb4 --- /dev/null +++ b/examples/parking_60.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8235828dee0acfa0e55ee67618f1db6de6262c717e4e6109e26ecf301fbd0898 +size 352603 diff --git a/examples/resize.py b/examples/resize.py new file mode 100644 index 0000000000000000000000000000000000000000..293e19becdf031870e8baf3bfb501e6005638748 --- /dev/null +++ b/examples/resize.py @@ -0,0 +1,20 @@ +import glob + +from PIL import Image +from torchvision import transforms +import cv2 +from torchvision.transforms import InterpolationMode + +patch_size = 48 + +for file in glob.glob("*.tif"): + img = transforms.ToTensor()(Image.open(file).convert('RGB')) * 255 + img_lr = transforms.Resize(patch_size, InterpolationMode.BICUBIC)( + transforms.CenterCrop(4 * patch_size)(img)) + + img_hr = transforms.CenterCrop(4 * patch_size)(img) + + cv2.imwrite(f'UC_{file.split(".")[0]}_LR.png', img_lr.permute((1, 2, 0)).numpy()) + print(f'UC_{file.split(".")[0]}_LR.png') + cv2.imwrite(f'UC_{file.split(".")[0]}_HR.png', img_hr.permute((1, 2, 0)).numpy()) + diff --git a/examples/school_161.jpg b/examples/school_161.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a0d4406d81643a885341317192527adcc2d1fa71 --- /dev/null +++ b/examples/school_161.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bb4ecf15901622c6be215e5cb44bdc70e277fbcde71ec8532ac8223fb0da1f85 +size 415617 diff --git a/examples/storagetanks54.tif b/examples/storagetanks54.tif new file mode 100644 index 0000000000000000000000000000000000000000..e7a6945c7a6066f8817c8010acd50e12794f281c Binary files /dev/null and b/examples/storagetanks54.tif differ diff --git a/models/__init__.py b/models/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..dab41ef12975f22503d615e220e09060523dad0c --- /dev/null +++ b/models/__init__.py @@ -0,0 +1,11 @@ +from .models import register, make +from . import edsr, rdn, rcan, swin_backbone +from . import mlp +from . import liif +from . import metasr +from . import rs_super, siren_modulation, transformer_neck, swin_neck +from . cnn_models import * +from . import rs_multiscale_super +from .funsr import FUNSR + +from .baselines import * diff --git a/models/baselines/OverNet.py b/models/baselines/OverNet.py new file mode 100644 index 0000000000000000000000000000000000000000..92bec65fbc7e1b6ded88c34bacdd35b194e20857 --- /dev/null +++ b/models/baselines/OverNet.py @@ -0,0 +1,239 @@ +import torch.nn as nn +import torch +import torch.nn.functional as F +import math +from models import register + + +class MeanShift(nn.Module): + def __init__(self, mean_rgb, sub): + super(MeanShift, self).__init__() + + sign = -1 if sub else 1 + r = mean_rgb[0] * sign + g = mean_rgb[1] * sign + b = mean_rgb[2] * sign + + self.shifter = nn.Conv2d(3, 3, 1, 1, 0) + self.shifter.weight.data = torch.eye(3).view(3, 3, 1, 1) + self.shifter.bias.data = torch.Tensor([r, g, b]) + + # Freeze the mean shift layer + for params in self.shifter.parameters(): + params.requires_grad = False + + def forward(self, x): + x = self.shifter(x) + return x + +class Scale(nn.Module): + + def __init__(self, init_value=1e-3): + super(Scale, self).__init__() + self.scale = nn.Parameter(torch.FloatTensor([init_value])) + + def forward(self, input): + return input * self.scale + +class SE(nn.Module): + def __init__(self, channel, reduction=16): + super(SE, self).__init__() + + self.avg_pool = nn.AdaptiveAvgPool2d(1) + + self.conv = nn.Sequential( + nn.Conv2d(channel, channel // reduction, 1, padding=0, bias=True), + nn.ReLU(inplace=True), + nn.Conv2d(channel // reduction, channel, 1, padding=0, bias=True), + nn.Sigmoid() + ) + + def forward(self, x): + y = self.avg_pool(x) + y = self.conv(y) + return x * y + + +class ResidualBlock(nn.Module): + def __init__(self, + wn, in_channels, out_channels): + super(ResidualBlock, self).__init__() + self.res_scale = Scale(1) + self.x_scale = Scale(1) + self.SE = SE(64, reduction=16) + body = [] + expand = 6 + linear = 0.8 + body.append( + wn(nn.Conv2d(64, 64*expand, 1, padding=1//2))) + body.append(nn.ReLU(inplace=True)) + body.append( + wn(nn.Conv2d(64*expand, int(64*linear), 1, padding=1//2))) + body.append( + wn(nn.Conv2d(int(64*linear), 64, 3, padding=3//2))) + self.body = nn.Sequential(*body) + + + def forward(self, x): + + out = self.body(x) + out = self.SE(out) + out = self.res_scale(out) + self.x_scale(x) + return out + + + +class BasicConv2d(nn.Module): + def __init__(self, wn, in_planes, out_planes, kernel_size, stride, padding=0): + super(BasicConv2d, self).__init__() + self.conv = wn(nn.Conv2d(in_planes, out_planes, + kernel_size=kernel_size, stride=stride, + padding=padding, bias=True)) + + self.LR = nn.ReLU(inplace=True) + + def forward(self, x): + x = self.conv(x) + x = self.LR(x) + return x + + + +class UpsampleBlock(nn.Module): + def __init__(self, n_channels, upscale, wn, group=1): + super(UpsampleBlock, self).__init__() + + self.up = _UpsampleBlock(n_channels, upscale=upscale, wn=wn, group=group) + + + def forward(self, x, upscale): + return self.up(x) + + +class _UpsampleBlock(nn.Module): + def __init__(self, n_channels, upscale, wn, group=1): + super(_UpsampleBlock, self).__init__() + + modules = [] + + if upscale == 2 or upscale == 4 or upscale == 8: + for _ in range(int(math.log(upscale, 2))): + modules += [wn(nn.Conv2d(n_channels, 4 * n_channels, 3, 1, 1, groups=group)), + nn.ReLU(inplace=True)] + modules += [nn.PixelShuffle(2)] + + elif upscale == 3: + modules += [wn(nn.Conv2d(n_channels, 9 * n_channels, 3, 1, 1, groups=group)), + nn.ReLU(inplace=True)] + modules += [nn.PixelShuffle(3)] + + elif upscale == 5: + modules += [wn(nn.Conv2d(n_channels, 25 * n_channels, 3, 1, 1, groups=group)), + nn.ReLU(inplace=True)] + modules += [nn.PixelShuffle(5)] + + self.body = nn.Sequential(*modules) + + def forward(self, x): + out = self.body(x) + return out + +#Local Dense Groups (LDGs) +class LDGs(nn.Module): + def __init__(self, + in_channels, out_channels, wn, + group=1): + super(LDGs, self).__init__() + + self.RB1 = ResidualBlock(wn, in_channels, out_channels) + self.RB2 = ResidualBlock(wn, in_channels, out_channels) + self.RB3 = ResidualBlock(wn, in_channels, out_channels) + + self.reduction1 = BasicConv2d(wn, in_channels*2, out_channels, 1, 1, 0) + self.reduction2 = BasicConv2d(wn, in_channels*3, out_channels, 1, 1, 0) + self.reduction3 = BasicConv2d(wn, in_channels*4, out_channels, 1, 1, 0) + + def forward(self, x): + c0 = o0 = x + + RB1 = self.RB1(o0) + concat1 = torch.cat([c0, RB1], dim=1) + out1 = self.reduction1(concat1) + + RB2 = self.RB2(out1) + concat2 = torch.cat([concat1, RB2], dim=1) + out2 = self.reduction2(concat2) + + RB3 = self.RB3(out2) + concat3 = torch.cat([concat2, RB3], dim=1) + out3 = self.reduction3(concat3) + + return out3 + + +@register('overnet') +class OverNet(nn.Module): + + def __init__(self, upscale=5, group=4, *args, **kwargs): + super(OverNet, self).__init__() + wn = lambda x: torch.nn.utils.weight_norm(x) + self.upscale = upscale + + # self.sub_mean = MeanShift((0.4488, 0.4371, 0.4040), sub=True) + # self.add_mean = MeanShift((0.4488, 0.4371, 0.4040), sub=False) + + self.entry_1 = wn(nn.Conv2d(3, 64, 3, 1, 1)) + + self.GDG1 = LDGs(64, 64, wn=wn) + self.GDG2 = LDGs(64, 64, wn=wn) + self.GDG3 = LDGs(64, 64, wn=wn) + + self.reduction1 = BasicConv2d(wn, 64*2, 64, 1, 1, 0) + self.reduction2 = BasicConv2d(wn, 64*3, 64, 1, 1, 0) + self.reduction3 = BasicConv2d(wn, 64*4, 64, 1, 1, 0) + + self.reduction = BasicConv2d(wn, 64*3, 64, 1, 1, 0) + + self.Global_skip = nn.Sequential(nn.AdaptiveAvgPool2d(1), nn.Conv2d(64, 64, 1, 1, 0), nn.ReLU(inplace=True)) + + self.upsample = UpsampleBlock(64, upscale=upscale, wn=wn, group=group) + + self.exit1 = wn(nn.Conv2d(64, 3, 3, 1, 1)) + + self.res_scale = Scale(1) + self.x_scale = Scale(1) + + def forward(self, x, out_size): + ori_h, ori_w = x.shape[-2:] + target_h, target_w = out_size + # x = self.sub_mean(x) + skip = x + + x = self.entry_1(x) + + c0 = o0 = x + + GDG1 = self.GDG1(o0) + concat1 = torch.cat([c0, GDG1], dim=1) + out1 = self.reduction1(concat1) + + GDG2 = self.GDG2(out1) + concat2 = torch.cat([concat1, GDG2], dim=1) + out2 = self.reduction2(concat2) + + GDG3 = self.GDG3(out2) + concat3 = torch.cat([concat2, GDG3], dim=1) + out3 = self.reduction3(concat3) + + output = self.reduction(torch.cat((out1, out2, out3),1)) + output = self.res_scale(output) + self.x_scale(self.Global_skip(x)) + + output = self.upsample(output, upscale=self.upscale) + + output = F.interpolate(output, out_size, mode='bicubic', align_corners=False) + skip = F.interpolate(skip, out_size, mode='bicubic', align_corners=False) + + output = self.exit1(output) + skip + # output = self.add_mean(output) + + return output diff --git a/models/baselines/RSI_HFAS.py b/models/baselines/RSI_HFAS.py new file mode 100644 index 0000000000000000000000000000000000000000..26f2c36ec2507ea2e5eb27a1e05dc53a2b8dda63 --- /dev/null +++ b/models/baselines/RSI_HFAS.py @@ -0,0 +1,496 @@ +import time +from collections import OrderedDict + +import torch +import torch.nn as nn +import math +import torchvision.utils as SI + +def make_model(args, parent=False): + return metafpn(args) + + +class Pos2Weight(nn.Module): + def __init__(self, inC, kernel_size=3, outC=3): + super(Pos2Weight, self).__init__() + self.inC = inC + self.kernel_size = kernel_size + self.outC = outC + self.meta_block = nn.Sequential( + nn.Linear(3, 256), + nn.ReLU(inplace=True), + nn.Linear(256, 512), + nn.ReLU(inplace=True), + nn.Linear(512, self.kernel_size * self.kernel_size * self.inC * self.outC) + ) + + def forward(self, x): + output = self.meta_block(x) + return output + + +class RDB_Conv(nn.Module): + def __init__(self, inChannels, growRate, kSize=3): + super(RDB_Conv, self).__init__() + Cin = inChannels + G = growRate + self.conv = nn.Sequential(*[ + nn.Conv2d(Cin, G, kSize, padding=(kSize - 1) // 2, stride=1), + nn.ReLU() + ]) + + def forward(self, x): + out = self.conv(x) + return out + + +class FPN(nn.Module): + def __init__(self, G0, kSize=3): + super(FPN, self).__init__() + + kSize1 = 1 + self.conv1 = RDB_Conv(G0, G0, kSize) + self.conv2 = RDB_Conv(G0, G0, kSize) + self.conv3 = RDB_Conv(G0, G0, kSize) + self.conv4 = RDB_Conv(G0, G0, kSize) + self.conv5 = RDB_Conv(G0, G0, kSize) + self.conv6 = RDB_Conv(G0, G0, kSize) + self.conv7 = RDB_Conv(G0, G0, kSize) + self.conv8 = RDB_Conv(G0, G0, kSize) + self.conv9 = RDB_Conv(G0, G0, kSize) + self.conv10 = RDB_Conv(G0, G0, kSize) + self.compress_in1 = nn.Conv2d(4 * G0, G0, kSize1, padding=(kSize1 - 1) // 2, stride=1) + self.compress_in2 = nn.Conv2d(3 * G0, G0, kSize1, padding=(kSize1 - 1) // 2, stride=1) + self.compress_in3 = nn.Conv2d(2 * G0, G0, kSize1, padding=(kSize1 - 1) // 2, stride=1) + self.compress_in4 = nn.Conv2d(2 * G0, G0, kSize1, padding=(kSize1 - 1) // 2, stride=1) + self.compress_out = nn.Conv2d(4 * G0, G0, kSize1, padding=(kSize1 - 1) // 2, stride=1) + + def forward(self, x): + x1 = self.conv1(x) + x2 = self.conv2(x1) + x3 = self.conv3(x2) + x4 = self.conv4(x3) + x11 = x + x4 + x5 = torch.cat((x1, x2, x3, x4), dim=1) + x5_res = self.compress_in1(x5) + x5 = self.conv5(x5_res) + x6 = self.conv6(x5) + x7 = self.conv7(x6) + x12 = x5_res + x7 + x8 = torch.cat((x5, x6, x7), dim=1) + x8_res = self.compress_in2(x8) + x8 = self.conv8(x8_res) + x9 = self.conv9(x8) + x13 = x8_res + x9 + x10 = torch.cat((x8, x9), dim=1) + x10_res = self.compress_in3(x10) + x10 = self.conv10(x10_res) + x14 = x10_res + x10 + output = torch.cat((x11, x12, x13, x14), dim=1) + output = self.compress_out(output) + output = output + x + return output + + +def default_conv(in_channels, out_channels, kernel_size, bias=True): + return nn.Conv2d( + in_channels, out_channels, kernel_size, + padding=(kernel_size // 2), bias=bias) + + +class MeanShift(nn.Conv2d): + def __init__(self, rgb_range, rgb_mean, rgb_std, sign=-1): + super(MeanShift, self).__init__(3, 3, kernel_size=1) + std = torch.Tensor(rgb_std) + self.weight.data = torch.eye(3).view(3, 3, 1, 1) + self.weight.data.div_(std.view(3, 1, 1, 1)) + self.bias.data = sign * rgb_range * torch.Tensor(rgb_mean) + self.bias.data.div_(std) + self.requires_grad = False + + +class BasicBlock(nn.Sequential): + def __init__( + self, in_channels, out_channels, kernel_size, stride=1, bias=False, + bn=True, act=nn.ReLU(True)): + + m = [nn.Conv2d( + in_channels, out_channels, kernel_size, + padding=(kernel_size // 2), stride=stride, bias=bias) + ] + if bn: m.append(nn.BatchNorm2d(out_channels)) + if act is not None: m.append(act) + super(BasicBlock, self).__init__(*m) + + +class ResBlock(nn.Module): + def __init__( + self, conv, n_feats, kernel_size, + bias=True, bn=False, act=nn.ReLU(True), res_scale=1): + + super(ResBlock, self).__init__() + m = [] + for i in range(2): + m.append(conv(n_feats, n_feats, kernel_size, bias=bias)) + if bn: m.append(nn.BatchNorm2d(n_feats)) + if i == 0: m.append(act) + + self.body = nn.Sequential(*m) + self.res_scale = res_scale + + def forward(self, x): + res = self.body(x).mul(self.res_scale) + res += x + + return res + + +class Upsampler(nn.Sequential): + def __init__(self, conv, scale, n_feats, bn=False, act=False, bias=True): + + m = [] + if (scale & (scale - 1)) == 0: # Is scale = 2^n? + for _ in range(int(math.log(scale, 2))): + m.append(conv(n_feats, 4 * n_feats, 3, bias)) + m.append(nn.PixelShuffle(2)) + if bn: m.append(nn.BatchNorm2d(n_feats)) + + if act == 'relu': + m.append(nn.ReLU(True)) + elif act == 'prelu': + m.append(nn.PReLU(n_feats)) + + elif scale == 3: + m.append(conv(n_feats, 9 * n_feats, 3, bias)) + m.append(nn.PixelShuffle(3)) + if bn: m.append(nn.BatchNorm2d(n_feats)) + + if act == 'relu': + m.append(nn.ReLU(True)) + elif act == 'prelu': + m.append(nn.PReLU(n_feats)) + else: + raise NotImplementedError + + super(Upsampler, self).__init__(*m) + + +class ResidualDenseBlock_8C(nn.Module): + ''' + Residual Dense Block + style: 8 convs + The core module of paper: (Residual Dense Network for Image Super-Resolution, CVPR 18) + ''' + + def __init__(self, nc, kernel_size=3, gc=32, stride=1, bias=True, pad_type='zero', norm_type=None, act_type='relu', + mode='CNA'): + super(ResidualDenseBlock_8C, self).__init__() + # gc: growth channel, i.e. intermediate channels + self.conv1 = ConvBlock(nc, gc, kernel_size, stride, bias=bias, pad_type=pad_type, norm_type=norm_type, + act_type=act_type, mode=mode) + self.conv2 = ConvBlock(nc + gc, gc, kernel_size, stride, bias=bias, pad_type=pad_type, norm_type=norm_type, + act_type=act_type, mode=mode) + self.conv3 = ConvBlock(nc + 2 * gc, gc, kernel_size, stride, bias=bias, pad_type=pad_type, norm_type=norm_type, + act_type=act_type, mode=mode) + self.conv4 = ConvBlock(nc + 3 * gc, gc, kernel_size, stride, bias=bias, pad_type=pad_type, norm_type=norm_type, + act_type=act_type, mode=mode) + self.conv5 = ConvBlock(nc + 4 * gc, gc, kernel_size, stride, bias=bias, pad_type=pad_type, norm_type=norm_type, + act_type=act_type, mode=mode) + self.conv6 = ConvBlock(nc + 5 * gc, gc, kernel_size, stride, bias=bias, pad_type=pad_type, norm_type=norm_type, + act_type=act_type, mode=mode) + self.conv7 = ConvBlock(nc + 6 * gc, gc, kernel_size, stride, bias=bias, pad_type=pad_type, norm_type=norm_type, + act_type=act_type, mode=mode) + self.conv8 = ConvBlock(nc + 7 * gc, gc, kernel_size, stride, bias=bias, pad_type=pad_type, norm_type=norm_type, + act_type=act_type, mode=mode) + if mode == 'CNA': + last_act = None + else: + last_act = act_type + self.conv9 = ConvBlock(nc + 8 * gc, nc, 1, stride, bias=bias, pad_type=pad_type, norm_type=norm_type, + act_type=last_act, mode=mode) + + def forward(self, x): + x1 = self.conv1(x) + x2 = self.conv2(torch.cat((x, x1), 1)) + x3 = self.conv3(torch.cat((x, x1, x2), 1)) + x4 = self.conv4(torch.cat((x, x1, x2, x3), 1)) + x5 = self.conv5(torch.cat((x, x1, x2, x3, x4), 1)) + x6 = self.conv6(torch.cat((x, x1, x2, x3, x4, x5), 1)) + x7 = self.conv7(torch.cat((x, x1, x2, x3, x4, x5, x6), 1)) + x8 = self.conv8(torch.cat((x, x1, x2, x3, x4, x5, x6, x7), 1)) + x9 = self.conv9(torch.cat((x, x1, x2, x3, x4, x5, x6, x7, x8), 1)) + return x9.mul(0.2) + x + + +def ConvBlock(in_channels, out_channels, kernel_size, stride=1, dilation=1, bias=True, valid_padding=True, padding=0, \ + act_type='relu', norm_type='bn', pad_type='zero', mode='CNA'): + assert (mode in ['CNA', 'NAC']), '[ERROR] Wrong mode in [%s]!' % sys.modules[__name__] + + if valid_padding: + padding = get_valid_padding(kernel_size, dilation) + else: + pass + p = pad(pad_type, padding) if pad_type and pad_type != 'zero' else None + conv = nn.Conv2d(in_channels, out_channels, kernel_size, stride=stride, padding=padding, dilation=dilation, + bias=bias) + + if mode == 'CNA': + act = activation(act_type) if act_type else None + n = norm(out_channels, norm_type) if norm_type else None + return sequential(p, conv, n, act) + elif mode == 'NAC': + act = activation(act_type, inplace=False) if act_type else None + n = norm(in_channels, norm_type) if norm_type else None + return sequential(n, act, p, conv) + + +def DeconvBlock(in_channels, out_channels, kernel_size, stride=1, dilation=1, bias=True, padding=0, \ + act_type='relu', norm_type='bn', pad_type='zero', mode='CNA'): + assert (mode in ['CNA', 'NAC']), '[ERROR] Wrong mode in [%s]!' % sys.modules[__name__] + + p = pad(pad_type, padding) if pad_type and pad_type != 'zero' else None + deconv = nn.ConvTranspose2d(in_channels, out_channels, kernel_size, stride, padding, dilation=dilation, bias=bias) + + if mode == 'CNA': + act = activation(act_type) if act_type else None + n = norm(out_channels, norm_type) if norm_type else None + return sequential(p, deconv, n, act) + elif mode == 'NAC': + act = activation(act_type, inplace=False) if act_type else None + n = norm(in_channels, norm_type) if norm_type else None + return sequential(n, act, p, deconv) + + +def get_valid_padding(kernel_size, dilation): + """ + Padding value to remain feature size. + """ + kernel_size = kernel_size + (kernel_size - 1) * (dilation - 1) + padding = (kernel_size - 1) // 2 + return padding + + +def pad(pad_type, padding): + pad_type = pad_type.lower() + if padding == 0: + return None + + layer = None + if pad_type == 'reflect': + layer = nn.ReflectionPad2d(padding) + elif pad_type == 'replicate': + layer = nn.ReplicationPad2d(padding) + else: + raise NotImplementedError('[ERROR] Padding layer [%s] is not implemented!' % pad_type) + return layer + + +def activation(act_type='relu', inplace=True, slope=0.2, n_prelu=1): + act_type = act_type.lower() + layer = None + if act_type == 'relu': + layer = nn.ReLU(inplace) + elif act_type == 'lrelu': + layer = nn.LeakyReLU(slope, inplace) + elif act_type == 'prelu': + layer = nn.PReLU(num_parameters=n_prelu, init=slope) + else: + raise NotImplementedError('[ERROR] Activation layer [%s] is not implemented!' % act_type) + return layer + + +def norm(n_feature, norm_type='bn'): + norm_type = norm_type.lower() + layer = None + if norm_type == 'bn': + layer = nn.BatchNorm2d(n_feature) + else: + raise NotImplementedError('[ERROR] Normalization layer [%s] is not implemented!' % norm_type) + return layer + + +def sequential(*args): + if len(args) == 1: + if isinstance(args[0], OrderedDict): + raise NotImplementedError('[ERROR] %s.sequential() does not support OrderedDict' % sys.modules[__name__]) + else: + return args[0] + modules = [] + for module in args: + if isinstance(module, nn.Sequential): + for submodule in module: + modules.append(submodule) + elif isinstance(module, nn.Module): + modules.append(module) + return nn.Sequential(*modules) + +class FeedbackBlock(nn.Module): + def __init__(self, num_features, num_groups, upscale_factor, act_type, norm_type): + super(FeedbackBlock, self).__init__() + if upscale_factor == 2: + stride = 2 + padding = 2 + kernel_size = 6 + elif upscale_factor == 3: + stride = 3 + padding = 2 + kernel_size = 7 + elif upscale_factor == 4: + stride = 4 + padding = 2 + kernel_size = 8 + elif upscale_factor == 8: + stride = 8 + padding = 2 + kernel_size = 12 + + kSize = 3 + kSize1 = 1 + + self.fpn1 = FPN(num_features) + self.fpn2 = FPN(num_features) + self.fpn3 = FPN(num_features) + self.fpn4 = FPN(num_features) + self.compress_in = nn.Conv2d(2 * num_features, num_features, kSize1, padding=(kSize1 - 1) // 2, stride=1) + self.compress_out = nn.Conv2d(4 * num_features, num_features, kSize1, padding=(kSize1 - 1) // 2, stride=1) + + def forward(self, x): + if self.should_reset: + self.last_hidden = torch.zeros(x.size()).cuda() + self.last_hidden.copy_(x) + self.should_reset = False + + x = torch.cat((x, self.last_hidden), dim=1) # tense拼接 + x = self.compress_in(x) + + fpn1 = self.fpn1(x) + fpn2 = self.fpn2(fpn1) + fpn3 = self.fpn3(fpn2) + fpn4 = self.fpn4(fpn3) + output = torch.cat((fpn1, fpn2, fpn3, fpn4), dim=1) + output = self.compress_out(output) + + self.last_hidden = output + + return output + + def reset_state(self): + self.should_reset = True + + +class metafpn(nn.Module): + def __init__(self, + RDNkSize=3, + G0=64, + n_colors=3, + act_type='prelu', + norm_type=None + ): + super(metafpn, self).__init__() # 第一句话,调用父类的构造函数,这是对继承自父类的属性进行初始化。而且是用父类的初始化方法来初始化继承的属性。也就是说,子类继承了父类的所有属性和方法,父类属性自然会用父类方法来进行初始化。当然,如果初始化的逻辑与父类的不同,不使用父类的方法,自己重新初始化也是可以的。 + + kernel_size = RDNkSize + self.num_steps = 4 + self.num_features = G0 + self.scale_idx = 0 + self.scale = 1 + in_channels = n_colors + num_groups = 6 + + # RGB mean for DIV2K + # rgb_mean = (0.4488, 0.4371, 0.4040) + # rgb_std = (1.0, 1.0, 1.0) + # self.sub_mean = common.MeanShift(args.rgb_range, rgb_mean, rgb_std) + # self.add_mean = common.MeanShift(args.rgb_range, rgb_mean, rgb_std, 1) + + # LR feature extraction block + self.conv_in = ConvBlock(in_channels, 4 * self.num_features, + # 3×3Conv 一个卷积核产生一个feature map就是num_features + kernel_size=3, + act_type=act_type, norm_type=norm_type) + self.feat_in = ConvBlock(4 * self.num_features, self.num_features, + kernel_size=1, + act_type=act_type, norm_type=norm_type) + + # basic block + self.block = FeedbackBlock(self.num_features, num_groups, self.scale, act_type, norm_type) + + # reconstruction block + # uncomment for pytorch 0.4.0 + # self.upsample = nn.Upsample(scale_factor=upscale_factor, mode='bilinear') + + # self.out = DeconvBlock(num_features, num_features, + # kernel_size=kernel_size, stride=stride, padding=padding, + # act_type='prelu', norm_type=norm_type) + self.P2W = Pos2Weight(inC=self.num_features) + + def repeat_x(self, x): + scale_int = math.ceil(self.scale) + N, C, H, W = x.size() + x = x.view(N, C, H, 1, W, 1) + + x = torch.cat([x] * scale_int, 3) + x = torch.cat([x] * scale_int, 5).permute(0, 3, 5, 1, 2, 4) + + return x.contiguous().view(-1, C, H, W) + + def forward(self, x, pos_mat): + self._reset_state() + + # x = self.sub_mean(x) + scale_int = math.ceil(self.scale) + # uncomment for pytorch 0.4.0 + # inter_res = self.upsample(x) + + # comment for pytorch 0.4.0 + inter_res = nn.functional.interpolate(x, scale_factor=scale_int, mode='bilinear', align_corners=False) + + x = self.conv_in(x) + x = self.feat_in(x) + + outs = [] + for _ in range(self.num_steps): + h = self.block(x) + + #output1 = h.clone() + # for i in range(60): + # output2 = output1[:,i:i+3,:,:] + # SI.save_image(output2,"results/result"+str(i)+".png") + + # meta########################################### + local_weight = self.P2W( + pos_mat.view(pos_mat.size(1), -1)) ### (outH*outW, outC*inC*kernel_size*kernel_size) + up_x = self.repeat_x(h) ### the output is (N*r*r,inC,inH,inW) + + # N*r^2 x [inC * kH * kW] x [inH * inW] + cols = nn.functional.unfold(up_x, 3, padding=1) + scale_int = math.ceil(self.scale) + + cols = cols.contiguous().view(cols.size(0) // (scale_int ** 2), scale_int ** 2, cols.size(1), cols.size(2), + 1).permute(0, 1, 3, 4, 2).contiguous() + + local_weight = local_weight.contiguous().view(x.size(2), scale_int, x.size(3), scale_int, -1, 3).permute(1, + 3, + 0, + 2, + 4, + 5).contiguous() + local_weight = local_weight.contiguous().view(scale_int ** 2, x.size(2) * x.size(3), -1, 3) + + out = torch.matmul(cols, local_weight).permute(0, 1, 4, 2, 3) + out = out.contiguous().view(x.size(0), scale_int, scale_int, 3, x.size(2), x.size(3)).permute(0, 3, 4, 1, 5, + 2) + out = out.contiguous().view(x.size(0), 3, scale_int * x.size(2), scale_int * x.size(3)) + + h = torch.add(inter_res, out) + # h = self.add_mean(h) + + outs.append(h) + + return outs # return output of every timesteps + + def _reset_state(self): + self.block.reset_state() + + def set_scale(self, scale_idx): + self.scale_idx = scale_idx + self.scale = self.args.scale[scale_idx] \ No newline at end of file diff --git a/models/baselines/__init__.py b/models/baselines/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..73c21e9f3894279b5ddaee031ebe59086576cfa2 --- /dev/null +++ b/models/baselines/__init__.py @@ -0,0 +1,8 @@ +from .diinn import DIINN +from .arbrcan import ArbRCAN +from .aliif import ALIIF +from .sadn import SADN +from .OverNet import OverNet + +from .basis import * +from .expansion import * \ No newline at end of file diff --git a/models/baselines/aliif.py b/models/baselines/aliif.py new file mode 100644 index 0000000000000000000000000000000000000000..5af06846a31671367a3ad5a281c573c5f74b79a9 --- /dev/null +++ b/models/baselines/aliif.py @@ -0,0 +1,131 @@ +import torch +import torch.nn as nn +import torch.nn.functional as F + +import models +from models import register +from utils import make_coord + + +@register('aliif') +class ALIIF(nn.Module): + + def __init__(self, encoder_spec, pdn_spec=None, basis_spec=None, imnet_spec=None, + local_ensemble=True, feat_unfold=True, cell_decode=True): + super().__init__() + self.local_ensemble = local_ensemble + self.feat_unfold = feat_unfold + self.cell_decode = cell_decode + + self.encoder = models.make(encoder_spec) + + if pdn_spec is not None: + self.pdn=models.make(pdn_spec) + self.use_pdn=True + else: + self.use_pdn = False + if basis_spec is not None: + self.basis=models.make(basis_spec) + self.use_basis=True + self.B,self.b=self.basis() + else: + self.use_basis = False + + if imnet_spec is not None: + imnet_in_dim = self.encoder.out_dim + if self.feat_unfold: + imnet_in_dim *= 9 + imnet_in_dim += 2 # attach coord + if self.cell_decode: + imnet_in_dim += 2 + self.imnet = models.make(imnet_spec, args={'in_dim': imnet_in_dim}) + else: + self.imnet = None + + def gen_feat(self, inp): + self.feat = self.encoder(inp) + return self.feat + + def query_rgb(self, coord, cell=None): + feat = self.feat + + if self.imnet is None: + ret = F.grid_sample(feat, coord.flip(-1).unsqueeze(1), + mode='nearest', align_corners=False)[:, :, 0, :] \ + .permute(0, 2, 1) + return ret + + if self.feat_unfold: + feat = F.unfold(feat, 3, padding=1).view( + feat.shape[0], feat.shape[1] * 9, feat.shape[2], feat.shape[3]) + + if self.local_ensemble: + vx_lst = [-1, 1] + vy_lst = [-1, 1] + eps_shift = 1e-6 + else: + vx_lst, vy_lst, eps_shift = [0], [0], 0 + + # field radius (global: [-1, 1]) + rx = 2 / feat.shape[-2] / 2 + ry = 2 / feat.shape[-1] / 2 + + feat_coord = make_coord(feat.shape[-2:], flatten=False).cuda() \ + .permute(2, 0, 1) \ + .unsqueeze(0).expand(feat.shape[0], 2, *feat.shape[-2:]) + + preds = [] + areas = [] + for vx in vx_lst: + for vy in vy_lst: + coord_ = coord.clone() + coord_[:, :, 0] += vx * rx + eps_shift + coord_[:, :, 1] += vy * ry + eps_shift + coord_.clamp_(-1 + 1e-6, 1 - 1e-6) + q_feat = F.grid_sample( + feat, coord_.flip(-1).unsqueeze(1), + mode='nearest', align_corners=False)[:, :, 0, :] \ + .permute(0, 2, 1) + q_coord = F.grid_sample( + feat_coord, coord_.flip(-1).unsqueeze(1), + mode='nearest', align_corners=False)[:, :, 0, :] \ + .permute(0, 2, 1) + rel_coord = coord - q_coord + rel_coord[:, :, 0] *= feat.shape[-2] + rel_coord[:, :, 1] *= feat.shape[-1] + inp = torch.cat([q_feat, rel_coord], dim=-1) + + if self.cell_decode: + rel_cell = cell.clone() + rel_cell[:, :, 0] *= feat.shape[-2] + rel_cell[:, :, 1] *= feat.shape[-1] + inp = torch.cat([inp, rel_cell], dim=-1) + + bs, q = coord.shape[:2] + + if self.use_pdn: + Coeff=self.pdn(inp) # out:(b,h*w,K) + else: + Coeff=torch.ones([inp.shape[0],inp.shape[1],1]) + if self.use_basis: + + pred = self.imnet(inp.view(bs * q, -1),Coeff.view(-1,Coeff.shape[2]),self.B,self.b).view(bs, q, -1) + else: + pred = self.imnet(inp.view(bs * q, -1)).view(bs, q, -1) + preds.append(pred) + + area = torch.abs(rel_coord[:, :, 0] * rel_coord[:, :, 1]) + areas.append(area + 1e-9) + + tot_area = torch.stack(areas).sum(dim=0) + if self.local_ensemble: + t = areas[0]; areas[0] = areas[3]; areas[3] = t + t = areas[1]; areas[1] = areas[2]; areas[2] = t + ret = 0 + for pred, area in zip(preds, areas): + ret = ret + pred * (area / tot_area).unsqueeze(-1) + return ret + + def forward(self, inp, coord, cell): + self.gen_feat(inp) + return self.query_rgb(coord, cell) diff --git a/models/baselines/arbrcan.py b/models/baselines/arbrcan.py new file mode 100644 index 0000000000000000000000000000000000000000..5d9b5ec1bdc1c64c3f2d18f1eac141f95fcabf2c --- /dev/null +++ b/models/baselines/arbrcan.py @@ -0,0 +1,341 @@ +import torch.nn as nn +import torch +import numpy as np +import torch.nn.functional as F +import math +import models +from models import register + + +def default_conv(in_channels, out_channels, kernel_size, bias=True): + return nn.Conv2d(in_channels, out_channels, kernel_size, padding=(kernel_size//2), bias=bias) + + +## Channel Attention (CA) Layer +class CALayer(nn.Module): + def __init__(self, channel, reduction=16): + super(CALayer, self).__init__() + self.avg_pool = nn.AdaptiveAvgPool2d(1) + self.conv_du = nn.Sequential( + nn.Conv2d(channel, channel // reduction, 1, padding=0, bias=True), + nn.ReLU(inplace=True), + nn.Conv2d(channel // reduction, channel, 1, padding=0, bias=True), + nn.Sigmoid() + ) + + def forward(self, x): + y = self.avg_pool(x) + y = self.conv_du(y) + return x * y + + +## Residual Channel Attention Block (RCAB) +class RCAB(nn.Module): + def __init__( + self, conv, n_feat, kernel_size, reduction, + bias=True, bn=False, act=nn.ReLU(True), res_scale=1): + + super(RCAB, self).__init__() + modules_body = [] + for i in range(2): + modules_body.append(conv(n_feat, n_feat, kernel_size, bias=bias)) + if bn: modules_body.append(nn.BatchNorm2d(n_feat)) + if i == 0: modules_body.append(act) + modules_body.append(CALayer(n_feat, reduction)) + self.body = nn.Sequential(*modules_body) + self.res_scale = res_scale + + def forward(self, x): + res = self.body(x) + res += x + return res + + +## Residual Group (RG) +class ResidualGroup(nn.Module): + def __init__(self, conv, n_feat, kernel_size, reduction, act, res_scale, n_resblocks): + super(ResidualGroup, self).__init__() + modules_body = [ + RCAB( + conv, n_feat, kernel_size, reduction, bias=True, bn=False, act=nn.ReLU(True), res_scale=1) \ + for _ in range(n_resblocks)] + modules_body.append(conv(n_feat, n_feat, kernel_size)) + self.body = nn.Sequential(*modules_body) + + def forward(self, x): + res = self.body(x) + res += x + return res + + +class SA_upsample(nn.Module): + def __init__(self, channels, num_experts=4, bias=False): + super(SA_upsample, self).__init__() + self.bias = bias + self.num_experts = num_experts + self.channels = channels + + # experts + weight_compress = [] + for i in range(num_experts): + weight_compress.append(nn.Parameter(torch.Tensor(channels//8, channels, 1, 1))) + nn.init.kaiming_uniform_(weight_compress[i], a=math.sqrt(5)) + self.weight_compress = nn.Parameter(torch.stack(weight_compress, 0)) + + weight_expand = [] + for i in range(num_experts): + weight_expand.append(nn.Parameter(torch.Tensor(channels, channels//8, 1, 1))) + nn.init.kaiming_uniform_(weight_expand[i], a=math.sqrt(5)) + self.weight_expand = nn.Parameter(torch.stack(weight_expand, 0)) + + # two FC layers + self.body = nn.Sequential( + nn.Conv2d(4, 64, 1, 1, 0, bias=True), + nn.ReLU(True), + nn.Conv2d(64, 64, 1, 1, 0, bias=True), + nn.ReLU(True), + ) + # routing head + self.routing = nn.Sequential( + nn.Conv2d(64, num_experts, 1, 1, 0, bias=True), + nn.Sigmoid() + ) + # offset head + self.offset = nn.Conv2d(64, 2, 1, 1, 0, bias=True) + + def forward(self, x, scale, scale2): + b, c, h, w = x.size() + + # (1) coordinates in LR space + ## coordinates in HR space + coor_hr = [torch.arange(0, round(h * scale), 1).unsqueeze(0).float().to(x.device), + torch.arange(0, round(w * scale2), 1).unsqueeze(0).float().to(x.device)] + + ## coordinates in LR space + coor_h = ((coor_hr[0] + 0.5) / scale) - (torch.floor((coor_hr[0] + 0.5) / scale + 1e-3)) - 0.5 + coor_h = coor_h.permute(1, 0) + coor_w = ((coor_hr[1] + 0.5) / scale2) - (torch.floor((coor_hr[1] + 0.5) / scale2 + 1e-3)) - 0.5 + + input = torch.cat(( + torch.ones_like(coor_h).expand([-1, round(scale2 * w)]).unsqueeze(0) / scale2, + torch.ones_like(coor_h).expand([-1, round(scale2 * w)]).unsqueeze(0) / scale, + coor_h.expand([-1, round(scale2 * w)]).unsqueeze(0), + coor_w.expand([round(scale * h), -1]).unsqueeze(0) + ), 0).unsqueeze(0) + + + # (2) predict filters and offsets + embedding = self.body(input) + ## offsets + offset = self.offset(embedding) + + ## filters + routing_weights = self.routing(embedding) + routing_weights = routing_weights.view(self.num_experts, round(scale*h) * round(scale2*w)).transpose(0, 1) # (h*w) * n + + weight_compress = self.weight_compress.view(self.num_experts, -1) + weight_compress = torch.matmul(routing_weights, weight_compress) + weight_compress = weight_compress.view(1, round(scale*h), round(scale2*w), self.channels//8, self.channels) + + weight_expand = self.weight_expand.view(self.num_experts, -1) + weight_expand = torch.matmul(routing_weights, weight_expand) + weight_expand = weight_expand.view(1, round(scale*h), round(scale2*w), self.channels, self.channels//8) + + # (3) grid sample & spatially varying filtering + ## grid sample + fea0 = grid_sample(x, offset, scale, scale2) ## b * h * w * c * 1 + fea = fea0.unsqueeze(-1).permute(0, 2, 3, 1, 4) ## b * h * w * c * 1 + + ## spatially varying filtering + out = torch.matmul(weight_compress.expand([b, -1, -1, -1, -1]), fea) + out = torch.matmul(weight_expand.expand([b, -1, -1, -1, -1]), out).squeeze(-1) + + return out.permute(0, 3, 1, 2) + fea0 + + +class SA_adapt(nn.Module): + def __init__(self, channels): + super(SA_adapt, self).__init__() + self.mask = nn.Sequential( + nn.Conv2d(channels, 16, 3, 1, 1), + nn.BatchNorm2d(16), + nn.ReLU(True), + nn.AvgPool2d(2), + nn.Conv2d(16, 16, 3, 1, 1), + nn.BatchNorm2d(16), + nn.ReLU(True), + nn.Conv2d(16, 16, 3, 1, 1), + nn.BatchNorm2d(16), + nn.ReLU(True), + nn.Upsample(scale_factor=2, mode='bilinear', align_corners=False), + nn.Conv2d(16, 1, 3, 1, 1), + nn.BatchNorm2d(1), + nn.Sigmoid() + ) + self.adapt = SA_conv(channels, channels, 3, 1, 1) + + def forward(self, x, scale, scale2): + mask = self.mask(x) + adapted = self.adapt(x, scale, scale2) + + return x + adapted * mask + + +class SA_conv(nn.Module): + def __init__(self, channels_in, channels_out, kernel_size=3, stride=1, padding=1, bias=False, num_experts=4): + super(SA_conv, self).__init__() + self.channels_out = channels_out + self.channels_in = channels_in + self.kernel_size = kernel_size + self.stride = stride + self.padding = padding + self.num_experts = num_experts + self.bias = bias + + # FC layers to generate routing weights + self.routing = nn.Sequential( + nn.Linear(2, 64), + nn.ReLU(True), + nn.Linear(64, num_experts), + nn.Softmax(1) + ) + + # initialize experts + weight_pool = [] + for i in range(num_experts): + weight_pool.append(nn.Parameter(torch.Tensor(channels_out, channels_in, kernel_size, kernel_size))) + nn.init.kaiming_uniform_(weight_pool[i], a=math.sqrt(5)) + self.weight_pool = nn.Parameter(torch.stack(weight_pool, 0)) + + if bias: + self.bias_pool = nn.Parameter(torch.Tensor(num_experts, channels_out)) + fan_in, _ = nn.init._calculate_fan_in_and_fan_out(self.weight_pool) + bound = 1 / math.sqrt(fan_in) + nn.init.uniform_(self.bias_pool, -bound, bound) + + def forward(self, x, scale, scale2): + # generate routing weights + scale = torch.ones(1, 1).to(x.device) / scale + scale2 = torch.ones(1, 1).to(x.device) / scale2 + routing_weights = self.routing(torch.cat((scale, scale2), 1)).view(self.num_experts, 1, 1) + + # fuse experts + fused_weight = (self.weight_pool.view(self.num_experts, -1, 1) * routing_weights).sum(0) + fused_weight = fused_weight.view(-1, self.channels_in, self.kernel_size, self.kernel_size) + + if self.bias: + fused_bias = torch.mm(routing_weights, self.bias_pool).view(-1) + else: + fused_bias = None + + # convolution + out = F.conv2d(x, fused_weight, fused_bias, stride=self.stride, padding=self.padding) + + return out + + +def grid_sample(x, offset, scale, scale2): + # generate grids + b, _, h, w = x.size() + grid = np.meshgrid(range(round(scale2*w)), range(round(scale*h))) + grid = np.stack(grid, axis=-1).astype(np.float64) + grid = torch.Tensor(grid).to(x.device) + + # project into LR space + grid[:, :, 0] = (grid[:, :, 0] + 0.5) / scale2 - 0.5 + grid[:, :, 1] = (grid[:, :, 1] + 0.5) / scale - 0.5 + + # normalize to [-1, 1] + grid[:, :, 0] = grid[:, :, 0] * 2 / (w - 1) -1 + grid[:, :, 1] = grid[:, :, 1] * 2 / (h - 1) -1 + grid = grid.permute(2, 0, 1).unsqueeze(0) + grid = grid.expand([b, -1, -1, -1]) + + # add offsets + offset_0 = torch.unsqueeze(offset[:, 0, :, :] * 2 / (w - 1), dim=1) + offset_1 = torch.unsqueeze(offset[:, 1, :, :] * 2 / (h - 1), dim=1) + grid = grid + torch.cat((offset_0, offset_1),1) + grid = grid.permute(0, 2, 3, 1) + + # sampling + output = F.grid_sample(x, grid, padding_mode='zeros') + + return output + + +@register('arbrcan') +class ArbRCAN(nn.Module): + def __init__(self, encoder_spec=None, conv=default_conv): + super(ArbRCAN, self).__init__() + + n_resgroups = 10 + n_resblocks = 20 + n_feats = 64 + kernel_size = 3 + reduction = 16 + act = nn.ReLU(True) + n_colors = 3 + res_scale = 1 + + self.n_resgroups = n_resgroups + + # head module + modules_head = [conv(n_colors, n_feats, kernel_size)] + self.head = nn.Sequential(*modules_head) + + # body module + modules_body = [ + ResidualGroup(conv, n_feats, kernel_size, reduction, act=act, res_scale=res_scale, + n_resblocks=n_resblocks) \ + for _ in range(n_resgroups)] + modules_body.append(conv(n_feats, n_feats, kernel_size)) + self.body = nn.Sequential(*modules_body) + + # tail module + modules_tail = [ + None, # placeholder to match pre-trained RCAN model + conv(n_feats, n_colors, kernel_size)] + self.tail = nn.Sequential(*modules_tail) + + ########## our plug-in module ########## + # scale-aware feature adaption block + # For RCAN, feature adaption is performed after each backbone block, i.e., K=1 + self.K = 1 + sa_adapt = [] + for i in range(self.n_resgroups // self.K): + sa_adapt.append(SA_adapt(64)) + self.sa_adapt = nn.Sequential(*sa_adapt) + + # scale-aware upsampling layer + self.sa_upsample = SA_upsample(64) + + def set_scale(self, scale, scale2): + self.scale = scale + self.scale2 = scale2 + + def forward(self, x, size): + B, C, H, W = x.shape + H_up, W_up = size + scale = H_up / H + scale2 = W_up / W + # head + x = self.head(x) + + # body + res = x + for i in range(self.n_resgroups): + res = self.body[i](res) + # scale-aware feature adaption + if (i+1) % self.K == 0: + res = self.sa_adapt[i](res, scale, scale2) + + res = self.body[-1](res) + res += x + + # scale-aware upsampling + res = self.sa_upsample(res, scale, scale2) + + # tail + x = self.tail[1](res) + + return x diff --git a/models/baselines/basis.py b/models/baselines/basis.py new file mode 100644 index 0000000000000000000000000000000000000000..95ebfd2feaed08bd2df2ac9aa0d47d8bf57a76c1 --- /dev/null +++ b/models/baselines/basis.py @@ -0,0 +1,79 @@ +import math +from argparse import Namespace + +import torch +import torch.nn as nn +import torch.nn.functional as F + +from models import register + + +class gen_basis(nn.Module): + def __init__(self, args): + super(gen_basis, self).__init__() + self.basis_num = args.basis_num + self.hidden = args.hidden + self.state = args.state + self.path=args.path + + def init_basis_bias(self): + self.w0 = nn.Parameter(torch.Tensor(self.basis_num,self.hidden*580), requires_grad=True) + nn.init.kaiming_uniform_(self.w0, a=math.sqrt(5)) + self.w1 = nn.Parameter(torch.Tensor(self.basis_num,self.hidden*self.hidden), requires_grad=True) + nn.init.kaiming_uniform_(self.w1, a=math.sqrt(5)) + self.w2 = nn.Parameter(torch.Tensor(self.basis_num,self.hidden*self.hidden), requires_grad=True) + nn.init.kaiming_uniform_(self.w2, a=math.sqrt(5)) + self.w3 = nn.Parameter(torch.Tensor(self.basis_num,self.hidden*self.hidden), requires_grad=True) + nn.init.kaiming_uniform_(self.w3, a=math.sqrt(5)) + self.w4 = nn.Parameter(torch.Tensor(self.basis_num,3*self.hidden), requires_grad=True) + nn.init.kaiming_uniform_(self.w4, a=math.sqrt(5)) + basis = [self.w0, self.w1, self.w2, self.w3, self.w4] + self.bias1 = nn.Parameter(torch.Tensor(self.basis_num,self.hidden), requires_grad=True) + self.bias2 = nn.Parameter(torch.Tensor(self.basis_num,self.hidden), requires_grad=True) + self.bias3 = nn.Parameter(torch.Tensor(self.basis_num,self.hidden), requires_grad=True) + self.bias4 = nn.Parameter(torch.Tensor(self.basis_num,self.hidden), requires_grad=True) + self.bias5 = nn.Parameter(torch.Tensor(self.basis_num,3), requires_grad=True) + bias = [self.bias1,self.bias2,self.bias3,self.bias4,self.bias5] + + for i in range(len(bias)): + fan_in, _ = nn.init._calculate_fan_in_and_fan_out(basis[i]) + bound = 1 / math.sqrt(fan_in) if fan_in > 0 else 0 + nn.init.uniform_(bias[i], -bound, bound) + + + + return basis,bias + + + def load_basis_for_test_kaiming(self,path): + model_spec = torch.load(path)['model'] + w0 = model_spec['sd']['basis.w0'] + w1 = model_spec['sd']['basis.w1'] + w2 = model_spec['sd']['basis.w2'] + w3 = model_spec['sd']['basis.w3'] + w4 = model_spec['sd']['basis.w4'] + b0 = model_spec['sd']['basis.bias1'] + b1 = model_spec['sd']['basis.bias2'] + b2 = model_spec['sd']['basis.bias3'] + b3 = model_spec['sd']['basis.bias4'] + b4 = model_spec['sd']['basis.bias5'] + torch.cuda.empty_cache() + return [w0,w1,w2,w3,w4],[b0,b1,b2,b3,b4] + + def forward(self): + if self.state=='train': + print('init_basis_use_kaiming') + res=self.init_basis_bias() + else: + print('load_basis_from_model') + res=self.load_basis_for_test_kaiming(self.path) + return res + +@register('basis') +def make_basis(basis_num=10,hidden=16,state=None,path=None): + args = Namespace() + args.basis_num = basis_num + args.hidden = hidden + args.state = state + args.path = path + return gen_basis(args) diff --git a/models/baselines/diinn.py b/models/baselines/diinn.py new file mode 100644 index 0000000000000000000000000000000000000000..699f7ae078128eeb189d3de2b8b01816517cdd3a --- /dev/null +++ b/models/baselines/diinn.py @@ -0,0 +1,181 @@ +import torch +import torch.nn as nn +import torch.nn.functional as F +import models +from models import register + + +@register('diinn') +class DIINN(nn.Module): + def __init__(self, + encoder_spec, + mode=3, init_q=False): + super().__init__() + + self.encoder = models.make(encoder_spec) + self.decoder = ImplicitDecoder(mode=mode, init_q=init_q) + + def forward(self, x, size, bsize=None): + x = self.encoder(x) + x = self.decoder(x, size, bsize) + return x + + +class SineAct(nn.Module): + def __init__(self): + super().__init__() + + def forward(self, x): + return torch.sin(x) + + +def patch_norm_2d(x, kernel_size=3): + # B, C, H, W = x.shape + # var, mean = torch.var_mean(F.unfold(x, kernel_size=kernel_size, padding=padding).view(B, C,kernel_size**2, H, W), dim=2, keepdim=False) + # return (x - mean) / torch.sqrt(var + 1e-6) + mean = F.avg_pool2d(x, kernel_size=kernel_size, padding=kernel_size // 2) + mean_sq = F.avg_pool2d(x ** 2, kernel_size=kernel_size, padding=kernel_size // 2) + var = mean_sq - mean ** 2 + return (x - mean) / (var + 1e-6) + + +class ImplicitDecoder(nn.Module): + def __init__(self, in_channels=64, hidden_dims=[256, 256, 256, 256], mode=3, init_q=False): + super().__init__() + + self.mode = mode + self.init_q = init_q + + last_dim_K = in_channels * 9 + + if self.init_q: + self.first_layer = nn.Sequential(nn.Conv2d(3, in_channels * 9, 1), + SineAct()) + last_dim_Q = in_channels * 9 + else: + last_dim_Q = 3 + + self.K = nn.ModuleList() + self.Q = nn.ModuleList() + if self.mode == 1: + for hidden_dim in hidden_dims: + self.K.append(nn.Sequential(nn.Conv2d(last_dim_K, hidden_dim, 1), + nn.ReLU())) + self.Q.append(nn.Sequential(nn.Conv2d(last_dim_Q, hidden_dim, 1), + SineAct())) + last_dim_K = hidden_dim + last_dim_Q = hidden_dim + elif self.mode == 2: + for hidden_dim in hidden_dims: + self.K.append(nn.Sequential(nn.Conv2d(last_dim_K, hidden_dim, 1), + nn.ReLU())) + self.Q.append(nn.Sequential(nn.Conv2d(last_dim_Q, hidden_dim, 1), + SineAct())) + last_dim_K = hidden_dim + in_channels * 9 + last_dim_Q = hidden_dim + elif self.mode == 3: + for hidden_dim in hidden_dims: + self.K.append(nn.Sequential(nn.Conv2d(last_dim_K, hidden_dim, 1), + nn.ReLU())) + self.Q.append(nn.Sequential(nn.Conv2d(last_dim_Q, hidden_dim, 1), + SineAct())) + last_dim_K = hidden_dim + in_channels * 9 + last_dim_Q = hidden_dim + elif self.mode == 4: + for hidden_dim in hidden_dims: + self.K.append(nn.Sequential(nn.Conv2d(last_dim_K, hidden_dim, 1), + nn.ReLU())) + self.Q.append(nn.Sequential(nn.Conv2d(last_dim_Q, hidden_dim, 1), + SineAct())) + last_dim_K = hidden_dim + in_channels * 9 + last_dim_Q = hidden_dim + if self.mode == 4: + self.last_layer = nn.Conv2d(hidden_dims[-1], 3, 3, padding=1, padding_mode='reflect') + else: + self.last_layer = nn.Conv2d(hidden_dims[-1], 3, 1) + + def _make_pos_encoding(self, x, size): + B, C, H, W = x.shape + H_up, W_up = size + + h_idx = -1 + 1 / H + 2 / H * torch.arange(H, device=x.device).float() + w_idx = -1 + 1 / W + 2 / W * torch.arange(W, device=x.device).float() + in_grid = torch.stack(torch.meshgrid(h_idx, w_idx, indexing='ij'), dim=0) + + h_idx_up = -1 + 1 / H_up + 2 / H_up * torch.arange(H_up, device=x.device).float() + w_idx_up = -1 + 1 / W_up + 2 / W_up * torch.arange(W_up, device=x.device).float() + up_grid = torch.stack(torch.meshgrid(h_idx_up, w_idx_up, indexing='ij'), dim=0) + + rel_grid = (up_grid - F.interpolate(in_grid.unsqueeze(0), size=(H_up, W_up), + mode='nearest-exact')) # important! mode='nearest' gives inconsistent results + rel_grid[:, 0, :, :] *= H + rel_grid[:, 1, :, :] *= W + + return rel_grid.contiguous().detach() + + def step(self, x, syn_inp): + if self.init_q: + syn_inp = self.first_layer(syn_inp) + x = syn_inp * x + if self.mode == 1: + k = self.K[0](x) + q = k * self.Q[0](syn_inp) + + for i in range(1, len(self.K)): + k = self.K[i](k) + q = k * self.Q[i](q) + + q = self.last_layer(q) + return q + elif self.mode == 2: + k = self.K[0](x) + q = k * self.Q[0](syn_inp) + for i in range(1, len(self.K)): + k = self.K[i](torch.cat([k, x], dim=1)) + q = k * self.Q[i](q) + q = self.last_layer(q) + return q + elif self.mode == 3: + k = self.K[0](x) + q = k * self.Q[0](syn_inp) + # q = k + self.Q[0](syn_inp) + for i in range(1, len(self.K)): + k = self.K[i](torch.cat([q, x], dim=1)) + q = k * self.Q[i](q) + # q = k + self.Q[i](q) + q = self.last_layer(q) + return q + elif self.mode == 4: + k = self.K[0](x) + q = k * self.Q[0](syn_inp) + for i in range(1, len(self.K)): + k = self.K[i](torch.cat([q, x], dim=1)) + q = k * self.Q[i](q) + q = self.last_layer(q) + return q + + def batched_step(self, x, syn_inp, bsize): + with torch.no_grad(): + h, w = syn_inp.shape[-2:] + ql = 0 + preds = [] + while ql < w: + qr = min(ql + bsize // h, w) + pred = self.step(x[:, :, :, ql: qr], syn_inp[:, :, :, ql: qr]) + preds.append(pred) + ql = qr + pred = torch.cat(preds, dim=-1) + return pred + + def forward(self, x, size, bsize=None): + B, C, H_in, W_in = x.shape + rel_coord = self._make_pos_encoding(x, size).expand(B, -1, *size) # 2 + ratio = x.new_tensor([(H_in * W_in) / (size[0] * size[1])]).view(1, -1, 1, 1).expand(B, -1, *size) # 2 + syn_inp = torch.cat([rel_coord, ratio], dim=1) + x = F.interpolate(F.unfold(x, 3, padding=1).view(B, C * 9, H_in, W_in), size=syn_inp.shape[-2:], + mode='nearest-exact') + if bsize is None: + pred = self.step(x, syn_inp) + else: + pred = self.batched_step(x, syn_inp, bsize) + return pred diff --git a/models/baselines/dynamic_layers.py b/models/baselines/dynamic_layers.py new file mode 100644 index 0000000000000000000000000000000000000000..613fc2ff5fa1cb4360ab175aacfa853056a4a7ec --- /dev/null +++ b/models/baselines/dynamic_layers.py @@ -0,0 +1,128 @@ +import torch +import torch.nn as nn +from torch.nn import functional as F +from torch.nn.utils import weight_norm + +class ScaleAwareAttention2d(nn.Module): + def __init__(self, in_channels, ratios, K, temperature, init_weight=True): + super().__init__() + assert temperature % 3 == 1 + self.avgpool = nn.AdaptiveAvgPool2d(1) + if in_channels != 3: + hidden_channels = int(in_channels * ratios) + 1 + else: + hidden_channels = K + self.fc1 = nn.Conv2d(in_channels, hidden_channels, 1, bias=False) + # self.bn = nn.BatchNorm2d(hidden_channels) + self.fc2 = nn.Conv2d(hidden_channels + 2, K, 1, bias=True) + self.temperature = temperature + if init_weight: + self._initialize_weights() + + def _initialize_weights(self): + for m in self.modules(): + if isinstance(m, nn.Conv2d): + nn.init.kaiming_normal_(m.weight, mode="fan_out", nonlinearity="relu") + if m.bias is not None: + nn.init.constant_(m.bias, 0) + if isinstance(m, nn.BatchNorm2d): + nn.init.constant_(m.weight, 1) + nn.init.constant_(m.bias, 0) + + def updata_temperature(self): + if self.temperature != 1: + self.temperature -= 3 + # print('Change temperature to:', str(self.temperature)) + + def forward(self, x, scale): + if not self.training: + temperature = 1 + else: + temperature = self.temperature + + batch_size = x.shape[0] + x = self.avgpool(x) + x = self.fc1(x) + x = F.relu(x) + x = torch.cat( + [x, torch.ones([batch_size, 2, 1, 1], device=x.device) * scale], dim=1 + ) + x = self.fc2(x).view(x.size(0), -1) + return F.softmax(x / temperature, 1) + + +class ScaleAwareDynamicConv2d(nn.Module): + def __init__( + self, + in_channels, + out_channels, + kernel_size, + ratio=0.25, + stride=1, + padding=0, + dilation=1, + groups=1, + bias=True, + K=4, + temperature=34, + init_weight=True, + ): + super().__init__() + assert in_channels % groups == 0 + self.in_channels = in_channels + self.out_channels = out_channels + self.kernel_size = kernel_size + self.stride = stride + self.padding = padding + self.dilation = dilation + self.groups = groups + self.bias = bias + self.K = K + self.attention = ScaleAwareAttention2d(in_channels, ratio, K, temperature) + + self.weight = nn.Parameter( + torch.randn( + K, out_channels, in_channels // groups, kernel_size, kernel_size + ), + requires_grad=True, + ) + if bias: + self.bias = nn.Parameter(torch.Tensor(K, out_channels)) + else: + self.bias = None + if init_weight: + self._initialize_weights() + + def _initialize_weights(self): + for i in range(self.K): + nn.init.kaiming_uniform_(self.weight[i]) + + def update_temperature(self): + self.attention.updata_temperature() + + def forward(self, x, scale): + softmax_attention = self.attention(x, scale) + batch_size, _, height, width = x.size() + x = x.view(1, -1, height, width) + weight = self.weight.view(self.K, -1) + + aggregate_weight = torch.mm(softmax_attention, weight).view( + -1, self.in_channels, self.kernel_size, self.kernel_size + ) + if self.bias is not None: + aggregate_bias = torch.mm(softmax_attention, self.bias).view(-1) + else: + aggregate_bias = None + output = F.conv2d( + x, + weight=aggregate_weight, + bias=aggregate_bias, + stride=self.stride, + padding=self.padding, + dilation=self.dilation, + groups=self.groups * batch_size, + ) + output = output.view( + batch_size, self.out_channels, output.size(-2), output.size(-1) + ) + return output diff --git a/models/baselines/expansion.py b/models/baselines/expansion.py new file mode 100644 index 0000000000000000000000000000000000000000..e848a21a31739e7ec4abc6173127383330a2caa4 --- /dev/null +++ b/models/baselines/expansion.py @@ -0,0 +1,43 @@ +import math +from argparse import Namespace + +import torch +import torch.nn as nn +import torch.nn.functional as F +import models +from models import register +import numpy as np + +class ExpansionNet(nn.Module): + def __init__(self, args): + super(ExpansionNet, self).__init__() + self.args = args + self.in_dim = args.in_dim + self.out_dim = args.out_dim + self.hidden_list = args.hidden_list + layers = [] + lastv = self.in_dim + hidden_list = self.hidden_list + out_dim = self.out_dim + for hidden in hidden_list: + layers.append(nn.Linear(lastv, hidden)) + layers.append(nn.ReLU()) + lastv = hidden + layers.append(nn.Linear(lastv, out_dim)) + self.layers = nn.Sequential(*layers) + + def forward(self, x): + b, _, c = x.shape + x = x.view(-1, c) + logits = self.layers(x) + out = nn.functional.normalize(logits, dim=1) + return out.view(b,_,self.out_dim) + + +@register('ExpansionNet') +def make_ExpansionNet(in_dim=580,out_dim=10,hidden_list=None): + args = Namespace() + args.in_dim = in_dim + args.out_dim = out_dim + args.hidden_list = hidden_list + return ExpansionNet(args) diff --git a/models/baselines/sadn.py b/models/baselines/sadn.py new file mode 100644 index 0000000000000000000000000000000000000000..7900fe97704398ddc1a298f06aedd244ef8b5d72 --- /dev/null +++ b/models/baselines/sadn.py @@ -0,0 +1,845 @@ +import torch +import torch.nn as nn +from matplotlib import pyplot as plt +from torch.nn.utils import weight_norm +import time +from os.path import exists +import os + +from . import upsampler +from .dynamic_layers import ScaleAwareDynamicConv2d +from easydict import EasyDict +import models +from models import register + + +def spatial_fold(input, fold): + if fold == 1: + return input + + batch, channel, height, width = input.shape + h_fold = height // fold + w_fold = width // fold + + return ( + input.view(batch, channel, h_fold, fold, w_fold, fold) + .permute(0, 1, 3, 5, 2, 4) + .reshape(batch, -1, h_fold, w_fold) + ) + + +def spatial_unfold(input, unfold): + if unfold == 1: + return input + + batch, channel, height, width = input.shape + h_unfold = height * unfold + w_unfold = width * unfold + + return ( + input.view(batch, -1, unfold, unfold, height, width) + .permute(0, 1, 4, 2, 5, 3) + .reshape(batch, -1, h_unfold, w_unfold) + ) + + +def default_conv(in_channels, out_channels, kernel_size, bias=True): + # logger.warning("The module is deprecated, and will be removed in the future! ") + return nn.Conv2d( + in_channels, out_channels, kernel_size, padding=(kernel_size // 2), bias=bias + ) + + +class WeightNormedConv(nn.Sequential): + def __init__( + self, + in_channels, + out_channels, + kernel_size, + stride=1, + bias=True, + act=nn.ReLU(True), + ): + conv = weight_norm( + nn.Conv2d( + in_channels, + out_channels, + kernel_size, + padding=kernel_size // 2, + stride=stride, + bias=bias, + ) + ) + m = [conv] + if act: + m.append(act) + super().__init__(*m) + + +class MeanShift(nn.Conv2d): + def __init__(self, rgb_range, rgb_mean, rgb_std, sign=-1): + if len(rgb_std) != len(rgb_mean): + assert len(rgb_std) == 1 + rgb_std = rgb_std * len(rgb_mean) + channel = len(rgb_mean) + super(MeanShift, self).__init__(channel, channel, kernel_size=1) + std = torch.Tensor(rgb_std) + self.weight.data = torch.eye(channel).view(channel, channel, 1, 1) + self.weight.data.div_(std.view(channel, 1, 1, 1)) + self.bias.data = sign * rgb_range * torch.Tensor(rgb_mean) + self.bias.data.div_(std) + self.requires_grad = False + + +class BasicBlock(nn.Sequential): + def __init__( + self, + in_channels, + out_channels, + kernel_size, + stride=1, + bias=False, + bn=True, + act=nn.ReLU(True), + ): + + m = [ + nn.Conv2d( + in_channels, + out_channels, + kernel_size, + padding=(kernel_size // 2), + stride=stride, + bias=bias, + ) + ] + if bn: + m.append(nn.BatchNorm2d(out_channels)) + if act is not None: + m.append(act) + super(BasicBlock, self).__init__(*m) + + +class ResBlock(nn.Module): + def __init__( + self, + conv, + n_feats, + kernel_size, + bias=True, + bn=False, + act=nn.ReLU(True), + res_scale=1, + ): + + super(ResBlock, self).__init__() + m = [] + for i in range(2): + m.append(conv(n_feats, n_feats, kernel_size, bias=bias)) + if bn: + m.append(nn.BatchNorm2d(n_feats)) + if i == 0: + m.append(act) + + self.body = nn.Sequential(*m) + self.res_scale = res_scale + + def forward(self, x): + res = self.body(x).mul(self.res_scale) + res += x + return res + + +def channel_shuffle(x, groups): + batchsize, num_channels, height, width = x.data.size() + + channels_per_group = num_channels // groups + + # reshape + x = x.view(batchsize, groups, channels_per_group, height, width) + + x = torch.transpose(x, 1, 2).contiguous() + + # flatten + x = x.view(batchsize, -1, height, width) + + return x + + +def make_coord(shape, ranges=None, flatten=True): + """Make coordinates at grid centers.""" + coord_seqs = [] + for i, n in enumerate(shape): + if ranges is None: + v0, v1 = -1, 1 + else: + v0, v1 = ranges[i] + r = (v1 - v0) / (2 * n) + seq = v0 + r + (2 * r) * torch.arange(n).float() + coord_seqs.append(seq) + ret = torch.stack(torch.meshgrid(*coord_seqs), dim=-1) + if flatten: + ret = ret.view(-1, ret.shape[-1]) + return ret + + + +class SEBlock(nn.Module): + def __init__(self, channels, reduction=16): + super().__init__() + self.avg_pool = nn.AdaptiveAvgPool2d(1) + self.fc = nn.Sequential( + nn.Linear(channels, channels // reduction, bias=False), + nn.ReLU(True), + nn.Linear(channels // reduction, channels, bias=False), + nn.Sigmoid(), + ) + + def forward(self, x): + b, c, _, _ = x.size() + y = self.avg_pool(x).view(b, c) + y = self.fc(y).view(b, c, 1, 1) + return x * y.expand_as(x) + + +class WideConvBlock(nn.Module): + def __init__(self, num_features, kernel_size, width_multiplier=4, reduction=4): + super().__init__() + + self.body = nn.Sequential( + *[ + WeightNormedConv( + num_features, int(num_features * width_multiplier), 3 + ), + WeightNormedConv( + int(num_features * width_multiplier), num_features, 3, act=None + ), + WeightNormedConv( + num_features, + num_features, + kernel_size, + act=None, + # res_scale=res_scale, + ), + SEBlock(num_features, reduction), + ] + ) + + def forward(self, x, scale): + return x + self.body(x) + + +class DynamicWideConvBlock(nn.Module): + def __init__( + self, + num_features, + kernel_size, + width_multiplier=4, + dynamic_K=4, + reduction=4, + ): + super().__init__() + + self.body = nn.Sequential( + *[ + WeightNormedConv( + num_features, + int(num_features * width_multiplier), + kernel_size, + # res_scale=2.0, + ), + WeightNormedConv( + int(num_features * width_multiplier), + num_features, + kernel_size, + act=None, + ), + ] + ) + self.d_conv = weight_norm( + ScaleAwareDynamicConv2d( + num_features, + num_features, + kernel_size, + padding=kernel_size // 2, + K=dynamic_K, + ) + ) + self.se_block = SEBlock(num_features, reduction) + + def forward(self, x, scale): + r = self.body(x) + r = self.d_conv(r, scale) + r = self.se_block(r) + return x + r + + +class LocalDenseGroup(nn.Module): + def __init__( + self, + num_features, + width_multiplier, + num_layers, + reduction, + use_dynamic_conv, + dynamic_K, + ): + super().__init__() + kSize = 3 + self.num_layers = num_layers + + self.ConvBlockList = nn.ModuleList() + self.compressList = nn.ModuleList() + self.use_dynamic_conv = use_dynamic_conv + for idx in range(num_layers): + if use_dynamic_conv: + self.ConvBlockList.append( + DynamicWideConvBlock( + num_features, + kSize, + width_multiplier=width_multiplier, + # res_scale=1 / math.sqrt(num_layers), + dynamic_K=dynamic_K, + reduction=reduction, + ) + ) + else: + self.ConvBlockList.append( + WideConvBlock( + num_features, + kSize, + width_multiplier=width_multiplier, + # res_scale=1 / math.sqrt(num_layers), + reduction=reduction, + ) + ) + for idx in range(1, num_layers): + self.compressList.append( + WeightNormedConv( + (idx + 1) * num_features, num_features, 1, act=None + ) + ) + + def forward(self, x, scale): + concat = x + for l in range(self.num_layers): + if l == 0: + out = self.ConvBlockList[l](concat, scale) + else: + concat = torch.cat([concat, out], dim=1) + out = self.compressList[l - 1](concat) + out = self.ConvBlockList[l](out, scale) + return out + + +class FeedbackBlock(nn.Module): + def __init__( + self, + num_features, + width_multiplier, + num_layers, + num_groups, + reduction, + use_dynamic_conv, + dynamic_K, + ): + super().__init__() + kSize = 3 + self.num_groups = num_groups + + self.LDGList = nn.ModuleList() + for _ in range(num_groups): + self.LDGList.append( + LocalDenseGroup( + num_features, + width_multiplier, + num_layers, + reduction, + use_dynamic_conv, + dynamic_K, + ) + ) + + self.compressList = nn.ModuleList() + for idx in range(1, num_groups): + self.compressList.append( + WeightNormedConv( + (idx + 1) * num_features, num_features, 1, act=None + ) + ) + + self.compress_in = WeightNormedConv( + 2 * num_features, num_features, kSize + ) + + self.should_reset = True + self.last_hidden = None + + def forward(self, x, scale): + if self.should_reset: + self.last_hidden = torch.zeros(x.size(), device=x.device) + self.last_hidden.copy_(x) + self.should_reset = False + + x = torch.cat((x, self.last_hidden), 1) + + concat = self.compress_in(x) + for l in range(self.num_groups): + if l == 0: + out = self.LDGList[l](concat, scale) + else: + concat = torch.cat([concat, out], dim=1) + out = self.compressList[l - 1](concat) + out = self.LDGList[l](out, scale) + + self.last_hidden = out + return out + + def reset_state(self): + self.should_reset = True + + +@register('sadnarc') +class SADN(nn.Module): + def __init__( + self, + in_channels=3, + out_channels=3, + num_features=64, + num_layers=4, + num_groups=4, + reduction=4, + width_multiplier=4, + interpolate_mode='bilinear', + levels=4, + use_dynamic_conv=True, + dynamic_K=3, + which_uplayer="UPLayer_MS_WN", + uplayer_ksize=3, + rgb_range=1, + # rgb_mean=[0.5, 0.5, 0.5], + # rgb_std=[0.5, 0.5, 0.5], + *args, + **kwargs + ): + super().__init__() + kernel_size = 3 + skip_kernel_size = 5 + num_inputs = in_channels + n_feats = num_features + self.interpolate_mode = interpolate_mode + self.levels = levels + + # self.sub_mean = MeanShift(rgb_range, rgb_mean, rgb_std) + # self.add_mean = MeanShift(rgb_range, rgb_mean, rgb_std, 1) + + self.head = nn.Sequential( + *[WeightNormedConv(num_inputs, num_features, kernel_size)] + ) + + self.body = FeedbackBlock( + num_features, + width_multiplier, + num_layers, + num_groups, + reduction, + use_dynamic_conv, + dynamic_K, + ) + + self.tail = nn.Sequential( + *[ + WeightNormedConv( + num_features, num_features, kernel_size, act=None + ) + ] + ) + + self.skip = WeightNormedConv( + num_inputs, num_features, skip_kernel_size, act=None + ) + + UpLayer = getattr(upsampler, which_uplayer) + self.uplayer = UpLayer( + n_feats, + uplayer_ksize, + out_channels, + interpolate_mode, + levels, + ) + + def update_temperature(self): + for m in self.modules(): + if isinstance(m, ScaleAwareDynamicConv2d): + m.update_temperature() + + def forward(self, x, out_size): + self.body.reset_state() + if isinstance(out_size, int): + out_size = [out_size, out_size] + scale = torch.tensor([x.shape[2] / out_size[0]], device=x.device) + # x = self.sub_mean(x) + skip = self.skip(x) + + x = self.head(x) + h_list = [] + + for _ in range(self.levels): + h = self.body(x, scale) + h = self.tail(h) + h = h + skip + h_list.append(h) + + x = self.uplayer(h_list, out_size) + + # x = self.add_mean(x) + + return x + + +class SADN_vis(nn.Module): + def __init__( + self, + in_channels, + out_channels, + num_features, + num_layers, + num_groups, + reduction, + width_multiplier, + interpolate_mode, + levels, + use_dynamic_conv, + dynamic_K, + which_uplayer, + uplayer_ksize, + rgb_range, + rgb_mean, + rgb_std, + ): + super().__init__() + kernel_size = 3 + skip_kernel_size = 5 + num_inputs = in_channels + n_feats = num_features + self.interpolate_mode = interpolate_mode + self.levels = levels + + self.sub_mean = MeanShift(rgb_range, rgb_mean, rgb_std) + self.add_mean = MeanShift(rgb_range, rgb_mean, rgb_std, 1) + + self.head = nn.Sequential( + *[WeightNormedConv(num_inputs, num_features, kernel_size)] + ) + + self.use_dynamic_conv = use_dynamic_conv + self.body = FeedbackBlock( + num_features, + width_multiplier, + num_layers, + num_groups, + reduction, + use_dynamic_conv, + dynamic_K, + ) + + self.tail = nn.Sequential( + *[ + WeightNormedConv( + num_features, num_features, kernel_size, act=None + ) + ] + ) + + self.skip = WeightNormedConv( + num_inputs, num_features, skip_kernel_size, act=None + ) + + UpLayer = getattr(upsampler, which_uplayer) + self.uplayer = UpLayer( + n_feats, + uplayer_ksize, + out_channels, + interpolate_mode, + levels, + ) + + def update_temperature(self): + for m in self.modules(): + if isinstance(m, ScaleAwareDynamicConv2d): + m.update_temperature() + + def forward(self, x, out_size): + self.body.reset_state() + if isinstance(out_size, int): + out_size = [out_size, out_size] + scale = torch.tensor([x.shape[2] / out_size[0]], device=x.device) + x = self.sub_mean(x) + skip = self.skip(x) + + x = self.head(x) + h_list = [] + + for _ in range(self.levels): + h = self.body(x, scale) + h = self.tail(h) + h = h + skip + h_list.append(h) + vis = torch.mean(h_list[-1], dim=1) + vis = (vis - vis.min()) / (vis.max() - vis.min()) + vis = vis[..., 88:217, 32:161] + # vis = vis + 0.2 + # vis.clamp_max_(1) + print(torch.min(vis), torch.max(vis)) + # print(vis.shape) + + savepath = "logs/vis" + filename = "geo_residential_t7.png" + + if self.use_dynamic_conv: + savepath = os.path.join(savepath, "dy" + filename.replace(".png", "")) + else: + savepath = os.path.join(savepath, "wo_dy" + filename.replace(".png", "")) + if not exists(savepath): + os.mkdir(savepath) + + savepath = os.path.join(savepath, "x{0}.png".format(int((1 / scale).item()))) + + plt.imsave(savepath, vis.cpu().numpy()[0], cmap="hsv") + + x = self.uplayer(h_list, out_size) + + x = self.add_mean(x) + + return x + +@register('edsr-sadn') +class EDSR_MS(nn.Module): + def __init__( + self, + n_resblocks=16, + n_feats=64, + in_channels=3, + out_channels=3, + res_scale=1, + which_uplayer="UPLayer_MS_WN", + uplayer_ksize=3, + interpolate_mode='bilinear', + levels=4, + *args, + **kwargs + ): + super().__init__() + + conv = default_conv + + kernel_size = 3 + act = nn.ReLU(True) + + # define head module + m_head = [conv(in_channels, n_feats, kernel_size)] + + # define body module + m_body = [ + ResBlock(conv, n_feats, kernel_size, act=act, res_scale=res_scale) + for _ in range(n_resblocks) + ] + m_body.append(conv(n_feats, n_feats, kernel_size)) + + self.head = nn.Sequential(*m_head) + self.body = nn.Sequential(*m_body) + UpLayer = getattr(upsampler, which_uplayer) + self.tail = UpLayer( + n_feats, + uplayer_ksize, + out_channels, + interpolate_mode, + levels, + ) + + def forward(self, x, out_size): + x = self.head(x) + + res = self.body(x) + res += x + + x = self.tail(res, out_size) + + return x + + +class RDB_Conv(nn.Module): + def __init__(self, inChannels, growRate, kSize=3): + super(RDB_Conv, self).__init__() + Cin = inChannels + G = growRate + self.conv = nn.Sequential( + *[nn.Conv2d(Cin, G, kSize, padding=(kSize - 1) // 2, stride=1), nn.ReLU()] + ) + + def forward(self, x): + out = self.conv(x) + return torch.cat((x, out), 1) + + +class RDB(nn.Module): + def __init__(self, growRate0, growRate, nConvLayers, kSize=3): + super(RDB, self).__init__() + G0 = growRate0 + G = growRate + C = nConvLayers + + convs = [] + for c in range(C): + convs.append(RDB_Conv(G0 + c * G, G)) + self.convs = nn.Sequential(*convs) + + # Local Feature Fusion + self.LFF = nn.Conv2d(G0 + C * G, G0, 1, padding=0, stride=1) + + def forward(self, x): + return self.LFF(self.convs(x)) + x + +class RDN(nn.Module): + def __init__( + self, + scale, + num_features, + num_blocks, + num_layers, + rgb_range, + in_channels, + out_channels, + rgb_mean=(0.4488, 0.4371, 0.4040), + rgb_std=(1.0, 1.0, 1.0), + ): + super().__init__() + r = scale + G0 = num_features + kSize = 3 + + # number of RDB blocks, conv layers, out channels + self.D, C, G = [num_blocks, num_layers, num_features] + # self.sub_mean = common.MeanShift(rgb_range, rgb_mean, rgb_std) + # self.add_mean = common.MeanShift(rgb_range, rgb_mean, rgb_std, 1) + + # Shallow feature extraction net + self.SFENet1 = nn.Conv2d( + in_channels, G0, kSize, padding=(kSize - 1) // 2, stride=1 + ) + self.SFENet2 = nn.Conv2d(G0, G0, kSize, padding=(kSize - 1) // 2, stride=1) + + # Redidual dense blocks and dense feature fusion + self.RDBs = nn.ModuleList() + for i in range(self.D): + self.RDBs.append(RDB(growRate0=G0, growRate=G, nConvLayers=C)) + + # Global Feature Fusion + self.GFF = nn.Sequential( + *[ + nn.Conv2d(self.D * G0, G0, 1, padding=0, stride=1), + nn.Conv2d(G0, G0, kSize, padding=(kSize - 1) // 2, stride=1), + ] + ) + + # Up-sampling net + if r == 2 or r == 3: + self.UPNet = nn.Sequential( + *[ + nn.Conv2d(G0, G * r * r, kSize, padding=(kSize - 1) // 2, stride=1), + nn.PixelShuffle(r), + nn.Conv2d( + G, out_channels, kSize, padding=(kSize - 1) // 2, stride=1 + ), + ] + ) + elif r == 4: + self.UPNet = nn.Sequential( + *[ + nn.Conv2d(G0, G * 4, kSize, padding=(kSize - 1) // 2, stride=1), + nn.PixelShuffle(2), + nn.Conv2d(G, G * 4, kSize, padding=(kSize - 1) // 2, stride=1), + nn.PixelShuffle(2), + nn.Conv2d( + G, out_channels, kSize, padding=(kSize - 1) // 2, stride=1 + ), + ] + ) + + def forward(self, x, return_features=False): + # x = self.sub_mean(x) + f__1 = self.SFENet1(x) + x = self.SFENet2(f__1) + + RDBs_out = [] + for i in range(self.D): + x = self.RDBs[i](x) + RDBs_out.append(x) + + x = self.GFF(torch.cat(RDBs_out, 1)) + feat = x + f__1 + + out = self.UPNet(feat) + # out = self.add_mean(out) + + if return_features: + return out, feat + return out + + +@register('rdn-sadn') +class RDN_MS(RDN): + """ + The multi scale version of RDN, and you can specify rgb_mean/rgb_std/rgb_range! + """ + + def __init__(self, **args): + args = EasyDict(args) + args.num_features = 64 + args.num_blocks = 16 + args.num_layers = 8 + args.rgb_range = 1 + args.in_channels = 3 + args.out_channels = 3 + args.which_uplayer = "UPLayer_MS_V9" + args.uplayer_ksize = 3 + args.width_multiplier = 4 + args.interpolate_mode = 'bilinear' + args.levels = 4 + super().__init__( + scale=0, + num_features=args.num_features, + num_blocks=args.num_blocks, + num_layers=args.num_layers, + rgb_range=args.rgb_range, + in_channels=args.in_channels, + out_channels=args.out_channels, + ) + # Redefine up-sampling net + UpLayer = getattr(upsampler, args.which_uplayer) + self.UPNet = UpLayer( + args.num_features, 3, args.out_channels, args.interpolate_mode, args.levels + ) + + rgb_mean = args.get("rgb_mean", (0.4488, 0.4371, 0.4040)) + rgb_std = args.get("rgb_std", (1.0, 1.0, 1.0)) + rgb_range = args.get("rgb_range") + # self.sub_mean = common.MeanShift(rgb_range, rgb_mean, rgb_std) + # self.add_mean = common.MeanShift(rgb_range, rgb_mean, rgb_std, 1) + + def forward(self, x, out_size): + # x = self.sub_mean(x) + f__1 = self.SFENet1(x) + x = self.SFENet2(f__1) + + RDBs_out = [] + for i in range(self.D): + x = self.RDBs[i](x) + RDBs_out.append(x) + + x = self.GFF(torch.cat(RDBs_out, 1)) + x += f__1 + + x = self.UPNet(x, out_size) + # x = self.add_mean(x) + return x diff --git a/models/baselines/upsampler.py b/models/baselines/upsampler.py new file mode 100644 index 0000000000000000000000000000000000000000..fbdddd29bd309e5e498a689d5d2ed25143c49dc9 --- /dev/null +++ b/models/baselines/upsampler.py @@ -0,0 +1,359 @@ +import torch +import torch.nn as nn +import torch.nn.functional as F +import torch.nn.utils.weight_norm as wn + +################ +# Upsampler +################ + +def make_coord(shape, ranges=None, flatten=True): + """Make coordinates at grid centers.""" + coord_seqs = [] + for i, n in enumerate(shape): + if ranges is None: + v0, v1 = -1, 1 + else: + v0, v1 = ranges[i] + r = (v1 - v0) / (2 * n) + seq = v0 + r + (2 * r) * torch.arange(n).float() + coord_seqs.append(seq) + ret = torch.stack(torch.meshgrid(*coord_seqs), dim=-1) + if flatten: + ret = ret.view(-1, ret.shape[-1]) + return ret + + +class UPLayer_MS_V9(nn.Module): + # Up-sampling net + def __init__(self, n_feats, kSize, out_channels, interpolate_mode, levels=4): + super().__init__() + self.interpolate_mode = interpolate_mode + self.levels = levels + + self.UPNet_x2_list = [] + + for _ in range(levels - 1): + self.UPNet_x2_list.append( + nn.Sequential( + *[ + nn.Conv2d( + n_feats, + n_feats * 4, + kSize, + padding=(kSize - 1) // 2, + stride=1, + ), + nn.PixelShuffle(2), + ] + ) + ) + + self.scale_aware_layer = nn.Sequential( + *[nn.Linear(1, 64), nn.ReLU(), nn.Linear(64, levels), nn.Sigmoid()] + ) + + self.UPNet_x2_list = nn.Sequential(*self.UPNet_x2_list) + + self.fuse = nn.Sequential( + *[ + nn.Conv2d(n_feats * levels, 256, kernel_size=1, padding=0, stride=1), + nn.ReLU(), + nn.Conv2d(256, 256, kernel_size=1, padding=0, stride=1), + nn.ReLU(), + nn.Conv2d(256, 256, kernel_size=1, padding=0, stride=1), + nn.ReLU(), + nn.Conv2d(256, 256, kernel_size=1, padding=0, stride=1), + nn.ReLU(), + nn.Conv2d(256, out_channels, kernel_size=1, padding=0, stride=1), + ] + ) + + def forward(self, x, out_size): + + if type(out_size) == int: + out_size = [out_size, out_size] + + if type(x) == list: + return self.forward_list(x, out_size) + + r = torch.tensor([x.shape[2] / out_size[0]], device="cuda") + + scale_w = self.scale_aware_layer(r.unsqueeze(0))[0] + + # scale_in = x.new_tensor(np.ones([x.shape[0], 1, out_size[0], out_size[1]])*r) + + x_list = [x] + for l in range(1, self.levels): + x_list.append(self.UPNet_x2_list[l - 1](x_list[l - 1])) + + x_resize_list = [] + for l in range(self.levels): + x_resize = F.interpolate( + x_list[l], out_size, mode=self.interpolate_mode, align_corners=False + ) + x_resize *= scale_w[l] + x_resize_list.append(x_resize) + + # x_resize_list.append(scale_in) + out = self.fuse(torch.cat(tuple(x_resize_list), 1)) + return out + + def forward_list(self, h_list, out_size): + assert ( + len(h_list) == self.levels + ), "The Length of input list must equal to the number of levels" + device = h_list[0].device + r = torch.tensor([h_list[0].shape[2] / out_size[0]], device=device) + scale_w = self.scale_aware_layer(r.unsqueeze(0))[0] + + x_resize_list = [] + for l in range(self.levels): + h = h_list[l] + for i in range(l): + h = self.UPNet_x2_list[i](h) + x_resize = F.interpolate( + h, out_size, mode=self.interpolate_mode, align_corners=False + ) + x_resize *= scale_w[l] + x_resize_list.append(x_resize) + + out = self.fuse(torch.cat(tuple(x_resize_list), 1)) + return out + + +class UPLayer_MS_WN(nn.Module): + # Up-sampling net + def __init__(self, n_feats, kSize, out_channels, interpolate_mode, levels=4): + super().__init__() + self.interpolate_mode = interpolate_mode + self.levels = levels + self.UPNet_x2_list = [] + + for _ in range(levels - 1): + self.UPNet_x2_list.append( + nn.Sequential( + *[ + wn( + nn.Conv2d( + n_feats, + n_feats * 4, + kSize, + padding=(kSize - 1) // 2, + stride=1, + ) + ), + nn.PixelShuffle(2), + ] + ) + ) + + self.scale_aware_layer = nn.Sequential( + *[wn(nn.Linear(1, 64)), nn.ReLU(), wn(nn.Linear(64, levels)), nn.Sigmoid()] + ) + + self.UPNet_x2_list = nn.Sequential(*self.UPNet_x2_list) + + self.fuse = nn.Sequential( + *[ + wn( + nn.Conv2d(n_feats * levels, 256, kernel_size=1, padding=0, stride=1) + ), + nn.ReLU(), + wn(nn.Conv2d(256, 256, kernel_size=1, padding=0, stride=1)), + nn.ReLU(), + wn(nn.Conv2d(256, 256, kernel_size=1, padding=0, stride=1)), + nn.ReLU(), + wn(nn.Conv2d(256, 256, kernel_size=1, padding=0, stride=1)), + nn.ReLU(), + wn(nn.Conv2d(256, out_channels, kernel_size=1, padding=0, stride=1)), + ] + ) + + assert self.interpolate_mode in ( + "bilinear", + "bicubic", + "nearest", + "MLP", + ), "Interpolate mode must be bilinear/bicubic/nearest/MLP" + if self.interpolate_mode == "MLP": + self.feature_interpolater = MLP_Interpolate(n_feats, radius=3) + elif self.interpolate_mode == "nearest": + self.feature_interpolater = lambda x, out_size: F.interpolate( + x, out_size, mode=self.interpolate_mode + ) + else: + self.feature_interpolater = lambda x, out_size: F.interpolate( + x, out_size, mode=self.interpolate_mode, align_corners=False + ) + + def forward(self, x, out_size): + if type(out_size) == int: + out_size = [out_size, out_size] + + if type(x) == list: + return self.forward_list(x, out_size) + + r = torch.tensor([x.shape[2] / out_size[0]], device="cuda") + + scale_w = self.scale_aware_layer(r.unsqueeze(0))[0] + + x_list = [x] + for l in range(1, self.levels): + x_list.append(self.UPNet_x2_list[l - 1](x_list[l - 1])) + + x_resize_list = [] + for l in range(self.levels): + x_resize = self.feature_interpolater(x_list[l], out_size) + x_resize *= scale_w[l] + x_resize_list.append(x_resize) + + out = self.fuse(torch.cat(tuple(x_resize_list), 1)) + return out + + def forward_list(self, h_list, out_size): + assert ( + len(h_list) == self.levels + ), "The Length of input list must equal to the number of levels" + device = h_list[0].device + r = torch.tensor([h_list[0].shape[2] / out_size[0]], device=device) + scale_w = self.scale_aware_layer(r.unsqueeze(0))[0] + + x_resize_list = [] + for l in range(self.levels): + h = h_list[l] + for i in range(l): + h = self.UPNet_x2_list[i](h) + x_resize = self.feature_interpolater(h, out_size) + x_resize *= scale_w[l] + x_resize_list.append(x_resize) + + out = self.fuse(torch.cat(tuple(x_resize_list), 1)) + return out + + +class UPLayer_MS_WN_woSA(UPLayer_MS_WN): + def __init__(self, n_feats, kSize, out_channels, interpolate_mode, levels=4): + super().__init__(n_feats, kSize, out_channels, interpolate_mode, levels) + + def forward(self, x, out_size): + if type(out_size) == int: + out_size = [out_size, out_size] + + if type(x) == list: + return self.forward_list(x, out_size) + + x_list = [x] + for l in range(1, self.levels): + x_list.append(self.UPNet_x2_list[l - 1](x_list[l - 1])) + + x_resize_list = [] + for l in range(self.levels): + x_resize = self.feature_interpolater(x_list[l], out_size) + x_resize_list.append(x_resize) + + out = self.fuse(torch.cat(tuple(x_resize_list), 1)) + return out + + def forward_list(self, h_list, out_size): + assert ( + len(h_list) == self.levels + ), "The Length of input list must equal to the number of levels" + + x_resize_list = [] + for l in range(self.levels): + h = h_list[l] + for i in range(l): + h = self.UPNet_x2_list[i](h) + x_resize = self.feature_interpolater(h, out_size) + x_resize_list.append(x_resize) + + out = self.fuse(torch.cat(tuple(x_resize_list), 1)) + return out + + +class OSM(nn.Module): + def __init__(self, n_feats, overscale): + super().__init__() + self.body = nn.Sequential( + wn(nn.Conv2d(n_feats, 1600, 3, padding=1)), + nn.PixelShuffle(overscale), + wn(nn.Conv2d(64, 3, 3, padding=1)), + ) + + def forward(self, x, out_size): + h = self.body(x) + return F.interpolate(h, out_size, mode="bicubic", align_corners=False) + + +class MLP_Interpolate(nn.Module): + def __init__(self, n_feat, radius=2): + super().__init__() + self.radius = radius + + self.f_transfer = nn.Sequential( + *[ + nn.Linear(n_feat * self.radius * self.radius + 2, n_feat), + nn.ReLU(True), + nn.Linear(n_feat, n_feat), + ] + ) + + def forward(self, x, out_size): + x_unfold = F.unfold(x, self.radius, padding=self.radius // 2) + x_unfold = x_unfold.view( + x.shape[0], x.shape[1] * (self.radius ** 2), x.shape[2], x.shape[3] + ) + + in_shape = x.shape[-2:] + in_coord = ( + make_coord(in_shape, flatten=False) + .cuda() + .permute(2, 0, 1) + .unsqueeze(0) + .expand(x.shape[0], 2, *in_shape) + ) + + if type(out_size) == int: + out_size = [out_size, out_size] + + out_coord = make_coord(out_size, flatten=True).cuda() + out_coord = out_coord.expand(x.shape[0], *out_coord.shape) + + q_feat = F.grid_sample( + x_unfold, + out_coord.flip(-1).unsqueeze(1), + mode="nearest", + align_corners=False, + )[:, :, 0, :].permute(0, 2, 1) + q_coord = F.grid_sample( + in_coord, + out_coord.flip(-1).unsqueeze(1), + mode="nearest", + align_corners=False, + )[:, :, 0, :].permute(0, 2, 1) + + rel_coord = out_coord - q_coord + rel_coord[:, :, 0] *= x.shape[-2] + rel_coord[:, :, 1] *= x.shape[-1] + + inp = torch.cat([q_feat, rel_coord], dim=-1) + + bs, q = out_coord.shape[:2] + pred = self.f_transfer(inp.view(bs * q, -1)).view(bs, q, -1) + pred = ( + pred.view(x.shape[0], *out_size, x.shape[1]) + .permute(0, 3, 1, 2) + .contiguous() + ) + + return pred + + +class LIIF_Upsampler(nn.Module): + def __init__(self): + super().__init__() + raise NotImplementedError + + def forward(self): + pass diff --git a/models/blocks/CSPLayer.py b/models/blocks/CSPLayer.py new file mode 100644 index 0000000000000000000000000000000000000000..807ed7ae503840e5b8b602549a8ab15d35b1bbe2 --- /dev/null +++ b/models/blocks/CSPLayer.py @@ -0,0 +1,148 @@ +import torch +import torch.nn as nn +from mmcv.cnn import ConvModule, DepthwiseSeparableConvModule + + +class DarknetBottleneck(nn.Module): + """The basic bottleneck block used in Darknet. + + Each ResBlock consists of two ConvModules and the input is added to the + final output. Each ConvModule is composed of Conv, BN, and LeakyReLU. + The first convLayer has filter size of 1x1 and the second one has the + filter size of 3x3. + + Args: + in_channels (int): The input channels of this Module. + out_channels (int): The output channels of this Module. + expansion (int): The kernel size of the convolution. Default: 0.5 + add_identity (bool): Whether to add identity to the out. + Default: True + use_depthwise (bool): Whether to use depthwise separable convolution. + Default: False + conv_cfg (dict): Config dict for convolution layer. Default: None, + which means using conv2d. + norm_cfg (dict): Config dict for normalization layer. + Default: dict(type='BN'). + act_cfg (dict): Config dict for activation layer. + Default: dict(type='Swish'). + """ + + def __init__(self, + in_channels, + out_channels, + expansion=0.5, + add_identity=True, + use_depthwise=False, + conv_cfg=None, + norm_cfg=dict(type='BN', momentum=0.03, eps=0.001), + act_cfg=dict(type='Swish'), + init_cfg=None): + super().__init__() + hidden_channels = int(out_channels * expansion) + conv = DepthwiseSeparableConvModule if use_depthwise else ConvModule + self.conv1 = ConvModule( + in_channels, + hidden_channels, + 1, + conv_cfg=conv_cfg, + norm_cfg=norm_cfg, + act_cfg=act_cfg) + self.conv2 = conv( + hidden_channels, + out_channels, + 3, + stride=1, + padding=1, + conv_cfg=conv_cfg, + norm_cfg=norm_cfg, + act_cfg=act_cfg) + self.add_identity = \ + add_identity and in_channels == out_channels + + def forward(self, x): + identity = x + out = self.conv1(x) + out = self.conv2(out) + + if self.add_identity: + return out + identity + else: + return out + + +class CSPLayer(nn.Module): + """Cross Stage Partial Layer. + + Args: + in_channels (int): The input channels of the CSP layer. + out_channels (int): The output channels of the CSP layer. + expand_ratio (float): Ratio to adjust the number of channels of the + hidden layer. Default: 0.5 + num_blocks (int): Number of blocks. Default: 1 + add_identity (bool): Whether to add identity in blocks. + Default: True + use_depthwise (bool): Whether to depthwise separable convolution in + blocks. Default: False + conv_cfg (dict, optional): Config dict for convolution layer. + Default: None, which means using conv2d. + norm_cfg (dict): Config dict for normalization layer. + Default: dict(type='BN') + act_cfg (dict): Config dict for activation layer. + Default: dict(type='Swish') + """ + + def __init__(self, + in_channels, + out_channels, + expand_ratio=0.5, + num_blocks=1, + add_identity=True, + use_depthwise=False, + conv_cfg=None, + norm_cfg=dict(type='BN', momentum=0.03, eps=0.001), + act_cfg=dict(type='Swish'), + init_cfg=None): + super().__init__() + mid_channels = int(out_channels * expand_ratio) + self.main_conv = ConvModule( + in_channels, + mid_channels, + 1, + conv_cfg=conv_cfg, + norm_cfg=norm_cfg, + act_cfg=act_cfg) + self.short_conv = ConvModule( + in_channels, + mid_channels, + 1, + conv_cfg=conv_cfg, + norm_cfg=norm_cfg, + act_cfg=act_cfg) + self.final_conv = ConvModule( + 2 * mid_channels, + out_channels, + 1, + conv_cfg=conv_cfg, + norm_cfg=norm_cfg, + act_cfg=act_cfg) + + self.blocks = nn.Sequential(*[ + DarknetBottleneck( + mid_channels, + mid_channels, + 1.0, + add_identity, + use_depthwise, + conv_cfg=conv_cfg, + norm_cfg=norm_cfg, + act_cfg=act_cfg) for _ in range(num_blocks) + ]) + + def forward(self, x): + x_short = self.short_conv(x) + + x_main = self.main_conv(x) + x_main = self.blocks(x_main) + + x_final = torch.cat((x_main, x_short), dim=1) + return self.final_conv(x_final) \ No newline at end of file diff --git a/models/cnn_models/__init__.py b/models/cnn_models/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e9304cb6ee9fd8caf17b2bd58104f5b7233f48d6 --- /dev/null +++ b/models/cnn_models/__init__.py @@ -0,0 +1,206 @@ +from .transenet import * +from .srcnn import SRCNN +from .fsrcnn import FSRCNN +from .lgcnet import LGCNET +from .dcm import DIM +from .vdsr import VDSR +# import os +# from importlib import import_module +# +# import torch +# import torch.nn as nn +# +# +# class Model(nn.Module): +# def __init__(self, args, ckp): +# super(Model, self).__init__() +# print('Making model...') +# +# self.scale = args.scale +# self.idx_scale = 0 +# self.self_ensemble = args.self_ensemble +# self.chop = args.chop +# self.precision = args.precision +# self.cpu = args.cpu +# self.device = torch.device('cpu' if args.cpu else 'cuda') +# self.n_GPUs = args.n_GPUs +# self.save_models = args.save_models +# +# module = import_module('model.' + args.model.lower()) +# self.model = module.make_model(args).to(self.device) +# if args.precision == 'half': self.model.half() +# +# if not args.cpu and args.n_GPUs > 1: +# self.model = nn.DataParallel(self.model, range(args.n_GPUs)) +# +# self.load( +# ckp.dir, +# pre_train=args.pre_train, +# resume=args.resume, +# cpu=args.cpu +# ) +# if args.print_model: print(self.model) +# +# def forward(self, x): +# target = self.get_model() +# +# if self.self_ensemble and not self.training: +# if self.chop: +# forward_function = self.forward_chop +# else: +# forward_function = self.model.forward +# +# return self.forward_x8(x, forward_function) +# elif self.chop and not self.training: +# return self.forward_chop(x) +# else: +# return self.model(x) +# +# def get_model(self): +# if self.n_GPUs == 1: +# return self.model +# else: +# return self.model.module +# +# def state_dict(self, **kwargs): +# target = self.get_model() +# return target.state_dict(**kwargs) +# +# def save(self, apath, epoch, is_best=False): +# target = self.get_model() +# torch.save( +# target.state_dict(), +# os.path.join(apath, 'model', 'model_latest.pt') +# ) +# if is_best: +# torch.save( +# target.state_dict(), +# os.path.join(apath, 'model', 'model_best.pt') +# ) +# +# if self.save_models: +# torch.save( +# target.state_dict(), +# os.path.join(apath, 'model', 'model_{}.pt'.format(epoch)) +# ) +# +# def load(self, apath, pre_train='.', resume=-1, cpu=False): +# if cpu: +# kwargs = {'map_location': lambda storage, loc: storage} +# else: +# kwargs = {} +# +# if resume == 1: # loading model from model_latest.pt file +# print('loading model from the model_latest.pt file...') +# self.get_model().load_state_dict( +# torch.load( +# os.path.join(apath, 'model', 'model_latest.pt'), +# **kwargs +# ), +# strict=False +# ) +# elif resume == 0: # loading model from a pre-trained model file ... +# if pre_train != '.': +# print('Loading model from {}'.format(pre_train)) +# self.get_model().load_state_dict( +# torch.load(pre_train, **kwargs), +# strict=False +# ) +# else: +# self.get_model().load_state_dict( +# torch.load( +# os.path.join(apath, 'model', 'model_{}.pt'.format(resume)), +# **kwargs +# ), +# strict=False +# ) +# +# def forward_chop(self, x, shave=10, min_size=160000): +# scale = self.scale[self.idx_scale] +# n_GPUs = min(self.n_GPUs, 4) +# b, c, h, w = x.size() +# h_half, w_half = h // 2, w // 2 +# h_size, w_size = h_half + shave, w_half + shave +# lr_list = [ +# x[:, :, 0:h_size, 0:w_size], +# x[:, :, 0:h_size, (w - w_size):w], +# x[:, :, (h - h_size):h, 0:w_size], +# x[:, :, (h - h_size):h, (w - w_size):w]] +# +# if w_size * h_size < min_size: +# sr_list = [] +# for i in range(0, 4, n_GPUs): +# lr_batch = torch.cat(lr_list[i:(i + n_GPUs)], dim=0) +# sr_batch = self.model(lr_batch) +# sr_list.extend(sr_batch.chunk(n_GPUs, dim=0)) +# else: +# sr_list = [ +# self.forward_chop(patch, shave=shave, min_size=min_size) \ +# for patch in lr_list +# ] +# +# h, w = scale * h, scale * w +# h_half, w_half = scale * h_half, scale * w_half +# h_size, w_size = scale * h_size, scale * w_size +# shave *= scale +# +# output = x.new(b, c, h, w) +# output[:, :, 0:h_half, 0:w_half] \ +# = sr_list[0][:, :, 0:h_half, 0:w_half] +# output[:, :, 0:h_half, w_half:w] \ +# = sr_list[1][:, :, 0:h_half, (w_size - w + w_half):w_size] +# output[:, :, h_half:h, 0:w_half] \ +# = sr_list[2][:, :, (h_size - h + h_half):h_size, 0:w_half] +# output[:, :, h_half:h, w_half:w] \ +# = sr_list[3][:, :, (h_size - h + h_half):h_size, (w_size - w + w_half):w_size] +# +# return output +# +# def forward_x8(self, x, forward_function): +# def _transform(v, op): +# if self.precision != 'single': v = v.float() +# +# v2np = v.data.cpu().numpy() +# if op == 'v': +# tfnp = v2np[:, :, :, ::-1].copy() +# elif op == 'h': +# tfnp = v2np[:, :, ::-1, :].copy() +# elif op == 't': +# tfnp = v2np.transpose((0, 1, 3, 2)).copy() +# +# ret = torch.Tensor(tfnp).to(self.device) +# if self.precision == 'half': ret = ret.half() +# +# return ret +# +# lr_list = [x] +# for tf in 'v', 'h', 't': +# lr_list.extend([_transform(t, tf) for t in lr_list]) +# +# sr_list = [forward_function(aug) for aug in lr_list] +# for i in range(len(sr_list)): +# if i > 3: +# sr_list[i] = _transform(sr_list[i], 't') +# if i % 4 > 1: +# sr_list[i] = _transform(sr_list[i], 'h') +# if (i % 4) % 2 == 1: +# sr_list[i] = _transform(sr_list[i], 'v') +# +# output_cat = torch.cat(sr_list, dim=0) +# output = output_cat.mean(dim=0, keepdim=True) +# +# return output +# +# +# +# +# +# +# +# +# +# +# +# +# +# diff --git a/models/cnn_models/basic.py b/models/cnn_models/basic.py new file mode 100644 index 0000000000000000000000000000000000000000..9332e56dc5d4ba928ee93de2e6d8cd278ea6635a --- /dev/null +++ b/models/cnn_models/basic.py @@ -0,0 +1,71 @@ +from . import common + +import torch.nn as nn + + +def make_model(args, parent=False): + return BASIC(args) + + +class BASIC(nn.Module): + def __init__(self, args, conv=common.default_conv): + super(BASIC, self).__init__() + + n_resblocks = args.n_resblocks + n_feats = args.n_feats + kernel_size = 3 + scale = args.scale[0] + act = nn.ReLU(True) + + # define head module + m_head = [conv(args.n_colors, n_feats, kernel_size)] + + # define body module + m_body = [ + common.ResBlock( + conv, n_feats, kernel_size, act=act, res_scale=args.res_scale + ) for _ in range(n_resblocks) + ] + m_body.append(conv(n_feats, n_feats, kernel_size)) + + # define tail module + m_tail = [ + common.Upsampler(conv, scale, n_feats), + conv(n_feats, args.n_colors, kernel_size) + ] + + self.head = nn.Sequential(*m_head) + self.body = nn.Sequential(*m_body) + self.tail = nn.Sequential(*m_tail) + + def forward(self, x): + x = self.head(x) + res = self.body(x) + res += x + x = self.tail(x) + + return x + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/models/cnn_models/common.py b/models/cnn_models/common.py new file mode 100644 index 0000000000000000000000000000000000000000..af82b921c526b369a838acbd97080f81b2a5ea42 --- /dev/null +++ b/models/cnn_models/common.py @@ -0,0 +1,140 @@ +import math + +import torch +import torch.nn as nn +import torch.nn.functional as F + +from torch.autograd import Variable + +def default_conv(in_channels, out_channels, kernel_size, bias=True): + return nn.Conv2d( + in_channels, out_channels, kernel_size, + padding=(kernel_size//2), bias=bias) + +class MeanShift(nn.Conv2d): + def __init__(self, rgb_range, rgb_mean, rgb_std, sign=-1): + super(MeanShift, self).__init__(3, 3, kernel_size=1) + std = torch.Tensor(rgb_std) + self.weight.data = torch.eye(3).view(3, 3, 1, 1) + self.weight.data.div_(std.view(3, 1, 1, 1)) + self.bias.data = sign * rgb_range * torch.Tensor(rgb_mean) + self.bias.data.div_(std) + self.requires_grad = False + +class BasicBlock(nn.Sequential): + def __init__( + self, conv, in_channels, out_channels, kernel_size, stride=1, bias=True, + bn=False, act=nn.ReLU(True)): + + m = [conv(in_channels, out_channels, kernel_size, bias=bias)] + if bn: + m.append(nn.BatchNorm2d(out_channels)) + if act is not None: + m.append(act) + super(BasicBlock, self).__init__(*m) + +class ResBlock(nn.Module): + def __init__( + self, conv, n_feat, kernel_size, + bias=True, bn=False, act=nn.ReLU(True), res_scale=1): + + super(ResBlock, self).__init__() + m = [] + for i in range(2): + m.append(conv(n_feat, n_feat, kernel_size, bias=bias)) + if bn: m.append(nn.BatchNorm2d(n_feat)) + if i == 0: m.append(act) + + self.body = nn.Sequential(*m) + self.res_scale = res_scale + + def forward(self, x): + res = self.body(x).mul(self.res_scale) + res += x + + return res + + +class Upsampler(nn.Sequential): + def __init__(self, conv, scale, n_feat, bn=False, act=False, bias=True): + + m = [] + if (scale & (scale - 1)) == 0: # Is scale = 2^n? + for _ in range(int(math.log(scale, 2))): + m.append(conv(n_feat, 4 * n_feat, 3, bias)) + m.append(nn.PixelShuffle(2)) + if bn: m.append(nn.BatchNorm2d(n_feat)) + if act: m.append(act()) + elif scale == 3: + m.append(conv(n_feat, 9 * n_feat, 3, bias)) + m.append(nn.PixelShuffle(3)) + if bn: m.append(nn.BatchNorm2d(n_feat)) + if act: m.append(act()) + else: + raise NotImplementedError + + super(Upsampler, self).__init__(*m) + + +class DownBlock(nn.Module): + def __init__(self, scale): + super().__init__() + + self.scale = scale + + def forward(self, x): + n, c, h, w = x.size() + x = x.view(n, c, h//self.scale, self.scale, w//self.scale, self.scale) + x = x.permute(0, 3, 5, 1, 2, 4).contiguous() + x = x.view(n, c * (self.scale**2), h//self.scale, w//self.scale) + return x + +# NONLocalBlock2D +# ref: https://github.com/AlexHex7/Non-local_pytorch/blob/master/Non-Local_pytorch_0.4.1_to_1.1.0/lib/non_local_dot_product.py +# ref: https://github.com/yulunzhang/RNAN/blob/master/SR/code/model/common.py +class NonLocalBlock2D(nn.Module): + def __init__(self, in_channels, inter_channels): + super(NonLocalBlock2D, self).__init__() + + self.in_channels = in_channels + self.inter_channels = inter_channels + + self.g = nn.Conv2d(in_channels=in_channels, out_channels=inter_channels, + kernel_size=1, stride=1, padding=0) + self.W = nn.Conv2d(in_channels=inter_channels, out_channels=in_channels, + kernel_size=1, stride=1, padding=0) + nn.init.constant_(self.W.weight, 0) + nn.init.constant_(self.W.bias, 0) + + self.theta = nn.Conv2d(in_channels=self.in_channels, out_channels=self.inter_channels, + kernel_size=1, stride=1, padding=0) + self.phi = nn.Conv2d(in_channels=self.in_channels, out_channels=self.inter_channels, + kernel_size=1, stride=1, padding=0) + + def forward(self, x): + + batch_size = x.size(0) + + g_x = self.g(x).view(batch_size, self.inter_channels, -1) + g_x = g_x.permute(0, 2, 1) + + theta_x = self.theta(x).view(batch_size, self.inter_channels, -1) + theta_x = theta_x.permute(0, 2, 1) + + phi_x = self.phi(x).view(batch_size, self.inter_channels, -1) + f = torch.matmul(theta_x, phi_x) + + # use dot production + # N = f.size(-1) + # f_div_C = f / N + + # use embedding gaussian + f_div_C = F.softmax(f, dim=-1) + + y = torch.matmul(f_div_C, g_x) + y = y.permute(0, 2, 1).contiguous() + y = y.view(batch_size, self.inter_channels, *x.size()[2:]) + W_y = self.W(y) + z = W_y + x + + return z \ No newline at end of file diff --git a/models/cnn_models/dcm.py b/models/cnn_models/dcm.py new file mode 100644 index 0000000000000000000000000000000000000000..b31372ef4a9fee7f4c343865f84eb497975fe60a --- /dev/null +++ b/models/cnn_models/dcm.py @@ -0,0 +1,108 @@ + +from . import common + +from argparse import Namespace + +import torch +import torch.nn as nn +from models import register +import torch.nn.functional as F + +def make_model(args, parent=False): + return DIM(args) + +@register('DCM') +def DCM(scale_ratio, rgb_range=1): + args = Namespace() + args.scale = [scale_ratio] + args.n_colors = 3 + args.rgb_range = rgb_range + return DIM(args) + +class DIM(nn.Module): + def __init__(self, args, conv=common.default_conv): + super(DIM, self).__init__() + + self.scale = args.scale[0] + + # feature extractor part + self.fe_conv1 = common.BasicBlock(conv, args.n_colors, 196, kernel_size=3, bias=True, act=nn.PReLU()) + self.fe_conv2 = common.BasicBlock(conv, 196, 166, kernel_size=3, bias=True, act=nn.PReLU()) + self.fe_conv3 = common.BasicBlock(conv, 166, 148, kernel_size=3, bias=True, act=nn.PReLU()) + self.fe_conv4 = common.BasicBlock(conv, 148, 133, kernel_size=3, bias=True, act=nn.PReLU()) + self.fe_conv5 = common.BasicBlock(conv, 133, 120, kernel_size=3, bias=True, act=nn.PReLU()) + self.fe_conv6 = common.BasicBlock(conv, 120, 108, kernel_size=3, bias=True, act=nn.PReLU()) + self.fe_conv7 = common.BasicBlock(conv, 108, 97, kernel_size=3, bias=True, act=nn.PReLU()) + self.fe_conv8 = common.BasicBlock(conv, 97, 86, kernel_size=3, bias=True, act=nn.PReLU()) + self.fe_conv9 = common.BasicBlock(conv, 86, 76, kernel_size=3, bias=True, act=nn.PReLU()) + self.fe_conv10 = common.BasicBlock(conv, 76, 66, kernel_size=3, bias=True, act=nn.PReLU()) + self.fe_conv11 = common.BasicBlock(conv, 66, 57, kernel_size=3, bias=True, act=nn.PReLU()) + self.fe_conv12 = common.BasicBlock(conv, 57, 48, kernel_size=3, bias=True, act=nn.PReLU()) + + # reconstruction part + self.re_a = common.BasicBlock(conv, 196 + 48, 64, kernel_size=3, bias=True, act=nn.PReLU()) + self.re_b1 = common.BasicBlock(conv, 196 + 48, 32, kernel_size=3, bias=True, act=nn.PReLU()) + self.re_b2 = common.BasicBlock(conv, 32, 32, kernel_size=3, bias=True, act=nn.PReLU()) + self.re_u = common.Upsampler(conv, self.scale, 96, act=False) + self.re_r = conv(96, args.n_colors, kernel_size=1) + + + def forward(self, x, out_size=None): + + residual = F.interpolate(x, scale_factor=self.scale, mode='bicubic') + + # feature extractor part + fe_conv1 = self.fe_conv1(x) + fe_conv2 = self.fe_conv2(fe_conv1) + fe_conv3 = self.fe_conv3(fe_conv2) + fe_conv4 = self.fe_conv4(fe_conv3) + fe_conv5 = self.fe_conv5(fe_conv4) + fe_conv6 = self.fe_conv6(fe_conv5) + fe_conv7 = self.fe_conv7(fe_conv6) + fe_conv8 = self.fe_conv8(fe_conv7) + fe_conv9 = self.fe_conv9(fe_conv8) + fe_conv10 = self.fe_conv10(fe_conv9) + fe_conv11 = self.fe_conv11(fe_conv10) + fe_conv12 = self.fe_conv12(fe_conv11) + + # reconstruction part + feat = torch.cat((fe_conv1, fe_conv12), dim=1) + re_a = self.re_a(feat) + re_b1 = self.re_b1(feat) + re_b2 = self.re_b2(re_b1) + feat = torch.cat((re_a, re_b2), dim=1) + re_u = self.re_u(feat) + re_r = self.re_r(re_u) + out = re_r + residual + + return out + + def load_state_dict(self, state_dict, strict=False): + own_state = self.state_dict() + for name, param in state_dict.items(): + if name in own_state: + if isinstance(param, nn.Parameter): + param = param.data + try: + own_state[name].copy_(param) + except Exception: + if name.find('tail') >= 0: + print('Replace pre-trained upsampler to new one...') + else: + raise RuntimeError('While copying the parameter named {}, ' + 'whose dimensions in the model are {} and ' + 'whose dimensions in the checkpoint are {}.' + .format(name, own_state[name].size(), param.size())) + elif strict: + if name.find('tail') == -1: + raise KeyError('unexpected key "{}" in state_dict' + .format(name)) + + if strict: + missing = set(own_state.keys()) - set(state_dict.keys()) + if len(missing) > 0: + raise KeyError('missing keys in state_dict: "{}"'.format(missing)) + + + + diff --git a/models/cnn_models/fsrcnn.py b/models/cnn_models/fsrcnn.py new file mode 100644 index 0000000000000000000000000000000000000000..5c82ebe987f2ed73c7c2e1baaec1c616ed4123dc --- /dev/null +++ b/models/cnn_models/fsrcnn.py @@ -0,0 +1,95 @@ + +# code ref: https://github.com/yjn870/FSRCNN-pytorch/blob/master/models.py + +from . import common +import math + +from argparse import Namespace +import torch.nn as nn +from models import register +import torch.nn.functional as F + + +def make_model(args, parent=False): + return FSRCNN(args) + + +@register('FSRCNN') +def FSRCNN(scale_ratio, rgb_range=1): + args = Namespace() + args.scale = [scale_ratio] + args.n_colors = 3 + args.rgb_range = rgb_range + return FSRCNN(args) + +class FSRCNN(nn.Module): + def __init__(self, args, conv=common.default_conv, d=56, s=12 * 3, m=8): + super(FSRCNN, self).__init__() + + scale = args.scale[0] + act = nn.PReLU() + + m_first_part = [] + m_first_part.append(conv(args.n_colors, d, kernel_size=5)) + m_first_part.append(act) + self.first_part = nn.Sequential(*m_first_part) + + m_mid_part = [] + m_mid_part.append(conv(d, s, kernel_size=1)) + m_mid_part.append(act) + for _ in range(m): + m_mid_part.append(conv(s, s, kernel_size=3)) + m_mid_part.append(act) + m_mid_part.append(conv(s, d, kernel_size=1)) + m_mid_part.append(act) + self.mid_part = nn.Sequential(*m_mid_part) + + self.last_part = nn.ConvTranspose2d(d, args.n_colors, kernel_size=9, stride=scale, padding=9//2, + output_padding=scale-1) + + # self._initialize_weights() + + + def _initialize_weights(self): + for m in self.first_part: + if isinstance(m, nn.Conv2d): + nn.init.normal_(m.weight.data, mean=0.0, std=math.sqrt(2/(m.out_channels*m.weight.data[0][0].numel()))) + nn.init.zeros_(m.bias.data) + for m in self.mid_part: + if isinstance(m, nn.Conv2d): + nn.init.normal_(m.weight.data, mean=0.0, std=math.sqrt(2/(m.out_channels*m.weight.data[0][0].numel()))) + nn.init.zeros_(m.bias.data) + nn.init.normal_(self.last_part.weight.data, mean=0.0, std=0.001) + nn.init.zeros_(self.last_part.bias.data) + + def forward(self, x, out_size=None): + x = self.first_part(x) + x = self.mid_part(x) + x = self.last_part(x) + return x + + def load_state_dict(self, state_dict, strict=False): + own_state = self.state_dict() + for name, param in state_dict.items(): + if name in own_state: + if isinstance(param, nn.Parameter): + param = param.data + try: + own_state[name].copy_(param) + except Exception: + if name.find('tail') >= 0: + print('Replace pre-trained upsampler to new one...') + else: + raise RuntimeError('While copying the parameter named {}, ' + 'whose dimensions in the model are {} and ' + 'whose dimensions in the checkpoint are {}.' + .format(name, own_state[name].size(), param.size())) + elif strict: + if name.find('tail') == -1: + raise KeyError('unexpected key "{}" in state_dict' + .format(name)) + + if strict: + missing = set(own_state.keys()) - set(state_dict.keys()) + if len(missing) > 0: + raise KeyError('missing keys in state_dict: "{}"'.format(missing)) \ No newline at end of file diff --git a/models/cnn_models/lgcnet.py b/models/cnn_models/lgcnet.py new file mode 100644 index 0000000000000000000000000000000000000000..7ed4030c67fbd155cdadb08b81b431bfce88733c --- /dev/null +++ b/models/cnn_models/lgcnet.py @@ -0,0 +1,119 @@ +from argparse import Namespace + +import torch +import torch.nn as nn +from models import register +import torch.nn.functional as F + +def make_model(args, parent=False): + return CNN7(args) + + +@register('LGCNET') +def LGCNET(scale_ratio, rgb_range=1): + args = Namespace() + args.scale = [scale_ratio] + args.n_colors = 3 + args.rgb_range = rgb_range + return LGCNET(args) + + +class LGCNET(nn.Module): + def __init__(self, args, nfeats = 32): + super(LGCNET, self).__init__() + self.conv1 = nn.Conv2d(args.n_colors, nfeats, kernel_size=3, stride=1, padding=1, bias=True) + self.conv2 = nn.Conv2d(nfeats, nfeats, kernel_size=3, stride=1, padding=1, bias=True) + self.conv3 = nn.Conv2d(nfeats, nfeats, kernel_size=3, stride=1, padding=1, bias=True) + self.conv4 = nn.Conv2d(nfeats, nfeats, kernel_size=3, stride=1, padding=1, bias=True) + self.conv5 = nn.Conv2d(nfeats, nfeats, kernel_size=3, stride=1, padding=1, bias=True) + self.conv6 = nn.Conv2d(nfeats*3, nfeats*2, kernel_size=5, stride=1, padding=2, bias=True) + self.conv7 = nn.Conv2d(nfeats*2, 3, kernel_size=3, stride=1, padding=1, bias=True) + self.relu = nn.ReLU() + + def forward(self, x, out_size): + x = F.interpolate(x, out_size, mode='bicubic') + residual = x + im1 = self.relu(self.conv1(x)) + im2 = self.relu(self.conv2(im1)) + im3 = self.relu(self.conv3(im2)) + im4 = self.relu(self.conv4(im3)) + im5 = self.relu(self.conv5(im4)) + out = self.relu(self.conv6(torch.cat((im3, im4, im5), dim = 1))) + out = self.conv7(out) + residual + return out + + def load_state_dict(self, state_dict, strict=False): + own_state = self.state_dict() + for name, param in state_dict.items(): + if name in own_state: + if isinstance(param, nn.Parameter): + param = param.data + try: + own_state[name].copy_(param) + except Exception: + if name.find('tail') >= 0: + print('Replace pre-trained upsampler to new one...') + else: + raise RuntimeError('While copying the parameter named {}, ' + 'whose dimensions in the model are {} and ' + 'whose dimensions in the checkpoint are {}.' + .format(name, own_state[name].size(), param.size())) + elif strict: + if name.find('tail') == -1: + raise KeyError('unexpected key "{}" in state_dict' + .format(name)) + + if strict: + missing = set(own_state.keys()) - set(state_dict.keys()) + if len(missing) > 0: + raise KeyError('missing keys in state_dict: "{}"'.format(missing)) + + +class CNN7(nn.Module): + def __init__(self, args, nfeats = 32): + super(CNN7, self).__init__() + self.conv1 = nn.Conv2d(args.n_colors, nfeats, kernel_size=3, stride=1, padding=1, bias=True) + self.conv2 = nn.Conv2d(nfeats, nfeats, kernel_size=3, stride=1, padding=1, bias=True) + self.conv3 = nn.Conv2d(nfeats, nfeats, kernel_size=3, stride=1, padding=1, bias=True) + self.conv4 = nn.Conv2d(nfeats, nfeats, kernel_size=3, stride=1, padding=1, bias=True) + self.conv5 = nn.Conv2d(nfeats, nfeats, kernel_size=3, stride=1, padding=1, bias=True) + self.conv6 = nn.Conv2d(nfeats, nfeats, kernel_size=3, stride=1, padding=1, bias=True) + self.conv7 = nn.Conv2d(nfeats, 3, kernel_size=3, stride=1, padding=1, bias=True) + self.relu = nn.ReLU() + + def forward(self, x): + residual = x + im1 = self.relu(self.conv1(x)) + im2 = self.relu(self.conv2(im1)) + im3 = self.relu(self.conv3(im2)) + im4 = self.relu(self.conv4(im3)) + im5 = self.relu(self.conv5(im4)) + im6 = self.relu(self.conv6(im5)) + out = self.conv7(im6) + residual + return out + + def load_state_dict(self, state_dict, strict=False): + own_state = self.state_dict() + for name, param in state_dict.items(): + if name in own_state: + if isinstance(param, nn.Parameter): + param = param.data + try: + own_state[name].copy_(param) + except Exception: + if name.find('tail') >= 0: + print('Replace pre-trained upsampler to new one...') + else: + raise RuntimeError('While copying the parameter named {}, ' + 'whose dimensions in the model are {} and ' + 'whose dimensions in the checkpoint are {}.' + .format(name, own_state[name].size(), param.size())) + elif strict: + if name.find('tail') == -1: + raise KeyError('unexpected key "{}" in state_dict' + .format(name)) + + if strict: + missing = set(own_state.keys()) - set(state_dict.keys()) + if len(missing) > 0: + raise KeyError('missing keys in state_dict: "{}"'.format(missing)) \ No newline at end of file diff --git a/models/cnn_models/srcnn.py b/models/cnn_models/srcnn.py new file mode 100644 index 0000000000000000000000000000000000000000..33fae3b3e6e62d632a28a026c2e3c50b2742dc74 --- /dev/null +++ b/models/cnn_models/srcnn.py @@ -0,0 +1,60 @@ +from argparse import Namespace +import torch.nn as nn +from models import register +import torch.nn.functional as F + + +def make_model(args, parent=False): + return SRCNN(args) + + +@register('SRCNN') +def SRCNN(scale_ratio=1, rgb_range=1): + args = Namespace() + args.scale = scale_ratio + args.rgb_range = rgb_range + args.n_colors = 3 + return SRCNN(args) + + +class SRCNN(nn.Module): + def __init__(self, args): + super(SRCNN, self).__init__() + self.conv1 = nn.Conv2d(args.n_colors, 64, kernel_size=9, padding=9 // 2) + self.conv2 = nn.Conv2d(64, 32, kernel_size=5, padding=5 // 2) + self.conv3 = nn.Conv2d(32, args.n_colors, kernel_size=5, padding=5 // 2) + self.relu = nn.ReLU(inplace=True) + self.scale = args.scale + + def forward(self, x, out_size): + x = F.interpolate(x, out_size, mode='bicubic') + x = self.relu(self.conv1(x)) + x = self.relu(self.conv2(x)) + x = self.conv3(x) + return x + + def load_state_dict(self, state_dict, strict=False): + own_state = self.state_dict() + for name, param in state_dict.items(): + if name in own_state: + if isinstance(param, nn.Parameter): + param = param.data + try: + own_state[name].copy_(param) + except Exception: + if name.find('tail') >= 0: + print('Replace pre-trained upsampler to new one...') + else: + raise RuntimeError('While copying the parameter named {}, ' + 'whose dimensions in the model are {} and ' + 'whose dimensions in the checkpoint are {}.' + .format(name, own_state[name].size(), param.size())) + elif strict: + if name.find('tail') == -1: + raise KeyError('unexpected key "{}" in state_dict' + .format(name)) + + if strict: + missing = set(own_state.keys()) - set(state_dict.keys()) + if len(missing) > 0: + raise KeyError('missing keys in state_dict: "{}"'.format(missing)) \ No newline at end of file diff --git a/models/cnn_models/transenet.py b/models/cnn_models/transenet.py new file mode 100644 index 0000000000000000000000000000000000000000..0e33e731ac93e819cbdf768ea9c9e6e31daa9ed4 --- /dev/null +++ b/models/cnn_models/transenet.py @@ -0,0 +1,226 @@ +from . import common + +import torch +import torch.nn as nn +from einops import rearrange, repeat + +from models import register +from .transformer import TransformerEncoder, TransformerDecoder +from argparse import Namespace + +MIN_NUM_PATCHES = 12 + + +def make_model(args, parent=False): + return TransENet(args) + + +class BasicModule(nn.Module): + def __init__(self, conv, n_feat, kernel_size, block_type='basic', bias=True, + bn=False, act=nn.ReLU(True)): + super(BasicModule, self).__init__() + + self.block_type = block_type + + m_body = [] + if block_type == 'basic': + n_blocks = 10 + m_body = [ + common.BasicBlock(conv, n_feat, n_feat, kernel_size, bias=bias, bn=bn) + # common.ResBlock(conv, n_feat, kernel_size) + for _ in range(n_blocks) + ] + elif block_type == 'residual': + n_blocks = 5 + m_body = [ + common.ResBlock(conv, n_feat, kernel_size) + for _ in range(n_blocks) + ] + else: + print('Error: not support this type') + self.body = nn.Sequential(*m_body) + + def forward(self, x): + + res = self.body(x) + if self.block_type == 'basic': + out = res + x + elif self.block_type == 'residual': + out = res + + return out + + +@register('TransENet') +def TransENet(scale_ratio, n_feats=64, rgb_range=1): + args = Namespace() + args.n_feats = n_feats + args.scale = [scale_ratio] + args.patch_size = 48 * args.scale[0] + + args.rgb_range = rgb_range + args.n_colors = 3 + args.en_depth = 6 + args.de_depth = 1 + return TransENet(args) + + +class TransENet(nn.Module): + + def __init__(self, args, conv=common.default_conv): + super(TransENet, self).__init__() + + self.args = args + self.scale = args.scale[0] + n_feats = args.n_feats + kernel_size = 3 + act = nn.ReLU(True) + + # rgb_mean = (0.4916, 0.4991, 0.4565) # UCMerced data + # rgb_std = (1.0, 1.0, 1.0) + # + # self.sub_mean = common.MeanShift(args.rgb_range, rgb_mean, rgb_std) + + # define head body + m_head = [ + conv(args.n_colors, n_feats, kernel_size), + ] + self.head = nn.Sequential(*m_head) + + # define main body + self.feat_extrat_stage1 = BasicModule(conv, n_feats, kernel_size, block_type='residual', act=act) + self.feat_extrat_stage2 = BasicModule(conv, n_feats, kernel_size, block_type='residual', act=act) + self.feat_extrat_stage3 = BasicModule(conv, n_feats, kernel_size, block_type='residual', act=act) + + reduction = 4 + self.stage1_conv1x1 = conv(n_feats, n_feats // reduction, 1) + self.stage2_conv1x1 = conv(n_feats, n_feats // reduction, 1) + self.stage3_conv1x1 = conv(n_feats, n_feats // reduction, 1) + self.up_conv1x1 = conv(n_feats, n_feats // reduction, 1) + self.span_conv1x1 = conv(n_feats // reduction, n_feats, 1) + + self.upsampler = common.Upsampler(conv, self.scale, n_feats, act=False) + + # define tail body + self.tail = conv(n_feats, args.n_colors, kernel_size) + # self.add_mean = common.MeanShift(args.rgb_range, rgb_mean, rgb_std, 1) + + # define transformer + image_size = args.patch_size // self.scale + patch_size = 4 + dim = 512 + en_depth = args.en_depth + de_depth = args.de_depth + heads = 6 + mlp_dim = 512 + channels = n_feats // reduction + dim_head = 32 + dropout = 0.0 + + assert image_size % patch_size == 0, 'Image dimensions must be divisible by the patch size.' + num_patches = (image_size // patch_size) ** 2 + + patch_dim = channels * patch_size ** 2 + assert num_patches > MIN_NUM_PATCHES, f'your number of patches ({num_patches}) is way too small for attention to be effective (at least 16). Try decreasing your patch size' + + self.patch_size = patch_size + self.patch_to_embedding_low1 = nn.Linear(patch_dim, dim) + self.patch_to_embedding_low2 = nn.Linear(patch_dim, dim) + self.patch_to_embedding_low3 = nn.Linear(patch_dim, dim) + self.patch_to_embedding_high = nn.Linear(patch_dim, dim) + + self.embedding_to_patch = nn.Linear(dim, patch_dim) + + self.encoder_stage1 = TransformerEncoder(dim, en_depth, heads, dim_head, mlp_dim, dropout) + self.encoder_stage2 = TransformerEncoder(dim, en_depth, heads, dim_head, mlp_dim, dropout) + self.encoder_stage3 = TransformerEncoder(dim, en_depth, heads, dim_head, mlp_dim, dropout) + self.encoder_up = TransformerEncoder(dim, en_depth, heads, dim_head, mlp_dim, dropout) + + self.decoder1 = TransformerDecoder(dim, de_depth, heads, dim_head, mlp_dim, dropout) + self.decoder2 = TransformerDecoder(dim, de_depth, heads, dim_head, mlp_dim, dropout) + self.decoder3 = TransformerDecoder(dim, de_depth, heads, dim_head, mlp_dim, dropout) + + + def forward(self, x, out_size=None): + + # x = self.sub_mean(x) + x = self.head(x) + + # feature extraction part + feat_stage1 = self.feat_extrat_stage1(x) + feat_stage2 = self.feat_extrat_stage2(x) + feat_stage3 = self.feat_extrat_stage3(x) + feat_ups = self.upsampler(feat_stage3) + + feat_stage1 = self.stage1_conv1x1(feat_stage1) + feat_stage2 = self.stage2_conv1x1(feat_stage2) + feat_stage3 = self.stage3_conv1x1(feat_stage3) + feat_ups = self.up_conv1x1(feat_ups) + + # transformer part: + p = self.patch_size + + feat_stage1 = rearrange(feat_stage1, 'b c (h p1) (w p2) -> b (h w) (p1 p2 c)', p1 = p, p2 = p) + feat_stage2 = rearrange(feat_stage2, 'b c (h p1) (w p2) -> b (h w) (p1 p2 c)', p1=p, p2=p) + feat_stage3 = rearrange(feat_stage3, 'b c (h p1) (w p2) -> b (h w) (p1 p2 c)', p1=p, p2=p) + feat_ups = rearrange(feat_ups, 'b c (h p1) (w p2) -> b (h w) (p1 p2 c)', p1 = p, p2 = p) + + feat_stage1 = self.patch_to_embedding_low1(feat_stage1) + feat_stage2 = self.patch_to_embedding_low2(feat_stage2) + feat_stage3 = self.patch_to_embedding_low3(feat_stage3) + feat_ups = self.patch_to_embedding_high(feat_ups) + + # encoder + feat_stage1 = self.encoder_stage1(feat_stage1) + feat_stage2 = self.encoder_stage2(feat_stage2) + feat_stage3 = self.encoder_stage3(feat_stage3) + feat_ups = self.encoder_up(feat_ups) + + feat_ups = self.decoder3(feat_ups, feat_stage3) + feat_ups = self.decoder2(feat_ups, feat_stage2) + feat_ups = self.decoder1(feat_ups, feat_stage1) + + feat_ups = self.embedding_to_patch(feat_ups) + feat_ups = rearrange(feat_ups, 'b (h w) (p1 p2 c) -> b c (h p1) (w p2)', h=self.args.patch_size // p, p1=p, p2=p) + + feat_ups = self.span_conv1x1(feat_ups) + + x = self.tail(feat_ups) + # x = self.add_mean(x) + + return x + + def load_state_dict(self, state_dict, strict=False): + own_state = self.state_dict() + for name, param in state_dict.items(): + if name in own_state: + if isinstance(param, nn.Parameter): + param = param.data + try: + own_state[name].copy_(param) + except Exception: + if name.find('tail') >= 0: + print('Replace pre-trained upsampler to new one...') + else: + raise RuntimeError('While copying the parameter named {}, ' + 'whose dimensions in the model are {} and ' + 'whose dimensions in the checkpoint are {}.' + .format(name, own_state[name].size(), param.size())) + elif strict: + if name.find('tail') == -1: + raise KeyError('unexpected key "{}" in state_dict' + .format(name)) + + if strict: + missing = set(own_state.keys()) - set(state_dict.keys()) + if len(missing) > 0: + raise KeyError('missing keys in state_dict: "{}"'.format(missing)) + + +if __name__ == "__main__": + from option import args + model = TransENet(args) + model.eval() + input = torch.rand(1, 3, 48, 48) + sr = model(input) + print(sr.size()) \ No newline at end of file diff --git a/models/cnn_models/transformer.py b/models/cnn_models/transformer.py new file mode 100644 index 0000000000000000000000000000000000000000..e774c4f53c461aee65bb99699b2e549a6a622330 --- /dev/null +++ b/models/cnn_models/transformer.py @@ -0,0 +1,186 @@ + +import torch +import torch.nn as nn +import torch.nn.functional as F +from einops import rearrange, repeat + +MIN_NUM_PATCHES = 16 + +""" +This is a new remote sensing super-resolution method based on the prevalent transformer + +ref: +https://github.com/lucidrains/vit-pytorch/blob/main/vit_pytorch/vit_pytorch.py +""" + +class Residual(nn.Module): + def __init__(self, fn): + super().__init__() + self.fn = fn + + def forward(self, x, **kwargs): + return self.fn(x, **kwargs) + x + + +class Residual2(nn.Module): + def __init__(self, fn): + super().__init__() + self.fn = fn + + def forward(self, x, m=None, **kwargs): + return self.fn(x, m, **kwargs) + x + + +class PreNorm(nn.Module): + def __init__(self, dim, fn): + super().__init__() + self.norm = nn.LayerNorm(dim) + self.fn = fn + + def forward(self, x, **kwargs): + return self.fn(self.norm(x), **kwargs) + + +class PreNorm2(nn.Module): + def __init__(self, dim, fn): + super().__init__() + self.norm = nn.LayerNorm(dim) + self.fn = fn + + def forward(self, x, m=None, **kwargs): + x = self.norm(x) + if m is not None: m = self.norm(m) + return self.fn(x, m, **kwargs) + + +class FeedForward(nn.Module): + def __init__(self, dim, hidden_dim, dropout = 0.): + super().__init__() + self.net = nn.Sequential( + nn.Linear(dim, hidden_dim), + nn.GELU(), + nn.Dropout(dropout), + nn.Linear(hidden_dim, dim), + nn.Dropout(dropout) + ) + + def forward(self, x): + return self.net(x) + + +class Attention(nn.Module): + def __init__(self, dim, heads = 8, dim_head = 64, dropout = 0.): + super().__init__() + inner_dim = dim_head * heads + self.heads = heads + self.scale = dim ** -0.5 + + self.to_qkv = nn.Linear(dim, inner_dim * 3, bias = False) + self.to_out = nn.Sequential( + nn.Linear(inner_dim, dim), + nn.Dropout(dropout) + ) + + def forward(self, x, mask = None): + b, n, _, h = *x.shape, self.heads + qkv = self.to_qkv(x).chunk(3, dim = -1) + q, k, v = map(lambda t: rearrange(t, 'b n (h d) -> b h n d', h = h), qkv) + + dots = torch.einsum('bhid,bhjd->bhij', q, k) * self.scale + mask_value = -torch.finfo(dots.dtype).max + + if mask is not None: + mask = F.pad(mask.flatten(1), (1, 0), value = True) + assert mask.shape[-1] == dots.shape[-1], 'mask has incorrect dimensions' + mask = mask[:, None, :] * mask[:, :, None] + dots.masked_fill_(~mask, mask_value) + del mask + + attn = dots.softmax(dim=-1) + + out = torch.einsum('bhij,bhjd->bhid', attn, v) + out = rearrange(out, 'b h n d -> b n (h d)') + out = self.to_out(out) + return out + + +class MixedAttention(nn.Module): + def __init__(self, dim, heads=8, dim_head=64, dropout=0.): + super().__init__() + inner_dim = dim_head * heads + self.heads = heads + self.scale = dim ** -0.5 + + self.to_q = nn.Linear(dim, inner_dim, bias=False) + self.to_k = nn.Linear(dim, inner_dim, bias=False) + self.to_v = nn.Linear(dim, inner_dim, bias=False) + self.to_out = nn.Sequential( + nn.Linear(inner_dim, dim), + nn.Dropout(dropout) + ) + + def forward(self, x, m, mask=None): + + b, n, _, h = *x.shape, self.heads + q = self.to_q(x) + k = self.to_k(m) + v = self.to_v(m) + q = rearrange(q, 'b n (h d) -> b h n d', h=h) + k = rearrange(k, 'b n (h d) -> b h n d', h=h) + v = rearrange(v, 'b n (h d) -> b h n d', h=h) + + dots = torch.einsum('bhid,bhjd->bhij', q, k) * self.scale + mask_value = -torch.finfo(dots.dtype).max + + if mask is not None: + mask = F.pad(mask.flatten(1), (1, 0), value = True) + assert mask.shape[-1] == dots.shape[-1], 'mask has incorrect dimensions' + mask = mask[:, None, :] * mask[:, :, None] + dots.masked_fill_(~mask, mask_value) + del mask + + attn = dots.softmax(dim=-1) + + out = torch.einsum('bhij,bhjd->bhid', attn, v) + out = rearrange(out, 'b h n d -> b n (h d)') + out = self.to_out(out) + return out + + +class TransformerEncoder(nn.Module): + def __init__(self, dim, depth, heads, dim_head, mlp_dim, dropout): + super().__init__() + self.layers = nn.ModuleList([]) + for _ in range(depth): + self.layers.append(nn.ModuleList([ + Residual(PreNorm(dim, Attention(dim, heads=heads, dim_head=dim_head, dropout=dropout))), + Residual(PreNorm(dim, FeedForward(dim, mlp_dim, dropout=dropout))) + ])) + + def forward(self, x, mask=None): + for attn, ff in self.layers: + x = attn(x, mask=mask) + x = ff(x) + return x + + +class TransformerDecoder(nn.Module): + def __init__(self, dim, depth, heads, dim_head, mlp_dim, dropout): + super().__init__() + self.layers = nn.ModuleList([]) + for _ in range(depth): + self.layers.append(nn.ModuleList([ + Residual(PreNorm(dim, Attention(dim, heads=heads, dim_head=dim_head, dropout=dropout))), + Residual2(PreNorm2(dim, MixedAttention(dim, heads=heads, dim_head=dim_head, dropout=dropout))), + Residual(PreNorm(dim, FeedForward(dim, mlp_dim, dropout=dropout))) + ])) + + def with_pos_embed(self, tensor, pos=None): + return tensor if pos is None else tensor + pos + + def forward(self, x, m, mask=None): + for attn1, attn2, ff in self.layers: + x = attn1(x, mask=mask) + x = attn2(x, m, mask=mask) + x = ff(x) + return x \ No newline at end of file diff --git a/models/cnn_models/vdsr.py b/models/cnn_models/vdsr.py new file mode 100644 index 0000000000000000000000000000000000000000..8252f7eb6f448e9d81c22f035e5147305d09694a --- /dev/null +++ b/models/cnn_models/vdsr.py @@ -0,0 +1,75 @@ +from . import common + +import torch +import torch.nn as nn +from models import register +import torch.nn.functional as F +from argparse import Namespace + +def make_model(args, parent=False): + return VDSR(args) + +@register('VDSR') +def VDSR(scale_ratio, rgb_range=1): + args = Namespace() + args.scale = [scale_ratio] + args.n_colors = 3 + args.rgb_range = rgb_range + return VDSR(args) + + +class VDSR(nn.Module): + def __init__(self, args, conv=common.default_conv): + super(VDSR, self).__init__() + + n_feats = 64 + kernel_size = 3 + + m_head = [common.BasicBlock(conv, args.n_colors, n_feats, kernel_size, bias=True, bn=True)] + + layer_nums = 18 + m_body = [ + common.BasicBlock(conv, n_feats, n_feats, kernel_size, bias=True, bn=True) + for _ in range(layer_nums) + ] + + m_tail = [conv(n_feats, args.n_colors, kernel_size, bias=True)] + + self.head = nn.Sequential(*m_head) + self.body = nn.Sequential(*m_body) + self.tail = nn.Sequential(*m_tail) + + def forward(self, x, out_size): + x = F.interpolate(x, size=out_size, mode='bicubic') + residual = x + x = self.head(x) + x = self.body(x) + x = self.tail(x) + out = x + residual + return out + + def load_state_dict(self, state_dict, strict=False): + own_state = self.state_dict() + for name, param in state_dict.items(): + if name in own_state: + if isinstance(param, nn.Parameter): + param = param.data + try: + own_state[name].copy_(param) + except Exception: + if name.find('tail') >= 0: + print('Replace pre-trained upsampler to new one...') + else: + raise RuntimeError('While copying the parameter named {}, ' + 'whose dimensions in the model are {} and ' + 'whose dimensions in the checkpoint are {}.' + .format(name, own_state[name].size(), param.size())) + elif strict: + if name.find('tail') == -1: + raise KeyError('unexpected key "{}" in state_dict' + .format(name)) + + if strict: + missing = set(own_state.keys()) - set(state_dict.keys()) + if len(missing) > 0: + raise KeyError('missing keys in state_dict: "{}"'.format(missing)) \ No newline at end of file diff --git a/models/edsr.py b/models/edsr.py new file mode 100644 index 0000000000000000000000000000000000000000..e5fac715d86c0270336bd0df175e1d44fc1319b2 --- /dev/null +++ b/models/edsr.py @@ -0,0 +1,201 @@ +# modified from: https://github.com/thstkdgus35/EDSR-PyTorch + +import math +from argparse import Namespace + +import torch +import torch.nn as nn +import torch.nn.functional as F + +from models import register + + +def default_conv(in_channels, out_channels, kernel_size, bias=True): + return nn.Conv2d( + in_channels, out_channels, kernel_size, + padding=(kernel_size//2), bias=bias) + +class MeanShift(nn.Conv2d): + def __init__( + self, rgb_range, + rgb_mean=(0.4488, 0.4371, 0.4040), rgb_std=(1.0, 1.0, 1.0), sign=-1): + + super(MeanShift, self).__init__(3, 3, kernel_size=1) + std = torch.Tensor(rgb_std) + self.weight.data = torch.eye(3).view(3, 3, 1, 1) / std.view(3, 1, 1, 1) + self.bias.data = sign * rgb_range * torch.Tensor(rgb_mean) / std + for p in self.parameters(): + p.requires_grad = False + +class ResBlock(nn.Module): + def __init__( + self, conv, n_feats, kernel_size, + bias=True, bn=False, act=nn.ReLU(True), res_scale=1): + + super(ResBlock, self).__init__() + m = [] + for i in range(2): + m.append(conv(n_feats, n_feats, kernel_size, bias=bias)) + if bn: + m.append(nn.BatchNorm2d(n_feats)) + if i == 0: + m.append(act) + + self.body = nn.Sequential(*m) + self.res_scale = res_scale + + def forward(self, x): + res = self.body(x).mul(self.res_scale) + res += x + + return res + +class Upsampler(nn.Sequential): + def __init__(self, conv, scale, n_feats, bn=False, act=False, bias=True): + + m = [] + if (scale & (scale - 1)) == 0: # Is scale = 2^n? + for _ in range(int(math.log(scale, 2))): + m.append(conv(n_feats, 4 * n_feats, 3, bias)) + m.append(nn.PixelShuffle(2)) + if bn: + m.append(nn.BatchNorm2d(n_feats)) + if act == 'relu': + m.append(nn.ReLU(True)) + elif act == 'prelu': + m.append(nn.PReLU(n_feats)) + + elif scale == 3: + m.append(conv(n_feats, 9 * n_feats, 3, bias)) + m.append(nn.PixelShuffle(3)) + if bn: + m.append(nn.BatchNorm2d(n_feats)) + if act == 'relu': + m.append(nn.ReLU(True)) + elif act == 'prelu': + m.append(nn.PReLU(n_feats)) + else: + raise NotImplementedError + + super(Upsampler, self).__init__(*m) + + +url = { + 'r16f64x2': 'https://cv.snu.ac.kr/research/EDSR/models/edsr_baseline_x2-1bc95232.pt', + 'r16f64x3': 'https://cv.snu.ac.kr/research/EDSR/models/edsr_baseline_x3-abf2a44e.pt', + 'r16f64x4': 'https://cv.snu.ac.kr/research/EDSR/models/edsr_baseline_x4-6b446fab.pt', + 'r32f256x2': 'https://cv.snu.ac.kr/research/EDSR/models/edsr_x2-0edfb8a3.pt', + 'r32f256x3': 'https://cv.snu.ac.kr/research/EDSR/models/edsr_x3-ea3ef2c6.pt', + 'r32f256x4': 'https://cv.snu.ac.kr/research/EDSR/models/edsr_x4-4f62e9ef.pt' +} + +class EDSR(nn.Module): + def __init__(self, args, conv=default_conv): + super(EDSR, self).__init__() + self.args = args + n_resblocks = args.n_resblocks + n_feats = args.n_feats + kernel_size = 3 + scale = args.scale[0] + act = nn.ReLU(True) + url_name = 'r{}f{}x{}'.format(n_resblocks, n_feats, scale) + if url_name in url: + self.url = url[url_name] + else: + self.url = None + self.sub_mean = MeanShift(args.rgb_range) + self.add_mean = MeanShift(args.rgb_range, sign=1) + + # define head module + m_head = [conv(args.n_colors, n_feats, kernel_size)] + + # define body module + m_body = [ + ResBlock( + conv, n_feats, kernel_size, act=act, res_scale=args.res_scale + ) for _ in range(n_resblocks) + ] + m_body.append(conv(n_feats, n_feats, kernel_size)) + + self.head = nn.Sequential(*m_head) + self.body = nn.Sequential(*m_body) + + if args.no_upsampling: + self.out_dim = n_feats + else: + self.out_dim = args.n_colors + # define tail module + m_tail = [ + Upsampler(conv, scale, n_feats, act=False), + conv(n_feats, args.n_colors, kernel_size) + ] + self.tail = nn.Sequential(*m_tail) + + self.load_state_dict('pretrained/'+self.url.split('/')[-1]) + + def forward(self, x): + #x = self.sub_mean(x) + x = self.head(x) + + res = self.body(x) + res += x + + if self.args.no_upsampling: + x = res + else: + x = self.tail(res) + #x = self.add_mean(x) + return x + + def load_state_dict(self, state_dict, strict=True): + state_dict = torch.load(state_dict, map_location='cpu') + own_state = self.state_dict() + print('loading pretrain model') + for name, param in state_dict.items(): + if name in own_state: + if isinstance(param, nn.Parameter): + param = param.data + try: + own_state[name].copy_(param) + except Exception: + if name.find('tail') == -1: + raise RuntimeError('While copying the parameter named {}, ' + 'whose dimensions in the model are {} and ' + 'whose dimensions in the checkpoint are {}.' + .format(name, own_state[name].size(), param.size())) + elif strict: + if name.find('tail') == -1: + raise KeyError('unexpected key "{}" in state_dict' + .format(name)) + + +@register('edsr-baseline') +def make_edsr_baseline(n_resblocks=16, n_feats=64, res_scale=1, + scale=2, no_upsampling=False, rgb_range=1): + args = Namespace() + args.n_resblocks = n_resblocks + args.n_feats = n_feats + args.res_scale = res_scale + + args.scale = [scale] + args.no_upsampling = no_upsampling + + args.rgb_range = rgb_range + args.n_colors = 3 + return EDSR(args) + + +@register('edsr') +def make_edsr(n_resblocks=32, n_feats=256, res_scale=0.1, + scale=2, no_upsampling=False, rgb_range=1): + args = Namespace() + args.n_resblocks = n_resblocks + args.n_feats = n_feats + args.res_scale = res_scale + + args.scale = [scale] + args.no_upsampling = no_upsampling + + args.rgb_range = rgb_range + args.n_colors = 3 + return EDSR(args) diff --git a/models/funsr.py b/models/funsr.py new file mode 100644 index 0000000000000000000000000000000000000000..b169dd84724beb47936b0d2a782c9f7d80fa8025 --- /dev/null +++ b/models/funsr.py @@ -0,0 +1,227 @@ +import torch +import torch.nn as nn +import torch.nn.functional as F +from einops import rearrange, repeat + +import models +from models import register +from utils import make_coord, to_coordinates + +from mmcv.cnn import ConvModule +from .blocks.CSPLayer import CSPLayer + + +@register('funsr') +class FUNSR(nn.Module): + def __init__(self, + encoder_spec, + has_multiscale=False, + neck=None, + decoder=None, + global_decoder=None, + encoder_rgb=False, + n_forward_times=1, + encode_hr_coord=False, + has_bn=True, + encode_scale_ratio=False, + local_unfold=False, + weight_gen_func='nearest-exact', + return_featmap=False, + ): + super().__init__() + self.weight_gen_func = weight_gen_func # 'bilinear', 'nearest-exact' + self.encoder = models.make(encoder_spec) + self.encoder_out_dim = self.encoder.out_dim + self.encode_scale_ratio = encode_scale_ratio + self.has_multiscale = has_multiscale + self.encoder_rgb = encoder_rgb + self.encode_hr_coord = encode_hr_coord + self.local_unfold = local_unfold + self.return_featmap = return_featmap + + self.multiscale_layers = nn.ModuleList() + + if self.has_multiscale: + # 48->24->12->6 + conv_cfg = None + if has_bn: + norm_cfg = dict(type='BN', momentum=0.03, eps=0.001) + else: + norm_cfg = None + act_cfg = dict(type='ReLU') + num_blocks = [2, 4, 6] + for n_idx in range(3): + conv_layer = ConvModule( + self.encoder_out_dim, + self.encoder_out_dim*2, + 3, + stride=2, + padding=1, + conv_cfg=conv_cfg, + norm_cfg=norm_cfg, + act_cfg=act_cfg + ) + csp_layer = CSPLayer( + self.encoder_out_dim*2, + self.encoder_out_dim, + num_blocks=num_blocks[n_idx], + add_identity=True, + use_depthwise=False, + conv_cfg=conv_cfg, + norm_cfg=norm_cfg, + act_cfg=act_cfg) + self.multiscale_layers.append(nn.Sequential(conv_layer, csp_layer)) + + if neck is not None: + self.neck = models.make(neck, args={'in_dim': self.encoder_out_dim}) + modulation_dim = self.neck.d_dim + else: + modulation_dim = self.encoder_out_dim + + self.n_forward_times = n_forward_times + + decoder_in_dim = 2 + if self.encode_scale_ratio: + decoder_in_dim += 2 + if self.encode_hr_coord: + decoder_in_dim += 2 + if self.encoder_rgb: + decoder_in_dim += 3 + + if decoder is not None: + if self.local_unfold: + self.down_dim_layer = nn.Conv2d(modulation_dim * 9, modulation_dim, 1) + self.decoder = models.make(decoder, args={'modulation_dim': modulation_dim, 'in_dim': decoder_in_dim}) + + if global_decoder is not None: + decoder_in_dim = 2 + if self.encode_scale_ratio: + decoder_in_dim += 2 + if self.encoder_rgb: + decoder_in_dim += 3 + + self.decoder_is_proj = global_decoder.get('is_proj', False) + + self.global_decoder = models.make(global_decoder, args={'modulation_dim': modulation_dim, 'in_dim': decoder_in_dim}) + + if self.decoder_is_proj: + self.input_proj = nn.Linear(modulation_dim, modulation_dim) + # self.output_proj = nn.Conv2d(6, 3, kernel_size=3, padding=1) + self.output_proj = nn.Conv2d(6, 3, kernel_size=1) + + def forward_step(self, + lr_img, + func_map, + global_func, + rel_coord, + lr_coord, + hr_coord, + scale_ratio_map=None, + pred_rgb_value=None + ): + # Expand funcmap + if self.local_unfold: + b, c, h, w = func_map.shape + func_map = F.unfold(func_map, 3, padding=1).view(b, c * 9, h, w) + func_map = self.down_dim_layer(func_map) + local_func_map = F.interpolate(func_map, size=hr_coord.shape[-2:], mode=self.weight_gen_func) + + rel_coord = repeat(rel_coord, 'b c h w -> (B b) c h w', B=lr_img.size(0)) + hr_coord = repeat(hr_coord, 'c h w -> B c h w', B=lr_img.size(0)) + local_input = rel_coord + if self.encode_scale_ratio: + local_input = torch.cat([local_input, scale_ratio_map], dim=1) + if self.encode_hr_coord: + local_input = torch.cat([local_input, hr_coord], dim=1) + if self.encoder_rgb: + if pred_rgb_value is None: + pred_rgb_value = F.interpolate(lr_img, size=hr_coord.shape[-2:], mode='bicubic', align_corners=True) + local_input = torch.cat((local_input, pred_rgb_value), dim=1) + + decoder_output = self.decoder(local_input, local_func_map) + + if hasattr(self, 'global_decoder'): + if self.decoder_is_proj: + global_func = self.input_proj(global_func) # B C + global_func = repeat(global_func, 'B C -> B C H W', H=hr_coord.shape[2], W=hr_coord.shape[3]) + + global_input = hr_coord + if self.encode_scale_ratio: + global_input = torch.cat([global_input, scale_ratio_map], dim=1) + if self.encoder_rgb: + if pred_rgb_value is None: + pred_rgb_value = F.interpolate(lr_img, size=hr_coord.shape[-2:], mode='bicubic', + align_corners=True) + global_input = torch.cat((global_input, pred_rgb_value), dim=1) + global_decoder_output = self.global_decoder(global_input, global_func) + + returned_featmap = None + if self.decoder_is_proj: + if self.return_featmap: + returned_featmap = torch.cat((global_decoder_output, decoder_output), dim=1) + decoder_output = self.output_proj(torch.cat((global_decoder_output, decoder_output), dim=1)) + else: + decoder_output = global_decoder_output + decoder_output + + return decoder_output, returned_featmap + + def forward_backbone(self, x, keep_ori_feat=True): + # x: img-BxCxHxW + x = self.encoder(x) + output_feats = [] + if keep_ori_feat: + output_feats.append(x) + for layer in self.multiscale_layers: + x = layer(x) + output_feats.append(x) + return output_feats + + def get_coordinate_map(self, x, hr_size): + B, C, H, W = x.shape + H_up, W_up = hr_size + x_coord = to_coordinates(x.shape[-2:], return_map=True).to(x.device).permute(2, 0, 1) + hr_coord = to_coordinates(hr_size, return_map=True).to(x.device).permute(2, 0, 1) + # important! mode='nearest' gives inconsistent results + # import pdb + # pdb.set_trace() + rel_grid = hr_coord - F.interpolate(x_coord.unsqueeze(0), size=hr_size, mode='nearest-exact') + rel_grid[:, 0, :, :] *= H + rel_grid[:, 1, :, :] *= W + + return rel_grid.contiguous().detach(), x_coord.contiguous().detach(), hr_coord.contiguous().detach() + + def forward(self, x, out_size): + B, C, H_lr, W_lr = x.shape + output_feats = self.forward_backbone(x) # List + if hasattr(self, 'neck'): + global_content, func_map = self.neck(output_feats) + else: + global_content = None + func_map = output_feats[0] + rel_coord, lr_coord, hr_coord = self.get_coordinate_map(x, out_size) + scale_ratio_map = None + if self.encode_scale_ratio: + h_ratio = x.shape[2] / out_size[0] + w_ratio = x.shape[3] / out_size[1] + scale_ratio_map = torch.tensor([h_ratio, w_ratio]).view(1, -1, 1, 1).expand(B, -1, *out_size).to(x.device) + + pred_rgb_value = None + return_pred_rgb_value = [] + + for n_time in range(self.n_forward_times): + pred_rgb_value, returned_featmaps = self.forward_step( + x, + func_map, + global_content, + rel_coord, + lr_coord, + hr_coord, + scale_ratio_map, + pred_rgb_value + ) + return_pred_rgb_value.append(pred_rgb_value) + if self.return_featmap: + return return_pred_rgb_value, returned_featmaps + return return_pred_rgb_value + + diff --git a/models/liif.py b/models/liif.py new file mode 100644 index 0000000000000000000000000000000000000000..d6099426081918556a32b81aca00a53be51d91fe --- /dev/null +++ b/models/liif.py @@ -0,0 +1,110 @@ +import torch +import torch.nn as nn +import torch.nn.functional as F + +import models +from models import register +from utils import make_coord + + +@register('liif') +class LIIF(nn.Module): + + def __init__(self, encoder_spec, imnet_spec=None, + local_ensemble=True, feat_unfold=True, cell_decode=True): + super().__init__() + self.local_ensemble = local_ensemble + self.feat_unfold = feat_unfold + self.cell_decode = cell_decode + + self.encoder = models.make(encoder_spec) + + if imnet_spec is not None: + imnet_in_dim = self.encoder.out_dim + if self.feat_unfold: + imnet_in_dim *= 9 + imnet_in_dim += 2 # attach coord + if self.cell_decode: + imnet_in_dim += 2 + self.imnet = models.make(imnet_spec, args={'in_dim': imnet_in_dim}) + else: + self.imnet = None + + def gen_feat(self, inp): + self.feat = self.encoder(inp) + return self.feat + + def query_rgb(self, coord, cell=None): + feat = self.feat + + if self.imnet is None: + ret = F.grid_sample(feat, coord.flip(-1).unsqueeze(1), + mode='nearest', align_corners=False)[:, :, 0, :] \ + .permute(0, 2, 1) + return ret + + if self.feat_unfold: + feat = F.unfold(feat, 3, padding=1).view( + feat.shape[0], feat.shape[1] * 9, feat.shape[2], feat.shape[3]) + + if self.local_ensemble: + vx_lst = [-1, 1] + vy_lst = [-1, 1] + eps_shift = 1e-6 + else: + vx_lst, vy_lst, eps_shift = [0], [0], 0 + + # field radius (global: [-1, 1]) + rx = 2 / feat.shape[-2] / 2 + ry = 2 / feat.shape[-1] / 2 + + feat_coord = make_coord(feat.shape[-2:], flatten=False).cuda() \ + .permute(2, 0, 1) \ + .unsqueeze(0).expand(feat.shape[0], 2, *feat.shape[-2:]) + + preds = [] + areas = [] + for vx in vx_lst: + for vy in vy_lst: + coord_ = coord.clone() + coord_[:, :, 0] += vx * rx + eps_shift + coord_[:, :, 1] += vy * ry + eps_shift + coord_.clamp_(-1 + 1e-6, 1 - 1e-6) + q_feat = F.grid_sample( + feat, coord_.flip(-1).unsqueeze(1), + mode='nearest', align_corners=False)[:, :, 0, :] \ + .permute(0, 2, 1) + q_coord = F.grid_sample( + feat_coord, coord_.flip(-1).unsqueeze(1), + mode='nearest', align_corners=False)[:, :, 0, :] \ + .permute(0, 2, 1) + rel_coord = coord - q_coord + rel_coord[:, :, 0] *= feat.shape[-2] + rel_coord[:, :, 1] *= feat.shape[-1] + inp = torch.cat([q_feat, rel_coord], dim=-1) + + if self.cell_decode: + rel_cell = cell.clone() + rel_cell[:, :, 0] *= feat.shape[-2] + rel_cell[:, :, 1] *= feat.shape[-1] + inp = torch.cat([inp, rel_cell], dim=-1) + + bs, q = coord.shape[:2] + pred = self.imnet(inp.view(bs * q, -1)).view(bs, q, -1) + preds.append(pred) + + area = torch.abs(rel_coord[:, :, 0] * rel_coord[:, :, 1]) + areas.append(area + 1e-9) + + tot_area = torch.stack(areas).sum(dim=0) + if self.local_ensemble: + t = areas[0]; areas[0] = areas[3]; areas[3] = t + t = areas[1]; areas[1] = areas[2]; areas[2] = t + ret = 0 + for pred, area in zip(preds, areas): + ret = ret + pred * (area / tot_area).unsqueeze(-1) + return ret + + def forward(self, inp, coord, cell): + self.gen_feat(inp) + return self.query_rgb(coord, cell) diff --git a/models/metasr.py b/models/metasr.py new file mode 100644 index 0000000000000000000000000000000000000000..83aa62d5dfbcc8c6e0e5ef84fd85fee5740d2128 --- /dev/null +++ b/models/metasr.py @@ -0,0 +1,70 @@ +import torch +import torch.nn as nn +import torch.nn.functional as F + +import models +from models import register +from utils import make_coord + + +@register('metasr') +class MetaSR(nn.Module): + + def __init__(self, encoder_spec): + super().__init__() + + self.encoder = models.make(encoder_spec) + imnet_spec = { + 'name': 'mlp', + 'args': { + 'in_dim': 3, + 'out_dim': self.encoder.out_dim * 9 * 3, + 'hidden_list': [256] + } + } + self.imnet = models.make(imnet_spec) + + def gen_feat(self, inp): + self.feat = self.encoder(inp) + return self.feat + + def query_rgb(self, coord, cell=None): + feat = self.feat + feat = F.unfold(feat, 3, padding=1).view( + feat.shape[0], feat.shape[1] * 9, feat.shape[2], feat.shape[3]) + + feat_coord = make_coord(feat.shape[-2:], flatten=False).cuda() + feat_coord[:, :, 0] -= (2 / feat.shape[-2]) / 2 + feat_coord[:, :, 1] -= (2 / feat.shape[-1]) / 2 + feat_coord = feat_coord.permute(2, 0, 1) \ + .unsqueeze(0).expand(feat.shape[0], 2, *feat.shape[-2:]) + + coord_ = coord.clone() + coord_[:, :, 0] -= cell[:, :, 0] / 2 + coord_[:, :, 1] -= cell[:, :, 1] / 2 + coord_q = (coord_ + 1e-6).clamp(-1 + 1e-6, 1 - 1e-6) + q_feat = F.grid_sample( + feat, coord_q.flip(-1).unsqueeze(1), + mode='nearest', align_corners=False)[:, :, 0, :] \ + .permute(0, 2, 1) + q_coord = F.grid_sample( + feat_coord, coord_q.flip(-1).unsqueeze(1), + mode='nearest', align_corners=False)[:, :, 0, :] \ + .permute(0, 2, 1) + + rel_coord = coord_ - q_coord + rel_coord[:, :, 0] *= feat.shape[-2] / 2 + rel_coord[:, :, 1] *= feat.shape[-1] / 2 + + r_rev = cell[:, :, 0] * (feat.shape[-2] / 2) + inp = torch.cat([rel_coord, r_rev.unsqueeze(-1)], dim=-1) + + bs, q = coord.shape[:2] + pred = self.imnet(inp.view(bs * q, -1)).view(bs * q, feat.shape[1], 3) + pred = torch.bmm(q_feat.contiguous().view(bs * q, 1, -1), pred) + pred = pred.view(bs, q, 3) + return pred + + def forward(self, inp, coord, cell): + self.gen_feat(inp) + return self.query_rgb(coord, cell) diff --git a/models/mlp.py b/models/mlp.py new file mode 100644 index 0000000000000000000000000000000000000000..94415e26b57219c7e7e41d9c02a45ac9c5dd2874 --- /dev/null +++ b/models/mlp.py @@ -0,0 +1,80 @@ +import torch +import torch.nn as nn + +from models import register + + +@register('mlp_pw') +class MLP(nn.Module): + + def __init__(self, in_dim, out_dim, hidden_list): + super().__init__() + self.relu_0 = nn.ReLU(inplace=True) + self.relu_1 = nn.ReLU(inplace=True) + self.relu_2 = nn.ReLU(inplace=True) + self.relu_3 = nn.ReLU(inplace=True) + self.hidden=hidden_list[0] + + def forward(self, x,Coeff,basis,bias): + # x(b*h*w,580) + # Coeff(b*h*w,10) + # basis[0](10,16*580) + # basis[1](10,16*16) + # basis[2](10,16*16) + # basis[3](10,16*16) + # basis[4](10,3*16) + # bias[0](10,16) + # bias[1](10,16) + # bias[2](10,16) + # bias[3](10,16) + # bias[4](10,3) + device=x.device + # Applies a linear transformation to the incoming data: :math:`y = xA^T + b + # Layer0 + x = x.unsqueeze(1) + # sum( (b*h*w,1,580)*(b*h*w,16,580) , dim=2 ) -> (b*h*w,16) + x = torch.sum(x*torch.matmul(Coeff.to(device),basis[0].to(device)).view(-1,self.hidden,580),dim=2) + # (b*h*w,16) + (b*h*w,16) -> (b*h*w,16) + x = x + torch.matmul(Coeff.to(device),bias[0].to(device)) + x = self.relu_0(x) + # Layer1 + x = x.unsqueeze(1) + x = torch.sum(x*torch.matmul(Coeff.to(device),basis[1].to(device)).view(-1,self.hidden,self.hidden),dim=2) + x = x + torch.matmul(Coeff.to(device),bias[1].to(device)) + x = self.relu_1(x) + # Layer2 + x = x.unsqueeze(1) + x = torch.sum(x*torch.matmul(Coeff.to(device),basis[2].to(device)).view(-1,self.hidden,self.hidden),dim=2) + x = x + torch.matmul(Coeff.to(device),bias[2].to(device)) + x = self.relu_2(x) + # Layer3 + x = x.unsqueeze(1) + x = torch.sum(x*torch.matmul(Coeff.to(device),basis[3].to(device)).view(-1,self.hidden,self.hidden),dim=2) + x = x + torch.matmul(Coeff.to(device),bias[3].to(device)) + x = self.relu_3(x) + # Layer4 + x = x.unsqueeze(1) + x = torch.sum(x*torch.matmul(Coeff.to(device),basis[4].to(device)).view(-1,3,self.hidden),dim=2) + x = x + torch.matmul(Coeff.to(device),bias[4].to(device)) + + return x + + +@register('mlp') +class MLP(nn.Module): + + def __init__(self, in_dim, out_dim, hidden_list): + super().__init__() + layers = [] + lastv = in_dim + for hidden in hidden_list: + layers.append(nn.Linear(lastv, hidden)) + layers.append(nn.ReLU()) + lastv = hidden + layers.append(nn.Linear(lastv, out_dim)) + self.layers = nn.Sequential(*layers) + + def forward(self, x): + shape = x.shape[:-1] + x = self.layers(x.view(-1, x.shape[-1])) + return x.view(*shape, -1) diff --git a/models/models.py b/models/models.py new file mode 100644 index 0000000000000000000000000000000000000000..0625a2d2fd2d8ee147930ec3cda0a643c895d8aa --- /dev/null +++ b/models/models.py @@ -0,0 +1,23 @@ +import copy + + +models = {} + + +def register(name): + def decorator(cls): + models[name] = cls + return cls + return decorator + + +def make(model_spec, args=None, load_sd=False): + if args is not None: + model_args = copy.deepcopy(model_spec['args']) + model_args.update(args) + else: + model_args = model_spec['args'] + model = models[model_spec['name']](**model_args) + if load_sd: + model.load_state_dict(model_spec['sd'], strict=True) + return model diff --git a/models/rcan.py b/models/rcan.py new file mode 100644 index 0000000000000000000000000000000000000000..76f661d79f679ade86940effcee389a31ef07c68 --- /dev/null +++ b/models/rcan.py @@ -0,0 +1,204 @@ +import math +from argparse import Namespace + +import torch +import torch.nn as nn + +from models import register + + +def default_conv(in_channels, out_channels, kernel_size, bias=True): + return nn.Conv2d( + in_channels, out_channels, kernel_size, + padding=(kernel_size//2), bias=bias) + +class MeanShift(nn.Conv2d): + def __init__(self, rgb_range, rgb_mean, rgb_std, sign=-1): + super(MeanShift, self).__init__(3, 3, kernel_size=1) + std = torch.Tensor(rgb_std) + self.weight.data = torch.eye(3).view(3, 3, 1, 1) + self.weight.data.div_(std.view(3, 1, 1, 1)) + self.bias.data = sign * rgb_range * torch.Tensor(rgb_mean) + self.bias.data.div_(std) + self.requires_grad = False + +class Upsampler(nn.Sequential): + def __init__(self, conv, scale, n_feat, bn=False, act=False, bias=True): + + m = [] + if (scale & (scale - 1)) == 0: # Is scale = 2^n? + for _ in range(int(math.log(scale, 2))): + m.append(conv(n_feat, 4 * n_feat, 3, bias)) + m.append(nn.PixelShuffle(2)) + if bn: m.append(nn.BatchNorm2d(n_feat)) + if act: m.append(act()) + elif scale == 3: + m.append(conv(n_feat, 9 * n_feat, 3, bias)) + m.append(nn.PixelShuffle(3)) + if bn: m.append(nn.BatchNorm2d(n_feat)) + if act: m.append(act()) + else: + raise NotImplementedError + + super(Upsampler, self).__init__(*m) + +## Channel Attention (CA) Layer +class CALayer(nn.Module): + def __init__(self, channel, reduction=16): + super(CALayer, self).__init__() + # global average pooling: feature --> point + self.avg_pool = nn.AdaptiveAvgPool2d(1) + # feature channel downscale and upscale --> channel weight + self.conv_du = nn.Sequential( + nn.Conv2d(channel, channel // reduction, 1, padding=0, bias=True), + nn.ReLU(inplace=True), + nn.Conv2d(channel // reduction, channel, 1, padding=0, bias=True), + nn.Sigmoid() + ) + + def forward(self, x): + y = self.avg_pool(x) + y = self.conv_du(y) + return x * y + +## Residual Channel Attention Block (RCAB) +class RCAB(nn.Module): + def __init__( + self, conv, n_feat, kernel_size, reduction, + bias=True, bn=False, act=nn.ReLU(True), res_scale=1): + + super(RCAB, self).__init__() + modules_body = [] + for i in range(2): + modules_body.append(conv(n_feat, n_feat, kernel_size, bias=bias)) + if bn: modules_body.append(nn.BatchNorm2d(n_feat)) + if i == 0: modules_body.append(act) + modules_body.append(CALayer(n_feat, reduction)) + self.body = nn.Sequential(*modules_body) + self.res_scale = res_scale + + def forward(self, x): + res = self.body(x) + #res = self.body(x).mul(self.res_scale) + res += x + return res + +## Residual Group (RG) +class ResidualGroup(nn.Module): + def __init__(self, conv, n_feat, kernel_size, reduction, act, res_scale, n_resblocks): + super(ResidualGroup, self).__init__() + modules_body = [] + modules_body = [ + RCAB( + conv, n_feat, kernel_size, reduction, bias=True, bn=False, act=nn.ReLU(True), res_scale=1) \ + for _ in range(n_resblocks)] + modules_body.append(conv(n_feat, n_feat, kernel_size)) + self.body = nn.Sequential(*modules_body) + + def forward(self, x): + res = self.body(x) + res += x + return res + +## Residual Channel Attention Network (RCAN) +class RCAN(nn.Module): + def __init__(self, args, conv=default_conv): + super(RCAN, self).__init__() + self.args = args + + n_resgroups = args.n_resgroups + n_resblocks = args.n_resblocks + n_feats = args.n_feats + kernel_size = 3 + reduction = args.reduction + scale = args.scale[0] + act = nn.ReLU(True) + + # RGB mean for DIV2K + rgb_mean = (0.4488, 0.4371, 0.4040) + rgb_std = (1.0, 1.0, 1.0) + self.sub_mean = MeanShift(args.rgb_range, rgb_mean, rgb_std) + + # define head module + modules_head = [conv(args.n_colors, n_feats, kernel_size)] + + # define body module + modules_body = [ + ResidualGroup( + conv, n_feats, kernel_size, reduction, act=act, res_scale=args.res_scale, n_resblocks=n_resblocks) \ + for _ in range(n_resgroups)] + + modules_body.append(conv(n_feats, n_feats, kernel_size)) + + self.add_mean = MeanShift(args.rgb_range, rgb_mean, rgb_std, 1) + + self.head = nn.Sequential(*modules_head) + self.body = nn.Sequential(*modules_body) + + if args.no_upsampling: + self.out_dim = n_feats + else: + self.out_dim = args.n_colors + # define tail module + modules_tail = [ + Upsampler(conv, scale, n_feats, act=False), + conv(n_feats, args.n_colors, kernel_size)] + self.tail = nn.Sequential(*modules_tail) + + def forward(self, x): + #x = self.sub_mean(x) + x = self.head(x) + + res = self.body(x) + res += x + + if self.args.no_upsampling: + x = res + else: + x = self.tail(res) + #x = self.add_mean(x) + return x + + def load_state_dict(self, state_dict, strict=False): + own_state = self.state_dict() + for name, param in state_dict.items(): + if name in own_state: + if isinstance(param, nn.Parameter): + param = param.data + try: + own_state[name].copy_(param) + except Exception: + if name.find('tail') >= 0: + print('Replace pre-trained upsampler to new one...') + else: + raise RuntimeError('While copying the parameter named {}, ' + 'whose dimensions in the model are {} and ' + 'whose dimensions in the checkpoint are {}.' + .format(name, own_state[name].size(), param.size())) + elif strict: + if name.find('tail') == -1: + raise KeyError('unexpected key "{}" in state_dict' + .format(name)) + + if strict: + missing = set(own_state.keys()) - set(state_dict.keys()) + if len(missing) > 0: + raise KeyError('missing keys in state_dict: "{}"'.format(missing)) + + +@register('rcan') +def make_rcan(n_resgroups=10, n_resblocks=20, n_feats=64, reduction=16, + scale=2, no_upsampling=False, rgb_range=1): + args = Namespace() + args.n_resgroups = n_resgroups + args.n_resblocks = n_resblocks + args.n_feats = n_feats + args.reduction = reduction + + args.scale = [scale] + args.no_upsampling = no_upsampling + + args.rgb_range = rgb_range + args.res_scale = 1 + args.n_colors = 3 + return RCAN(args) diff --git a/models/rdn.py b/models/rdn.py new file mode 100644 index 0000000000000000000000000000000000000000..39a95054857d485edf08310fed1ac665a2db196a --- /dev/null +++ b/models/rdn.py @@ -0,0 +1,128 @@ +# Residual Dense Network for Image Super-Resolution +# https://arxiv.org/abs/1802.08797 +# modified from: https://github.com/thstkdgus35/EDSR-PyTorch + +from argparse import Namespace + +import torch +import torch.nn as nn + +from models import register + + +class RDB_Conv(nn.Module): + def __init__(self, inChannels, growRate, kSize=3): + super(RDB_Conv, self).__init__() + Cin = inChannels + G = growRate + self.conv = nn.Sequential(*[ + nn.Conv2d(Cin, G, kSize, padding=(kSize-1)//2, stride=1), + nn.ReLU() + ]) + + def forward(self, x): + out = self.conv(x) + return torch.cat((x, out), 1) + +class RDB(nn.Module): + def __init__(self, growRate0, growRate, nConvLayers, kSize=3): + super(RDB, self).__init__() + G0 = growRate0 + G = growRate + C = nConvLayers + + convs = [] + for c in range(C): + convs.append(RDB_Conv(G0 + c*G, G)) + self.convs = nn.Sequential(*convs) + + # Local Feature Fusion + self.LFF = nn.Conv2d(G0 + C*G, G0, 1, padding=0, stride=1) + + def forward(self, x): + return self.LFF(self.convs(x)) + x + +class RDN(nn.Module): + def __init__(self, args): + super(RDN, self).__init__() + self.args = args + r = args.scale[0] + G0 = args.G0 + kSize = args.RDNkSize + + # number of RDB blocks, conv layers, out channels + self.D, C, G = { + 'A': (20, 6, 32), + 'B': (16, 8, 64), + }[args.RDNconfig] + + # Shallow feature extraction net + self.SFENet1 = nn.Conv2d(args.n_colors, G0, kSize, padding=(kSize-1)//2, stride=1) + self.SFENet2 = nn.Conv2d(G0, G0, kSize, padding=(kSize-1)//2, stride=1) + + # Redidual dense blocks and dense feature fusion + self.RDBs = nn.ModuleList() + for i in range(self.D): + self.RDBs.append( + RDB(growRate0 = G0, growRate = G, nConvLayers = C) + ) + + # Global Feature Fusion + self.GFF = nn.Sequential(*[ + nn.Conv2d(self.D * G0, G0, 1, padding=0, stride=1), + nn.Conv2d(G0, G0, kSize, padding=(kSize-1)//2, stride=1) + ]) + + if args.no_upsampling: + self.out_dim = G0 + else: + self.out_dim = args.n_colors + # Up-sampling net + if r == 2 or r == 3: + self.UPNet = nn.Sequential(*[ + nn.Conv2d(G0, G * r * r, kSize, padding=(kSize-1)//2, stride=1), + nn.PixelShuffle(r), + nn.Conv2d(G, args.n_colors, kSize, padding=(kSize-1)//2, stride=1) + ]) + elif r == 4: + self.UPNet = nn.Sequential(*[ + nn.Conv2d(G0, G * 4, kSize, padding=(kSize-1)//2, stride=1), + nn.PixelShuffle(2), + nn.Conv2d(G, G * 4, kSize, padding=(kSize-1)//2, stride=1), + nn.PixelShuffle(2), + nn.Conv2d(G, args.n_colors, kSize, padding=(kSize-1)//2, stride=1) + ]) + else: + raise ValueError("scale must be 2 or 3 or 4.") + + def forward(self, x): + f__1 = self.SFENet1(x) + x = self.SFENet2(f__1) + + RDBs_out = [] + for i in range(self.D): + x = self.RDBs[i](x) + RDBs_out.append(x) + + x = self.GFF(torch.cat(RDBs_out,1)) + x += f__1 + + if self.args.no_upsampling: + return x + else: + return self.UPNet(x) + + +@register('rdn') +def make_rdn(G0=64, RDNkSize=3, RDNconfig='B', + scale=2, no_upsampling=False): + args = Namespace() + args.G0 = G0 + args.RDNkSize = RDNkSize + args.RDNconfig = RDNconfig + + args.scale = [scale] + args.no_upsampling = no_upsampling + + args.n_colors = 3 + return RDN(args) diff --git a/models/rs_multiscale_super.py b/models/rs_multiscale_super.py new file mode 100644 index 0000000000000000000000000000000000000000..2628e4b125d2442f970c0ba950c8f80582f19e5e --- /dev/null +++ b/models/rs_multiscale_super.py @@ -0,0 +1,274 @@ +import torch +import torch.nn as nn +import torch.nn.functional as F +from einops import rearrange, repeat + +import models +from models import register +from utils import make_coord, to_coordinates + +from mmcv.cnn import ConvModule +from .blocks.CSPLayer import CSPLayer + + +@register('rs_multiscale_super') +class RSMultiScaleSuper(nn.Module): + def __init__(self, + encoder_spec, + multiscale=False, + neck=None, + decoder=None, + has_bn=True, + input_rgb=False, + n_forward_times=1, + global_decoder=None, + encode_scale_ratio=False + ): + super().__init__() + self.encoder = models.make(encoder_spec) + self.multiscale = multiscale + self.encoder_out_dim = self.encoder.out_dim + self.encode_scale_ratio = encode_scale_ratio + + conv_cfg = None + if has_bn: + norm_cfg = dict(type='BN', momentum=0.03, eps=0.001) + else: + norm_cfg = None + act_cfg = dict(type='ReLU') + + if self.multiscale: + self.multiscale_layers = nn.ModuleList() + # 32->16->8->4 + num_blocks = [2, 4, 6] + for n_idx in range(3): + conv_layer = ConvModule( + self.encoder.out_dim, + self.encoder.out_dim*2, + 3, + stride=2, + padding=1, + conv_cfg=conv_cfg, + norm_cfg=norm_cfg, + act_cfg=act_cfg + ) + csp_layer = CSPLayer( + self.encoder.out_dim*2, + self.encoder.out_dim, + num_blocks=num_blocks[n_idx], + add_identity=True, + use_depthwise=False, + conv_cfg=conv_cfg, + norm_cfg=norm_cfg, + act_cfg=act_cfg) + self.multiscale_layers.append(nn.Sequential(conv_layer, csp_layer)) + + if neck is not None: + self.neck = models.make(neck, args={'in_dim': self.encoder.out_dim}) + modulation_dim = self.neck.d_dim + else: + modulation_dim = self.encoder.out_dim + + self.n_forward_times = n_forward_times + + self.input_rgb = input_rgb + decoder_in_dim = 5 if self.input_rgb else 2 + if encode_scale_ratio: + decoder_in_dim += 2 + + if decoder is not None: + self.decoder = models.make(decoder, args={'modulation_dim': modulation_dim, 'in_dim': decoder_in_dim}) + + if global_decoder is not None: + decoder_in_dim = 5 if self.input_rgb else 2 + if encode_scale_ratio: + decoder_in_dim += 2 + + self.decoder_is_proj = global_decoder.get('is_proj', False) + self.grid_global = global_decoder.get('grid_global', False) + + self.global_decoder = models.make(global_decoder, args={'modulation_dim': modulation_dim, 'in_dim': decoder_in_dim}) + + if self.decoder_is_proj: + self.input_proj = nn.Sequential( + nn.Linear(modulation_dim, modulation_dim) + ) + self.output_proj = nn.Sequential( + nn.Linear(3, 3) + ) + + def query_rgb(self, coord, cell=None): + feat = self.feat + + if self.imnet is None: + ret = F.grid_sample(feat, coord.flip(-1).unsqueeze(1), + mode='nearest', align_corners=False)[:, :, 0, :] \ + .permute(0, 2, 1) + return ret + + if self.feat_unfold: + # if kernel_size=2 and stride=2, x should has shape (B, 4*C, H/2*W/2) + feat = F.unfold(feat, 3, padding=1).view( + feat.shape[0], feat.shape[1] * 9, feat.shape[2], feat.shape[3]) + + if self.local_ensemble: + vx_lst = [-1, 1] + vy_lst = [-1, 1] + eps_shift = 1e-6 + else: + vx_lst, vy_lst, eps_shift = [0], [0], 0 + + # field radius (global: [-1, 1]) + rx = 2 / feat.shape[-2] / 2 + ry = 2 / feat.shape[-1] / 2 + + feat_coord = make_coord(feat.shape[-2:], flatten=False).cuda() \ + .permute(2, 0, 1) \ + .unsqueeze(0).expand(feat.shape[0], 2, *feat.shape[-2:]) + + preds = [] + areas = [] + for vx in vx_lst: + for vy in vy_lst: + coord_ = coord.clone() + coord_[:, :, 0] += vx * rx + eps_shift + coord_[:, :, 1] += vy * ry + eps_shift + coord_.clamp_(-1 + 1e-6, 1 - 1e-6) + q_feat = F.grid_sample( + feat, coord_.flip(-1).unsqueeze(1), + mode='nearest', align_corners=False)[:, :, 0, :] \ + .permute(0, 2, 1) + q_coord = F.grid_sample( + feat_coord, coord_.flip(-1).unsqueeze(1), + mode='nearest', align_corners=False)[:, :, 0, :] \ + .permute(0, 2, 1) + rel_coord = coord - q_coord + rel_coord[:, :, 0] *= feat.shape[-2] + rel_coord[:, :, 1] *= feat.shape[-1] + inp = torch.cat([q_feat, rel_coord], dim=-1) + + if self.cell_decode: + rel_cell = cell.clone() + rel_cell[:, :, 0] *= feat.shape[-2] + rel_cell[:, :, 1] *= feat.shape[-1] + inp = torch.cat([inp, rel_cell], dim=-1) + + bs, q = coord.shape[:2] + pred = self.imnet(inp.view(bs * q, -1)).view(bs, q, -1) + preds.append(pred) + + area = torch.abs(rel_coord[:, :, 0] * rel_coord[:, :, 1]) + areas.append(area + 1e-9) + + tot_area = torch.stack(areas).sum(dim=0) + if self.local_ensemble: + t = areas[0]; areas[0] = areas[3]; areas[3] = t + t = areas[1]; areas[1] = areas[2]; areas[2] = t + ret = 0 + for pred, area in zip(preds, areas): + ret = ret + pred * (area / tot_area).unsqueeze(-1) + return ret + + def forward_step(self, + ori_img, + coord, + func_map, + global_content, + pred_rgb_value=None, + scale_ratio=None + ): + weight_gen_func = 'bilinear' # 'bilinear' + # grid: 先x再y + coord_ = coord.clone().unsqueeze(1).flip(-1) # Bx1xNxC + funcs = F.grid_sample( + func_map, coord_, padding_mode='border', mode=weight_gen_func, align_corners=True).squeeze(2) # B C N + funcs = rearrange(funcs, 'B C N -> (B N) C') + + feat_coord = to_coordinates(func_map.shape[-2:], return_map=True).to(func_map.device) + feat_coord = repeat(feat_coord, 'H W C -> B C H W', B=coord.size(0)) # 坐标是[y, x] + nearest_coord = F.grid_sample(feat_coord, coord_, mode='nearest', align_corners=True).squeeze(2) # B 2 N + nearest_coord = rearrange(nearest_coord, 'B C N -> B N C') # B N 2 + + relative_coord = coord - nearest_coord + relative_coord[:, :, 0] *= func_map.shape[-2] + relative_coord[:, :, 1] *= func_map.shape[-1] + relative_coord = rearrange(relative_coord, 'B N C -> (B N) C') + decoder_input = relative_coord + + interpolated_rgb = None + if self.input_rgb: + if pred_rgb_value is not None: + interpolated_rgb = rearrange(pred_rgb_value, 'B N C -> (B N) C') + else: + interpolated_rgb = F.grid_sample( + ori_img, coord_, padding_mode='border', mode='bilinear', align_corners=True).squeeze(2) # B 3 N + interpolated_rgb = rearrange(interpolated_rgb, 'B C N -> (B N) C') + decoder_input = torch.cat((decoder_input, interpolated_rgb), dim=-1) + if self.encode_scale_ratio: + scale_ratio = rearrange(scale_ratio, 'B N C -> (B N) C') + decoder_input = torch.cat((decoder_input, scale_ratio), dim=-1) + + decoder_output = self.decoder(decoder_input, funcs) + decoder_output = rearrange(decoder_output, '(B N) C -> B N C', B=func_map.size(0)) + + if hasattr(self, 'global_decoder'): + # coord: BxNx2 + # global_content: Bx1xC + if self.decoder_is_proj: + global_content = self.input_proj(global_content) # B 1 C + global_funcs = repeat(global_content, 'B C -> B N C', N=coord.size(1)) + global_funcs = rearrange(global_funcs, 'B N C -> (B N) C') + + if self.grid_global: + global_decoder_input = decoder_input + else: + global_decoder_input = rearrange(coord, 'B N C -> (B N) C') + if self.input_rgb: + global_decoder_input = torch.cat((global_decoder_input, interpolated_rgb), dim=-1) + if self.encode_scale_ratio: + global_decoder_input = torch.cat((global_decoder_input, scale_ratio), dim=-1) + + global_decoder_output = self.global_decoder(global_decoder_input, global_funcs) + global_decoder_output = rearrange(global_decoder_output, '(B N) C -> B N C', B=func_map.size(0)) + + if self.decoder_is_proj: + decoder_output = self.output_proj(global_decoder_output + decoder_output) + else: + decoder_output = global_decoder_output + decoder_output + + return decoder_output + + def forward_backbone(self, inp): + # inp: img-BxCxHxW + return self.encoder(inp) + + def forward_multiscale(self, feats, keep_ori_featmap=False): + if keep_ori_featmap: + output_feats = feats + else: + output_feats = [] + x = feats[0] + for layer in self.multiscale_layers: + x = layer(x) + output_feats.append(x) + return output_feats + + def forward(self, inp, coord, scale_ratio=None): + output_feats = [self.forward_backbone(inp)] + if self.multiscale: + output_feats = self.forward_multiscale(output_feats) + if hasattr(self, 'neck'): + global_content, func_maps = self.neck(output_feats) + else: + global_content = None + func_maps = output_feats[0] + + pred_rgb_value = None + return_pred_rgb_value = [] + + for n_time in range(self.n_forward_times): + pred_rgb_value = self.forward_step(inp, coord, func_maps, global_content, pred_rgb_value, scale_ratio) + return_pred_rgb_value.append(pred_rgb_value) + return return_pred_rgb_value + + diff --git a/models/rs_super.py b/models/rs_super.py new file mode 100644 index 0000000000000000000000000000000000000000..6483f645e0b81be1936e358b11ab526025292ddf --- /dev/null +++ b/models/rs_super.py @@ -0,0 +1,194 @@ +import torch +import torch.nn as nn +import torch.nn.functional as F +from einops import rearrange, repeat + +import models +from models import register +from utils import make_coord, to_coordinates + + +@register('rs_super') +class RSSuper(nn.Module): + def __init__(self, + encoder_spec, + neck=None, + decoder=None, + input_rgb=True, + n_forward_times=1, + global_decoder=None + ): + super().__init__() + self.n_forward_times = n_forward_times + self.encoder = models.make(encoder_spec) + if neck is not None: + self.neck = models.make(neck, args={'in_dim': self.encoder.out_dim}) + + self.input_rgb = input_rgb + decoder_in_dim = 5 if self.input_rgb else 2 + if decoder is not None: + self.decoder = models.make(decoder, args={'modulation_dim': self.neck.out_dim, 'in_dim': decoder_in_dim}) + + if global_decoder is not None: + decoder_in_dim = 5 if self.input_rgb else 2 + self.decoder_is_proj = global_decoder.get('is_proj', False) + self.grid_global = global_decoder.get('grid_global', False) + + self.global_decoder = models.make(global_decoder, args={'modulation_dim': self.neck.out_dim, 'in_dim': decoder_in_dim}) + + if self.decoder_is_proj: + self.input_proj = nn.Sequential( + nn.Linear(self.neck.out_dim, self.neck.out_dim) + ) + self.output_proj = nn.Sequential( + nn.Linear(3, 3) + ) + + def query_rgb(self, coord, cell=None): + feat = self.feat + + if self.imnet is None: + ret = F.grid_sample(feat, coord.flip(-1).unsqueeze(1), + mode='nearest', align_corners=False)[:, :, 0, :] \ + .permute(0, 2, 1) + return ret + + if self.feat_unfold: + feat = F.unfold(feat, 3, padding=1).view( + feat.shape[0], feat.shape[1] * 9, feat.shape[2], feat.shape[3]) + + if self.local_ensemble: + vx_lst = [-1, 1] + vy_lst = [-1, 1] + eps_shift = 1e-6 + else: + vx_lst, vy_lst, eps_shift = [0], [0], 0 + + # field radius (global: [-1, 1]) + rx = 2 / feat.shape[-2] / 2 + ry = 2 / feat.shape[-1] / 2 + + feat_coord = make_coord(feat.shape[-2:], flatten=False).cuda() \ + .permute(2, 0, 1) \ + .unsqueeze(0).expand(feat.shape[0], 2, *feat.shape[-2:]) + + preds = [] + areas = [] + for vx in vx_lst: + for vy in vy_lst: + coord_ = coord.clone() + coord_[:, :, 0] += vx * rx + eps_shift + coord_[:, :, 1] += vy * ry + eps_shift + coord_.clamp_(-1 + 1e-6, 1 - 1e-6) + q_feat = F.grid_sample( + feat, coord_.flip(-1).unsqueeze(1), + mode='nearest', align_corners=False)[:, :, 0, :] \ + .permute(0, 2, 1) + q_coord = F.grid_sample( + feat_coord, coord_.flip(-1).unsqueeze(1), + mode='nearest', align_corners=False)[:, :, 0, :] \ + .permute(0, 2, 1) + rel_coord = coord - q_coord + rel_coord[:, :, 0] *= feat.shape[-2] + rel_coord[:, :, 1] *= feat.shape[-1] + inp = torch.cat([q_feat, rel_coord], dim=-1) + + if self.cell_decode: + rel_cell = cell.clone() + rel_cell[:, :, 0] *= feat.shape[-2] + rel_cell[:, :, 1] *= feat.shape[-1] + inp = torch.cat([inp, rel_cell], dim=-1) + + bs, q = coord.shape[:2] + pred = self.imnet(inp.view(bs * q, -1)).view(bs, q, -1) + preds.append(pred) + + area = torch.abs(rel_coord[:, :, 0] * rel_coord[:, :, 1]) + areas.append(area + 1e-9) + + tot_area = torch.stack(areas).sum(dim=0) + if self.local_ensemble: + t = areas[0]; areas[0] = areas[3]; areas[3] = t + t = areas[1]; areas[1] = areas[2]; areas[2] = t + ret = 0 + for pred, area in zip(preds, areas): + ret = ret + pred * (area / tot_area).unsqueeze(-1) + return ret + + def forward_backbone_neck(self, inp, coord): + # inp: 64x3x32x32 + # coord: BxNx2 + feat = self.encoder(inp) # 64x64x32x32 + global_content, x_rep = self.neck(feat) # Bx1xC; BxCxHxW + return feat, x_rep, global_content + + def forward_step(self, inp, coord, feat, x_rep, global_content, pred_rgb_value=None): + weight_gen_func = 'bilinear' # 'bilinear' + # grid: 先x再y + coord_ = coord.clone().unsqueeze(1).flip(-1) # Bx1xNxC + modulations = F.grid_sample(x_rep, coord_, padding_mode='border', mode=weight_gen_func, + align_corners=True).squeeze(2) # B C N + modulations = rearrange(modulations, 'B C N -> (B N) C') + + feat_coord = to_coordinates(feat.shape[-2:], return_map=True).to(inp.device) + feat_coord = repeat(feat_coord, 'H W C -> B C H W', B=inp.size(0)) # 坐标是[y, x] + nearest_coord = F.grid_sample(feat_coord, coord_, mode='nearest', align_corners=True).squeeze(2) # B 2 N + nearest_coord = rearrange(nearest_coord, 'B C N -> B N C') # B N 2 + + relative_coord = coord - nearest_coord + relative_coord[:, :, 0] *= feat.shape[-2] + relative_coord[:, :, 1] *= feat.shape[-1] + relative_coord = rearrange(relative_coord, 'B N C -> (B N) C') + decoder_input = relative_coord + + interpolated_rgb = None + if self.input_rgb: + if pred_rgb_value is not None: + interpolated_rgb = rearrange(pred_rgb_value, 'B N C -> (B N) C') + else: + interpolated_rgb = F.grid_sample(inp, coord_, padding_mode='border', mode='bilinear', align_corners=True).squeeze(2) # B 3 N + interpolated_rgb = rearrange(interpolated_rgb, 'B C N -> (B N) C') + decoder_input = torch.cat((decoder_input, interpolated_rgb), dim=-1) + + decoder_output = self.decoder(decoder_input, modulations) + decoder_output = rearrange(decoder_output, '(B N) C -> B N C', B=inp.size(0)) + + if hasattr(self, 'global_decoder'): + # coord: BxNx2 + # global_content: Bx1xC + if self.decoder_is_proj: + global_content = self.input_proj(global_content) # B 1 C + global_modulations = repeat(global_content, 'B N C -> B (N S) C', S=coord.size(1)) + global_modulations = rearrange(global_modulations, 'B N C -> (B N) C') + + if self.grid_global: + # import pdb + # pdb.set_trace() + global_decoder_input = decoder_input + else: + global_decoder_input = rearrange(coord, 'B N C -> (B N) C') + if self.input_rgb: + global_decoder_input = torch.cat((global_decoder_input, interpolated_rgb), dim=-1) + + global_decoder_output = self.global_decoder(global_decoder_input, global_modulations) + global_decoder_output = rearrange(global_decoder_output, '(B N) C -> B N C', B=inp.size(0)) + + if self.decoder_is_proj: + decoder_output = self.output_proj(global_decoder_output + decoder_output) + else: + decoder_output = global_decoder_output + decoder_output + + return decoder_output + + def forward(self, inp, coord): + # import pdb + # pdb.set_trace() + pred_rgb_value = None + feat, x_rep, global_content = self.forward_backbone_neck(inp, coord) + return_pred_rgb_value = [] + for n_time in range(self.n_forward_times): + pred_rgb_value = self.forward_step(inp, coord, feat, x_rep, global_content, pred_rgb_value) + return_pred_rgb_value.append(pred_rgb_value) + return return_pred_rgb_value + + diff --git a/models/siren_modulation.py b/models/siren_modulation.py new file mode 100644 index 0000000000000000000000000000000000000000..019cf9fadf90d745b3295d562b481b0b9f46e219 --- /dev/null +++ b/models/siren_modulation.py @@ -0,0 +1,65 @@ +from collections import OrderedDict +import torch +import torch.nn as nn +from models import register + + +@register('sirens') +class Sirens(nn.Module): + def __init__(self, + num_inner_layers, + in_dim, + modulation_dim, + out_dim=3, + base_channels=256, + is_residual=False, + ): + super(Sirens, self).__init__() + self.in_dim = in_dim + self.num_inner_layers = num_inner_layers + + self.is_residual = is_residual + + self.first_mod = nn.Sequential( + nn.Conv2d(modulation_dim, base_channels, 1), + nn.ReLU() + ) + self.first_coord = nn.Conv2d(in_dim, base_channels, 1) + self.inner_mods = nn.ModuleList() + self.inner_coords = nn.ModuleList() + for _ in range(self.num_inner_layers): + self.inner_mods.append( + nn.Sequential( + nn.Conv2d(modulation_dim+base_channels+base_channels, base_channels, 1), + nn.ReLU() + ) + ) + self.inner_coords.append( + nn.Conv2d(base_channels, base_channels, 1) + ) + self.last_coord = nn.Sequential( + # nn.Conv2d(base_channels, base_channels//2, 1), + # nn.ReLU(), + nn.Conv2d(base_channels, out_dim, 1), + ) + + def forward(self, x, ori_modulations=None): + modulations = self.first_mod(ori_modulations) + x = self.first_coord(x) # B 2 H W -> B C H W + x = x + modulations + x = torch.sin(x) + for i_layer in range(self.num_inner_layers): + modulations = self.inner_mods[i_layer]( + torch.cat((ori_modulations, modulations, x), dim=1)) + # modulations = self.inner_mods[i_layer]( + # torch.cat((ori_modulations, x), dim=1)) + residual = self.inner_coords[i_layer](x) + residual = residual + modulations + residual = torch.sin(residual) + if self.is_residual: + x = x + residual + else: + x = residual + x = self.last_coord(x) + return x + diff --git a/models/swin_backbone.py b/models/swin_backbone.py new file mode 100644 index 0000000000000000000000000000000000000000..1f35260448678961fbe39a25d56f48186257029e --- /dev/null +++ b/models/swin_backbone.py @@ -0,0 +1,51 @@ +from models import register +from einops import rearrange +from mmcv.cnn import build_norm_layer, constant_init, trunc_normal_init +import torch +import torch.nn as nn +import torch.nn.functional as F +import torch.utils.checkpoint as cp +from .swin_neck import SwinTransformer, PatchEmbed, SwinBlockSequence + + +@register('Swin_backbone') +class SwinTransformerBackbone(nn.Module): + def __init__(self, in_channels=3, embed_dims=256, depth=4, drop_path_rate=0.1): + super().__init__() + + self.patch_embed = PatchEmbed( + in_channels=in_channels, + embed_dims=embed_dims, + conv_type='Conv2d', + kernel_size=5, + stride=1, + padding='same', + norm_cfg=dict(type='LN') + ) + + dpr = [ + x.item() for x in torch.linspace(0, drop_path_rate, depth) + ] + + self.stage = SwinBlockSequence( + embed_dims=embed_dims, + num_heads=8, + feedforward_channels=embed_dims * 2, + depth=depth, + window_size=4, + drop_path_rate=dpr, + downsample=None + ) + + self.norm_layer = build_norm_layer(dict(type='LN'), embed_dims)[1] + self.out_dim = embed_dims + + def forward(self, x): + + x, hw_shape = self.patch_embed(x) + x, hw_shape, out, out_hw_shape = self.stage(x, hw_shape) + out = self.norm_layer(out) + x = out.view(-1, *out_hw_shape, self.out_dim).permute(0, 3, 1, 2).contiguous() + + return x + diff --git a/models/swin_neck.py b/models/swin_neck.py new file mode 100644 index 0000000000000000000000000000000000000000..9844ce09288656f4d99b6f48c7f6197ea5caac2a --- /dev/null +++ b/models/swin_neck.py @@ -0,0 +1,1133 @@ +from typing import Sequence +import math +from models import register +from einops import rearrange + +import warnings +from collections import OrderedDict +from copy import deepcopy + +import torch +import torch.nn as nn +import torch.nn.functional as F +import torch.utils.checkpoint as cp +from mmcv.cnn import build_norm_layer, constant_init, trunc_normal_init, build_conv_layer +from mmcv.cnn.bricks.transformer import FFN, build_dropout +from mmcv.cnn.utils.weight_init import trunc_normal_ +from mmcv.runner import BaseModule, ModuleList, _load_checkpoint +from mmcv.utils import to_2tuple + + +@register('Swintransformer_neck') +class SwinTransformerNeck(nn.Module): + def __init__(self, in_dim, out_dim=256, depth=4, w_neck=True, drop_path_rate=0.1): + super().__init__() + self.input_proj = nn.Conv2d(in_dim, out_dim, kernel_size=3, padding=1) + self.global_op = nn.Sequential( + nn.AdaptiveAvgPool2d(output_size=(1, 1)), + nn.Conv2d(out_dim, out_dim, kernel_size=1) + ) + self.w_neck = w_neck + if w_neck: + dpr = [ + x.item() for x in torch.linspace(0, drop_path_rate, depth) + ] + + self.stage = SwinBlockSequence( + embed_dims=out_dim, + num_heads=8, + feedforward_channels=out_dim * 2, + depth=depth, + window_size=4, + drop_path_rate=dpr, + downsample=None + ) + + self.norm_layer = build_norm_layer(dict(type='LN'), out_dim)[1] + + self.out_dim = out_dim + + def forward(self, x): + x = self.input_proj(x) # x: BxCxHxW + hw = x.shape[-2:] + global_content = self.global_op(x) # BxCx1x1 + if self.w_neck: + x = rearrange(x, ' B C H W -> B (H W) C') + x, hw_shape, out, out_hw_shape = self.stage(x, hw) + out = self.norm_layer(out) + x_rep = out.view(-1, *out_hw_shape, self.out_dim).permute(0, 3, 1, 2).contiguous() + else: + x_rep = x + global_content = rearrange(global_content, 'B C H W -> B (H W) C') + return global_content, x_rep + + +class WindowMSA(BaseModule): + """Window based multi-head self-attention (W-MSA) module with relative + position bias. + + Args: + embed_dims (int): Number of input channels. + num_heads (int): Number of attention heads. + window_size (tuple[int]): The height and width of the window. + qkv_bias (bool, optional): If True, add a learnable bias to q, k, v. + Default: True. + qk_scale (float | None, optional): Override default qk scale of + head_dim ** -0.5 if set. Default: None. + attn_drop_rate (float, optional): Dropout ratio of attention weight. + Default: 0.0 + proj_drop_rate (float, optional): Dropout ratio of output. Default: 0. + init_cfg (dict | None, optional): The Config for initialization. + Default: None. + """ + + def __init__(self, + embed_dims, + num_heads, + window_size, + qkv_bias=True, + qk_scale=None, + attn_drop_rate=0., + proj_drop_rate=0., + init_cfg=None): + + super().__init__() + self.embed_dims = embed_dims + self.window_size = window_size # Wh, Ww + self.num_heads = num_heads + head_embed_dims = embed_dims // num_heads + self.scale = qk_scale or head_embed_dims**-0.5 + self.init_cfg = init_cfg + + # define a parameter table of relative position bias + self.relative_position_bias_table = nn.Parameter( + torch.zeros((2 * window_size[0] - 1) * (2 * window_size[1] - 1), + num_heads)) # 2*Wh-1 * 2*Ww-1, nH + + # About 2x faster than original impl + Wh, Ww = self.window_size + rel_index_coords = self.double_step_seq(2 * Ww - 1, Wh, 1, Ww) + rel_position_index = rel_index_coords + rel_index_coords.T + rel_position_index = rel_position_index.flip(1).contiguous() + self.register_buffer('relative_position_index', rel_position_index) + + self.qkv = nn.Linear(embed_dims, embed_dims * 3, bias=qkv_bias) + self.attn_drop = nn.Dropout(attn_drop_rate) + self.proj = nn.Linear(embed_dims, embed_dims) + self.proj_drop = nn.Dropout(proj_drop_rate) + + self.softmax = nn.Softmax(dim=-1) + + def init_weights(self): + trunc_normal_(self.relative_position_bias_table, std=0.02) + + def forward(self, x, mask=None): + """ + Args: + + x (tensor): input features with shape of (num_windows*B, N, C) + mask (tensor | None, Optional): mask with shape of (num_windows, + Wh*Ww, Wh*Ww), value should be between (-inf, 0]. + """ + # import pdb + # pdb.set_trace() + + B, N, C = x.shape + qkv = self.qkv(x).reshape(B, N, 3, self.num_heads, C // self.num_heads).permute(2, 0, 3, 1, 4) + # make torchscript happy (cannot use tensor as tuple) + q, k, v = qkv[0], qkv[1], qkv[2] + + q = q * self.scale + attn = (q @ k.transpose(-2, -1)) + + relative_position_bias = self.relative_position_bias_table[ + self.relative_position_index.view(-1)].view( + self.window_size[0] * self.window_size[1], + self.window_size[0] * self.window_size[1], + -1) # Wh*Ww,Wh*Ww,nH + relative_position_bias = relative_position_bias.permute( + 2, 0, 1).contiguous() # nH, Wh*Ww, Wh*Ww + attn = attn + relative_position_bias.unsqueeze(0) + + if mask is not None: + nW = mask.shape[0] + attn = attn.view(B // nW, nW, self.num_heads, N, + N) + mask.unsqueeze(1).unsqueeze(0) + attn = attn.view(-1, self.num_heads, N, N) + attn = self.softmax(attn) + + attn = self.attn_drop(attn) + + x = (attn @ v).transpose(1, 2).reshape(B, N, C) + x = self.proj(x) + x = self.proj_drop(x) + return x + + @staticmethod + def double_step_seq(step1, len1, step2, len2): + seq1 = torch.arange(0, step1 * len1, step1) + seq2 = torch.arange(0, step2 * len2, step2) + return (seq1[:, None] + seq2[None, :]).reshape(1, -1) + + +class ShiftWindowMSA(BaseModule): + """Shifted Window Multihead Self-Attention Module. + + Args: + embed_dims (int): Number of input channels. + num_heads (int): Number of attention heads. + window_size (int): The height and width of the window. + shift_size (int, optional): The shift step of each window towards + right-bottom. If zero, act as regular window-msa. Defaults to 0. + qkv_bias (bool, optional): If True, add a learnable bias to q, k, v. + Default: True + qk_scale (float | None, optional): Override default qk scale of + head_dim ** -0.5 if set. Defaults: None. + attn_drop_rate (float, optional): Dropout ratio of attention weight. + Defaults: 0. + proj_drop_rate (float, optional): Dropout ratio of output. + Defaults: 0. + dropout_layer (dict, optional): The dropout_layer used before output. + Defaults: dict(type='DropPath', drop_prob=0.). + init_cfg (dict, optional): The extra config for initialization. + Default: None. + """ + + def __init__(self, + embed_dims, + num_heads, + window_size, + shift_size=0, + qkv_bias=True, + qk_scale=None, + attn_drop_rate=0, + proj_drop_rate=0, + dropout_layer=dict(type='DropPath', drop_prob=0.), + init_cfg=None): + super().__init__(init_cfg) + + self.window_size = window_size + self.shift_size = shift_size + assert 0 <= self.shift_size < self.window_size + + self.w_msa = WindowMSA( + embed_dims=embed_dims, + num_heads=num_heads, + window_size=to_2tuple(window_size), + qkv_bias=qkv_bias, + qk_scale=qk_scale, + attn_drop_rate=attn_drop_rate, + proj_drop_rate=proj_drop_rate, + init_cfg=None) + + self.drop = build_dropout(dropout_layer) + + def forward(self, query, hw_shape): + B, L, C = query.shape + H, W = hw_shape + assert L == H * W, 'input feature has wrong size' + query = query.view(B, H, W, C) + + # pad feature maps to multiples of window size + pad_r = (self.window_size - W % self.window_size) % self.window_size + pad_b = (self.window_size - H % self.window_size) % self.window_size + query = F.pad(query, (0, 0, 0, pad_r, 0, pad_b)) + H_pad, W_pad = query.shape[1], query.shape[2] + + # cyclic shift + if self.shift_size > 0: + shifted_query = torch.roll( + query, + shifts=(-self.shift_size, -self.shift_size), + dims=(1, 2)) + + # calculate attention mask for SW-MSA + img_mask = torch.zeros((1, H_pad, W_pad, 1), device=query.device) + h_slices = (slice(0, -self.window_size), + slice(-self.window_size, + -self.shift_size), slice(-self.shift_size, None)) + w_slices = (slice(0, -self.window_size), + slice(-self.window_size, + -self.shift_size), slice(-self.shift_size, None)) + cnt = 0 + for h in h_slices: + for w in w_slices: + img_mask[:, h, w, :] = cnt + cnt += 1 + + # nW, window_size, window_size, 1 + mask_windows = self.window_partition(img_mask) + mask_windows = mask_windows.view( + -1, self.window_size * self.window_size) + attn_mask = mask_windows.unsqueeze(1) - mask_windows.unsqueeze(2) + attn_mask = attn_mask.masked_fill(attn_mask != 0, + float(-100.0)).masked_fill( + attn_mask == 0, float(0.0)) + else: + shifted_query = query + attn_mask = None + + # nW*B, window_size, window_size, C + query_windows = self.window_partition(shifted_query) + # nW*B, window_size*window_size, C + query_windows = query_windows.view(-1, self.window_size**2, C) + + # W-MSA/SW-MSA (nW*B, window_size*window_size, C) + attn_windows = self.w_msa(query_windows, mask=attn_mask) + + # merge windows + attn_windows = attn_windows.view(-1, self.window_size, + self.window_size, C) + + # B H' W' C + shifted_x = self.window_reverse(attn_windows, H_pad, W_pad) + # reverse cyclic shift + if self.shift_size > 0: + x = torch.roll( + shifted_x, + shifts=(self.shift_size, self.shift_size), + dims=(1, 2)) + else: + x = shifted_x + + if pad_r > 0 or pad_b: + x = x[:, :H, :W, :].contiguous() + + x = x.view(B, H * W, C) + + x = self.drop(x) + return x + + def window_reverse(self, windows, H, W): + """ + Args: + windows: (num_windows*B, window_size, window_size, C) + H (int): Height of image + W (int): Width of image + Returns: + x: (B, H, W, C) + """ + window_size = self.window_size + B = int(windows.shape[0] / (H * W / window_size / window_size)) + x = windows.view(B, H // window_size, W // window_size, window_size, + window_size, -1) + x = x.permute(0, 1, 3, 2, 4, 5).contiguous().view(B, H, W, -1) + return x + + def window_partition(self, x): + """ + Args: + x: (B, H, W, C) + Returns: + windows: (num_windows*B, window_size, window_size, C) + """ + B, H, W, C = x.shape + window_size = self.window_size + x = x.view(B, H // window_size, window_size, W // window_size, + window_size, C) + windows = x.permute(0, 1, 3, 2, 4, 5).contiguous() + windows = windows.view(-1, window_size, window_size, C) + return windows + + +class SwinBlock(BaseModule): + """" + Args: + embed_dims (int): The feature dimension. + num_heads (int): Parallel attention heads. + feedforward_channels (int): The hidden dimension for FFNs. + window_size (int, optional): The local window scale. Default: 7. + shift (bool, optional): whether to shift window or not. Default False. + qkv_bias (bool, optional): enable bias for qkv if True. Default: True. + qk_scale (float | None, optional): Override default qk scale of + head_dim ** -0.5 if set. Default: None. + drop_rate (float, optional): Dropout rate. Default: 0. + attn_drop_rate (float, optional): Attention dropout rate. Default: 0. + drop_path_rate (float, optional): Stochastic depth rate. Default: 0. + act_cfg (dict, optional): The config dict of activation function. + Default: dict(type='GELU'). + norm_cfg (dict, optional): The config dict of normalization. + Default: dict(type='LN'). + with_cp (bool, optional): Use checkpoint or not. Using checkpoint + will save some memory while slowing down the training speed. + Default: False. + init_cfg (dict | list | None, optional): The init config. + Default: None. + """ + + def __init__(self, + embed_dims, + num_heads, + feedforward_channels, + window_size=7, + shift=False, + qkv_bias=True, + qk_scale=None, + drop_rate=0., + attn_drop_rate=0., + drop_path_rate=0., + act_cfg=dict(type='GELU'), + norm_cfg=dict(type='LN'), + with_cp=False, + init_cfg=None): + + super(SwinBlock, self).__init__() + + self.init_cfg = init_cfg + self.with_cp = with_cp + + self.norm1 = build_norm_layer(norm_cfg, embed_dims)[1] + self.attn = ShiftWindowMSA( + embed_dims=embed_dims, + num_heads=num_heads, + window_size=window_size, + shift_size=window_size // 2 if shift else 0, + qkv_bias=qkv_bias, + qk_scale=qk_scale, + attn_drop_rate=attn_drop_rate, + proj_drop_rate=drop_rate, + dropout_layer=dict(type='DropPath', drop_prob=drop_path_rate), + init_cfg=None) + + self.norm2 = build_norm_layer(norm_cfg, embed_dims)[1] + self.ffn = FFN( + embed_dims=embed_dims, + feedforward_channels=feedforward_channels, + num_fcs=2, + ffn_drop=drop_rate, + dropout_layer=dict(type='DropPath', drop_prob=drop_path_rate), + act_cfg=act_cfg, + add_identity=True, + init_cfg=None) + + def forward(self, x, hw_shape): + + def _inner_forward(x): + identity = x + x = self.norm1(x) + x = self.attn(x, hw_shape) + + x = x + identity + + identity = x + x = self.norm2(x) + x = self.ffn(x, identity=identity) + + return x + + if self.with_cp and x.requires_grad: + x = cp.checkpoint(_inner_forward, x) + else: + x = _inner_forward(x) + + return x + + +class SwinBlockSequence(BaseModule): + """Implements one stage in Swin Transformer. + + Args: + embed_dims (int): The feature dimension. + num_heads (int): Parallel attention heads. + feedforward_channels (int): The hidden dimension for FFNs. + depth (int): The number of blocks in this stage. + window_size (int, optional): The local window scale. Default: 7. + qkv_bias (bool, optional): enable bias for qkv if True. Default: True. + qk_scale (float | None, optional): Override default qk scale of + head_dim ** -0.5 if set. Default: None. + drop_rate (float, optional): Dropout rate. Default: 0. + attn_drop_rate (float, optional): Attention dropout rate. Default: 0. + drop_path_rate (float | list[float], optional): Stochastic depth + rate. Default: 0. + downsample (BaseModule | None, optional): The downsample operation + module. Default: None. + act_cfg (dict, optional): The config dict of activation function. + Default: dict(type='GELU'). + norm_cfg (dict, optional): The config dict of normalization. + Default: dict(type='LN'). + with_cp (bool, optional): Use checkpoint or not. Using checkpoint + will save some memory while slowing down the training speed. + Default: False. + init_cfg (dict | list | None, optional): The init config. + Default: None. + """ + + def __init__(self, + embed_dims, + num_heads, + feedforward_channels, + depth, + window_size=7, + qkv_bias=True, + qk_scale=None, + drop_rate=0., + attn_drop_rate=0., + drop_path_rate=0., + downsample=None, + act_cfg=dict(type='GELU'), + norm_cfg=dict(type='LN'), + with_cp=False, + init_cfg=None): + super().__init__(init_cfg=init_cfg) + + if isinstance(drop_path_rate, list): + drop_path_rates = drop_path_rate + assert len(drop_path_rates) == depth + else: + drop_path_rates = [deepcopy(drop_path_rate) for _ in range(depth)] + + self.blocks = ModuleList() + for i in range(depth): + block = SwinBlock( + embed_dims=embed_dims, + num_heads=num_heads, + feedforward_channels=feedforward_channels, + window_size=window_size, + shift=False if i % 2 == 0 else True, + qkv_bias=qkv_bias, + qk_scale=qk_scale, + drop_rate=drop_rate, + attn_drop_rate=attn_drop_rate, + drop_path_rate=drop_path_rates[i], + act_cfg=act_cfg, + norm_cfg=norm_cfg, + with_cp=with_cp, + init_cfg=None) + self.blocks.append(block) + + self.downsample = downsample + + def forward(self, x, hw_shape): + for block in self.blocks: + x = block(x, hw_shape) + + if self.downsample: + x_down, down_hw_shape = self.downsample(x, hw_shape) + return x_down, down_hw_shape, x, hw_shape + else: + return x, hw_shape, x, hw_shape + + + +class SwinTransformer(BaseModule): + """ Swin Transformer + A PyTorch implement of : `Swin Transformer: + Hierarchical Vision Transformer using Shifted Windows` - + https://arxiv.org/abs/2103.14030 + + Inspiration from + https://github.com/microsoft/Swin-Transformer + + Args: + pretrain_img_size (int | tuple[int]): The size of input image when + pretrain. Defaults: 224. + in_channels (int): The num of input channels. + Defaults: 3. + embed_dims (int): The feature dimension. Default: 96. + patch_size (int | tuple[int]): Patch size. Default: 4. + window_size (int): Window size. Default: 7. + mlp_ratio (int): Ratio of mlp hidden dim to embedding dim. + Default: 4. + depths (tuple[int]): Depths of each Swin Transformer stage. + Default: (2, 2, 6, 2). + num_heads (tuple[int]): Parallel attention heads of each Swin + Transformer stage. Default: (3, 6, 12, 24). + strides (tuple[int]): The patch merging or patch embedding stride of + each Swin Transformer stage. (In swin, we set kernel size equal to + stride.) Default: (4, 2, 2, 2). + out_indices (tuple[int]): Output from which stages. + Default: (0, 1, 2, 3). + qkv_bias (bool, optional): If True, add a learnable bias to query, key, + value. Default: True + qk_scale (float | None, optional): Override default qk scale of + head_dim ** -0.5 if set. Default: None. + patch_norm (bool): If add a norm layer for patch embed and patch + merging. Default: True. + drop_rate (float): Dropout rate. Defaults: 0. + attn_drop_rate (float): Attention dropout rate. Default: 0. + drop_path_rate (float): Stochastic depth rate. Defaults: 0.1. + use_abs_pos_embed (bool): If True, add absolute position embedding to + the patch embedding. Defaults: False. + act_cfg (dict): Config dict for activation layer. + Default: dict(type='LN'). + norm_cfg (dict): Config dict for normalization layer at + output of backone. Defaults: dict(type='LN'). + with_cp (bool, optional): Use checkpoint or not. Using checkpoint + will save some memory while slowing down the training speed. + Default: False. + pretrained (str, optional): model pretrained path. Default: None. + convert_weights (bool): The flag indicates whether the + pre-trained model is from the original repo. We may need + to convert some keys to make it compatible. + Default: False. + frozen_stages (int): Stages to be frozen (stop grad and set eval mode). + Default: -1 (-1 means not freezing any parameters). + init_cfg (dict, optional): The Config for initialization. + Defaults to None. + """ + + def __init__(self, + pretrain_img_size=224, + in_channels=3, + embed_dims=96, + patch_size=4, + window_size=7, + mlp_ratio=4, + depths=(2, 2, 6, 2), + num_heads=(3, 6, 12, 24), + strides=(4, 2, 2, 2), + out_indices=(0, 1, 2, 3), + qkv_bias=True, + qk_scale=None, + patch_norm=True, + drop_rate=0., + attn_drop_rate=0., + drop_path_rate=0.1, + use_abs_pos_embed=False, + act_cfg=dict(type='GELU'), + norm_cfg=dict(type='LN'), + with_cp=False, + pretrained=None, + convert_weights=False, + frozen_stages=-1, + init_cfg=None): + self.convert_weights = convert_weights + self.frozen_stages = frozen_stages + if isinstance(pretrain_img_size, int): + pretrain_img_size = to_2tuple(pretrain_img_size) + elif isinstance(pretrain_img_size, tuple): + if len(pretrain_img_size) == 1: + pretrain_img_size = to_2tuple(pretrain_img_size[0]) + assert len(pretrain_img_size) == 2, \ + f'The size of image should have length 1 or 2, ' \ + f'but got {len(pretrain_img_size)}' + + assert not (init_cfg and pretrained), \ + 'init_cfg and pretrained cannot be specified at the same time' + if isinstance(pretrained, str): + warnings.warn('DeprecationWarning: pretrained is deprecated, ' + 'please use "init_cfg" instead') + self.init_cfg = dict(type='Pretrained', checkpoint=pretrained) + elif pretrained is None: + self.init_cfg = init_cfg + else: + raise TypeError('pretrained must be a str or None') + + super(SwinTransformer, self).__init__(init_cfg=init_cfg) + + num_layers = len(depths) + self.out_indices = out_indices + self.use_abs_pos_embed = use_abs_pos_embed + + assert strides[0] == patch_size, 'Use non-overlapping patch embed.' + + self.patch_embed = PatchEmbed( + in_channels=in_channels, + embed_dims=embed_dims, + conv_type='Conv2d', + kernel_size=patch_size, + stride=strides[0], + norm_cfg=norm_cfg if patch_norm else None, + init_cfg=None) + + if self.use_abs_pos_embed: + patch_row = pretrain_img_size[0] // patch_size + patch_col = pretrain_img_size[1] // patch_size + num_patches = patch_row * patch_col + self.absolute_pos_embed = nn.Parameter( + torch.zeros((1, num_patches, embed_dims))) + + self.drop_after_pos = nn.Dropout(p=drop_rate) + + # set stochastic depth decay rule + total_depth = sum(depths) + dpr = [ + x.item() for x in torch.linspace(0, drop_path_rate, total_depth) + ] + + self.stages = ModuleList() + in_channels = embed_dims + for i in range(num_layers): + if i < num_layers - 1: + downsample = PatchMerging( + in_channels=in_channels, + out_channels=2 * in_channels, + stride=strides[i + 1], + norm_cfg=norm_cfg if patch_norm else None, + init_cfg=None) + else: + downsample = None + + stage = SwinBlockSequence( + embed_dims=in_channels, + num_heads=num_heads[i], + feedforward_channels=mlp_ratio * in_channels, + depth=depths[i], + window_size=window_size, + qkv_bias=qkv_bias, + qk_scale=qk_scale, + drop_rate=drop_rate, + attn_drop_rate=attn_drop_rate, + drop_path_rate=dpr[sum(depths[:i]):sum(depths[:i + 1])], + downsample=downsample, + act_cfg=act_cfg, + norm_cfg=norm_cfg, + with_cp=with_cp, + init_cfg=None) + self.stages.append(stage) + if downsample: + in_channels = downsample.out_channels + + self.num_features = [int(embed_dims * 2**i) for i in range(num_layers)] + # Add a norm layer for each output + for i in out_indices: + layer = build_norm_layer(norm_cfg, self.num_features[i])[1] + layer_name = f'norm{i}' + self.add_module(layer_name, layer) + + def train(self, mode=True): + """Convert the model into training mode while keep layers freezed.""" + super(SwinTransformer, self).train(mode) + self._freeze_stages() + + def _freeze_stages(self): + if self.frozen_stages >= 0: + self.patch_embed.eval() + for param in self.patch_embed.parameters(): + param.requires_grad = False + if self.use_abs_pos_embed: + self.absolute_pos_embed.requires_grad = False + self.drop_after_pos.eval() + + for i in range(1, self.frozen_stages + 1): + + if (i - 1) in self.out_indices: + norm_layer = getattr(self, f'norm{i-1}') + norm_layer.eval() + for param in norm_layer.parameters(): + param.requires_grad = False + + m = self.stages[i - 1] + m.eval() + for param in m.parameters(): + param.requires_grad = False + + def init_weights(self): + logger = get_root_logger() + if self.init_cfg is None: + logger.warn(f'No pre-trained weights for ' + f'{self.__class__.__name__}, ' + f'training start from scratch') + if self.use_abs_pos_embed: + trunc_normal_(self.absolute_pos_embed, std=0.02) + for m in self.modules(): + if isinstance(m, nn.Linear): + trunc_normal_init(m, std=.02, bias=0.) + elif isinstance(m, nn.LayerNorm): + constant_init(m, 1.0) + else: + assert 'checkpoint' in self.init_cfg, f'Only support ' \ + f'specify `Pretrained` in ' \ + f'`init_cfg` in ' \ + f'{self.__class__.__name__} ' + ckpt = _load_checkpoint( + self.init_cfg.checkpoint, logger=logger, map_location='cpu') + if 'state_dict' in ckpt: + _state_dict = ckpt['state_dict'] + elif 'model' in ckpt: + _state_dict = ckpt['model'] + else: + _state_dict = ckpt + if self.convert_weights: + # supported loading weight from original repo, + _state_dict = swin_converter(_state_dict) + + state_dict = OrderedDict() + for k, v in _state_dict.items(): + if k.startswith('backbone.'): + state_dict[k[9:]] = v + + # strip prefix of state_dict + if list(state_dict.keys())[0].startswith('module.'): + state_dict = {k[7:]: v for k, v in state_dict.items()} + + # reshape absolute position embedding + if state_dict.get('absolute_pos_embed') is not None: + absolute_pos_embed = state_dict['absolute_pos_embed'] + N1, L, C1 = absolute_pos_embed.size() + N2, C2, H, W = self.absolute_pos_embed.size() + if N1 != N2 or C1 != C2 or L != H * W: + logger.warning('Error in loading absolute_pos_embed, pass') + else: + state_dict['absolute_pos_embed'] = absolute_pos_embed.view( + N2, H, W, C2).permute(0, 3, 1, 2).contiguous() + + # interpolate position bias table if needed + relative_position_bias_table_keys = [ + k for k in state_dict.keys() + if 'relative_position_bias_table' in k + ] + for table_key in relative_position_bias_table_keys: + table_pretrained = state_dict[table_key] + table_current = self.state_dict()[table_key] + L1, nH1 = table_pretrained.size() + L2, nH2 = table_current.size() + if nH1 != nH2: + logger.warning(f'Error in loading {table_key}, pass') + elif L1 != L2: + S1 = int(L1**0.5) + S2 = int(L2**0.5) + table_pretrained_resized = F.interpolate( + table_pretrained.permute(1, 0).reshape(1, nH1, S1, S1), + size=(S2, S2), + mode='bicubic') + state_dict[table_key] = table_pretrained_resized.view( + nH2, L2).permute(1, 0).contiguous() + + # load state_dict + self.load_state_dict(state_dict, False) + + def forward(self, x): + x, hw_shape = self.patch_embed(x) + + if self.use_abs_pos_embed: + x = x + self.absolute_pos_embed + x = self.drop_after_pos(x) + + outs = [] + for i, stage in enumerate(self.stages): + x, hw_shape, out, out_hw_shape = stage(x, hw_shape) + if i in self.out_indices: + norm_layer = getattr(self, f'norm{i}') + out = norm_layer(out) + out = out.view(-1, *out_hw_shape, + self.num_features[i]).permute(0, 3, 1, + 2).contiguous() + outs.append(out) + + return outs + +class PatchEmbed(BaseModule): + """Image to Patch Embedding. + + We use a conv layer to implement PatchEmbed. + + Args: + in_channels (int): The num of input channels. Default: 3 + embed_dims (int): The dimensions of embedding. Default: 768 + conv_type (str): The config dict for embedding + conv layer type selection. Default: "Conv2d. + kernel_size (int): The kernel_size of embedding conv. Default: 16. + stride (int): The slide stride of embedding conv. + Default: None (Would be set as `kernel_size`). + padding (int | tuple | string ): The padding length of + embedding conv. When it is a string, it means the mode + of adaptive padding, support "same" and "corner" now. + Default: "corner". + dilation (int): The dilation rate of embedding conv. Default: 1. + bias (bool): Bias of embed conv. Default: True. + norm_cfg (dict, optional): Config dict for normalization layer. + Default: None. + input_size (int | tuple | None): The size of input, which will be + used to calculate the out size. Only work when `dynamic_size` + is False. Default: None. + init_cfg (`mmcv.ConfigDict`, optional): The Config for initialization. + Default: None. + """ + + def __init__( + self, + in_channels=3, + embed_dims=768, + conv_type='Conv2d', + kernel_size=16, + stride=16, + padding='corner', + dilation=1, + bias=True, + norm_cfg=None, + input_size=None, + init_cfg=None, + ): + super(PatchEmbed, self).__init__(init_cfg=init_cfg) + + self.embed_dims = embed_dims + if stride is None: + stride = kernel_size + + kernel_size = to_2tuple(kernel_size) + stride = to_2tuple(stride) + dilation = to_2tuple(dilation) + + if isinstance(padding, str): + self.adap_padding = AdaptivePadding( + kernel_size=kernel_size, + stride=stride, + dilation=dilation, + padding=padding) + # disable the padding of conv + padding = 0 + else: + self.adap_padding = None + padding = to_2tuple(padding) + + self.projection = build_conv_layer( + dict(type=conv_type), + in_channels=in_channels, + out_channels=embed_dims, + kernel_size=kernel_size, + stride=stride, + padding=padding, + dilation=dilation, + bias=bias) + + if norm_cfg is not None: + self.norm = build_norm_layer(norm_cfg, embed_dims)[1] + else: + self.norm = None + + if input_size: + input_size = to_2tuple(input_size) + # `init_out_size` would be used outside to + # calculate the num_patches + # when `use_abs_pos_embed` outside + self.init_input_size = input_size + if self.adap_padding: + pad_h, pad_w = self.adap_padding.get_pad_shape(input_size) + input_h, input_w = input_size + input_h = input_h + pad_h + input_w = input_w + pad_w + input_size = (input_h, input_w) + + # https://pytorch.org/docs/stable/generated/torch.nn.Conv2d.html + h_out = (input_size[0] + 2 * padding[0] - dilation[0] * + (kernel_size[0] - 1) - 1) // stride[0] + 1 + w_out = (input_size[1] + 2 * padding[1] - dilation[1] * + (kernel_size[1] - 1) - 1) // stride[1] + 1 + self.init_out_size = (h_out, w_out) + else: + self.init_input_size = None + self.init_out_size = None + + def forward(self, x): + """ + Args: + x (Tensor): Has shape (B, C, H, W). In most case, C is 3. + + Returns: + tuple: Contains merged results and its spatial shape. + + - x (Tensor): Has shape (B, out_h * out_w, embed_dims) + - out_size (tuple[int]): Spatial shape of x, arrange as + (out_h, out_w). + """ + + if self.adap_padding: + x = self.adap_padding(x) + + x = self.projection(x) + out_size = (x.shape[2], x.shape[3]) + x = x.flatten(2).transpose(1, 2) + if self.norm is not None: + x = self.norm(x) + return x, out_size + + +class PatchMerging(BaseModule): + """Merge patch feature map. + + This layer groups feature map by kernel_size, and applies norm and linear + layers to the grouped feature map. Our implementation uses `nn.Unfold` to + merge patch, which is about 25% faster than original implementation. + Instead, we need to modify pretrained models for compatibility. + + Args: + in_channels (int): The num of input channels. + to gets fully covered by filter and stride you specified.. + Default: True. + out_channels (int): The num of output channels. + kernel_size (int | tuple, optional): the kernel size in the unfold + layer. Defaults to 2. + stride (int | tuple, optional): the stride of the sliding blocks in the + unfold layer. Default: None. (Would be set as `kernel_size`) + padding (int | tuple | string ): The padding length of + embedding conv. When it is a string, it means the mode + of adaptive padding, support "same" and "corner" now. + Default: "corner". + dilation (int | tuple, optional): dilation parameter in the unfold + layer. Default: 1. + bias (bool, optional): Whether to add bias in linear layer or not. + Defaults: False. + norm_cfg (dict, optional): Config dict for normalization layer. + Default: dict(type='LN'). + init_cfg (dict, optional): The extra config for initialization. + Default: None. + """ + + def __init__(self, + in_channels, + out_channels, + kernel_size=2, + stride=None, + padding='corner', + dilation=1, + bias=False, + norm_cfg=dict(type='LN'), + init_cfg=None): + super().__init__(init_cfg=init_cfg) + self.in_channels = in_channels + self.out_channels = out_channels + if stride: + stride = stride + else: + stride = kernel_size + + kernel_size = to_2tuple(kernel_size) + stride = to_2tuple(stride) + dilation = to_2tuple(dilation) + + if isinstance(padding, str): + self.adap_padding = AdaptivePadding( + kernel_size=kernel_size, + stride=stride, + dilation=dilation, + padding=padding) + # disable the padding of unfold + padding = 0 + else: + self.adap_padding = None + + padding = to_2tuple(padding) + self.sampler = nn.Unfold( + kernel_size=kernel_size, + dilation=dilation, + padding=padding, + stride=stride) + + sample_dim = kernel_size[0] * kernel_size[1] * in_channels + + if norm_cfg is not None: + self.norm = build_norm_layer(norm_cfg, sample_dim)[1] + else: + self.norm = None + + self.reduction = nn.Linear(sample_dim, out_channels, bias=bias) + + def forward(self, x, input_size): + """ + Args: + x (Tensor): Has shape (B, H*W, C_in). + input_size (tuple[int]): The spatial shape of x, arrange as (H, W). + Default: None. + + Returns: + tuple: Contains merged results and its spatial shape. + + - x (Tensor): Has shape (B, Merged_H * Merged_W, C_out) + - out_size (tuple[int]): Spatial shape of x, arrange as + (Merged_H, Merged_W). + """ + B, L, C = x.shape + assert isinstance(input_size, Sequence), f'Expect ' \ + f'input_size is ' \ + f'`Sequence` ' \ + f'but get {input_size}' + + H, W = input_size + assert L == H * W, 'input feature has wrong size' + + x = x.view(B, H, W, C).permute([0, 3, 1, 2]) # B, C, H, W + # Use nn.Unfold to merge patch. About 25% faster than original method, + # but need to modify pretrained model for compatibility + + if self.adap_padding: + x = self.adap_padding(x) + H, W = x.shape[-2:] + + x = self.sampler(x) + # if kernel_size=2 and stride=2, x should has shape (B, 4*C, H/2*W/2) + + out_h = (H + 2 * self.sampler.padding[0] - self.sampler.dilation[0] * + (self.sampler.kernel_size[0] - 1) - + 1) // self.sampler.stride[0] + 1 + out_w = (W + 2 * self.sampler.padding[1] - self.sampler.dilation[1] * + (self.sampler.kernel_size[1] - 1) - + 1) // self.sampler.stride[1] + 1 + + output_size = (out_h, out_w) + x = x.transpose(1, 2) # B, H/2*W/2, 4*C + x = self.norm(x) if self.norm else x + x = self.reduction(x) + return x, output_size + + +class AdaptivePadding(nn.Module): + """Applies padding to input (if needed) so that input can get fully covered + by filter you specified. It support two modes "same" and "corner". The + "same" mode is same with "SAME" padding mode in TensorFlow, pad zero around + input. The "corner" mode would pad zero to bottom right. + + Args: + kernel_size (int | tuple): Size of the kernel: + stride (int | tuple): Stride of the filter. Default: 1: + dilation (int | tuple): Spacing between kernel elements. + Default: 1 + padding (str): Support "same" and "corner", "corner" mode + would pad zero to bottom right, and "same" mode would + pad zero around input. Default: "corner". + Example: + >>> kernel_size = 16 + >>> stride = 16 + >>> dilation = 1 + >>> input = torch.rand(1, 1, 15, 17) + >>> adap_pad = AdaptivePadding( + >>> kernel_size=kernel_size, + >>> stride=stride, + >>> dilation=dilation, + >>> padding="corner") + >>> out = adap_pad(input) + >>> assert (out.shape[2], out.shape[3]) == (16, 32) + >>> input = torch.rand(1, 1, 16, 17) + >>> out = adap_pad(input) + >>> assert (out.shape[2], out.shape[3]) == (16, 32) + """ + + def __init__(self, kernel_size=1, stride=1, dilation=1, padding='corner'): + + super(AdaptivePadding, self).__init__() + + assert padding in ('same', 'corner') + + kernel_size = to_2tuple(kernel_size) + stride = to_2tuple(stride) + padding = to_2tuple(padding) + dilation = to_2tuple(dilation) + + self.padding = padding + self.kernel_size = kernel_size + self.stride = stride + self.dilation = dilation + + def get_pad_shape(self, input_shape): + input_h, input_w = input_shape + kernel_h, kernel_w = self.kernel_size + stride_h, stride_w = self.stride + output_h = math.ceil(input_h / stride_h) + output_w = math.ceil(input_w / stride_w) + pad_h = max((output_h - 1) * stride_h + + (kernel_h - 1) * self.dilation[0] + 1 - input_h, 0) + pad_w = max((output_w - 1) * stride_w + + (kernel_w - 1) * self.dilation[1] + 1 - input_w, 0) + return pad_h, pad_w + + def forward(self, x): + pad_h, pad_w = self.get_pad_shape(x.size()[-2:]) + if pad_h > 0 or pad_w > 0: + if self.padding == 'corner': + x = F.pad(x, [0, pad_w, 0, pad_h]) + elif self.padding == 'same': + x = F.pad(x, [ + pad_w // 2, pad_w - pad_w // 2, pad_h // 2, + pad_h - pad_h // 2 + ]) + return x \ No newline at end of file diff --git a/models/transformer_neck.py b/models/transformer_neck.py new file mode 100644 index 0000000000000000000000000000000000000000..eefc62179373462ce8ab3b6b7a6cd3cbdaa78a38 --- /dev/null +++ b/models/transformer_neck.py @@ -0,0 +1,118 @@ +import torch +import torch.nn as nn + +from models import register +from torch.nn import TransformerEncoderLayer, TransformerEncoder, LayerNorm +from torch.nn.init import xavier_uniform_ +from einops import rearrange +# from mmcv.runner.base_module import BaseModule, ModuleList +# from mmcv.cnn import build_norm_layer +from mmcv.cnn.bricks.transformer import FFN, PatchEmbed +# from mmcv.cnn.utils.weight_init import trunc_normal_ +# from mmcv.cnn.bricks.registry import DROPOUT_LAYERS + + +@register('transformer_neck') +class TransformerNeck(nn.Module): + def __init__(self, + in_dim, + d_dim=256, + downsample=True, + has_pe=True, + has_norm=True, + class_token=True, + num_encoder_layers=3, + dim_feedforward=512, + drop_rate=0.1 + ): + super().__init__() + self.input_proj = nn.Conv2d(in_dim, d_dim, kernel_size=1) + self.downsample = downsample + + if self.downsample: + self.sampler = nn.Conv2d(d_dim, d_dim, kernel_size=3, stride=2, padding=1) + + encoder_layer = TransformerEncoderLayer( + d_model=d_dim, + nhead=8, + dim_feedforward=dim_feedforward, + dropout=drop_rate, + activation='gelu', + batch_first=True + ) + if has_norm: + encoder_norm = LayerNorm(d_dim) + else: + encoder_norm = None + self.trans_encoder = TransformerEncoder(encoder_layer, num_encoder_layers, encoder_norm) + + if self.downsample: + self.uplayer = nn.Sequential( + nn.Conv2d(d_dim, d_dim*4, kernel_size=3, padding=1), + nn.PixelShuffle(2), + nn.Conv2d(d_dim, d_dim, kernel_size=3, padding=1) + ) + + # for p in self.parameters(): + # if p.dim() > 1: + # xavier_uniform_(p) + + self.d_dim = d_dim + self.class_token = class_token + self.has_pe = has_pe + + if self.class_token: + self.cls_token = nn.Parameter(torch.zeros(1, 1, self.d_dim)) + + if self.has_pe: + self.pos_embed = nn.Parameter( + torch.randn(1, d_dim, 24, 24) * 0.02 + ) + self.drop_after_pos = nn.Dropout(p=drop_rate) + + def forward(self, x): + # x: List + x = [self.input_proj(x_tmp) for x_tmp in x] + if self.downsample: + x[0] = self.sampler(x[0]) + B, C, H, W = x[0].shape + + if self.has_pe: + assert W == self.pos_embed.shape[-1] + x_with_pe = [] + for x_tmp in x: + b_tmp, c_tmp, h_tmp, w_tmp = x_tmp.shape + pe = nn.functional.interpolate(self.pos_embed, size=[h_tmp, w_tmp], mode='bicubic', align_corners=True) + x_tmp = x_tmp + pe + x_with_pe.append(x_tmp) + else: + x_with_pe = x + + x_flatten = [] + for x in x_with_pe: + x = rearrange(x, 'b c h w -> b (h w) c') + x_flatten.append(x) + x_flatten = torch.cat(x_flatten, dim=1) + + if self.has_pe: + x_flatten = self.drop_after_pos(x_flatten) + + if self.class_token: + cls_tokens = self.cls_token.expand(B, -1, -1) + x = torch.cat((cls_tokens, x_flatten), dim=1) + else: + x = x_flatten + + x = self.trans_encoder(x) + + if self.class_token: + global_content = x[:, 0] + func_map = x[:, 1:(1 + H * W), :] + else: + global_content = x.mean(dim=1) # global pool without cls token + func_map = x[:, :(H * W), :] + + func_map = rearrange(func_map, 'b (h w) c -> b c h w', h=H) + if self.downsample: + func_map = self.uplayer(func_map) + return global_content, func_map diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..b991e99582ccd7674a094aec353b460280c3402d --- /dev/null +++ b/requirements.txt @@ -0,0 +1,8 @@ +tensorboardX +matplotlib +einops +pyyaml +opencv-python +pandas +scikit-image +tqdm \ No newline at end of file diff --git a/scripts/resize.py b/scripts/resize.py new file mode 100644 index 0000000000000000000000000000000000000000..be41cb906c7139533c001b8a1b91b9f2b2b3a1b4 --- /dev/null +++ b/scripts/resize.py @@ -0,0 +1,18 @@ +import os +from PIL import Image +from tqdm import tqdm + +inp = r'H:\DataSet\SceneCls\UCMerced_LandUse\UCMerced_LandUse\Images' + +for size in [256, 128, 64, 32]: + if size == 256: + inp = './data1024x1024' + else: + inp = './256' + print(size) + os.mkdir(str(size)) + filenames = os.listdir(inp) + for filename in tqdm(filenames): + Image.open(os.path.join(inp, filename)) \ + .resize((size, size), Image.BICUBIC) \ + .save(os.path.join('.', str(size), filename.split('.')[0] + '.png')) diff --git a/scripts/test_script.py b/scripts/test_script.py new file mode 100644 index 0000000000000000000000000000000000000000..c332b7a2705ffaeb214d67fd1841453fc3cc55e4 --- /dev/null +++ b/scripts/test_script.py @@ -0,0 +1,40 @@ +import os + +# os.system('cd ..') +exp = 'EXP20221219_3' + +# for cp in ['epoch-best.pth', 'epoch-last.pth'] + [f'epoch-{x}.pth' for x in range(300, 4000, 300)]: +for cp in ['epoch-best.pth', 'epoch-last.pth']: +# for cp in ['epoch-last.pth']: +# for cp in ['epoch-best.pth']: +# for cp in ['epoch-300.pth']: + for scale_ratio in [2, 2.5, 3, 3.5, 4.0, 6, 8, 10]: + # for scale_ratio in [4]: + print(cp, ' ', scale_ratio) + + # os.system(f'CUDA_DEVICES_VISIBLE=0 python test_interpolate_sr.py ' + # f'--config configs/test_interpolate.yaml ' + # f'--scale_ratio {scale_ratio}') + + # os.system(f'CUDA_VISIBLE_DEVICES=1 python test_inr_liif_metasr_aliif.py ' + # f'--config configs/baselines/test_INR_liif_metasr_aliif.yaml ' + # f'--model checkpoints/{exp}/{cp} ' + # f'--scale_ratio {scale_ratio}') + + # os.system(f'CUDA_VISIBLE_DEVICES=7 python test_inr_mysr.py ' + # f'--config configs/test_UC_INR_mysr.yaml ' + # f'--model checkpoints/{exp}/{cp} ' + # f'--scale_ratio {scale_ratio}') + + os.system(f'CUDA_VISIBLE_DEVICES=1 python test_inr_diinn_arbrcan_sadnarc_funsr_overnet.py ' + f'--config configs/test_INR_diinn_arbrcan_funsr_overnet.yaml ' + f'--model checkpoints/{exp}/{cp} ' + f'--scale_ratio {scale_ratio} ' + f'--dataset_name AID') + + # os.system(f'CUDA_DEVICES_VISIBLE=0 python test_cnn_sr.py ' + # f'--config configs/test_CNN.yaml ' + # f'--model checkpoints/{exp}/{cp} ' + # f'--scale_ratio {scale_ratio}') + + print('*' * 30) diff --git a/scripts/train_multi_gpus_with_ddp.py b/scripts/train_multi_gpus_with_ddp.py new file mode 100644 index 0000000000000000000000000000000000000000..9acd27cda70f2605795601f111006a8603a4f512 --- /dev/null +++ b/scripts/train_multi_gpus_with_ddp.py @@ -0,0 +1,11 @@ +import os +import sys +# sys.path.append(sys.path[0]+'/../') + +os.system( + "CUDA_VISIBLE_DEVICES=1,2,3,4,5,6,7 " + "torchrun " + "--nnodes=1 " + "--nproc_per_node=6 " + "train_inr_funsr_ddp.py" +) \ No newline at end of file diff --git a/test_cnn_sr.py b/test_cnn_sr.py new file mode 100644 index 0000000000000000000000000000000000000000..4998928bda622b95bd41a2edc247f6de07a79b7f --- /dev/null +++ b/test_cnn_sr.py @@ -0,0 +1,204 @@ +import argparse +import json +import os +import math +from functools import partial + +import cv2 +import numpy as np +import yaml +import torch +from einops import rearrange +from torch.utils.data import DataLoader +from tqdm import tqdm + +import datasets +import models +import utils + + +device = 'cuda:0' if torch.cuda.is_available() else 'cpu' + +def batched_predict(model, img, bsize): + with torch.no_grad(): + pred = model(img) + return pred + + +def eval_psnr(loader, class_names, model, + data_norm=None, eval_type=None, save_fig=False, + scale_ratio=1, save_path=None, verbose=False, crop_border=4, + cal_metrics=True,): + crop_border = int(crop_border) if crop_border else crop_border + print('crop border: ', crop_border) + model.eval() + + if data_norm is None: + data_norm = { + 'img': {'sub': [0], 'div': [1]}, + 'gt': {'sub': [0], 'div': [1]} + } + t = data_norm['img'] + img_sub = torch.FloatTensor(t['sub']).view(1, -1, 1, 1).to(device) + img_div = torch.FloatTensor(t['div']).view(1, -1, 1, 1).to(device) + t = data_norm['gt'] + gt_sub = torch.FloatTensor(t['sub']).view(1, -1, 1, 1).to(device) + gt_div = torch.FloatTensor(t['div']).view(1, -1, 1, 1).to(device) + + if eval_type is None: + metric_fn = [utils.calculate_psnr_pt, utils.calculate_ssim_pt] + elif eval_type == 'psnr+ssim': + metric_fn = [utils.calculate_psnr_pt, utils.calculate_ssim_pt] + elif eval_type.startswith('div2k'): + scale = int(eval_type.split('-')[1]) + metric_fn = partial(utils.calc_psnr, dataset='div2k', scale=scale) + elif eval_type.startswith('benchmark'): + scale = int(eval_type.split('-')[1]) + metric_fn = partial(utils.calc_psnr, dataset='benchmark', scale=scale) + else: + raise NotImplementedError + + val_res_psnr = utils.Averager(class_names) + val_res_ssim = utils.Averager(class_names) + + pbar = tqdm(loader, leave=False, desc='val') + for batch in pbar: + for k, v in batch.items(): + if torch.is_tensor(v): + batch[k] = v.to(device) + + img = (batch['img'] - img_sub) / img_div + with torch.no_grad(): + pred = model(img, batch['gt'].shape[-2:]) + if isinstance(pred, list): + pred = pred[-1] + pred = pred * gt_div + gt_sub + + if cal_metrics: + res_psnr = metric_fn[0]( + pred, + batch['gt'], + crop_border=crop_border + ) + res_ssim = metric_fn[1]( + pred, + batch['gt'], + crop_border=crop_border + ) + else: + res_psnr = torch.ones(len(pred)) + res_ssim = torch.ones(len(pred)) + + file_names = batch.get('filename', None) + if file_names is not None and save_fig: + for idx in range(len(batch['img'])): + ori_img = batch['img'][idx].cpu().numpy() * 255 + ori_img = np.clip(ori_img, a_min=0, a_max=255) + ori_img = ori_img.astype(np.uint8) + ori_img = rearrange(ori_img, 'C H W -> H W C') + + pred_img = pred[idx].cpu().numpy() * 255 + pred_img = np.clip(pred_img, a_min=0, a_max=255) + pred_img = pred_img.astype(np.uint8) + pred_img = rearrange(pred_img, 'C H W -> H W C') + + gt_img = batch['gt'][idx].cpu().numpy() * 255 + gt_img = np.clip(gt_img, a_min=0, a_max=255) + gt_img = gt_img.astype(np.uint8) + gt_img = rearrange(gt_img, 'C H W -> H W C') + + psnr = res_psnr[idx].cpu().numpy() + ssim = res_ssim[idx].cpu().numpy() + ori_file_name = f'{save_path}/{file_names[idx]}_Ori.png' + cv2.imwrite(ori_file_name, ori_img) + pred_file_name = f'{save_path}/{file_names[idx]}_{scale_ratio}X_{psnr:.2f}_{ssim:.4f}.png' + cv2.imwrite(pred_file_name, pred_img) + gt_file_name = f'{save_path}/{file_names[idx]}_GT.png' + cv2.imwrite(gt_file_name, gt_img) + + val_res_psnr.add(batch['class_name'], res_psnr) + val_res_ssim.add(batch['class_name'], res_ssim) + + if verbose: + pbar.set_description( + 'val psnr: {:.4f} ssim: {:.4f}'.format(val_res_psnr.item()['all'], val_res_ssim.item()['all'])) + + return val_res_psnr.item(), val_res_ssim.item() + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('--config', default='configs/test_CNN.yaml') + parser.add_argument('--model', default='checkpoints/EXP20220610_5/epoch-best.pth') + parser.add_argument('--scale_ratio', default=4, type=float) + parser.add_argument('--save_fig', default=False, type=bool) + parser.add_argument('--save_path', default='tmp', type=str) + parser.add_argument('--cal_metrics', default=True, type=bool) + parser.add_argument('--return_class_metrics', default=False, type=bool) + parser.add_argument('--dataset_name', default='UC', type=str) + args = parser.parse_args() + + with open(args.config, 'r') as f: + config = yaml.load(f, Loader=yaml.FullLoader) + root_split_file = {'UC': + { + 'root_path': '/data/kyanchen/datasets/UC/256', + 'split_file': 'data_split/UC_split.json' + }, + 'AID': + { + 'root_path': '/data/kyanchen/datasets/AID', + 'split_file': 'data_split/AID_split.json' + } + } + config['test_dataset']['dataset']['args']['root_path'] = root_split_file[args.dataset_name]['root_path'] + config['test_dataset']['dataset']['args']['split_file'] = root_split_file[args.dataset_name]['split_file'] + + config['test_dataset']['wrapper']['args']['scale_ratio'] = args.scale_ratio + + spec = config['test_dataset'] + dataset = datasets.make(spec['dataset']) + dataset = datasets.make(spec['wrapper'], args={'dataset': dataset}) + loader = DataLoader(dataset, batch_size=spec['batch_size'], num_workers=0, pin_memory=True, shuffle=False, + drop_last=False) + if not os.path.exists(args.model): + assert NameError + model_spec = torch.load(args.model)['model'] + print(model_spec['args']) + model = models.make(model_spec, load_sd=True).to(device) + + file_names = json.load(open(config['test_dataset']['dataset']['args']['split_file']))['test'] + class_names = list(set([os.path.basename(os.path.dirname(x)) for x in file_names])) + + crop_border = config['test_dataset']['wrapper']['args']['scale_ratio'] + 5 + dataset_name = os.path.basename(config['test_dataset']['dataset']['args']['split_file']).split('_')[0] + max_scale = {'UC': 5, 'AID': 12} + if args.scale_ratio > max_scale[dataset_name]: + crop_border = int((args.scale_ratio - max_scale[dataset_name]) / 2 * 48) + + if args.save_fig: + os.makedirs(args.save_path, exist_ok=True) + + res = eval_psnr( + loader, class_names, model, + data_norm=config.get('data_norm'), + eval_type=config.get('eval_type'), + crop_border=crop_border, + verbose=True, + save_fig=args.save_fig, + scale_ratio=args.scale_ratio, + save_path=args.save_path, + cal_metrics=args.cal_metrics + ) + + if args.return_class_metrics: + keys = list(res[0].keys()) + keys.sort() + print('psnr') + for k in keys: + print(f'{k}: {res[0][k]:0.2f}') + print('ssim') + for k in keys: + print(f'{k}: {res[1][k]:0.4f}') + print(f'psnr: {res[0]["all"]:0.2f}') + print(f'ssim: {res[1]["all"]:0.4f}') diff --git a/test_inr_diinn_arbrcan_sadnarc_funsr_overnet.py b/test_inr_diinn_arbrcan_sadnarc_funsr_overnet.py new file mode 100644 index 0000000000000000000000000000000000000000..fa5ce80a910e26c23c14d66e37a46b852665322c --- /dev/null +++ b/test_inr_diinn_arbrcan_sadnarc_funsr_overnet.py @@ -0,0 +1,287 @@ +import argparse +import json +import os + +import math +from functools import partial +import seaborn as sns +import cv2.dnn +import numpy as np +import yaml +import torch +from einops import rearrange +from matplotlib import pyplot as plt +from torch.utils.data import DataLoader +from tqdm import tqdm + +import datasets +import models +import utils + +device = 'cuda:0' if torch.cuda.is_available() else 'cpu' + +def batched_predict(model, img, coord, bsize): + with torch.no_grad(): + pred = model(img, coord) + return pred + + +def eval_psnr(loader, class_names, model, + data_norm=None, eval_type=None, save_fig=False, save_featmap=False, + scale_ratio=1, save_path=None, verbose=False, crop_border=4, + cal_metrics=True, + ): + crop_border = int(crop_border) if crop_border else crop_border + print('crop border: ', crop_border) + model.eval() + + if data_norm is None: + data_norm = { + 'img': {'sub': [0], 'div': [1]}, + 'gt': {'sub': [0], 'div': [1]} + } + t = data_norm['img'] + img_sub = torch.FloatTensor(t['sub']).view(1, -1, 1, 1).to(device) + img_div = torch.FloatTensor(t['div']).view(1, -1, 1, 1).to(device) + t = data_norm['gt'] + gt_sub = torch.FloatTensor(t['sub']).view(1, -1, 1, 1).to(device) + gt_div = torch.FloatTensor(t['div']).view(1, -1, 1, 1).to(device) + + if eval_type is None: + metric_fn = [utils.calculate_psnr_pt, utils.calculate_ssim_pt] + elif eval_type == 'psnr+ssim': + metric_fn = [utils.calculate_psnr_pt, utils.calculate_ssim_pt] + elif eval_type.startswith('div2k'): + scale = int(eval_type.split('-')[1]) + metric_fn = partial(utils.calc_psnr, dataset='div2k', scale=scale) + elif eval_type.startswith('benchmark'): + scale = int(eval_type.split('-')[1]) + metric_fn = partial(utils.calc_psnr, dataset='benchmark', scale=scale) + else: + raise NotImplementedError + + val_res_psnr = utils.Averager(class_names) + val_res_ssim = utils.Averager(class_names) + + pbar = tqdm(loader, leave=False, desc='val') + for batch in pbar: + for k, v in batch.items(): + if torch.is_tensor(v): + batch[k] = v.to(device) + + img = (batch['img'] - img_sub) / img_div + with torch.no_grad(): + preds = model(img, batch['gt'].shape[-2:]) + if save_featmap: + pred = preds[0][-1] + returned_featmap = preds[1] + assert returned_featmap.size(1) == 6 + else: + if isinstance(preds, list): + pred = preds[-1] + # import pdb + # pdb.set_trace() + pred = pred * gt_div + gt_sub + # if eval_type is not None: # reshape for shaving-eval + # ih, iw = batch['img'].shape[-2:] + # s = math.sqrt(batch['coord'].shape[1] / (ih * iw)) + # if s > 1: + # shape = [batch['img'].shape[0], round(ih * s), round(iw * s), 3] + # else: + # shape = [batch['img'].shape[0], 32, batch['coord'].shape[1]//32, 3] + # + # pred = pred.view(*shape) \ + # .permute(0, 3, 1, 2).contiguous() + # batch['gt'] = batch['gt'].view(*shape) \ + # .permute(0, 3, 1, 2).contiguous() + + # if crop_border is not None: + # h = math.sqrt(pred.shape[1]) + # shape = [img.shape[0], round(h), round(h), 3] + # pred = pred.view(*shape).permute(0, 3, 1, 2).contiguous() + # batch['gt'] = batch['gt'].view(*shape).permute(0, 3, 1, 2).contiguous() + # else: + # pred = pred.permute(0, 2, 1).contiguous() # B 3 N + # batch['gt'] = batch['gt'].permute(0, 2, 1).contiguous() + + # import pdb + # pdb.set_trace() + + if cal_metrics: + res_psnr = metric_fn[0]( + pred, + batch['gt'], + crop_border=crop_border + ) + res_ssim = metric_fn[1]( + pred, + batch['gt'], + crop_border=crop_border + ) + else: + res_psnr = torch.ones(len(pred)) + res_ssim = torch.ones(len(pred)) + + file_names = batch.get('filename', None) + if file_names is not None and save_featmap: + for idx in range(len(batch['img'])): + ori_img = batch['img'][idx].cpu().numpy() * 255 + ori_img = np.clip(ori_img, a_min=0, a_max=255) + ori_img = ori_img.astype(np.uint8) + ori_img = rearrange(ori_img, 'C H W -> H W C') + + pred_img = pred[idx].cpu().numpy() * 255 + pred_img = np.clip(pred_img, a_min=0, a_max=255) + pred_img = pred_img.astype(np.uint8) + pred_img = rearrange(pred_img, 'C H W -> H W C') + + is_normalize = True + f_tensors = returned_featmap[idx] + for idx_f in range(len(f_tensors)): + f_tensor = f_tensors[idx_f] + if is_normalize: + # normalize the features / feature maps + f_tensor = torch.sigmoid(f_tensor) + f_tensor = f_tensor.detach().cpu().numpy() + # for better visualization, you can normalize the feature heatmap + f_tensor = (f_tensor - np.min(f_tensor)) / (np.max(f_tensor) - np.min(f_tensor)) + # f_tensor = (f_tensor - np.min(f_tensor)) / (np.max(f_tensor) - np.min(f_tensor)) + sns.heatmap(f_tensor, vmin=0, vmax=1, cmap="jet", center=0.5) + plt.axis('off') + plt.xticks([]) + plt.yticks([]) + # plt.imshow(heatmap, cmap='YlGnBu', vmin=0, vmax=1) + # plt.show() + ori_file_name = f'{save_path}/{file_names[idx]}_{idx_f}.png' + plt.savefig(ori_file_name, dpi=600) + plt.close() + + gt_img = batch['gt'][idx].cpu().numpy() * 255 + gt_img = np.clip(gt_img, a_min=0, a_max=255) + gt_img = gt_img.astype(np.uint8) + gt_img = rearrange(gt_img, 'C H W -> H W C') + + psnr = res_psnr[idx].cpu().numpy() + ssim = res_ssim[idx].cpu().numpy() + ori_file_name = f'{save_path}/{file_names[idx]}_Ori.png' + cv2.imwrite(ori_file_name, ori_img) + pred_file_name = f'{save_path}/{file_names[idx]}_{scale_ratio}X_{psnr:.2f}_{ssim:.4f}.png' + cv2.imwrite(pred_file_name, pred_img) + gt_file_name = f'{save_path}/{file_names[idx]}_GT.png' + cv2.imwrite(gt_file_name, gt_img) + # import pdb + # pdb.set_trace() + + if file_names is not None and save_fig: + for idx in range(len(batch['img'])): + ori_img = batch['img'][idx].cpu().numpy() * 255 + ori_img = np.clip(ori_img, a_min=0, a_max=255) + ori_img = ori_img.astype(np.uint8) + ori_img = rearrange(ori_img, 'C H W -> H W C') + + pred_img = pred[idx].cpu().numpy() * 255 + pred_img = np.clip(pred_img, a_min=0, a_max=255) + pred_img = pred_img.astype(np.uint8) + pred_img = rearrange(pred_img, 'C H W -> H W C') + + gt_img = batch['gt'][idx].cpu().numpy() * 255 + gt_img = np.clip(gt_img, a_min=0, a_max=255) + gt_img = gt_img.astype(np.uint8) + gt_img = rearrange(gt_img, 'C H W -> H W C') + + psnr = res_psnr[idx].cpu().numpy() + ssim = res_ssim[idx].cpu().numpy() + ori_file_name = f'{save_path}/{file_names[idx]}_Ori.png' + cv2.imwrite(ori_file_name, ori_img) + pred_file_name = f'{save_path}/{file_names[idx]}_{scale_ratio}X_{psnr:.2f}_{ssim:.4f}.png' + cv2.imwrite(pred_file_name, pred_img) + gt_file_name = f'{save_path}/{file_names[idx]}_GT.png' + cv2.imwrite(gt_file_name, gt_img) + + val_res_psnr.add(batch['class_name'], res_psnr) + val_res_ssim.add(batch['class_name'], res_ssim) + + if verbose: + pbar.set_description( + 'val psnr: {:.4f} ssim: {:.4f}'.format(val_res_psnr.item()['all'], val_res_ssim.item()['all'])) + + return val_res_psnr.item(), val_res_ssim.item() + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('--config', default='configs/test_UC_INR_mysr.yaml') + parser.add_argument('--model', default='checkpoints/EXP20220610_5/epoch-best.pth') + parser.add_argument('--scale_ratio', default=4, type=float) + parser.add_argument('--save_fig', default=False, type=bool) + parser.add_argument('--save_featmap', default=False, type=bool) + parser.add_argument('--save_path', default='tmp', type=str) + parser.add_argument('--cal_metrics', default=True, type=bool) + parser.add_argument('--return_class_metrics', default=False, type=bool) + parser.add_argument('--dataset_name', default='UC', type=str) + args = parser.parse_args() + + with open(args.config, 'r') as f: + config = yaml.load(f, Loader=yaml.FullLoader) + root_split_file = {'UC': + { + 'root_path': '/Users/kyanchen/Documents/UC/256', + 'split_file': '/Users/kyanchen/My_Code/sr/data_split/UC_split.json' + }, + 'AID': + { + 'root_path': '/data/kyanchen/datasets/AID', + 'split_file': 'data_split/AID_split.json' + } + } + config['test_dataset']['dataset']['args']['root_path'] = root_split_file[args.dataset_name]['root_path'] + config['test_dataset']['dataset']['args']['split_file'] = root_split_file[args.dataset_name]['split_file'] + + config['test_dataset']['wrapper']['args']['scale_ratio'] = args.scale_ratio + + spec = config['test_dataset'] + dataset = datasets.make(spec['dataset']) + dataset = datasets.make(spec['wrapper'], args={'dataset': dataset}) + loader = DataLoader(dataset, batch_size=spec['batch_size'], num_workers=0, pin_memory=True, shuffle=False, drop_last=False) + if not os.path.exists(args.model): + assert NameError + model_spec = torch.load(args.model, map_location='cpu')['model'] + print(model_spec['args']) + model = models.make(model_spec, load_sd=True).to(device) + + file_names = json.load(open(config['test_dataset']['dataset']['args']['split_file']))['test'] + class_names = list(set([os.path.basename(os.path.dirname(x)) for x in file_names])) + + crop_border = config['test_dataset']['wrapper']['args']['scale_ratio'] + 5 + dataset_name = os.path.basename(config['test_dataset']['dataset']['args']['split_file']).split('_')[0] + max_scale = {'UC': 5, 'AID': 12} + if args.scale_ratio > max_scale[dataset_name]: + crop_border = int((args.scale_ratio - max_scale[dataset_name]) / 2 * 48) + + if args.save_fig or args.save_featmap: + os.makedirs(args.save_path, exist_ok=True) + + res = eval_psnr( + loader, class_names, model, + data_norm=config.get('data_norm'), + eval_type=config.get('eval_type'), + crop_border=crop_border, + verbose=True, + save_fig=args.save_fig, + save_featmap=args.save_featmap, + scale_ratio=args.scale_ratio, + save_path=args.save_path, + cal_metrics=args.cal_metrics + ) + + if args.return_class_metrics: + keys = list(res[0].keys()) + keys.sort() + print('psnr') + for k in keys: + print(f'{k}: {res[0][k]:0.2f}') + print('ssim') + for k in keys: + print(f'{k}: {res[1][k]:0.4f}') + print(f'psnr: {res[0]["all"]:0.2f}') + print(f'ssim: {res[1]["all"]:0.4f}') diff --git a/test_inr_liif_metasr_aliif.py b/test_inr_liif_metasr_aliif.py new file mode 100644 index 0000000000000000000000000000000000000000..e8c471fc58c54e710e5129ad88a0cf103f0de72b --- /dev/null +++ b/test_inr_liif_metasr_aliif.py @@ -0,0 +1,216 @@ +import argparse +import json +import os + +import math +from functools import partial + +import cv2 +import numpy as np +import yaml +import torch +from einops import rearrange +from torch.utils.data import DataLoader +from tqdm import tqdm + +import datasets +import models +import utils + +device = 'cuda:0' if torch.cuda.is_available() else 'cpu' + +def batched_predict(model, inp, coord, bsize): + with torch.no_grad(): + pred = model(inp, coord) + return pred + + +def eval_psnr(loader, class_names, model, + data_norm=None, eval_type=None, save_fig=False, + scale_ratio=1, save_path=None, verbose=False, crop_border=4, + cal_metrics=True, + ): + crop_border = int(crop_border) if crop_border else crop_border + print('crop border: ', crop_border) + model.eval() + + if data_norm is None: + data_norm = { + 'inp': {'sub': [0], 'div': [1]}, + 'gt': {'sub': [0], 'div': [1]} + } + t = data_norm['inp'] + inp_sub = torch.FloatTensor(t['sub']).view(1, -1, 1, 1).to(device) + inp_div = torch.FloatTensor(t['div']).view(1, -1, 1, 1).to(device) + t = data_norm['gt'] + gt_sub = torch.FloatTensor(t['sub']).view(1, 1, -1).to(device) + gt_div = torch.FloatTensor(t['div']).view(1, 1, -1).to(device) + + if eval_type is None: + metric_fn = [utils.calculate_psnr_pt, utils.calculate_ssim_pt] + elif eval_type == 'psnr+ssim': + metric_fn = [utils.calculate_psnr_pt, utils.calculate_ssim_pt] + elif eval_type.startswith('div2k'): + scale = int(eval_type.split('-')[1]) + metric_fn = partial(utils.calc_psnr, dataset='div2k', scale=scale) + elif eval_type.startswith('benchmark'): + scale = int(eval_type.split('-')[1]) + metric_fn = partial(utils.calc_psnr, dataset='benchmark', scale=scale) + else: + raise NotImplementedError + + val_res_psnr = utils.Averager(class_names) + val_res_ssim = utils.Averager(class_names) + + pbar = tqdm(loader, leave=False, desc='val') + for batch in pbar: + for k, v in batch.items(): + if torch.is_tensor(v): + batch[k] = v.to(device) + + inp = (batch['inp'] - inp_sub) / inp_div + + with torch.no_grad(): + pred = model(inp, batch['coord'], batch['cell']) + pred = pred * gt_div + gt_sub + + if eval_type is not None: # reshape for shaving-eval + ih, iw = batch['inp'].shape[-2:] + s = math.sqrt(batch['coord'].shape[1] / (ih * iw)) + if s > 1: + shape = [batch['inp'].shape[0], round(ih * s), round(iw * s), 3] + else: + shape = [batch['inp'].shape[0], 32, batch['coord'].shape[1]//32, 3] + + pred = pred.view(*shape) \ + .permute(0, 3, 1, 2).contiguous() + batch['gt'] = batch['gt'].view(*shape) \ + .permute(0, 3, 1, 2).contiguous() + if cal_metrics: + res_psnr = metric_fn[0]( + pred, + batch['gt'], + crop_border=crop_border + ) + res_ssim = metric_fn[1]( + pred, + batch['gt'], + crop_border=crop_border + ) + else: + res_psnr = torch.ones(len(pred)) + res_ssim = torch.ones(len(pred)) + + file_names = batch.get('filename', None) + if file_names is not None and save_fig: + for idx in range(len(batch['inp'])): + ori_img = batch['inp'][idx].cpu().numpy() * 255 + ori_img = np.clip(ori_img, a_min=0, a_max=255) + ori_img = ori_img.astype(np.uint8) + ori_img = rearrange(ori_img, 'C H W -> H W C') + + pred_img = pred[idx].cpu().numpy() * 255 + pred_img = np.clip(pred_img, a_min=0, a_max=255) + pred_img = pred_img.astype(np.uint8) + pred_img = rearrange(pred_img, 'C H W -> H W C') + + gt_img = batch['gt'][idx].cpu().numpy() * 255 + gt_img = np.clip(gt_img, a_min=0, a_max=255) + gt_img = gt_img.astype(np.uint8) + gt_img = rearrange(gt_img, 'C H W -> H W C') + + psnr = res_psnr[idx].cpu().numpy() + ssim = res_ssim[idx].cpu().numpy() + ori_file_name = f'{save_path}/{file_names[idx]}_Ori.png' + cv2.imwrite(ori_file_name, ori_img) + pred_file_name = f'{save_path}/{file_names[idx]}_{scale_ratio}X_{psnr:.2f}_{ssim:.4f}.png' + cv2.imwrite(pred_file_name, pred_img) + gt_file_name = f'{save_path}/{file_names[idx]}_GT.png' + cv2.imwrite(gt_file_name, gt_img) + + val_res_psnr.add(batch['class_name'], res_psnr) + val_res_ssim.add(batch['class_name'], res_ssim) + + if verbose: + pbar.set_description( + 'val psnr: {:.4f} ssim: {:.4f}'.format(val_res_psnr.item()['all'], val_res_ssim.item()['all'])) + + return val_res_psnr.item(), val_res_ssim.item() + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('--config', default='configs/test_INR_mysr.yaml') + parser.add_argument('--model', default='checkpoints/EXP20220610_5/epoch-best.pth') + parser.add_argument('--scale_ratio', default=4, type=float) + parser.add_argument('--save_fig', default=False, type=bool) + parser.add_argument('--save_path', default='tmp', type=str) + parser.add_argument('--cal_metrics', default=True, type=bool) + parser.add_argument('--return_class_metrics', default=False, type=bool) + parser.add_argument('--dataset_name', default='UC', type=str) + args = parser.parse_args() + + with open(args.config, 'r') as f: + config = yaml.load(f, Loader=yaml.FullLoader) + root_split_file = {'UC': + { + 'root_path': '/data/kyanchen/datasets/UC/256', + 'split_file': 'data_split/UC_split.json' + }, + 'AID': + { + 'root_path': '/data/kyanchen/datasets/AID', + 'split_file': 'data_split/AID_split.json' + } + } + config['test_dataset']['dataset']['args']['root_path'] = root_split_file[args.dataset_name]['root_path'] + config['test_dataset']['dataset']['args']['split_file'] = root_split_file[args.dataset_name]['split_file'] + + config['test_dataset']['wrapper']['args']['scale_ratio'] = args.scale_ratio + + spec = config['test_dataset'] + dataset = datasets.make(spec['dataset']) + dataset = datasets.make(spec['wrapper'], args={'dataset': dataset}) + loader = DataLoader(dataset, batch_size=spec['batch_size'], num_workers=0, pin_memory=True, shuffle=False, + drop_last=False) + if not os.path.exists(args.model): + assert NameError + model_spec = torch.load(args.model)['model'] + print(model_spec['args']) + model = models.make(model_spec, load_sd=True).to(device) + + file_names = json.load(open(config['test_dataset']['dataset']['args']['split_file']))['test'] + class_names = list(set([os.path.basename(os.path.dirname(x)) for x in file_names])) + + crop_border = config['test_dataset']['wrapper']['args']['scale_ratio'] + 5 + dataset_name = os.path.basename(config['test_dataset']['dataset']['args']['split_file']).split('_')[0] + max_scale = {'UC': 5, 'AID': 12} + if args.scale_ratio > max_scale[dataset_name]: + crop_border = int((args.scale_ratio - max_scale[dataset_name]) / 2 * 48) + + if args.save_fig: + os.makedirs(args.save_path, exist_ok=True) + + res = eval_psnr( + loader, class_names, model, + data_norm=config.get('data_norm'), + eval_type=config.get('eval_type'), + crop_border=crop_border, + verbose=True, + save_fig=args.save_fig, + scale_ratio=args.scale_ratio, + save_path=args.save_path, + cal_metrics=args.cal_metrics + ) + + if args.return_class_metrics: + keys = list(res[0].keys()) + keys.sort() + print('psnr') + for k in keys: + print(f'{k}: {res[0][k]:0.2f}') + print('ssim') + for k in keys: + print(f'{k}: {res[1][k]:0.4f}') + print(f'psnr: {res[0]["all"]:0.2f}') + print(f'ssim: {res[1]["all"]:0.4f}') diff --git a/test_inr_mysr.py b/test_inr_mysr.py new file mode 100644 index 0000000000000000000000000000000000000000..c4b08d90901d7826b1a01fc39df0526118aecb78 --- /dev/null +++ b/test_inr_mysr.py @@ -0,0 +1,168 @@ +import argparse +import json +import os + +import math +from functools import partial + +import yaml +import torch +from torch.utils.data import DataLoader +from tqdm import tqdm + +import datasets +import models +import utils + +device = 'cuda:0' if torch.cuda.is_available() else 'cpu' + +def batched_predict(model, inp, coord, bsize): + with torch.no_grad(): + pred = model(inp, coord) + return pred + + +def eval_psnr(loader, class_names, model, data_norm=None, eval_type=None, eval_bsize=None, verbose=False, crop_border=4): + crop_border = int(crop_border) if crop_border else crop_border + print('crop border: ', crop_border) + model.eval() + + if data_norm is None: + data_norm = { + 'inp': {'sub': [0], 'div': [1]}, + 'gt': {'sub': [0], 'div': [1]} + } + t = data_norm['inp'] + inp_sub = torch.FloatTensor(t['sub']).view(1, -1, 1, 1).to(device) + inp_div = torch.FloatTensor(t['div']).view(1, -1, 1, 1).to(device) + t = data_norm['gt'] + gt_sub = torch.FloatTensor(t['sub']).view(1, 1, -1).to(device) + gt_div = torch.FloatTensor(t['div']).view(1, 1, -1).to(device) + + if eval_type is None: + metric_fn = [utils.calculate_psnr_pt, utils.calculate_ssim_pt] + elif eval_type == 'psnr+ssim': + metric_fn = [utils.calculate_psnr_pt, utils.calculate_ssim_pt] + elif eval_type.startswith('div2k'): + scale = int(eval_type.split('-')[1]) + metric_fn = partial(utils.calc_psnr, dataset='div2k', scale=scale) + elif eval_type.startswith('benchmark'): + scale = int(eval_type.split('-')[1]) + metric_fn = partial(utils.calc_psnr, dataset='benchmark', scale=scale) + else: + raise NotImplementedError + + val_res_psnr = utils.Averager(class_names) + val_res_ssim = utils.Averager(class_names) + + pbar = tqdm(loader, leave=False, desc='val') + for batch in pbar: + for k, v in batch.items(): + if torch.is_tensor(v): + batch[k] = v.to(device) + + inp = (batch['inp'] - inp_sub) / inp_div + # import pdb + # pdb.set_trace() + if eval_bsize is None: + with torch.no_grad(): + scale_ratios = batch.get('scale_ratio', None) + if scale_ratios is None: + pred = model(inp, batch['coord'])[-1] + else: + # scale_ratios = (scale_ratios - gt_sub) / gt_div + pred = model(inp, batch['coord'], scale_ratios)[-1] + else: + pred = batched_predict(model, inp, batch['coord'], eval_bsize) + pred = pred * gt_div + gt_sub + + if eval_type is not None: # reshape for shaving-eval + ih, iw = batch['inp'].shape[-2:] + s = math.sqrt(batch['coord'].shape[1] / (ih * iw)) + if s > 1: + shape = [batch['inp'].shape[0], round(ih * s), round(iw * s), 3] + else: + shape = [batch['inp'].shape[0], 32, batch['coord'].shape[1]//32, 3] + + pred = pred.view(*shape) \ + .permute(0, 3, 1, 2).contiguous() + batch['gt'] = batch['gt'].view(*shape) \ + .permute(0, 3, 1, 2).contiguous() + + # if crop_border is not None: + # h = math.sqrt(pred.shape[1]) + # shape = [inp.shape[0], round(h), round(h), 3] + # pred = pred.view(*shape).permute(0, 3, 1, 2).contiguous() + # batch['gt'] = batch['gt'].view(*shape).permute(0, 3, 1, 2).contiguous() + # else: + # pred = pred.permute(0, 2, 1).contiguous() # B 3 N + # batch['gt'] = batch['gt'].permute(0, 2, 1).contiguous() + + res_psnr = metric_fn[0]( + pred, + batch['gt'], + crop_border=crop_border + ) + res_ssim = metric_fn[1]( + pred, + batch['gt'], + crop_border=crop_border + ) + + val_res_psnr.add(batch['class_name'], res_psnr) + val_res_ssim.add(batch['class_name'], res_ssim) + + if verbose: + pbar.set_description( + 'val psnr: {:.4f} ssim: {:.4f}'.format(val_res_psnr.item()['all'], val_res_ssim.item()['all'])) + + return val_res_psnr.item(), val_res_ssim.item() + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('--config', default='configs/test_UC_INR_mysr.yaml') + parser.add_argument('--model', default='checkpoints/EXP20220610_5/epoch-best.pth') + # parser.add_argument('--model', default='checkpoints/EXP20220610_5/epoch-last.pth') + parser.add_argument('--scale_ratio', default=4, type=float) + parser.add_argument('--gpu', default='0') + args = parser.parse_args() + + with open(args.config, 'r') as f: + config = yaml.load(f, Loader=yaml.FullLoader) + + config['test_dataset']['wrapper']['args']['scale_ratio'] = args.scale_ratio + + spec = config['test_dataset'] + dataset = datasets.make(spec['dataset']) + dataset = datasets.make(spec['wrapper'], args={'dataset': dataset}) + loader = DataLoader(dataset, batch_size=spec['batch_size'], num_workers=0, pin_memory=True, shuffle=False, drop_last=False) + + model_spec = torch.load(args.model)['model'] + print(model_spec['args']) + model = models.make(model_spec, load_sd=True).to(device) + + file_names = json.load(open(config['test_dataset']['dataset']['args']['split_file']))['test'] + class_names = list(set([os.path.basename(os.path.dirname(x)) for x in file_names])) + + crop_border = config['test_dataset']['wrapper']['args']['scale_ratio']+5 + dataset_name = os.path.basename(config['test_dataset']['dataset']['args']['split_file']).split('_')[0] + max_scale = {'UC': 5, 'AID': 12} + if args.scale_ratio > max_scale[dataset_name]: + crop_border = int((args.scale_ratio - max_scale[dataset_name]) / 2 * 48) + + res = eval_psnr( + loader, class_names, model, + data_norm=config.get('data_norm'), + eval_type=config.get('eval_type'), + eval_bsize=config.get('eval_bsize'), + crop_border=crop_border, + verbose=True) + # print('psnr') + # for k, v in res[0].items(): + # print(f'{k}: {v:0.2f}') + # print('ssim') + # for k, v in res[1].items(): + # print(f'{k}: {v:0.4f}') + print(f'psnr: {res[0]["all"]:0.2f}') + print(f'ssim: {res[1]["all"]:0.4f}') \ No newline at end of file diff --git a/test_interpolate_sr.py b/test_interpolate_sr.py new file mode 100644 index 0000000000000000000000000000000000000000..1df5073b494b7d8e3cfdc4bfe56b7266db2f5c81 --- /dev/null +++ b/test_interpolate_sr.py @@ -0,0 +1,193 @@ +import argparse +import json +import os +import math +from functools import partial + +import cv2 +import numpy as np +import yaml +import torch +from PIL.Image import Image +from einops import rearrange +from torch.utils.data import DataLoader +from torchvision import transforms +from torchvision.transforms import InterpolationMode +from tqdm import tqdm +import datasets +import models +import utils + + +device = 'cuda:0' if torch.cuda.is_available() else 'cpu' + +def batched_predict(model, img, bsize): + with torch.no_grad(): + pred = model(img) + return pred + + +def eval_psnr(loader, class_names, + data_norm=None, eval_type=None, save_fig=False, + scale_ratio=1, save_path=None, verbose=False, crop_border=4, + cal_metrics=True, + ): + crop_border = int(crop_border) if crop_border else crop_border + print('crop border: ', crop_border) + + if data_norm is None: + data_norm = { + 'img': {'sub': [0], 'div': [1]}, + 'gt': {'sub': [0], 'div': [1]} + } + t = data_norm['img'] + img_sub = torch.FloatTensor(t['sub']).view(1, -1, 1, 1).to(device) + img_div = torch.FloatTensor(t['div']).view(1, -1, 1, 1).to(device) + t = data_norm['gt'] + gt_sub = torch.FloatTensor(t['sub']).view(1, 1, -1).to(device) + gt_div = torch.FloatTensor(t['div']).view(1, 1, -1).to(device) + + if eval_type is None: + metric_fn = utils.calculate_psnr_pt + elif eval_type == 'psnr+ssim': + metric_fn = [utils.calculate_psnr_pt, utils.calculate_ssim_pt] + elif eval_type.startswith('div2k'): + scale = int(eval_type.split('-')[1]) + metric_fn = partial(utils.calc_psnr, dataset='div2k', scale=scale) + elif eval_type.startswith('benchmark'): + scale = int(eval_type.split('-')[1]) + metric_fn = partial(utils.calc_psnr, dataset='benchmark', scale=scale) + else: + raise NotImplementedError + + val_res_psnr = utils.Averager(class_names) + val_res_ssim = utils.Averager(class_names) + + pbar = tqdm(loader, leave=False, desc='val') + for batch in pbar: + for k, v in batch.items(): + if torch.is_tensor(v): + batch[k] = v.to(device) + + img = (batch['img'] - img_sub) / img_div + pred = transforms.Resize(batch['gt'].size(-1), InterpolationMode.BICUBIC)(img) + pred = pred * gt_div + gt_sub + + if cal_metrics: + res_psnr = metric_fn[0]( + pred, + batch['gt'], + crop_border=crop_border + ) + res_ssim = metric_fn[1]( + pred, + batch['gt'], + crop_border=crop_border + ) + else: + res_psnr = torch.ones(len(pred)) + res_ssim = torch.ones(len(pred)) + + file_names = batch.get('filename', None) + if file_names is not None and save_fig: + for idx in range(len(batch['img'])): + ori_img = batch['img'][idx].cpu().numpy() * 255 + ori_img = np.clip(ori_img, a_min=0, a_max=255) + ori_img = ori_img.astype(np.uint8) + ori_img = rearrange(ori_img, 'C H W -> H W C') + + pred_img = pred[idx].cpu().numpy() * 255 + pred_img = np.clip(pred_img, a_min=0, a_max=255) + pred_img = pred_img.astype(np.uint8) + pred_img = rearrange(pred_img, 'C H W -> H W C') + + gt_img = batch['gt'][idx].cpu().numpy() * 255 + gt_img = np.clip(gt_img, a_min=0, a_max=255) + gt_img = gt_img.astype(np.uint8) + gt_img = rearrange(gt_img, 'C H W -> H W C') + + psnr = res_psnr[idx].cpu().numpy() + ssim = res_ssim[idx].cpu().numpy() + ori_file_name = f'{save_path}/{file_names[idx]}_Ori.png' + cv2.imwrite(ori_file_name, ori_img) + pred_file_name = f'{save_path}/{file_names[idx]}_{scale_ratio}X_{psnr:.2f}_{ssim:.4f}.png' + cv2.imwrite(pred_file_name, pred_img) + gt_file_name = f'{save_path}/{file_names[idx]}_GT.png' + cv2.imwrite(gt_file_name, gt_img) + + val_res_psnr.add(batch['class_name'], res_psnr) + val_res_ssim.add(batch['class_name'], res_ssim) + + if verbose: + pbar.set_description('val psnr: {:.4f} ssim: {:.4f}'.format(val_res_psnr.item()['all'], val_res_ssim.item()['all'])) + + return val_res_psnr.item(), val_res_ssim.item() + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('--config', default='configs/test_fixed_scale_sr.yaml') + parser.add_argument('--model', default='checkpoints/EXP20220610_5/epoch-best.pth') + parser.add_argument('--scale_ratio', default=4, type=float) + parser.add_argument('--save_fig', default=False, type=bool) + parser.add_argument('--save_path', default='tmp', type=str) + parser.add_argument('--cal_metrics', default=True, type=bool) + parser.add_argument('--return_class_metrics', default=False, type=bool) + parser.add_argument('--dataset_name', default='UC', type=str) + args = parser.parse_args() + + with open(args.config, 'r') as f: + config = yaml.load(f, Loader=yaml.FullLoader) + root_split_file = {'UC': + { + 'root_path': '/data/kyanchen/datasets/UC/256', + 'split_file': 'data_split/UC_split.json' + }, + 'AID': + { + 'root_path': '/data/kyanchen/datasets/AID', + 'split_file': 'data_split/AID_split.json' + } + } + config['test_dataset']['dataset']['args']['root_path'] = root_split_file[args.dataset_name]['root_path'] + config['test_dataset']['dataset']['args']['split_file'] = root_split_file[args.dataset_name]['split_file'] + config['test_dataset']['wrapper']['args']['scale_ratio'] = args.scale_ratio + spec = config['test_dataset'] + dataset = datasets.make(spec['dataset']) + dataset = datasets.make(spec['wrapper'], args={'dataset': dataset}) + loader = DataLoader(dataset, batch_size=spec['batch_size'], num_workers=0, pin_memory=True, shuffle=False, drop_last=False) + + file_names = json.load(open(config['test_dataset']['dataset']['args']['split_file']))['test'] + class_names = list(set([os.path.basename(os.path.dirname(x)) for x in file_names])) + + crop_border = config['test_dataset']['wrapper']['args']['scale_ratio'] + dataset_name = os.path.basename(config['test_dataset']['dataset']['args']['split_file']).split('_')[0] + max_scale = {'UC': 5, 'AID': 12} + if args.scale_ratio > max_scale[dataset_name]: + crop_border = int((args.scale_ratio-max_scale[dataset_name])/2*48) + if args.save_fig: + os.makedirs(args.save_path, exist_ok=True) + + res = eval_psnr( + loader, class_names, + data_norm=config.get('data_norm'), + eval_type=config.get('eval_type'), + crop_border=crop_border, + verbose=True, + save_fig=args.save_fig, + scale_ratio=args.scale_ratio, + save_path=args.save_path, + cal_metrics=args.cal_metrics + ) + + if args.return_class_metrics: + keys = list(res[0].keys()) + keys.sort() + print('psnr') + for k in keys: + print(f'{k}: {res[0][k]:0.2f}') + print('ssim') + for k in keys: + print(f'{k}: {res[1][k]:0.4f}') + print(f'psnr: {res[0]["all"]:0.2f}') + print(f'ssim: {res[1]["all"]:0.4f}') diff --git a/tools/data_tools/__init__.py b/tools/data_tools/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tools/data_tools/create_lmdb_with_keys.py b/tools/data_tools/create_lmdb_with_keys.py new file mode 100644 index 0000000000000000000000000000000000000000..46a1fe44bf89258d646651e3a6c70303c1827650 --- /dev/null +++ b/tools/data_tools/create_lmdb_with_keys.py @@ -0,0 +1,60 @@ +import glob +import os + +import lmdb +import numpy as np +import pickle +import sys +import tqdm +import shutil + +pre_path = r'H:\DataSet\SceneCls\UCMerced_LandUse\UCMerced_LandUse\Images' +file_list = glob.glob(pre_path+'/*/*') +dataset_name = 'UCMerced' +cache_keys = ['filename', 'gt_label'] + + +lmdb_path = os.path.abspath(pre_path + f'/../{dataset_name}_lmdb') +# if os.path.exists(pre_path + f'/lmdb'): +# shutil.rmtree(pre_path + f'/lmdb') +os.makedirs(lmdb_path, exist_ok=True) + +data_size_per_item = sys.getsizeof(open(file_list[0], 'rb').read()) +print(f'data size:{data_size_per_item}') + + +env = lmdb.open(lmdb_path+f'\\{os.path.basename(lmdb_path)}.lmdb', map_size=data_size_per_item * 1e5) +txn = env.begin(write=True) + +commit_interval = 5 +keys_list = [] +for idx, file in enumerate(file_list): + key = f'{dataset_name}_{os.path.basename(file).split(".")[0]}' + keys_list.append(key) + + for cache_key in cache_keys: + if cache_key == 'filename': + value = os.path.basename(os.path.dirname(file)) + '/' + os.path.basename(file) + elif cache_key == 'img': + with open(file, 'rb') as f: + # 读取图像文件的二进制格式数据 + value = f.read() + elif cache_key == 'gt_label': + value = os.path.basename(os.path.dirname(file)) + cache_key = key + f'_{cache_key}' + cache_key = cache_key.encode() + + if isinstance(value, bytes): + txn.put(cache_key, value) + else: + # 标签类型为str, 转为bytes + txn.put(cache_key, value.encode()) # 编码 + if idx % commit_interval == 1: + txn.commit() + txn = env.begin(write=True) +txn.commit() +env.close() +keys_list = np.array(keys_list) +np.savetxt(open(pre_path+'/../keys_list.txt', 'w'), keys_list, fmt='%s') +print(f'Finish writing!') + diff --git a/tools/data_tools/get_all_data_list.py b/tools/data_tools/get_all_data_list.py new file mode 100644 index 0000000000000000000000000000000000000000..6d3fab7d8525b555a362d7a43bff267c1ce6889a --- /dev/null +++ b/tools/data_tools/get_all_data_list.py @@ -0,0 +1,25 @@ +import glob +import os + +import numpy as np +import pickle +import sys +import tqdm +import shutil +from skimage import io + +pre_path = r'H:\DataSet\SceneCls\UCMerced_LandUse\UCMerced_LandUse\Images' +sub_folder_list = glob.glob(pre_path +'/*') +all_data_list = [] +for sub_folder in sub_folder_list: + img_list = glob.glob(sub_folder+'/*') + all_data_list += img_list + +with open(pre_path+f'/../all_img_list.txt', 'w') as f: + for file in tqdm.tqdm(all_data_list): + img = io.imread(file, as_gray=True) + if 0 < img.shape[0]: + file_name = os.path.basename(os.path.dirname(file)) + '/' + os.path.basename(file) + gt_label = os.path.basename(os.path.dirname(file)) + f.write(file_name+' '+gt_label+'\n') + diff --git a/tools/data_tools/get_classes_list.py b/tools/data_tools/get_classes_list.py new file mode 100644 index 0000000000000000000000000000000000000000..6119dbd33a196586d795b0fc81986a1d71aebfa0 --- /dev/null +++ b/tools/data_tools/get_classes_list.py @@ -0,0 +1,17 @@ +import glob +import os + +import numpy as np +import pickle +import sys +import tqdm +import shutil + +pre_path = r'H:\DataSet\SceneCls\UCMerced_LandUse\UCMerced_LandUse\Images' +sub_folder_list = glob.glob(pre_path +'/*') + +with open(pre_path+f'/../class_names.txt', 'w') as f: + for sub_folder in sub_folder_list: + sub_folder_name = os.path.basename(sub_folder) + f.write(sub_folder_name+'\n') + diff --git a/tools/data_tools/get_dataset_infos.py b/tools/data_tools/get_dataset_infos.py new file mode 100644 index 0000000000000000000000000000000000000000..de75980f6cbd07f7c0726c7f705cd425e3c0e47d --- /dev/null +++ b/tools/data_tools/get_dataset_infos.py @@ -0,0 +1,15 @@ +import pickle + + +ann_data_prefix = 'I:/CodeRep/INRCls/data_list/UC' +data_prefix = 'I:/CodeRep/INRCls/results/EXP20220422_3' +ann_file = ann_data_prefix + '/train_list.txt' + +# 48x +with open(ann_file) as f: + samples = [x.strip().rsplit('.tif ', 1) for x in f.readlines()] + +for filename in samples: + with open(data_prefix+ '/' + results['img_info']['filename'], 'rb') as f: + results['img'] = pickle.load(f)['modulations'] + results['img'] = np.array(results['img']).astype(np.float32).reshape(-1) \ No newline at end of file diff --git a/tools/data_tools/get_train_val_list.py b/tools/data_tools/get_train_val_list.py new file mode 100644 index 0000000000000000000000000000000000000000..4316bbe4223a3fcf7ca52e1626b9dd6851ea28d5 --- /dev/null +++ b/tools/data_tools/get_train_val_list.py @@ -0,0 +1,49 @@ +import glob +import json +import os + +import numpy as np +import pickle +import sys +import tqdm +import shutil +from skimage import io + +pre_path = '/Users/kyanchen/Documents/AID/AID' +sub_folder_list = glob.glob(pre_path +'/*') +# train_val_frac = [0.6, 0.2] +train_val_frac = [0.8, 0.2] + +train_list = [] +val_list = [] +test_list = [] +for sub_folder in sub_folder_list: + img_list = glob.glob(sub_folder+'/*') + # img_list = [x for x in img_list if 0 < io.imread(x).shape[0] < 60] + np.random.shuffle(img_list) + np.random.shuffle(img_list) + np.random.shuffle(img_list) + # img_list = img_list + + # for UC datasets + # num_train_samps = int(len(img_list) * train_val_frac[0]) + # num_val_samps = int(len(img_list) * train_val_frac[1]) + # train_list += img_list[:num_train_samps] + # val_list += img_list[num_train_samps:num_train_samps+num_val_samps] + # test_list += img_list[num_train_samps+num_val_samps:] + + # for AID datasets + num_train_samps = int(len(img_list) * train_val_frac[0]) - 10 + num_val_samps = 10 + + train_list += img_list[:num_train_samps] + val_list += img_list[num_train_samps:num_train_samps + num_val_samps] + test_list += img_list[num_train_samps + num_val_samps:] + +data = {} +folder = pre_path + f'/..' +os.makedirs(folder, exist_ok=True) +for phase in ['train_list', 'val_list', 'test_list']: + data[phase.split('_')[0]] = [os.path.basename(os.path.dirname(file)) + '/' + os.path.basename(file) for file in eval(phase)] + +json.dump(data, open(folder+'/AID_split.json', 'w')) \ No newline at end of file diff --git a/tools/paper_vis_tools/get_continuous_vis.py b/tools/paper_vis_tools/get_continuous_vis.py new file mode 100644 index 0000000000000000000000000000000000000000..014382e2cca9a093a3310aeb9b89302551dce858 --- /dev/null +++ b/tools/paper_vis_tools/get_continuous_vis.py @@ -0,0 +1,19 @@ +import os + +# os.system('cd ..') +exp = 'EXP20221219_1' + +for cp in ['epoch-last.pth']: + for scale_ratio in [1.5, 2, 2.5, 3, 3.5, 4.0]: + print(cp, ' ', scale_ratio) + + os.system(f'CUDA_VISIBLE_DEVICES=1 python test_inr_diinn_arbrcan_sadnarc_funsr_overnet.py ' + f'--config tools/paper_tools/vis_continuous_UC_INR_diinn_arbrcan_funsr_overnet.yaml ' + f'--model checkpoints/{exp}/{cp} ' + f'--scale_ratio {scale_ratio} ' + f'--save_fig True ' + f'--save_path vis_AID_testset ' + f'--cal_metrics False' + ) + + print('*' * 30) diff --git a/tools/paper_vis_tools/get_feature_map_vis.py b/tools/paper_vis_tools/get_feature_map_vis.py new file mode 100644 index 0000000000000000000000000000000000000000..df500a566a5a1394dd5311a3853b3e719d799de9 --- /dev/null +++ b/tools/paper_vis_tools/get_feature_map_vis.py @@ -0,0 +1,43 @@ +import os +# import sys +# sys.path.append(sys.path[0]+'/../../') + +exp = 'EXP20221219_1' +model_name = 'FunSR-RDN' # bicubic, SRCNN, FSRCNN, LGCNet +dataset_name = 'AID' # UC, AID + +for cp in ['epoch-last.pth']: + for scale_ratio in [4.0]: + # os.system(f'CUDA_VISIBLE_DEVICES=2 python test_cnn_sr.py ' + # f'--config tools/paper_tools/vis_fixed_scale_UC_INR_diinn_arbrcan_funsr_overnet.yaml ' + # f'--model checkpoints/{exp}/{cp} ' + # f'--scale_ratio {scale_ratio} ' + # f'--save_fig True ' + # f'--save_path vis_{model_name}_{dataset_name}_4x_testset ' + # f'--cal_metrics True ' + # f'--dataset_name {dataset_name}' + # ) + + os.system(f'CUDA_VISIBLE_DEVICES=2 python test_inr_diinn_arbrcan_sadnarc_funsr_overnet.py ' + f'--config tools/paper_tools/vis_fixed_scale_UC_INR_diinn_arbrcan_funsr_overnet.yaml ' + f'--model checkpoints/{exp}/{cp} ' + f'--scale_ratio {scale_ratio} ' + f'--save_fig False ' + f'--save_featmap True ' + f'--save_path vis_{model_name}_{dataset_name}_4x_testset_featmap ' + f'--cal_metrics True ' + f'--dataset_name {dataset_name}' + ) + + # os.system(f'CUDA_VISIBLE_DEVICES=5 python test_inr_liif_metasr_aliif.py ' + # f'--config tools/paper_tools/vis_fixed_scale_UC_INR_liif_metasr_aliif.yaml ' + # f'--model checkpoints/{exp}/{cp} ' + # f'--scale_ratio {scale_ratio} ' + # f'--save_fig True ' + # f'--save_path vis_{model_name}_{dataset_name}_4x_testset ' + # f'--cal_metrics True ' + # f'--dataset_name {dataset_name}' + # ) + +# os.system(f'zip -q -r vis_{model_name}_{dataset_name}_4x_testset_featmap.zip vis_{model_name}_{dataset_name}_4x_testset') +# os.system(f'aws s3 cp vis_{model_name}_{dataset_name}_4x_testset_featmap.zip s3://xhs.bravo/user/kyanchen/tmp/') diff --git a/tools/paper_vis_tools/get_fixed_scale_vis.py b/tools/paper_vis_tools/get_fixed_scale_vis.py new file mode 100644 index 0000000000000000000000000000000000000000..301499ea75dd0e7956b4ce876751d91c8d7fa218 --- /dev/null +++ b/tools/paper_vis_tools/get_fixed_scale_vis.py @@ -0,0 +1,40 @@ +import os + +exp = 'EXP20221219_3' +model_name = 'FunSR-RCAN' # bicubic, SRCNN, FSRCNN, LGCNet +dataset_name = 'AID' # UC, AID + +for cp in ['epoch-last.pth']: + for scale_ratio in [4.0]: + # os.system(f'CUDA_VISIBLE_DEVICES=2 python test_cnn_sr.py ' + # f'--config tools/paper_tools/vis_fixed_scale_UC_INR_diinn_arbrcan_funsr_overnet.yaml ' + # f'--model checkpoints/{exp}/{cp} ' + # f'--scale_ratio {scale_ratio} ' + # f'--save_fig True ' + # f'--save_path vis_{model_name}_{dataset_name}_4x_testset ' + # f'--cal_metrics True ' + # f'--dataset_name {dataset_name}' + # ) + + os.system(f'CUDA_VISIBLE_DEVICES=5 python test_inr_diinn_arbrcan_sadnarc_funsr_overnet.py ' + f'--config tools/paper_tools/vis_fixed_scale_UC_INR_diinn_arbrcan_funsr_overnet.yaml ' + f'--model checkpoints/{exp}/{cp} ' + f'--scale_ratio {scale_ratio} ' + f'--save_fig True ' + f'--save_path vis_{model_name}_{dataset_name}_4x_testset ' + f'--cal_metrics True ' + f'--dataset_name {dataset_name}' + ) + + # os.system(f'CUDA_VISIBLE_DEVICES=5 python test_inr_liif_metasr_aliif.py ' + # f'--config tools/paper_tools/vis_fixed_scale_UC_INR_liif_metasr_aliif.yaml ' + # f'--model checkpoints/{exp}/{cp} ' + # f'--scale_ratio {scale_ratio} ' + # f'--save_fig True ' + # f'--save_path vis_{model_name}_{dataset_name}_4x_testset ' + # f'--cal_metrics True ' + # f'--dataset_name {dataset_name}' + # ) + +os.system(f'zip -q -r vis_{model_name}_{dataset_name}_4x_testset.zip vis_{model_name}_{dataset_name}_4x_testset') +os.system(f'aws s3 cp vis_{model_name}_{dataset_name}_4x_testset.zip s3://xhs.bravo/user/kyanchen/tmp/') diff --git a/tools/paper_vis_tools/rearange_x4_PSNR_SSIM.py b/tools/paper_vis_tools/rearange_x4_PSNR_SSIM.py new file mode 100644 index 0000000000000000000000000000000000000000..f2f6ec0b60dd323327a440cd8f640b6efa017173 --- /dev/null +++ b/tools/paper_vis_tools/rearange_x4_PSNR_SSIM.py @@ -0,0 +1,152 @@ +all = '''1 & 27.96/0.7853 & 28.24/0.7950 & 28.31/0.7961 & 28.25/0.7947 & 28.42/0.7987 & 28.32/0.7960 +\\ +2 & 35.39/0.8411 & 35.43/0.8424 & 35.43/0.8429 & 35.41/0.8424 & 35.45/0.8434 & 35.43/0.8426 +\\ +3 & 34.87/0.8769 & 35.12/0.8815 & 35.15/0.8818 & 35.11/0.8812 & 35.22/0.8831 & 35.18/0.8825 +\\ +4 & 32.33/0.8027 & 32.43/0.8048 & 32.43/0.8054 & 32.42/0.8051 & 32.47/0.8065 & 32.43/0.8056 +\\ +5 & 30.93/0.8502 & 31.46/0.8619 & 31.49/0.8627 & 31.44/0.8615 & 31.63/0.8658 & 31.49/0.8629 +\\ +6 & 28.98/0.8123 & 29.59/0.8283 & 29.64/0.8314 & 29.56/0.8281 & 29.78/0.8354 & 29.63/0.8303 +\\ +7 & 23.31/0.6780 & 23.60/0.6920 & 23.62/0.6950 & 23.60/0.6923 & 23.74/0.7005 & 23.66/0.6966 +\\ +8 & 25.97/0.7552 & 26.24/0.7662 & 26.26/0.7672 & 26.21/0.7653 & 26.32/0.7695 & 26.26/0.7672 +\\ +9 & 23.06/0.6636 & 23.27/0.6754 & 23.31/0.6784 & 23.26/0.6757 & 23.36/0.6822 & 23.30/0.6789 +\\ +10 & 37.39/0.8860 & 37.48/0.8877 & 37.51/0.8884 & 37.50/0.8883 & 37.52/0.8885 & 37.50/0.8882 +\\ +11 & 34.65/0.8620 & 34.90/0.8673 & 34.92/0.8676 & 34.90/0.8670 & 34.97/0.8688 & 34.93/0.8679 +\\ +12 & 27.50/0.6394 & 27.61/0.6457 & 27.62/0.6482 & 27.60/0.6452 & 27.66/0.6519 & 27.64/0.6495 +\\ +13 & 26.16/0.7576 & 26.53/0.7741 & 26.55/0.7762 & 26.50/0.7731 & 26.65/0.7807 & 26.56/0.7763 +\\ +14 & 33.27/0.7518 & 33.35/0.7539 & 33.38/0.7551 & 33.33/0.7546 & 33.35/0.7555 & 33.36/0.7545 +\\ +15 & 25.48/0.6900 & 25.80/0.7014 & 25.84/0.7043 & 25.80/0.7025 & 25.90/0.7069 & 25.83/0.7055 +\\ +16 & 27.97/0.7213 & 28.06/0.7250 & 28.07/0.7255 & 28.06/0.7251 & 28.10/0.7272 & 28.08/0.7258 +\\ +17 & 28.74/0.7631 & 28.89/0.7689 & 28.91/0.7699 & 28.88/0.7689 & 28.95/0.7719 & 28.91/0.7702 +\\ +18 & 23.36/0.7927 & 24.24/0.8179 & 24.31/0.8203 & 24.20/0.8171 & 24.62/0.8280 & 24.36/0.8209 +\\ +19 & 36.85/0.8920 & 37.28/0.8992 & 37.30/0.8995 & 37.23/0.8987 & 37.43/0.9015 & 37.25/0.8989 +\\ +20 & 38.02/0.9129 & 38.18/0.9146 & 38.17/0.9147 & 38.15/0.9147 & 38.26/0.9156 & 38.17/0.9149 +\\ +21 & 26.89/0.8433 & 27.38/0.8545 & 27.39/0.8554 & 27.33/0.8541 & 27.48/0.8579 & 27.39/0.8562 +\\ +22 & 27.68/0.8091 & 28.19/0.8263 & 28.21/0.8265 & 28.13/0.8239 & 28.31/0.8300 & 28.20/0.8256 +\\ +23 & 26.26/0.7492 & 26.51/0.7588 & 26.55/0.7606 & 26.50/0.7589 & 26.64/0.7645 & 26.54/0.7611 +\\ +24 & 30.09/0.7624 & 30.22/0.7659 & 30.23/0.7670 & 30.22/0.7665 & 30.26/0.7680 & 30.23/0.7666 +\\ +25 & 25.07/0.7363 & 25.35/0.7471 & 25.41/0.7499 & 25.36/0.7475 & 25.47/0.7525 & 25.41/0.7504 +\\ +26 & 24.39/0.6501 & 24.61/0.6580 & 24.64/0.6604 & 24.61/0.6588 & 24.72/0.6637 & 24.66/0.6616 +\\ +27 & 29.42/0.8154 & 29.74/0.8258 & 29.81/0.8276 & 29.72/0.8255 & 29.86/0.8306 & 29.80/0.8272 +\\ +28 & 33.46/0.8813 & 33.99/0.8921 & 34.09/0.8930 & 33.94/0.8905 & 34.20/0.8944 & 33.99/0.8898 +\\ +29 & 24.60/0.7345 & 25.04/0.7488 & 25.08/0.7505 & 25.02/0.7481 & 25.16/0.7544 & 25.06/0.7507 +\\ +30 & 27.60/0.7737 & 28.12/0.7944 & 28.17/0.7966 & 28.10/0.7934 & 28.26/0.8005 & 28.17/0.7964 +\\ +''' +all = all.split('\n') + +results = '''psnr +Airport: 28.57 +BareLand: 35.46 +BaseballField: 35.29 +Beach: 32.51 +Bridge: 31.74 +Center: 29.99 +Church: 23.83 +Commercial: 26.39 +DenseResidential: 23.50 +Desert: 37.67 +Farmland: 35.00 +Forest: 27.67 +Industrial: 26.76 +Meadow: 33.40 +MediumResidential: 25.95 +Mountain: 28.14 +Park: 28.98 +Parking: 24.89 +Playground: 37.54 +Pond: 38.28 +Port: 27.63 +RailwayStation: 28.43 +Resort: 26.67 +River: 30.28 +School: 25.57 +SparseResidential: 24.75 +Square: 29.98 +Stadium: 34.48 +StorageTanks: 25.29 +Viaduct: 28.34 +all: 29.78 +ssim +Airport: 0.8013 +BareLand: 0.8439 +BaseballField: 0.8848 +Beach: 0.8085 +Bridge: 0.8668 +Center: 0.8403 +Church: 0.7053 +Commercial: 0.7717 +DenseResidential: 0.6879 +Desert: 0.8926 +Farmland: 0.8697 +Forest: 0.6541 +Industrial: 0.7845 +Meadow: 0.7578 +MediumResidential: 0.7100 +Mountain: 0.7296 +Park: 0.7738 +Parking: 0.8344 +Playground: 0.9032 +Pond: 0.9158 +Port: 0.8612 +RailwayStation: 0.8327 +Resort: 0.7658 +River: 0.7694 +School: 0.7561 +SparseResidential: 0.6652 +Square: 0.8330 +Stadium: 0.8983 +StorageTanks: 0.7574 +Viaduct: 0.8030 +all: 0.8013''' +results = results.split('\n') +n_len = len(results) +total_psnr = 0 +total_ssim = 0 +all_data = '' +idx_all = 0 +for i in range(1, n_len//2): + name = results[i].split(':')[0] + name_tmp = results[i+n_len//2].split(':')[0] + assert name == name_tmp + psnr_val = results[i].split(':')[-1].strip() + psnr_val = float(psnr_val) + ssim_val = results[i+n_len//2].split(':')[-1].strip() + ssim_val = float(ssim_val) + if name == 'all': + all_data = name+':'+str(psnr_val)+'/'+str(ssim_val) + continue + total_psnr += psnr_val + total_ssim += ssim_val + print(all[idx_all] +' & ' +f'{psnr_val:.2f}'+'/'+f'{ssim_val:.4f}') + idx_all += 2 + print('\\\\') +print(all_data) +print(total_psnr/(n_len//2-2)) +print(total_ssim/(n_len//2-2)) diff --git a/tools/paper_vis_tools/vis_continuous_UC_INR_diinn_arbrcan_funsr_overnet.yaml b/tools/paper_vis_tools/vis_continuous_UC_INR_diinn_arbrcan_funsr_overnet.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a057b18d1dab66514dade860b4951c5576ff534b --- /dev/null +++ b/tools/paper_vis_tools/vis_continuous_UC_INR_diinn_arbrcan_funsr_overnet.yaml @@ -0,0 +1,26 @@ +test_dataset: + dataset: + name: hr_data_loader + args: +# root_path: /data/kyanchen/datasets/UC/256 +# split_file: data_split/UC_split.json + root_path: /data/kyanchen/datasets/AID + split_file: data_split/AID_split.json + split_key: test + cache: none + wrapper: + name: cnn_fixed_scale_sr_warp + args: + scale_ratio: 5 + patch_size: 48 + augment: false + val_mode: false + test_mode: true + vis_continuous: true + batch_size: 8 + +eval_type: psnr+ssim + +data_norm: + img: {sub: [0.5], div: [0.5]} + gt: {sub: [0.5], div: [0.5]} diff --git a/tools/paper_vis_tools/vis_fixed_scale_UC_INR_diinn_arbrcan_funsr_overnet.yaml b/tools/paper_vis_tools/vis_fixed_scale_UC_INR_diinn_arbrcan_funsr_overnet.yaml new file mode 100644 index 0000000000000000000000000000000000000000..963e4efc9a19bffa4483edc46235aac1c088dc51 --- /dev/null +++ b/tools/paper_vis_tools/vis_fixed_scale_UC_INR_diinn_arbrcan_funsr_overnet.yaml @@ -0,0 +1,26 @@ +test_dataset: + dataset: + name: hr_data_loader + args: + root_path: /Users/kyanchen/Documents/UC/256 + split_file: /Users/kyanchen/My_Code/sr/data_split/UC_split.json +# root_path: /data/kyanchen/datasets/AID +# split_file: data_split/AID_split.json + split_key: test + cache: none + wrapper: + name: cnn_fixed_scale_sr_warp + args: + scale_ratio: 4 + patch_size: 48 + augment: false + val_mode: false + test_mode: true + vis_continuous: false + batch_size: 8 + +eval_type: psnr+ssim + +data_norm: + img: {sub: [0.5], div: [0.5]} + gt: {sub: [0.5], div: [0.5]} diff --git a/tools/paper_vis_tools/vis_fixed_scale_UC_INR_liif_metasr_aliif.yaml b/tools/paper_vis_tools/vis_fixed_scale_UC_INR_liif_metasr_aliif.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6f01d586e6c01b77321eace8478642b6b37c446a --- /dev/null +++ b/tools/paper_vis_tools/vis_fixed_scale_UC_INR_liif_metasr_aliif.yaml @@ -0,0 +1,24 @@ +test_dataset: + dataset: + name: hr_data_loader + args: + root_path: /data/kyanchen/datasets/UC/256 + split_file: data_split/UC_split.json +# root_path: /data/kyanchen/datasets/AID +# split_file: data_split/AID_split.json + split_key: test + cache: none + wrapper: + name: inr_fixed_scale_sr_warp + args: + scale_ratio: 4 + patch_size: 48 + augment: false + val_mode: false + test_mode: true + return_cell: true + batch_size: 1 +eval_type: psnr+ssim +data_norm: + inp: {sub: [0.5], div: [0.5]} + gt: {sub: [0.5], div: [0.5]} \ No newline at end of file diff --git a/tools/resize.py b/tools/resize.py new file mode 100644 index 0000000000000000000000000000000000000000..581049936fceb789bfc801f3a9c3288175c98f96 --- /dev/null +++ b/tools/resize.py @@ -0,0 +1,20 @@ +import os +from skimage import io +from tqdm import tqdm +import cv2 +import glob +import mmcv + +inp = r'H:\DataSet\SceneCls\UCMerced_LandUse\UCMerced_LandUse\Images' + +for size in [256, 32]: + print(size) + filenames = glob.glob(inp+'/*/*') + for filename in tqdm(filenames): + img = io.imread(filename) + h, w = img.shape[:2] + if size != h: + img = cv2.resize(img, (size, size), cv2.INTER_CUBIC) + save_path = os.path.dirname(inp) + f'/{size}/' + os.path.basename(os.path.dirname(filename)) + '/' + os.path.basename(filename) + mmcv.mkdir_or_exist(os.path.dirname(save_path)) + io.imsave(save_path, img) diff --git a/train_cnn_sr.py b/train_cnn_sr.py new file mode 100644 index 0000000000000000000000000000000000000000..98cabe64048a80d5891208d4efa5fcde13a97538 --- /dev/null +++ b/train_cnn_sr.py @@ -0,0 +1,221 @@ +import argparse +import json +import os +os.environ['CUDA_VISIBLE_DEVICES'] = '0' + +import yaml +import torch +import torch.nn as nn +from tqdm import tqdm +from torch.utils.data import DataLoader +from torch.optim.lr_scheduler import MultiStepLR, CosineAnnealingLR + +import datasets +import models +import utils +from test_cnn_sr import eval_psnr + + +def make_data_loader(spec, tag=''): + if spec is None: + return None + + dataset = datasets.make(spec['dataset']) + dataset = datasets.make(spec['wrapper'], args={'dataset': dataset}) + + log('{} dataset: size={}'.format(tag, len(dataset))) + for k, v in dataset[0].items(): + if torch.is_tensor(v): + log(' {}: shape={}'.format(k, v.shape)) + elif isinstance(v, str): + pass + elif isinstance(v, dict): + for k0, v0 in v.items(): + if hasattr(v0, 'shape'): + log(' {}: shape={}'.format(k0, v0.shape)) + else: + raise NotImplementedError + + loader = DataLoader(dataset, batch_size=spec['batch_size'], + shuffle=(tag == 'train'), num_workers=4, pin_memory=True) + return loader + + +def make_data_loaders(): + train_loader = make_data_loader(config.get('train_dataset'), tag='train') + val_loader = make_data_loader(config.get('val_dataset'), tag='val') + return train_loader, val_loader + + +def prepare_training(): + if config.get('resume') is not None: + sv_file = torch.load(config['resume']) + model = models.make(sv_file['model'], load_sd=True).cuda() + optimizer = utils.make_optimizer( + model.parameters(), sv_file['optimizer'], load_sd=True) + epoch_start = sv_file['epoch'] + 1 + if config.get('multi_step_lr') is None: + lr_scheduler = None + else: + lr_scheduler = MultiStepLR(optimizer, **config['multi_step_lr']) + for _ in range(epoch_start - 1): + lr_scheduler.step() + else: + model = models.make(config['model']).cuda() + optimizer = utils.make_optimizer( + model.parameters(), config['optimizer']) + epoch_start = 1 + lr_scheduler = config.get('lr_scheduler') + lr_scheduler_name = lr_scheduler.pop('name') + if 'MultiStepLR' == lr_scheduler_name: + lr_scheduler = MultiStepLR(optimizer, **lr_scheduler) + elif 'CosineAnnealingLR' == lr_scheduler_name: + lr_scheduler = CosineAnnealingLR(optimizer, **lr_scheduler) + + log('model: #params={}'.format(utils.compute_num_params(model, text=True))) + return model, optimizer, epoch_start, lr_scheduler + + +def train(train_loader, model, optimizer): + model.train() + loss_fn = nn.L1Loss() + train_loss = utils.AveragerList() + + data_norm = config['data_norm'] + t = data_norm['img'] + img_sub = torch.FloatTensor(t['sub']).view(1, -1, 1, 1).cuda() + img_div = torch.FloatTensor(t['div']).view(1, -1, 1, 1).cuda() + t = data_norm['gt'] + gt_sub = torch.FloatTensor(t['sub']).view(1, 1, -1).cuda() + gt_div = torch.FloatTensor(t['div']).view(1, 1, -1).cuda() + + for batch in tqdm(train_loader, leave=False, desc='train'): + for k, v in batch.items(): + if torch.is_tensor(v): + batch[k] = v.cuda() + # import pdb + # pdb.set_trace() + img = (batch['img'] - img_sub) / img_div + gt = (batch['gt'] - gt_sub) / gt_div + pred = model(img, gt.shape[-2:]) + loss = loss_fn(pred, gt) + + train_loss.add(loss.item()) + + optimizer.zero_grad() + loss.backward() + optimizer.step() + + return train_loss.item() + + +def main(config_, save_path): + global config, log, writer + config = config_ + log, writer = utils.set_save_path(save_path) + with open(os.path.join(save_path, 'config.yaml'), 'w') as f: + yaml.dump(config, f, sort_keys=False) + + train_loader, val_loader = make_data_loaders() + if config.get('data_norm') is None: + config['data_norm'] = { + 'img': {'sub': [0], 'div': [1]}, + 'gt': {'sub': [0], 'div': [1]} + } + + model, optimizer, epoch_start, lr_scheduler = prepare_training() + + n_gpus = len(os.environ['CUDA_VISIBLE_DEVICES'].split(',')) + if n_gpus > 1: + model = nn.parallel.DataParallel(model) + + epoch_max = config['epoch_max'] + epoch_val_interval = config.get('epoch_val_interval') + epoch_save_interval = config.get('epoch_save_interval') + max_val_v = -1e18 + + timer = utils.Timer() + + for epoch in range(epoch_start, epoch_max + 1): + t_epoch_start = timer.t() + log_info = ['epoch {}/{}'.format(epoch, epoch_max)] + + writer.add_scalar('lr', optimizer.param_groups[0]['lr'], epoch) + + train_loss = train(train_loader, model, optimizer) + if lr_scheduler is not None: + lr_scheduler.step() + + log_info.append('train: loss={:.4f}'.format(train_loss)) + writer.add_scalars('loss', {'train': train_loss}, epoch) + + if n_gpus > 1: + model_ = model.module + else: + model_ = model + model_spec = config['model'] + model_spec['sd'] = model_.state_dict() + optimizer_spec = config['optimizer'] + optimizer_spec['sd'] = optimizer.state_dict() + sv_file = { + 'model': model_spec, + 'optimizer': optimizer_spec, + 'epoch': epoch + } + + torch.save(sv_file, os.path.join(save_path, 'epoch-last.pth')) + + if (epoch_save_interval is not None) and (epoch % epoch_save_interval == 0): + torch.save(sv_file, os.path.join(save_path, 'epoch-{}.pth'.format(epoch))) + + if (epoch_val_interval is not None) and (epoch % epoch_val_interval == 0): + if n_gpus > 1 and (config.get('eval_bsize') is not None): + model_ = model.module + else: + model_ = model + + file_names = json.load(open(config['val_dataset']['dataset']['args']['split_file']))['test'] + class_names = list(set([os.path.basename(os.path.dirname(x)) for x in file_names])) + + val_res_psnr, val_res_ssim = eval_psnr(val_loader, class_names, model_, + data_norm=config['data_norm'], + eval_type=config.get('eval_type'), + eval_bsize=config.get('eval_bsize'), + crop_border=4) + + log_info.append('val: psnr={:.4f}'.format(val_res_psnr['all'])) + writer.add_scalars('psnr', {'val': val_res_psnr['all']}, epoch) + if val_res_psnr['all'] > max_val_v: + max_val_v = val_res_psnr['all'] + torch.save(sv_file, os.path.join(save_path, 'epoch-best.pth')) + + t = timer.t() + prog = (epoch - epoch_start + 1) / (epoch_max - epoch_start + 1) + t_epoch = utils.time_text(t - t_epoch_start) + t_elapsed, t_all = utils.time_text(t), utils.time_text(t / prog) + log_info.append('{} {}/{}'.format(t_epoch, t_elapsed, t_all)) + + log(', '.join(log_info)) + writer.flush() + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('--config', default='configs/train_CNN.yaml') + parser.add_argument('--name', default='EXP20230101_10') + parser.add_argument('--tag', default=None) + parser.add_argument('--gpu', default='0') + args = parser.parse_args() + + with open(args.config, 'r') as f: + config = yaml.load(f, Loader=yaml.FullLoader) + print('config loaded.') + + save_name = args.name + if save_name is None: + save_name = '_' + args.config.split('/')[-1][:-len('.yaml')] + if args.tag is not None: + save_name += '_' + args.tag + save_path = os.path.join('./checkpoints', save_name) + + main(config, save_path) diff --git a/train_diinn_arbrcan_sadn_overnet.py b/train_diinn_arbrcan_sadn_overnet.py new file mode 100644 index 0000000000000000000000000000000000000000..87aaf8f4ea1d0ebf9eaf08225afb635f0f75a7d0 --- /dev/null +++ b/train_diinn_arbrcan_sadn_overnet.py @@ -0,0 +1,225 @@ +import argparse +import json +import os +os.environ['CUDA_VISIBLE_DEVICES'] = '2' + +import yaml +import torch +import torch.nn as nn +from tqdm import tqdm +from torch.utils.data import DataLoader +from torch.optim.lr_scheduler import MultiStepLR, CosineAnnealingLR + +import datasets +import models +import utils +from test_inr_diinn_arbrcan_sadnarc_funsr_overnet import eval_psnr + +device = 'cuda:0' if torch.cuda.is_available() else 'cpu' + +def make_data_loader(spec, tag=''): + if spec is None: + return None + + dataset = datasets.make(spec['dataset']) + dataset = datasets.make(spec['wrapper'], args={'dataset': dataset}) + + log('{} dataset: size={}'.format(tag, len(dataset))) + for k, v in dataset[0].items(): + if torch.is_tensor(v): + log(' {}: shape={}'.format(k, v.shape)) + elif isinstance(v, str): + pass + elif isinstance(v, dict): + for k0, v0 in v.items(): + if hasattr(v0, 'shape'): + log(' {}: shape={}'.format(k0, v0.shape)) + else: + raise NotImplementedError + + loader = DataLoader(dataset, batch_size=spec['batch_size'], + shuffle=(tag == 'train'), num_workers=4, pin_memory=True) + return loader + + +def make_data_loaders(): + train_loader = make_data_loader(config.get('train_dataset'), tag='train') + val_loader = make_data_loader(config.get('val_dataset'), tag='val') + return train_loader, val_loader + + +def prepare_training(): + if config.get('resume') is not None: + sv_file = torch.load(config['resume']) + model = models.make(sv_file['model'], load_sd=True).cuda() + optimizer = utils.make_optimizer( + model.parameters(), sv_file['optimizer'], load_sd=True) + epoch_start = sv_file['epoch'] + 1 + if config.get('multi_step_lr') is None: + lr_scheduler = None + else: + lr_scheduler = MultiStepLR(optimizer, **config['multi_step_lr']) + for _ in range(epoch_start - 1): + lr_scheduler.step() + else: + model = models.make(config['model']).cuda() + optimizer = utils.make_optimizer( + model.parameters(), config['optimizer']) + epoch_start = 1 + lr_scheduler = config.get('lr_scheduler') + lr_scheduler_name = lr_scheduler.pop('name') + if 'MultiStepLR' == lr_scheduler_name: + lr_scheduler = MultiStepLR(optimizer, **lr_scheduler) + elif 'CosineAnnealingLR' == lr_scheduler_name: + lr_scheduler = CosineAnnealingLR(optimizer, **lr_scheduler) + + log('model: #params={}'.format(utils.compute_num_params(model, text=True))) + return model, optimizer, epoch_start, lr_scheduler + + +def train(train_loader, model, optimizer): + model.train() + loss_fn = nn.L1Loss() + train_loss = utils.AveragerList() + + data_norm = config['data_norm'] + t = data_norm['img'] + img_sub = torch.FloatTensor(t['sub']).view(1, -1, 1, 1).cuda() + img_div = torch.FloatTensor(t['div']).view(1, -1, 1, 1).cuda() + t = data_norm['gt'] + gt_sub = torch.FloatTensor(t['sub']).view(1, 1, -1).cuda() + gt_div = torch.FloatTensor(t['div']).view(1, 1, -1).cuda() + + for batch in tqdm(train_loader, leave=False, desc='train'): + # import pdb + # pdb.set_trace() + keys = list(batch.keys()) + batch = batch[keys[torch.randint(0, len(keys), [])]] + for k, v in batch.items(): + if torch.is_tensor(v): + batch[k] = v.to(device) + + img = (batch['img'] - img_sub) / img_div + gt = (batch['gt'] - gt_sub) / gt_div + pred = model(img, gt.shape[-2:]) + loss = loss_fn(pred, gt) + + train_loss.add(loss.item()) + + optimizer.zero_grad() + loss.backward() + optimizer.step() + + return train_loss.item() + + +def main(config_, save_path): + global config, log, writer + config = config_ + log, writer = utils.set_save_path(save_path) + with open(os.path.join(save_path, 'config.yaml'), 'w') as f: + yaml.dump(config, f, sort_keys=False) + + train_loader, val_loader = make_data_loaders() + if config.get('data_norm') is None: + config['data_norm'] = { + 'img': {'sub': [0], 'div': [1]}, + 'gt': {'sub': [0], 'div': [1]} + } + + model, optimizer, epoch_start, lr_scheduler = prepare_training() + + n_gpus = len(os.environ['CUDA_VISIBLE_DEVICES'].split(',')) + if n_gpus > 1: + model = nn.parallel.DataParallel(model) + + epoch_max = config['epoch_max'] + epoch_val_interval = config.get('epoch_val_interval') + epoch_save_interval = config.get('epoch_save_interval') + max_val_v = -1e18 + + timer = utils.Timer() + + for epoch in range(epoch_start, epoch_max + 1): + t_epoch_start = timer.t() + log_info = ['epoch {}/{}'.format(epoch, epoch_max)] + + writer.add_scalar('lr', optimizer.param_groups[0]['lr'], epoch) + + train_loss = train(train_loader, model, optimizer) + if lr_scheduler is not None: + lr_scheduler.step() + + log_info.append('train: loss={:.4f}'.format(train_loss)) + writer.add_scalars('loss', {'train': train_loss}, epoch) + + if device != 'cpu' and n_gpus > 1: + model_ = model.module + else: + model_ = model + model_spec = config['model'] + model_spec['sd'] = model_.state_dict() + optimizer_spec = config['optimizer'] + optimizer_spec['sd'] = optimizer.state_dict() + sv_file = { + 'model': model_spec, + 'optimizer': optimizer_spec, + 'epoch': epoch + } + + torch.save(sv_file, os.path.join(save_path, 'epoch-last.pth')) + + if (epoch_save_interval is not None) and (epoch % epoch_save_interval == 0): + torch.save(sv_file, os.path.join(save_path, 'epoch-{}.pth'.format(epoch))) + + if (epoch_val_interval is not None) and (epoch % epoch_val_interval == 0): + if device != 'cpu' and n_gpus > 1 and (config.get('eval_bsize') is not None): + model_ = model.module + else: + model_ = model + + file_names = json.load(open(config['val_dataset']['dataset']['args']['split_file']))['test'] + class_names = list(set([os.path.basename(os.path.dirname(x)) for x in file_names])) + + val_res_psnr, val_res_ssim = eval_psnr(val_loader, class_names, model_, + data_norm=config['data_norm'], + eval_type=config.get('eval_type'), + eval_bsize=config.get('eval_bsize'), + crop_border=4) + + log_info.append('val: psnr={:.4f}'.format(val_res_psnr['all'])) + writer.add_scalars('psnr', {'val': val_res_psnr['all']}, epoch) + if val_res_psnr['all'] > max_val_v: + max_val_v = val_res_psnr['all'] + torch.save(sv_file, os.path.join(save_path, 'epoch-best.pth')) + + t = timer.t() + prog = (epoch - epoch_start + 1) / (epoch_max - epoch_start + 1) + t_epoch = utils.time_text(t - t_epoch_start) + t_elapsed, t_all = utils.time_text(t), utils.time_text(t / prog) + log_info.append('{} {}/{}'.format(t_epoch, t_elapsed, t_all)) + + log(', '.join(log_info)) + writer.flush() + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('--config', default='configs/baselines/train_UC_1x-5x_INR_diinn_arbrcan_sadnarc_overnet.yaml') + parser.add_argument('--name', default='EXP20221208_2') + parser.add_argument('--tag', default=None) + parser.add_argument('--gpu', default='0') + args = parser.parse_args() + + with open(args.config, 'r') as f: + config = yaml.load(f, Loader=yaml.FullLoader) + print('config loaded.') + + save_name = args.name + if save_name is None: + save_name = '_' + args.config.split('/')[-1][:-len('.yaml')] + if args.tag is not None: + save_name += '_' + args.tag + save_path = os.path.join('./checkpoints', save_name) + + main(config, save_path) diff --git a/train_inr_funsr.py b/train_inr_funsr.py new file mode 100644 index 0000000000000000000000000000000000000000..920408d871e3a343eb7a4543fc0a7855069abdc0 --- /dev/null +++ b/train_inr_funsr.py @@ -0,0 +1,241 @@ +import argparse +import json +import os +os.environ['CUDA_VISIBLE_DEVICES'] = '0' +# os.environ['CUDA_VISIBLE_DEVICES'] = '0,1,2,3,4,5,6,7' + +import yaml +import torch +import torch.nn as nn +from tqdm import tqdm +from torch.utils.data import DataLoader +from torch.optim.lr_scheduler import MultiStepLR, CosineAnnealingLR + +import datasets +import models +import utils +from test_inr_diinn_arbrcan_sadnarc_funsr_overnet import eval_psnr + +device = 'cuda:0' if torch.cuda.is_available() else 'cpu' + +def make_data_loader(spec, tag=''): + if spec is None: + return None + + dataset = datasets.make(spec['dataset']) + dataset = datasets.make(spec['wrapper'], args={'dataset': dataset}) + + log('{} dataset: size={}'.format(tag, len(dataset))) + for k, v in dataset[0].items(): + if torch.is_tensor(v): + log(' {}: shape={}'.format(k, v.shape)) + elif isinstance(v, str): + pass + elif isinstance(v, dict): + for k0, v0 in v.items(): + if hasattr(v0, 'shape'): + log(' {}: shape={}'.format(k0, v0.shape)) + else: + raise NotImplementedError + + loader = DataLoader(dataset, batch_size=spec['batch_size'], + shuffle=(tag == 'train'), num_workers=spec['num_workers'], pin_memory=True) + return loader + + +def make_data_loaders(): + train_loader = make_data_loader(config.get('train_dataset'), tag='train') + val_loader = make_data_loader(config.get('val_dataset'), tag='val') + return train_loader, val_loader + + +def prepare_training(): + if config.get('resume') is not None: + sv_file = torch.load(config['resume']) + model = models.make(sv_file['model'], load_sd=True).cuda() + optimizer = utils.make_optimizer( + model.parameters(), sv_file['optimizer'], load_sd=False) + # epoch_start = sv_file['epoch'] + 1 + epoch_start = 1 + + lr_scheduler = config.get('lr_scheduler') + lr_scheduler_name = lr_scheduler.pop('name') + if 'MultiStepLR' == lr_scheduler_name: + lr_scheduler = MultiStepLR(optimizer, **lr_scheduler) + elif 'CosineAnnealingLR' == lr_scheduler_name: + lr_scheduler = CosineAnnealingLR(optimizer, **lr_scheduler) + elif 'CosineAnnealingWarmUpLR' == lr_scheduler_name: + lr_scheduler = utils.warm_up_cosine_lr_scheduler(optimizer, **lr_scheduler) + # for _ in range(epoch_start - 1): + # lr_scheduler.step() + else: + model = models.make(config['model']).cuda() + optimizer = utils.make_optimizer( + model.parameters(), config['optimizer']) + epoch_start = 1 + lr_scheduler = config.get('lr_scheduler') + lr_scheduler_name = lr_scheduler.pop('name') + if 'MultiStepLR' == lr_scheduler_name: + lr_scheduler = MultiStepLR(optimizer, **lr_scheduler) + elif 'CosineAnnealingLR' == lr_scheduler_name: + lr_scheduler = CosineAnnealingLR(optimizer, **lr_scheduler) + elif 'CosineAnnealingWarmUpLR' == lr_scheduler_name: + lr_scheduler = utils.warm_up_cosine_lr_scheduler(optimizer, **lr_scheduler) + + log('model: #params={}'.format(utils.compute_num_params(model, text=True))) + return model, optimizer, epoch_start, lr_scheduler + + +def train(train_loader, model, optimizer): + model.train() + loss_fn = nn.L1Loss() + train_loss = utils.AveragerList() + + data_norm = config['data_norm'] + t = data_norm['img'] + img_sub = torch.FloatTensor(t['sub']).view(1, -1, 1, 1).cuda() + img_div = torch.FloatTensor(t['div']).view(1, -1, 1, 1).cuda() + t = data_norm['gt'] + gt_sub = torch.FloatTensor(t['sub']).view(1, 1, -1).cuda() + gt_div = torch.FloatTensor(t['div']).view(1, 1, -1).cuda() + + for batch in tqdm(train_loader, leave=False, desc='train'): + # import pdb + # pdb.set_trace() + keys = list(batch.keys()) + batch = batch[keys[torch.randint(0, len(keys), [])]] + for k, v in batch.items(): + if torch.is_tensor(v): + batch[k] = v.to(device) + + img = (batch['img'] - img_sub) / img_div + gt = (batch['gt'] - gt_sub) / gt_div + pred = model(img, gt.shape[-2:]) + if isinstance(pred, tuple): + loss = 0.2 * loss_fn(pred[0], gt) + loss_fn(pred[1], gt) + elif isinstance(pred, list): + losses = [loss_fn(x, gt) for x in pred] + losses = [x * (idx + 1) for idx, x in enumerate(losses)] + loss = sum(losses) / ((1 + len(losses)) * len(losses) / 2) + else: + loss = loss_fn(pred, gt) + + train_loss.add(loss.item()) + + optimizer.zero_grad() + loss.backward() + optimizer.step() + + return train_loss.item() + + +def main(config_, save_path): + global config, log, writer + config = config_ + log, writer = utils.set_save_path(save_path) + with open(os.path.join(save_path, 'config.yaml'), 'w') as f: + yaml.dump(config, f, sort_keys=False) + + train_loader, val_loader = make_data_loaders() + if config.get('data_norm') is None: + config['data_norm'] = { + 'img': {'sub': [0], 'div': [1]}, + 'gt': {'sub': [0], 'div': [1]} + } + + model, optimizer, epoch_start, lr_scheduler = prepare_training() + + n_gpus = len(os.environ['CUDA_VISIBLE_DEVICES'].split(',')) + if n_gpus > 1: + model = nn.parallel.DataParallel(model) + + epoch_max = config['epoch_max'] + epoch_val_interval = config.get('epoch_val_interval') + epoch_save_interval = config.get('epoch_save_interval') + max_val_v = -1e18 + + timer = utils.Timer() + + for epoch in range(epoch_start, epoch_max + 1): + t_epoch_start = timer.t() + log_info = ['epoch {}/{}'.format(epoch, epoch_max)] + + writer.add_scalar('lr', optimizer.param_groups[0]['lr'], epoch) + + train_loss = train(train_loader, model, optimizer) + if lr_scheduler is not None: + lr_scheduler.step() + + log_info.append('train: loss={:.4f}'.format(train_loss)) + writer.add_scalars('loss', {'train': train_loss}, epoch) + + if device != 'cpu' and n_gpus > 1: + model_ = model.module + else: + model_ = model + model_spec = config['model'] + model_spec['sd'] = model_.state_dict() + optimizer_spec = config['optimizer'] + optimizer_spec['sd'] = optimizer.state_dict() + sv_file = { + 'model': model_spec, + 'optimizer': optimizer_spec, + 'epoch': epoch + } + + torch.save(sv_file, os.path.join(save_path, 'epoch-last.pth')) + + if (epoch_save_interval is not None) and (epoch % epoch_save_interval == 0): + torch.save(sv_file, os.path.join(save_path, 'epoch-{}.pth'.format(epoch))) + + if (epoch_val_interval is not None) and (epoch % epoch_val_interval == 0): + if device != 'cpu' and n_gpus > 1 and (config.get('eval_bsize') is not None): + model_ = model.module + else: + model_ = model + + file_names = json.load(open(config['val_dataset']['dataset']['args']['split_file']))['test'] + class_names = list(set([os.path.basename(os.path.dirname(x)) for x in file_names])) + + val_res_psnr, val_res_ssim = eval_psnr(val_loader, class_names, model_, + data_norm=config['data_norm'], + eval_type=config.get('eval_type'), + eval_bsize=config.get('eval_bsize'), + crop_border=4) + + log_info.append('val: psnr={:.4f}'.format(val_res_psnr['all'])) + writer.add_scalars('psnr', {'val': val_res_psnr['all']}, epoch) + if val_res_psnr['all'] > max_val_v: + max_val_v = val_res_psnr['all'] + torch.save(sv_file, os.path.join(save_path, 'epoch-best.pth')) + + t = timer.t() + prog = (epoch - epoch_start + 1) / (epoch_max - epoch_start + 1) + t_epoch = utils.time_text(t - t_epoch_start) + t_elapsed, t_all = utils.time_text(t), utils.time_text(t / prog) + log_info.append('{} {}/{}'.format(t_epoch, t_elapsed, t_all)) + + log(', '.join(log_info)) + writer.flush() + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('--config', default='configs/train_1x-5x_INR_funsr.yaml') + parser.add_argument('--name', default='tmp') + parser.add_argument('--tag', default=None) + parser.add_argument('--gpu', default='0') + args = parser.parse_args() + + with open(args.config, 'r') as f: + config = yaml.load(f, Loader=yaml.FullLoader) + print('config loaded.') + + save_name = args.name + if save_name is None: + save_name = '_' + args.config.split('/')[-1][:-len('.yaml')] + if args.tag is not None: + save_name += '_' + args.tag + save_path = os.path.join('./checkpoints', save_name) + + main(config, save_path) diff --git a/train_inr_funsr_ddp.py b/train_inr_funsr_ddp.py new file mode 100644 index 0000000000000000000000000000000000000000..524a4053e48167703d543a3b784380cc06a79f64 --- /dev/null +++ b/train_inr_funsr_ddp.py @@ -0,0 +1,347 @@ +import argparse +import json +import os +import torch.distributed as dist +from torch.nn.parallel import DistributedDataParallel as DDP + +import yaml +import torch +import torch.nn as nn +from tqdm import tqdm +from torch.utils.data import DataLoader +from torch.optim.lr_scheduler import MultiStepLR, CosineAnnealingLR + +import datasets +import models +import utils + + +def make_data_loader(spec, tag='', local_rank=0): + if spec is None: + return None + + dataset = datasets.make(spec['dataset']) + dataset = datasets.make(spec['wrapper'], args={'dataset': dataset}) + if local_rank == 0: + print('{} dataset: size={}'.format(tag, len(dataset))) + for k, v in dataset[0].items(): + if torch.is_tensor(v): + print(' {}: shape={}'.format(k, v.shape)) + elif isinstance(v, str): + pass + elif isinstance(v, dict): + for k0, v0 in v.items(): + if hasattr(v0, 'shape'): + print(' {}: shape={}'.format(k0, v0.shape)) + else: + raise NotImplementedError + sampler = torch.utils.data.distributed.DistributedSampler(dataset, shuffle=(tag == 'train')) + loader = torch.utils.data.DataLoader(dataset, + batch_size=spec['batch_size'], + num_workers=spec['num_workers'], + pin_memory=True, + sampler=sampler) + return loader + + +def make_data_loaders(config, local_rank): + train_loader = make_data_loader(config.get('train_dataset'), tag='train', local_rank=local_rank) + val_loader = make_data_loader(config.get('val_dataset'), tag='val', local_rank=local_rank) + return train_loader, val_loader + + +def prepare_training(config, local_rank): + if config.get('resume') is not None: + sv_file = torch.load(config['resume']) + model = models.make(sv_file['model'], load_sd=True).cuda() + model = torch.nn.SyncBatchNorm.convert_sync_batchnorm(model) + optimizer = utils.make_optimizer( + model.parameters(), sv_file['optimizer'], load_sd=True) + epoch_start = sv_file['epoch'] + 1 + if config.get('multi_step_lr') is None: + lr_scheduler = None + else: + lr_scheduler = MultiStepLR(optimizer, **config['multi_step_lr']) + for _ in range(epoch_start - 1): + lr_scheduler.step() + else: + model = models.make(config['model']).cuda(local_rank) + model = torch.nn.SyncBatchNorm.convert_sync_batchnorm(model) + model = torch.nn.parallel.DistributedDataParallel(model, device_ids=[local_rank]) + optimizer = utils.make_optimizer( + model.parameters(), config['optimizer']) + epoch_start = 1 + lr_scheduler = config.get('lr_scheduler') + lr_scheduler_name = lr_scheduler.pop('name') + if 'MultiStepLR' == lr_scheduler_name: + lr_scheduler = MultiStepLR(optimizer, **lr_scheduler) + elif 'CosineAnnealingLR' == lr_scheduler_name: + lr_scheduler = CosineAnnealingLR(optimizer, **lr_scheduler) + elif 'CosineAnnealingWarmUpLR' == lr_scheduler_name: + lr_scheduler = utils.warm_up_cosine_lr_scheduler(optimizer, **lr_scheduler) + if local_rank == 0: + print('model: #params={}'.format(utils.compute_num_params(model, text=True))) + return model, optimizer, epoch_start, lr_scheduler + +def reduce_mean(tensor, nprocs): + rt = tensor.clone() + dist.all_reduce(rt, op=dist.ReduceOp.SUM) + rt /= nprocs + return rt + +class AverageMeter(object): + """Computes and stores the average and current value""" + def __init__(self, name, fmt=':f'): + self.name = name + self.fmt = fmt + self.reset() + + def reset(self): + self.val = 0 + self.avg = 0 + self.sum = 0 + self.count = 0 + + def update(self, val, n=1): + self.val = val + self.sum += val * n + self.count += n + self.avg = self.sum / self.count + + def return_avg(self): + return self.avg + + def __str__(self): + fmtstr = '{name} {val' + self.fmt + '} ({avg' + self.fmt + '})' + return fmtstr.format(**self.__dict__) + +def train(train_loader, model, optimizer, local_rank): + model = model.train() + loss_fn = nn.L1Loss().cuda(local_rank) + train_losses = AverageMeter('Loss', ':.4e') + + data_norm = config['data_norm'] + t = data_norm['img'] + img_sub = torch.FloatTensor(t['sub']).view(1, -1, 1, 1).cuda(local_rank) + img_div = torch.FloatTensor(t['div']).view(1, -1, 1, 1).cuda(local_rank) + t = data_norm['gt'] + gt_sub = torch.FloatTensor(t['sub']).view(1, 1, -1).cuda(local_rank) + gt_div = torch.FloatTensor(t['div']).view(1, 1, -1).cuda(local_rank) + + if local_rank == 0: + pbar = tqdm(total=len(train_loader), desc='train', leave=False) + + for i, batch in enumerate(train_loader): + if local_rank == 0: + pbar.update(1) + keys = list(batch.keys()) + batch = batch[keys[torch.randint(0, len(keys), [])]] + for k, v in batch.items(): + if torch.is_tensor(v): + batch[k] = v.cuda(local_rank, non_blocking=True) + img = (batch['img'] - img_sub) / img_div + gt = (batch['gt'] - gt_sub) / gt_div + pred = model(img, gt.shape[-2:]) + if isinstance(pred, tuple): + loss = 0.2 * loss_fn(pred[0], gt) + loss_fn(pred[1], gt) + elif isinstance(pred, list): + losses = [loss_fn(x, gt) for x in pred] + losses = [x * (idx + 1) for idx, x in enumerate(losses)] + loss = sum(losses) / ((1 + len(losses)) * len(losses) / 2) + else: + loss = loss_fn(pred, gt) + + torch.distributed.barrier() + reduced_loss = reduce_mean(loss, dist.get_world_size()) + train_losses.update(reduced_loss.item(), img.size(0)) + + optimizer.zero_grad() + loss.backward() + optimizer.step() + + if local_rank == 0: + pbar.close() + return train_losses.avg + + +def eval_psnr(loader, class_names, model, local_rank, data_norm=None, eval_type=None, eval_bsize=None, verbose=False, crop_border=4): + crop_border = int(crop_border) if crop_border else crop_border + if local_rank == 0: + print('crop border: ', crop_border) + model = model.eval() + + if data_norm is None: + data_norm = { + 'img': {'sub': [0], 'div': [1]}, + 'gt': {'sub': [0], 'div': [1]} + } + t = data_norm['img'] + img_sub = torch.FloatTensor(t['sub']).view(1, -1, 1, 1).cuda(local_rank) + img_div = torch.FloatTensor(t['div']).view(1, -1, 1, 1).cuda(local_rank) + t = data_norm['gt'] + gt_sub = torch.FloatTensor(t['sub']).view(1, -1, 1, 1).cuda(local_rank) + gt_div = torch.FloatTensor(t['div']).view(1, -1, 1, 1).cuda(local_rank) + + if eval_type is None: + metric_fn = [utils.calculate_psnr_pt, utils.calculate_ssim_pt] + elif eval_type == 'psnr+ssim': + metric_fn = [utils.calculate_psnr_pt, utils.calculate_ssim_pt] + elif eval_type.startswith('div2k'): + scale = int(eval_type.split('-')[1]) + metric_fn = partial(utils.calc_psnr, dataset='div2k', scale=scale) + elif eval_type.startswith('benchmark'): + scale = int(eval_type.split('-')[1]) + metric_fn = partial(utils.calc_psnr, dataset='benchmark', scale=scale) + else: + raise NotImplementedError + + val_res_psnr = AverageMeter('psnr', ':.4f') + val_res_ssim = AverageMeter('ssim', ':.4f') + + if local_rank == 0: + pbar = tqdm(total=len(loader), desc='val', leave=False) + for batch in loader: + if local_rank == 0: + pbar.update(1) + for k, v in batch.items(): + if torch.is_tensor(v): + batch[k] = v.cuda(local_rank, non_blocking=True) + + img = (batch['img'] - img_sub) / img_div + with torch.no_grad(): + pred = model(img, batch['gt'].shape[-2:]) + if isinstance(pred, list): + pred = pred[-1] + pred = pred * gt_div + gt_sub + + res_psnr = metric_fn[0]( + pred, + batch['gt'], + crop_border=crop_border + ).mean() + res_ssim = metric_fn[1]( + pred, + batch['gt'], + crop_border=crop_border + ).mean() + + torch.distributed.barrier() + reduced_val_res_psnr = reduce_mean(res_psnr, dist.get_world_size()) + reduced_val_res_ssim = reduce_mean(res_ssim, dist.get_world_size()) + + val_res_psnr.update(reduced_val_res_psnr.item(), img.size(0)) + val_res_ssim.update(reduced_val_res_ssim.item(), img.size(0)) + + if verbose and local_rank == 0: + pbar.set_description( + 'val psnr: {:.4f} ssim: {:.4f}'.format(val_res_psnr.avg, val_res_ssim.avg)) + if local_rank == 0: + pbar.close() + return val_res_psnr.avg, val_res_ssim.avg + + +def main(config, save_path): + # torch.backends.cudnn.benchmark = True + dist.init_process_group("nccl") + rank = dist.get_rank() + local_rank = int(os.environ["LOCAL_RANK"]) + world_size = dist.get_world_size() + print(f'rank: {rank} local_rank: {local_rank} world_size: {world_size}') + # print(f'local_rank: {torch.distributed.local_rank()}') + if local_rank == 0: + log, writer = utils.set_save_path(save_path) + with open(os.path.join(save_path, 'config.yaml'), 'w') as f: + yaml.dump(config, f, sort_keys=False) + + train_loader, val_loader = make_data_loaders(config, local_rank) + if config.get('data_norm') is None: + config['data_norm'] = { + 'img': {'sub': [0], 'div': [1]}, + 'gt': {'sub': [0], 'div': [1]} + } + + model, optimizer, epoch_start, lr_scheduler = prepare_training(config, local_rank) + + epoch_max = config['epoch_max'] + epoch_val_interval = config.get('epoch_val_interval') + epoch_save_interval = config.get('epoch_save_interval') + max_val_v = -1e18 + + timer = utils.Timer() + + for epoch in range(epoch_start, epoch_max + 1): + t_epoch_start = timer.t() + train_loader.sampler.set_epoch(epoch) + + train_loss = train(train_loader, model, optimizer, local_rank) + if lr_scheduler is not None: + lr_scheduler.step() + + if rank == 0: + log_info = ['epoch {}/{}'.format(epoch, epoch_max)] + log_info.append('train: loss={:.4f}'.format(train_loss)) + writer.add_scalar('lr', optimizer.param_groups[0]['lr'], epoch) + writer.add_scalars('loss', {'train': train_loss}, epoch) + + model_ = model.module + model_spec = config['model'] + model_spec['sd'] = model_.state_dict() + optimizer_spec = config['optimizer'] + optimizer_spec['sd'] = optimizer.state_dict() + sv_file = { + 'model': model_spec, + 'optimizer': optimizer_spec, + 'epoch': epoch + } + if rank == 0: + torch.save(sv_file, os.path.join(save_path, 'epoch-last.pth')) + + if (epoch_save_interval is not None) and (epoch % epoch_save_interval == 0): + if rank == 0: + torch.save(sv_file, os.path.join(save_path, 'epoch-{}.pth'.format(epoch))) + + if (epoch_val_interval is not None) and (epoch % epoch_val_interval == 0): + file_names = json.load(open(config['val_dataset']['dataset']['args']['split_file']))['test'] + class_names = list(set([os.path.basename(os.path.dirname(x)) for x in file_names])) + + val_res_psnr, val_res_ssim = eval_psnr(val_loader, class_names, model_, local_rank, + data_norm=config['data_norm'], + eval_type=config.get('eval_type'), + eval_bsize=config.get('eval_bsize'), + crop_border=4) + if rank == 0: + log_info.append('val: psnr={:.4f}'.format(val_res_psnr)) + writer.add_scalars('psnr', {'val': val_res_psnr}, epoch) + if val_res_psnr > max_val_v: + max_val_v = val_res_psnr + if rank == 0: + torch.save(sv_file, os.path.join(save_path, 'epoch-best.pth')) + + t = timer.t() + if rank == 0: + prog = (epoch - epoch_start + 1) / (epoch_max - epoch_start + 1) + t_epoch = utils.time_text(t - t_epoch_start) + t_elapsed, t_all = utils.time_text(t), utils.time_text(t / prog) + log_info.append('{} {}/{}'.format(t_epoch, t_elapsed, t_all)) + log(', '.join(log_info)) + writer.flush() + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('--config', default='configs/train_1x-5x_INR_funsr.yaml') + parser.add_argument('--name', default='EXP20221216_11') + parser.add_argument('--tag', default=None) + args = parser.parse_args() + + with open(args.config, 'r') as f: + config = yaml.load(f, Loader=yaml.FullLoader) + print('config loaded.') + + save_name = args.name + if save_name is None: + save_name = '_' + args.config.split('/')[-1][:-len('.yaml')] + if args.tag is not None: + save_name += '_' + args.tag + save_path = os.path.join('./checkpoints', save_name) + main(config, save_path) diff --git a/train_liif_metasr_aliff.py b/train_liif_metasr_aliff.py new file mode 100644 index 0000000000000000000000000000000000000000..61efef89c45eeb787115de2d2fe68a645d50d9de --- /dev/null +++ b/train_liif_metasr_aliff.py @@ -0,0 +1,227 @@ +import argparse +import json +import math +import os +os.environ['CUDA_VISIBLE_DEVICES'] = '1' + +import yaml +import torch +import torch.nn as nn +from tqdm import tqdm +from torch.utils.data import DataLoader +from torch.optim.lr_scheduler import MultiStepLR, CosineAnnealingLR + +import datasets +import models +import utils +from test_inr_liif_metasr_aliif import eval_psnr + +device = 'cuda:0' if torch.cuda.is_available() else 'cpu' + +def make_data_loader(spec, tag=''): + if spec is None: + return None + + dataset = datasets.make(spec['dataset']) + dataset = datasets.make(spec['wrapper'], args={'dataset': dataset}) + + log('{} dataset: size={}'.format(tag, len(dataset))) + for k, v in dataset[0].items(): + if hasattr(v, 'shape'): + log(' {}: shape={}'.format(k, tuple(v.shape))) + + loader = DataLoader(dataset, batch_size=spec['batch_size'], + shuffle=(tag == 'train'), num_workers=spec['num_workers'], pin_memory=True) + return loader + + +def make_data_loaders(): + train_loader = make_data_loader(config.get('train_dataset'), tag='train') + val_loader = make_data_loader(config.get('val_dataset'), tag='val') + return train_loader, val_loader + + +def prepare_training(): + if config.get('resume') is not None: + sv_file = torch.load(config['resume']) + model = models.make(sv_file['model'], load_sd=True).to(device) + optimizer = utils.make_optimizer( + model.parameters(), sv_file['optimizer'], load_sd=True) + epoch_start = sv_file['epoch'] + 1 + if config.get('multi_step_lr') is None: + lr_scheduler = None + else: + lr_scheduler = MultiStepLR(optimizer, **config['multi_step_lr']) + for _ in range(epoch_start - 1): + lr_scheduler.step() + else: + model = models.make(config['model']).to(device) + optimizer = utils.make_optimizer( + model.parameters(), config['optimizer']) + epoch_start = 1 + lr_scheduler = config.get('lr_scheduler') + lr_scheduler_name = lr_scheduler.pop('name') + + if 'MultiStepLR' == lr_scheduler_name: + lr_scheduler = MultiStepLR(optimizer, **lr_scheduler) + elif 'CosineAnnealingLR' == lr_scheduler_name: + lr_scheduler = CosineAnnealingLR(optimizer, **lr_scheduler) + + log('model: #params={}'.format(utils.compute_num_params(model, text=True))) + return model, optimizer, epoch_start, lr_scheduler + + +def train(train_loader, model, optimizer): + model.train() + loss_fn = nn.L1Loss() + + train_loss = utils.AveragerList() + + data_norm = config['data_norm'] + t = data_norm['inp'] + inp_sub = torch.FloatTensor(t['sub']).view(1, -1, 1, 1).to(device) + inp_div = torch.FloatTensor(t['div']).view(1, -1, 1, 1).to(device) + t = data_norm['gt'] + gt_sub = torch.FloatTensor(t['sub']).view(1, 1, -1).to(device) + gt_div = torch.FloatTensor(t['div']).view(1, 1, -1).to(device) + + for batch in tqdm(train_loader, leave=False, desc='train'): + for k, v in batch.items(): + if torch.is_tensor(v): + batch[k] = v.to(device) + + inp = (batch['inp'] - inp_sub) / inp_div + pred = model(inp, batch['coord'], batch['cell']) + gt = (batch['gt'] - gt_sub) / gt_div + + if isinstance(pred, tuple): + loss = 0.2 * loss_fn(pred[0], gt) + loss_fn(pred[1], gt) + elif isinstance(pred, list): + losses = [loss_fn(x, gt) for x in pred] + losses = [x*(idx+1) for idx, x in enumerate(losses)] + loss = sum(losses) / ((1+len(losses))*len(losses)/2) + else: + loss = loss_fn(pred, gt) + + train_loss.add(loss.item()) + + optimizer.zero_grad() + loss.backward() + optimizer.step() + + return train_loss.item() + + +def main(config_, save_path): + global config, log, writer + config = config_ + log, writer = utils.set_save_path(save_path) + with open(os.path.join(save_path, 'config.yaml'), 'w') as f: + yaml.dump(config, f, sort_keys=False) + + train_loader, val_loader = make_data_loaders() + if config.get('data_norm') is None: + config['data_norm'] = { + 'inp': {'sub': [0], 'div': [1]}, + 'gt': {'sub': [0], 'div': [1]} + } + + model, optimizer, epoch_start, lr_scheduler = prepare_training() + + if device != 'cpu': + n_gpus = len(os.environ['CUDA_VISIBLE_DEVICES'].split(',')) + if n_gpus > 1: + model = nn.parallel.DataParallel(model) + + epoch_max = config['epoch_max'] + epoch_val_interval = config.get('epoch_val_interval') + epoch_save_interval = config.get('epoch_save_interval') + max_val_v = -1e18 + + timer = utils.Timer() + + for epoch in range(epoch_start, epoch_max + 1): + t_epoch_start = timer.t() + log_info = ['epoch {}/{}'.format(epoch, epoch_max)] + + writer.add_scalar('lr', optimizer.param_groups[0]['lr'], epoch) + + train_loss = train(train_loader, model, optimizer) + if lr_scheduler is not None: + lr_scheduler.step() + + log_info.append('train: loss={:.4f}'.format(train_loss)) + writer.add_scalars('loss', {'train': train_loss}, epoch) + + if device != 'cpu' and n_gpus > 1: + model_ = model.module + else: + model_ = model + model_spec = config['model'] + model_spec['sd'] = model_.state_dict() + optimizer_spec = config['optimizer'] + optimizer_spec['sd'] = optimizer.state_dict() + sv_file = { + 'model': model_spec, + 'optimizer': optimizer_spec, + 'epoch': epoch + } + + torch.save(sv_file, os.path.join(save_path, 'epoch-last.pth')) + + if (epoch_save_interval is not None) and (epoch % epoch_save_interval == 0): + torch.save(sv_file, os.path.join(save_path, 'epoch-{}.pth'.format(epoch))) + + if (epoch_val_interval is not None) and (epoch % epoch_val_interval == 0): + if device != 'cpu' and n_gpus > 1 and (config.get('eval_bsize') is not None): + model_ = model.module + else: + model_ = model + + file_names = json.load(open(config['val_dataset']['dataset']['args']['split_file']))['test'] + class_names = list(set([os.path.basename(os.path.dirname(x)) for x in file_names])) + + val_res_psnr, val_res_ssim = eval_psnr(val_loader, class_names, model_, + data_norm=config['data_norm'], + eval_type=config.get('eval_type'), + eval_bsize=config.get('eval_bsize'), + crop_border=4) + + log_info.append('val: psnr={:.4f}'.format(val_res_psnr['all'])) + writer.add_scalars('psnr', {'val': val_res_psnr['all']}, epoch) + if val_res_psnr['all'] > max_val_v: + max_val_v = val_res_psnr['all'] + torch.save(sv_file, os.path.join(save_path, 'epoch-best.pth')) + + t = timer.t() + prog = (epoch - epoch_start + 1) / (epoch_max - epoch_start + 1) + t_epoch = utils.time_text(t - t_epoch_start) + t_elapsed, t_all = utils.time_text(t), utils.time_text(t / prog) + log_info.append('{} {}/{}'.format(t_epoch, t_elapsed, t_all)) + + log(', '.join(log_info)) + writer.flush() + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + # parser.add_argument('--config', default='configs/baselines/train_1x-5x_INR_liif.yaml') + # parser.add_argument('--config', default='configs/baselines/train_1x-5x_INR_metasr.yaml') + parser.add_argument('--config', default='configs/baselines/train_1x-5x_INR_aliif.yaml') + parser.add_argument('--name', default='EXP20221204_1') + parser.add_argument('--tag', default=None) + parser.add_argument('--gpu', default='0') + args = parser.parse_args() + + with open(args.config, 'r') as f: + config = yaml.load(f, Loader=yaml.FullLoader) + print('config loaded.') + + save_name = args.name + if save_name is None: + save_name = '_' + args.config.split('/')[-1][:-len('.yaml')] + if args.tag is not None: + save_name += '_' + args.tag + save_path = os.path.join('./checkpoints', save_name) + + main(config, save_path) diff --git a/utils.py b/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..6846f4f255d79a6bc414f9a660373398370a7bc6 --- /dev/null +++ b/utils.py @@ -0,0 +1,329 @@ +import os +import time +import shutil +import math + +import cv2 +import torch +import numpy as np +from einops import rearrange +from torch.optim import SGD, Adam, AdamW +from tensorboardX import SummaryWriter +import torch.nn.functional as F + + +def warm_up_cosine_lr_scheduler(optimizer, epochs=100, warm_up_epochs=5, eta_min=1e-9): + """ + Description: + - Warm up cosin learning rate scheduler, first epoch lr is too small + + Arguments: + - optimizer: input optimizer for the training + - epochs: int, total epochs for your training, default is 100. NOTE: you should pass correct epochs for your training + - warm_up_epochs: int, default is 5, which mean the lr will be warm up for 5 epochs. if warm_up_epochs=0, means no need + to warn up, will be as cosine lr scheduler + - eta_min: float, setup ConsinAnnealingLR eta_min while warm_up_epochs = 0 + + Returns: + - scheduler + """ + + if warm_up_epochs <= 0: + scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=epochs, eta_min=eta_min) + + else: + warm_up_with_cosine_lr = lambda epoch: eta_min + (epoch / warm_up_epochs) \ + if epoch <= warm_up_epochs else \ + 0.5 * (np.cos((epoch - warm_up_epochs) / (epochs - warm_up_epochs) * np.pi) + 1) + scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda=warm_up_with_cosine_lr) + + return scheduler + + +class Averager(): + + def __init__(self, class_names=['all']): + if 'all' not in class_names: + class_names.append('all') + self.values = {k: [] for k in class_names} + + def add(self, ks, vs): + if torch.is_tensor(vs): + vs = vs.cpu().tolist() + for k, v in zip(ks, vs): + self.values[k].append(v) + self.values['all'].append(v) + + def item(self): + return_dict = {} + for k, v in self.values.items(): + if len(v): + return_dict[k] = sum(v) / len(v) + else: + return_dict[k] = 0 + return return_dict + +class AveragerList(): + + def __init__(self): + self.values = [] + + def add(self, vs): + if torch.is_tensor(vs): + vs = vs.cpu().tolist() + if isinstance(vs, list): + self.values += vs + else: + self.values += [vs] + + def item(self): + return sum(self.values) / len(self.values) + + +class Timer(): + + def __init__(self): + self.v = time.time() + + def s(self): + self.v = time.time() + + def t(self): + return time.time() - self.v + + +def time_text(t): + if t >= 3600: + return '{:.1f}h'.format(t / 3600) + elif t >= 60: + return '{:.1f}m'.format(t / 60) + else: + return '{:.1f}s'.format(t) + + +_log_path = None + + +def set_log_path(path): + global _log_path + _log_path = path + + +def log(obj, filename='log.txt'): + print(obj) + if _log_path is not None: + with open(os.path.join(_log_path, filename), 'a') as f: + print(obj, file=f) + + +def ensure_path(path, remove=True): + basename = os.path.basename(path.rstrip('/')) + if os.path.exists(path): + print('{} exists!'.format(path)) + # if remove and (basename.startswith('_') + # or input('{} exists, remove? (y/[n]): '.format(path)) == 'y'): + # shutil.rmtree(path) + # os.makedirs(path) + else: + os.makedirs(path) + + +def set_save_path(save_path, remove=True): + ensure_path(save_path, remove=remove) + set_log_path(save_path) + writer = SummaryWriter(os.path.join(save_path, 'tensorboard')) + return log, writer + + +def compute_num_params(model, text=False): + tot = int(sum([np.prod(p.shape) for p in model.parameters()])) + if text: + if tot >= 1e6: + return '{:.1f}M'.format(tot / 1e6) + else: + return '{:.1f}K'.format(tot / 1e3) + else: + return tot + + +def make_optimizer(param_list, optimizer_spec, load_sd=False): + Optimizer = { + 'sgd': SGD, + 'adam': Adam, + 'adamw': AdamW, + }[optimizer_spec['name']] + default_args = { + 'sgd': {}, + 'adam': + { + 'betas': (0.9, 0.999), + 'eps': 1e-08, + 'weight_decay': 0, + 'amsgrad': False + }, + 'adamw': {}, + }[optimizer_spec['name']] + default_args.update(optimizer_spec['args']) + optimizer = Optimizer(param_list, **default_args) + if load_sd: + optimizer.load_state_dict(optimizer_spec['sd']) + return optimizer + + +def make_coord(shape, ranges=None, flatten=True): + """ Make coordinates at grid centers. + """ + coord_seqs = [] + for i, n in enumerate(shape): + if ranges is None: + v0, v1 = -1, 1 + else: + v0, v1 = ranges[i] + r = (v1 - v0) / (2 * n) + seq = v0 + r + (2 * r) * torch.arange(n).float() + coord_seqs.append(seq) + ret = torch.stack(torch.meshgrid(*coord_seqs), dim=-1) + if flatten: + ret = ret.view(-1, ret.shape[-1]) + return ret + + +def to_coordinates(size=(56, 56), return_map=True): + """Converts an image to a set of coordinates and features. + + Args: + img (torch.Tensor): Shape (channels, height, width). + """ + # H, W + # Coordinates are indices of all non zero locations of a tensor of ones of + # same shape as spatial dimensions of image + coordinates = torch.ones(size).nonzero(as_tuple=False).float() + # Normalize coordinates to lie in [-.5, .5] + coordinates[..., 0] = coordinates[..., 0] / (size[0] - 1) - 0.5 + coordinates[..., 1] = coordinates[..., 1] / (size[1] - 1) - 0.5 + # Convert to range [-1, 1] + coordinates *= 2 + if return_map: + coordinates = rearrange(coordinates, '(H W) C -> H W C', H=size[0]) + # [y, x] + return coordinates + + +def to_pixel_samples(img): + """ Convert the image to coord-RGB pairs. + img: Tensor, (3, H, W) + """ + coord = make_coord(img.shape[-2:]) + rgb = img.view(3, -1).permute(1, 0) + return coord, rgb + + +def get_clamped_psnr(img, img_recon, rgb_range=1, crop_border=None): + # Values may lie outside [0, 1], so clamp input + img_recon = torch.clamp(img_recon, 0., 1.) + # Pixel values lie in {0, ..., 255}, so round float tensor + img_recon = torch.round(img_recon * 255) / 255. + diff = img - img_recon + if crop_border is not None: + assert len(diff.size()) == 4 + valid = diff[..., crop_border:-crop_border, crop_border:-crop_border] + else: + valid = diff + + psnr_list = [] + for i in range(len(img)): + psnr = 20. * np.log10(1.) - 10. * valid[i].detach().pow(2).mean().log10().to('cpu').item() + psnr_list.append(psnr) + return psnr_list + + +def _ssim_pth(img, img2): + """Calculate SSIM (structural similarity) (PyTorch version). + It is called by func:`calculate_ssim_pt`. + Args: + img (Tensor): Images with range [0, 1], shape (n, 3/1, h, w). + img2 (Tensor): Images with range [0, 1], shape (n, 3/1, h, w). + Returns: + float: SSIM result. + """ + c1 = (0.01 * 255)**2 + c2 = (0.03 * 255)**2 + + kernel = cv2.getGaussianKernel(11, 1.5) + window = np.outer(kernel, kernel.transpose()) + window = torch.from_numpy(window).view(1, 1, 11, 11).expand(img.size(1), 1, 11, 11).to(img.dtype).to(img.device) + + mu1 = F.conv2d(img, window, stride=1, padding=0, groups=img.shape[1]) # valid mode + mu2 = F.conv2d(img2, window, stride=1, padding=0, groups=img2.shape[1]) # valid mode + mu1_sq = mu1.pow(2) + mu2_sq = mu2.pow(2) + mu1_mu2 = mu1 * mu2 + sigma1_sq = F.conv2d(img * img, window, stride=1, padding=0, groups=img.shape[1]) - mu1_sq + sigma2_sq = F.conv2d(img2 * img2, window, stride=1, padding=0, groups=img.shape[1]) - mu2_sq + sigma12 = F.conv2d(img * img2, window, stride=1, padding=0, groups=img.shape[1]) - mu1_mu2 + + cs_map = (2 * sigma12 + c2) / (sigma1_sq + sigma2_sq + c2) + ssim_map = ((2 * mu1_mu2 + c1) / (mu1_sq + mu2_sq + c1)) * cs_map + return ssim_map.mean([1, 2, 3]) + + +def calculate_ssim_pt(img, img2, crop_border, test_y_channel=False, **kwargs): + """Calculate SSIM (structural similarity) (PyTorch version). + ``Paper: Image quality assessment: From error visibility to structural similarity`` + The results are the same as that of the official released MATLAB code in + https://ece.uwaterloo.ca/~z70wang/research/ssim/. + For three-channel images, SSIM is calculated for each channel and then + averaged. + Args: + img (Tensor): Images with range [0, 1], shape (n, 3/1, h, w). + img2 (Tensor): Images with range [0, 1], shape (n, 3/1, h, w). + crop_border (int): Cropped pixels in each edge of an image. These pixels are not involved in the calculation. + test_y_channel (bool): Test on Y channel of YCbCr. Default: False. + Returns: + float: SSIM result. + """ + + assert img.shape == img2.shape, f'Image shapes are different: {img.shape}, {img2.shape}.' + + if crop_border != 0: + img = img[:, :, crop_border:-crop_border, crop_border:-crop_border] + img2 = img2[:, :, crop_border:-crop_border, crop_border:-crop_border] + + if test_y_channel: + img = rgb2ycbcr_pt(img, y_only=True) + img2 = rgb2ycbcr_pt(img2, y_only=True) + + img = img.to(torch.float64) + img2 = img2.to(torch.float64) + + ssim = _ssim_pth(img * 255., img2 * 255.) + return ssim + + +def calculate_psnr_pt(img, img2, crop_border, test_y_channel=False, **kwargs): + """Calculate PSNR (Peak Signal-to-Noise Ratio) (PyTorch version). + Reference: https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio + Args: + img (Tensor): Images with range [0, 1], shape (n, 3/1, h, w). + img2 (Tensor): Images with range [0, 1], shape (n, 3/1, h, w). + crop_border (int): Cropped pixels in each edge of an image. These pixels are not involved in the calculation. + test_y_channel (bool): Test on Y channel of YCbCr. Default: False. + Returns: + float: PSNR result. + """ + + assert img.shape == img2.shape, (f'Image shapes are different: {img.shape}, {img2.shape}.') + + if crop_border != 0: + img = img[:, :, crop_border:-crop_border, crop_border:-crop_border] + img2 = img2[:, :, crop_border:-crop_border, crop_border:-crop_border] + + if test_y_channel: + img = rgb2ycbcr_pt(img, y_only=True) + img2 = rgb2ycbcr_pt(img2, y_only=True) + + img = img.to(torch.float64) + img2 = img2.to(torch.float64) + + mse = torch.mean((img - img2)**2, dim=[1, 2, 3]) + return 10. * torch.log10(1. / (mse + 1e-8))