Spaces:
Configuration error
Configuration error
Upload 60 files
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .gitattributes +8 -0
- =1.4 +52 -0
- DexiNed-TF2/README.md +47 -0
- DexiNed-TF2/dataset_manager.py +280 -0
- DexiNed-TF2/mainTF.py +99 -0
- DexiNed-TF2/model.py +346 -0
- DexiNed-TF2/run_model.py +234 -0
- DexiNed-TF2/utls.py +257 -0
- LICENSE +21 -0
- README.md +204 -19
- __pycache__/datasets.cpython-312.pyc +0 -0
- __pycache__/dexi_utils.cpython-312.pyc +0 -0
- __pycache__/losses.cpython-312.pyc +0 -0
- __pycache__/model.cpython-312.pyc +0 -0
- app.py +84 -0
- checkpoints/BIPED/10/10_model.pth +3 -0
- data/1739757991209.png +3 -0
- dataset-lists/MDBD/test_pair.lst +20 -0
- datasets.py +490 -0
- dexi_utils.py +87 -0
- figs/DexiNed_banner.png +3 -0
- legacy/README.md +132 -0
- legacy/figs/DexiNed_banner.png +3 -0
- legacy/models/dexined.py +503 -0
- legacy/requirements.txt +33 -0
- legacy/run_model.py +134 -0
- legacy/test.py +129 -0
- legacy/train.py +150 -0
- legacy/utls/dataset_manager.py +1336 -0
- legacy/utls/losses.py +47 -0
- legacy/utls/utls.py +385 -0
- losses.py +148 -0
- main.py +481 -0
- model.py +286 -0
- requirements.txt +8 -3
- res/BIPED/DexiNed-a/eval_bdry.txt +1 -0
- res/BIPED/DexiNed-a/eval_bdry_img.txt +50 -0
- res/BIPED/DexiNed-a/eval_bdry_thr.txt +99 -0
- res/BIPED/DexiNed-a/ios_res.txt +51 -0
- res/BIPED/DexiNed-f/eval_bdry.txt +1 -0
- res/BIPED/DexiNed-f/eval_bdry_img.txt +50 -0
- res/BIPED/DexiNed-f/eval_bdry_thr.txt +99 -0
- res/BIPED/DexiNed-f/ios_res.txt +51 -0
- res/MDBD/DexiNed-a/eval_bdry.txt +1 -0
- res/MDBD/DexiNed-a/eval_bdry_img.txt +20 -0
- res/MDBD/DexiNed-a/eval_bdry_thr.txt +99 -0
- res/MDBD/DexiNed-a/ios_res.txt +21 -0
- res/MDBD/DexiNed-f/eval_bdry.txt +1 -0
- res/MDBD/DexiNed-f/eval_bdry_img.txt +20 -0
- res/MDBD/DexiNed-f/eval_bdry_thr.txt +99 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,11 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
data/1739757991209.png filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
figs/DexiNed_banner.png filter=lfs diff=lfs merge=lfs -text
|
| 38 |
+
legacy/figs/DexiNed_banner.png filter=lfs diff=lfs merge=lfs -text
|
| 39 |
+
result/BIPED2CLASSIC/avg/1739757991209.png filter=lfs diff=lfs merge=lfs -text
|
| 40 |
+
result/BIPED2CLASSIC/avg/Hyundai_Komponen_Mobil_utamaaa.png filter=lfs diff=lfs merge=lfs -text
|
| 41 |
+
result/BIPED2CLASSIC/avg/jalan-rusak-di-ruas-jalan-solo-semarang-boyolali_169.png filter=lfs diff=lfs merge=lfs -text
|
| 42 |
+
result/BIPED2CLASSIC/avg/TC[[:space:]]10[[:space:]]MARET[[:space:]]-[[:space:]]TIPS[[:space:]]MENGHINDAR[[:space:]]DARI[[:space:]]LUBANG[[:space:]]JALAN[[:space:]](UMUM).png filter=lfs diff=lfs merge=lfs -text
|
| 43 |
+
result/BIPED2CLASSIC/fused/1739757991209.png filter=lfs diff=lfs merge=lfs -text
|
=1.4
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Collecting torch
|
| 2 |
+
Downloading torch-2.7.0-cp312-cp312-manylinux_2_28_x86_64.whl.metadata (29 kB)
|
| 3 |
+
Collecting filelock (from torch)
|
| 4 |
+
Downloading filelock-3.18.0-py3-none-any.whl.metadata (2.9 kB)
|
| 5 |
+
Collecting typing-extensions>=4.10.0 (from torch)
|
| 6 |
+
Downloading typing_extensions-4.13.2-py3-none-any.whl.metadata (3.0 kB)
|
| 7 |
+
Collecting setuptools (from torch)
|
| 8 |
+
Downloading setuptools-80.8.0-py3-none-any.whl.metadata (6.6 kB)
|
| 9 |
+
Collecting sympy>=1.13.3 (from torch)
|
| 10 |
+
Downloading sympy-1.14.0-py3-none-any.whl.metadata (12 kB)
|
| 11 |
+
Collecting networkx (from torch)
|
| 12 |
+
Downloading networkx-3.4.2-py3-none-any.whl.metadata (6.3 kB)
|
| 13 |
+
Collecting jinja2 (from torch)
|
| 14 |
+
Downloading jinja2-3.1.6-py3-none-any.whl.metadata (2.9 kB)
|
| 15 |
+
Collecting fsspec (from torch)
|
| 16 |
+
Downloading fsspec-2025.5.0-py3-none-any.whl.metadata (11 kB)
|
| 17 |
+
Collecting nvidia-cuda-nvrtc-cu12==12.6.77 (from torch)
|
| 18 |
+
Downloading nvidia_cuda_nvrtc_cu12-12.6.77-py3-none-manylinux2014_x86_64.whl.metadata (1.5 kB)
|
| 19 |
+
Collecting nvidia-cuda-runtime-cu12==12.6.77 (from torch)
|
| 20 |
+
Downloading nvidia_cuda_runtime_cu12-12.6.77-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.metadata (1.5 kB)
|
| 21 |
+
Collecting nvidia-cuda-cupti-cu12==12.6.80 (from torch)
|
| 22 |
+
Downloading nvidia_cuda_cupti_cu12-12.6.80-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.metadata (1.6 kB)
|
| 23 |
+
Collecting nvidia-cudnn-cu12==9.5.1.17 (from torch)
|
| 24 |
+
Downloading nvidia_cudnn_cu12-9.5.1.17-py3-none-manylinux_2_28_x86_64.whl.metadata (1.6 kB)
|
| 25 |
+
Collecting nvidia-cublas-cu12==12.6.4.1 (from torch)
|
| 26 |
+
Downloading nvidia_cublas_cu12-12.6.4.1-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.metadata (1.5 kB)
|
| 27 |
+
Collecting nvidia-cufft-cu12==11.3.0.4 (from torch)
|
| 28 |
+
Downloading nvidia_cufft_cu12-11.3.0.4-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.metadata (1.5 kB)
|
| 29 |
+
Collecting nvidia-curand-cu12==10.3.7.77 (from torch)
|
| 30 |
+
Downloading nvidia_curand_cu12-10.3.7.77-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.metadata (1.5 kB)
|
| 31 |
+
Collecting nvidia-cusolver-cu12==11.7.1.2 (from torch)
|
| 32 |
+
Downloading nvidia_cusolver_cu12-11.7.1.2-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.metadata (1.6 kB)
|
| 33 |
+
Collecting nvidia-cusparse-cu12==12.5.4.2 (from torch)
|
| 34 |
+
Downloading nvidia_cusparse_cu12-12.5.4.2-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.metadata (1.6 kB)
|
| 35 |
+
Collecting nvidia-cusparselt-cu12==0.6.3 (from torch)
|
| 36 |
+
Downloading nvidia_cusparselt_cu12-0.6.3-py3-none-manylinux2014_x86_64.whl.metadata (6.8 kB)
|
| 37 |
+
Collecting nvidia-nccl-cu12==2.26.2 (from torch)
|
| 38 |
+
Downloading nvidia_nccl_cu12-2.26.2-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.metadata (2.0 kB)
|
| 39 |
+
Collecting nvidia-nvtx-cu12==12.6.77 (from torch)
|
| 40 |
+
Downloading nvidia_nvtx_cu12-12.6.77-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.metadata (1.6 kB)
|
| 41 |
+
Collecting nvidia-nvjitlink-cu12==12.6.85 (from torch)
|
| 42 |
+
Downloading nvidia_nvjitlink_cu12-12.6.85-py3-none-manylinux2010_x86_64.manylinux_2_12_x86_64.whl.metadata (1.5 kB)
|
| 43 |
+
Collecting nvidia-cufile-cu12==1.11.1.6 (from torch)
|
| 44 |
+
Downloading nvidia_cufile_cu12-1.11.1.6-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.metadata (1.5 kB)
|
| 45 |
+
Collecting triton==3.3.0 (from torch)
|
| 46 |
+
Downloading triton-3.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.metadata (1.5 kB)
|
| 47 |
+
Collecting mpmath<1.4,>=1.1.0 (from sympy>=1.13.3->torch)
|
| 48 |
+
Downloading mpmath-1.3.0-py3-none-any.whl.metadata (8.6 kB)
|
| 49 |
+
Collecting MarkupSafe>=2.0 (from jinja2->torch)
|
| 50 |
+
Downloading MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (4.0 kB)
|
| 51 |
+
Downloading torch-2.7.0-cp312-cp312-manylinux_2_28_x86_64.whl (865.0 MB)
|
| 52 |
+
━━━━━━━━━━━━━━━━━━━━━╸ 466.4/865.0 MB 2.4 MB/s eta 0:02:48
|
DexiNed-TF2/README.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
In cosntruction
|
| 2 |
+
|
| 3 |
+
# DexiNed-TF2
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
This repo is an official unofficial version of DexiNed in TensorFlow Keras. The first official version of [DexiNed is in Tensorflow1.13](https://github.com/xavysp/DexiNed).
|
| 7 |
+
|
| 8 |
+
## Requerements
|
| 9 |
+
|
| 10 |
+
* Python 3.7
|
| 11 |
+
* Tensorflow 2.2.
|
| 12 |
+
* OpenCV
|
| 13 |
+
|
| 14 |
+
## Training and Testing Settings
|
| 15 |
+
|
| 16 |
+
Either for training or testing you should set dataset_manager.py, there you could find details of datasets like size, source, and so on, you should set before running DexiNed-TF2.
|
| 17 |
+
Then you can set the following code in main.py:
|
| 18 |
+
```
|
| 19 |
+
DATASET_NAME= ['BIPED','BSDS','BSDS300','CID','DCD','MULTICUE',
|
| 20 |
+
'PASCAL','NYUD','CLASSIC'] # 8
|
| 21 |
+
TEST_DATA = DATASET_NAME[1]
|
| 22 |
+
TRAIN_DATA = DATASET_NAME[0]
|
| 23 |
+
...
|
| 24 |
+
parser.add_argument("--model_state",default='test', choices=["train", "test", "export"])
|
| 25 |
+
|
| 26 |
+
```
|
| 27 |
+
Model_state should be "train" for training :)
|
| 28 |
+
To train DexiNed-TF2 is similar to training in Tensorflow. For more details see [DexiNed](https://github.com/xavysp/DexiNed/blob/master/README.md).
|
| 29 |
+
|
| 30 |
+
To summarize: firstly you should download and unzip the BIPED dataset hosted in [Kaggle](https://www.kaggle.com/xavysp/biped). Secondly, augment the dataset with [this ripo](https://github.com/xavysp/MBIPED). Once the BIPED is augmented run.
|
| 31 |
+
|
| 32 |
+
If you want to use just for testing with single images please choice "Classic" dataset, make a dir "data" into DexiNed-TF2, and leave the images for testing into "data" dir and run in "test" mode. You will find the model's weights [Here](https://drive.google.com/file/d/19Gwa6egqzNolvX4eUoXn-SjRKzxB68AA/view?usp=sharing)
|
| 33 |
+
|
| 34 |
+
# Citation
|
| 35 |
+
Please cite our paper if you find helpful,
|
| 36 |
+
```
|
| 37 |
+
@InProceedings{soria2020dexined,
|
| 38 |
+
title={Dense Extreme Inception Network: Towards a Robust CNN Model for Edge Detection},
|
| 39 |
+
author={Xavier Soria and Edgar Riba and Angel Sappa},
|
| 40 |
+
booktitle={The IEEE Winter Conference on Applications of Computer Vision (WACV '20)},
|
| 41 |
+
year={2020}
|
| 42 |
+
}
|
| 43 |
+
```
|
| 44 |
+
```diff
|
| 45 |
+
+ If you find some typos or you think we can improve the code, we will appreciate your contribution
|
| 46 |
+
|
| 47 |
+
```
|
DexiNed-TF2/dataset_manager.py
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import tensorflow as tf
|
| 2 |
+
import numpy as np
|
| 3 |
+
import h5py, os
|
| 4 |
+
import random
|
| 5 |
+
import cv2 as cv
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
AUTOTUNE = tf.data.experimental.AUTOTUNE
|
| 9 |
+
BUFFER_SIZE = 1024
|
| 10 |
+
|
| 11 |
+
img_shape =None
|
| 12 |
+
|
| 13 |
+
class DataLoader(tf.keras.utils.Sequence):
|
| 14 |
+
|
| 15 |
+
def __init__(self,data_name,arg=None, is_val=False):
|
| 16 |
+
|
| 17 |
+
self.is_training = True if arg.model_state.lower() == 'train' else False
|
| 18 |
+
self.dim_w = arg.image_width if self.is_training else arg.test_img_width
|
| 19 |
+
self.dim_h = arg.image_height if self.is_training else arg.test_img_height
|
| 20 |
+
self.args = arg
|
| 21 |
+
self.base_dir = arg.train_dir if arg.model_state.lower()=='train' else arg.test_dir
|
| 22 |
+
self.is_val = is_val
|
| 23 |
+
self.data_name =data_name
|
| 24 |
+
self.bs = arg.batch_size if self.is_training else arg.test_bs
|
| 25 |
+
self.shuffle=self.is_training
|
| 26 |
+
if not self.is_training and arg.model_state=="test":
|
| 27 |
+
i_width = self.dim_w if self.dim_w%16==0 else (self.dim_w//16+1)*16
|
| 28 |
+
i_height= self.dim_h if self.dim_h%16==0 else (self.dim_h//16+1)*16
|
| 29 |
+
self.input_shape = (None,i_height, i_width,3)
|
| 30 |
+
self.dim_w = i_width
|
| 31 |
+
self.dim_h = i_height
|
| 32 |
+
self.imgs_shape = []
|
| 33 |
+
# OMSIV real size= 320,580,3
|
| 34 |
+
self.data_list = self._build_index()
|
| 35 |
+
self.on_epoch_end()
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
def _build_index(self):
|
| 39 |
+
|
| 40 |
+
# base_dir = os.path.join(self.base_dir, self.args.model_state.lower())
|
| 41 |
+
list_name= self.args.train_list if self.is_training else self.args.test_list
|
| 42 |
+
|
| 43 |
+
if not self.data_name.lower()=='classic':
|
| 44 |
+
file_path = os.path.join(self.base_dir, list_name)
|
| 45 |
+
with open(file_path,'r') as f:
|
| 46 |
+
file_list = f.readlines()
|
| 47 |
+
file_list = [line.strip() for line in file_list] # to clean the '\n'
|
| 48 |
+
file_list = [line.split(' ') for line in file_list] # separate paths
|
| 49 |
+
if self.data_name.lower() in ['biped','mbiped']:
|
| 50 |
+
m_mode = 'train' if self.is_training else 'test'
|
| 51 |
+
input_path = [os.path.join(
|
| 52 |
+
self.base_dir,'imgs',m_mode,line[0]) for line in file_list]
|
| 53 |
+
gt_path = [os.path.join(
|
| 54 |
+
self.base_dir,'edge_maps',m_mode,line[1]) for line in file_list]
|
| 55 |
+
elif self.data_name.lower()=='classic':
|
| 56 |
+
file_list = os.listdir(self.base_dir)
|
| 57 |
+
input_path = [os.path.join(self.base_dir,line) for line in file_list]
|
| 58 |
+
gt_path = None
|
| 59 |
+
else:
|
| 60 |
+
input_path = [os.path.join(self.base_dir, line[0]) for line in file_list]
|
| 61 |
+
gt_path = [os.path.join(self.base_dir, line[1]) for line in file_list]
|
| 62 |
+
|
| 63 |
+
# split training and validation, val=10%
|
| 64 |
+
if self.is_training and self.is_val:
|
| 65 |
+
input_path = input_path[int(0.9 * len(input_path)):]
|
| 66 |
+
gt_path = gt_path[int(0.9 * len(gt_path)):]
|
| 67 |
+
elif self.is_training:
|
| 68 |
+
input_path = input_path[:int(0.9 * len(input_path))]
|
| 69 |
+
gt_path = gt_path[:int(0.9 * len(gt_path))]
|
| 70 |
+
|
| 71 |
+
if not self.is_training:
|
| 72 |
+
self.imgs_name = [os.path.basename(k) for k in input_path]
|
| 73 |
+
for tmp_path in input_path:
|
| 74 |
+
tmp_i = cv.imread(tmp_path)
|
| 75 |
+
tmp_shape = tmp_i.shape[:2]
|
| 76 |
+
self.imgs_shape.append(tmp_shape)
|
| 77 |
+
sample_indeces= [input_path, gt_path]
|
| 78 |
+
return sample_indeces
|
| 79 |
+
|
| 80 |
+
def on_epoch_end(self):
|
| 81 |
+
self.indices = np.arange(len(self.data_list[0]))
|
| 82 |
+
if self.shuffle:
|
| 83 |
+
np.random.shuffle(self.indices)
|
| 84 |
+
|
| 85 |
+
def __len__(self):
|
| 86 |
+
return len(self.indices)//self.bs
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
def __getitem__(self, index):
|
| 90 |
+
|
| 91 |
+
indices = self.indices[index*self.bs:(index+1)*self.bs]
|
| 92 |
+
if not self.data_name.lower()=='classic':
|
| 93 |
+
|
| 94 |
+
x_list,y_list = self.data_list
|
| 95 |
+
tmp_x_path = [x_list[k] for k in indices]
|
| 96 |
+
tmp_y_path = [y_list[k] for k in indices]
|
| 97 |
+
|
| 98 |
+
x,y = self.__data_generation(tmp_x_path,tmp_y_path)
|
| 99 |
+
else:
|
| 100 |
+
x_list, _ = self.data_list
|
| 101 |
+
tmp_x_path = [x_list[k] for k in indices]
|
| 102 |
+
x, y = self.__data_generation(tmp_x_path, None)
|
| 103 |
+
return x,y
|
| 104 |
+
|
| 105 |
+
def __data_generation(self,x_path,y_path):
|
| 106 |
+
if self.args.scale is not None and self.args.model_state.lower()!='train':
|
| 107 |
+
scl= self.args.scale
|
| 108 |
+
scl_h = int(self.dim_h*scl) if (self.dim_h*scl)%16==0 else \
|
| 109 |
+
int(((self.dim_h*scl) // 16 + 1) * 16)
|
| 110 |
+
scl_w = int(self.dim_w * scl) if (self.dim_w * scl) % 16 == 0 else \
|
| 111 |
+
int(((self.dim_h * scl) // 16 + 1) * 16)
|
| 112 |
+
|
| 113 |
+
x = np.empty((self.bs, scl_h, scl_w, 3), dtype="float32")
|
| 114 |
+
else:
|
| 115 |
+
x = np.empty((self.bs, self.dim_h, self.dim_w, 3), dtype="float32")
|
| 116 |
+
y = np.empty((self.bs, self.dim_h, self.dim_w, 1), dtype="float32")
|
| 117 |
+
|
| 118 |
+
for i,tmp_data in enumerate(x_path):
|
| 119 |
+
tmp_x_path = tmp_data
|
| 120 |
+
tmp_y_path = y_path[i] if not self.data_name.lower()=='classic' else None
|
| 121 |
+
tmp_x,tmp_y = self.transformer(tmp_x_path,tmp_y_path)
|
| 122 |
+
x[i,]=tmp_x
|
| 123 |
+
y[i,]=tmp_y
|
| 124 |
+
|
| 125 |
+
return x,y
|
| 126 |
+
|
| 127 |
+
def transformer(self, x_path, y_path):
|
| 128 |
+
tmp_x = cv.imread(x_path)
|
| 129 |
+
if y_path is not None:
|
| 130 |
+
tmp_y = cv.imread(y_path,cv.IMREAD_GRAYSCALE)
|
| 131 |
+
else:
|
| 132 |
+
tmp_y=None
|
| 133 |
+
h,w,_ = tmp_x.shape
|
| 134 |
+
if self.args.model_state == "train":
|
| 135 |
+
if self.args.crop_img:
|
| 136 |
+
i_h = random.randint(0,h-self.dim_h)
|
| 137 |
+
i_w = random.randint(0,w-self.dim_w)
|
| 138 |
+
tmp_x = tmp_x[i_h:i_h+self.dim_h,i_w:i_w+self.dim_w,]
|
| 139 |
+
tmp_y = tmp_y[i_h:i_h+self.dim_h,i_w:i_w+self.dim_w,]
|
| 140 |
+
else:
|
| 141 |
+
tmp_x = cv.resize(tmp_x,(self.dim_w,self.dim_h))
|
| 142 |
+
tmp_y = cv.resize(tmp_y,(self.dim_w,self.dim_h))
|
| 143 |
+
else:
|
| 144 |
+
if self.dim_w!=w and self.dim_h!=h:
|
| 145 |
+
tmp_x = cv.resize(tmp_x, (self.dim_w, self.dim_h))
|
| 146 |
+
if self.args.scale is not None:
|
| 147 |
+
scl = self.args.scale
|
| 148 |
+
scl_h = int(self.dim_h * scl) if (self.dim_h * scl) % 16 == 0 else \
|
| 149 |
+
int(((self.dim_h * scl) // 16 + 1) * 16)
|
| 150 |
+
scl_w = int(self.dim_w * scl) if (self.dim_w * scl) % 16 == 0 else \
|
| 151 |
+
int(((self.dim_h * scl) // 16 + 1) * 16)
|
| 152 |
+
tmp_x = cv.resize(tmp_x,dsize=(scl_w,scl_h))
|
| 153 |
+
if tmp_y is not None:
|
| 154 |
+
tmp_y = cv.resize(tmp_y, (self.dim_w, self.dim_h))
|
| 155 |
+
|
| 156 |
+
if tmp_y is not None:
|
| 157 |
+
tmp_y = np.expand_dims(np.float32(tmp_y)/255.,axis=-1)
|
| 158 |
+
tmp_x = np.float32(tmp_x)
|
| 159 |
+
return tmp_x, tmp_y
|
| 160 |
+
|
| 161 |
+
# def __read_h5(self,file_path):
|
| 162 |
+
#
|
| 163 |
+
# with h5py.File(file_path,'r') as h5f:
|
| 164 |
+
# # n_var = len(list(h5f.keys()))
|
| 165 |
+
# data = np.array(h5f.get('data'))
|
| 166 |
+
# return data
|
| 167 |
+
|
| 168 |
+
def dataset_info(dataset_name, is_linux=False):
|
| 169 |
+
|
| 170 |
+
if is_linux:
|
| 171 |
+
|
| 172 |
+
config = {
|
| 173 |
+
'BSDS': {'img_height':400,# 321
|
| 174 |
+
'img_width':400,#481
|
| 175 |
+
'test_list': 'test_pair.lst',
|
| 176 |
+
'data_dir': '/opt/dataset/BSDS', # mean_rgb
|
| 177 |
+
'yita': 0.5},
|
| 178 |
+
'BSDS300': {'img_height': 321,
|
| 179 |
+
'img_width': 481,
|
| 180 |
+
'test_list': 'test_pair.lst',
|
| 181 |
+
'data_dir': '/opt/dataset/BSDS300', # NIR
|
| 182 |
+
'yita': 0.5},
|
| 183 |
+
'PASCAL': {'img_height':375,
|
| 184 |
+
'img_width':500,
|
| 185 |
+
'test_list': 'test_pair.lst',
|
| 186 |
+
'data_dir': '/opt/dataset/PASCAL', # mean_rgb
|
| 187 |
+
'yita': 0.3},
|
| 188 |
+
'CID': {'img_height':512,
|
| 189 |
+
'img_width':512,
|
| 190 |
+
'test_list': 'test_pair.lst',
|
| 191 |
+
'data_dir': '/opt/dataset/CID', # mean_rgb
|
| 192 |
+
'yita': 0.3},
|
| 193 |
+
'NYUD': {'img_height':425,
|
| 194 |
+
'img_width':560,
|
| 195 |
+
'test_list': 'test_pair.lst',
|
| 196 |
+
'data_dir': '/opt/dataset/NYUD', # mean_rgb
|
| 197 |
+
'yita': 0.5},
|
| 198 |
+
'MULTICUE': {'img_height':720,
|
| 199 |
+
'img_width':1280,
|
| 200 |
+
'test_list': 'test_pair.lst',
|
| 201 |
+
'data_dir': '/opt/dataset/MULTICUE', # mean_rgb
|
| 202 |
+
'yita': 0.3},
|
| 203 |
+
'BIPED': {'img_height': 720,
|
| 204 |
+
'img_width': 1280,
|
| 205 |
+
'test_list': 'test_rgb.lst',
|
| 206 |
+
'train_list': 'train_rgb.lst',
|
| 207 |
+
'data_dir': '/opt/dataset/BIPED/edges', # WIN: '../.../dataset/BIPED/edges'
|
| 208 |
+
'yita': 0.5},
|
| 209 |
+
'MBIPED': {'img_height': 720,
|
| 210 |
+
'img_width': 1280,
|
| 211 |
+
'test_list': 'test_rgbn.lst',
|
| 212 |
+
'train_list': 'train_rgbn.lst',
|
| 213 |
+
'data_dir': '/opt/dataset/BIPED/edges', # WIN: '../.../dataset/BIPED/edges'
|
| 214 |
+
'yita': 0.5},
|
| 215 |
+
'CLASSIC': {'img_height':512, # 4032
|
| 216 |
+
'img_width': 512, # 3024
|
| 217 |
+
'test_list': None,
|
| 218 |
+
'data_dir': 'data', # mean_rgb
|
| 219 |
+
'yita': 0.5},
|
| 220 |
+
'DCD': {'img_height': 336,# 240
|
| 221 |
+
'img_width': 448,#360
|
| 222 |
+
|
| 223 |
+
'test_list':'test_pair.lst',
|
| 224 |
+
'data_dir': '/opt/dataset/DCD', # mean_rgb
|
| 225 |
+
'yita': 0.2}
|
| 226 |
+
}
|
| 227 |
+
data_info = config[dataset_name]
|
| 228 |
+
return data_info
|
| 229 |
+
else:
|
| 230 |
+
config = {
|
| 231 |
+
'BSDS': {'img_height': 512,#321
|
| 232 |
+
'img_width': 512,#481
|
| 233 |
+
'test_list': 'test_pair.lst',
|
| 234 |
+
'data_dir': '../../dataset/BSDS', # mean_rgb
|
| 235 |
+
'yita': 0.5},
|
| 236 |
+
'BSDS300': {'img_height': 512,#321
|
| 237 |
+
'img_width': 512,#481
|
| 238 |
+
'test_list': 'test_pair.lst',
|
| 239 |
+
'data_dir': '../../dataset/BSDS300', # NIR
|
| 240 |
+
'yita': 0.5},
|
| 241 |
+
'PASCAL': {'img_height': 375,
|
| 242 |
+
'img_width': 500,
|
| 243 |
+
'test_list': 'test_pair.lst',
|
| 244 |
+
'data_dir': '/opt/dataset/PASCAL', # mean_rgb
|
| 245 |
+
'yita': 0.3},
|
| 246 |
+
'CID': {'img_height': 512,
|
| 247 |
+
'img_width': 512,
|
| 248 |
+
'test_list': 'test_pair.lst',
|
| 249 |
+
'data_dir': '../../dataset/CID', # mean_rgb
|
| 250 |
+
'yita': 0.3},
|
| 251 |
+
'NYUD': {'img_height': 425,
|
| 252 |
+
'img_width': 560,
|
| 253 |
+
'test_list': 'test_pair.lst',
|
| 254 |
+
'data_dir': '/opt/dataset/NYUD', # mean_rgb
|
| 255 |
+
'yita': 0.5},
|
| 256 |
+
'MULTICUE': {'img_height': 720,
|
| 257 |
+
'img_width': 1280,
|
| 258 |
+
'test_list': 'test_pair.lst',
|
| 259 |
+
'data_dir': '../../dataset/MULTICUE', # mean_rgb
|
| 260 |
+
'yita': 0.3},
|
| 261 |
+
'BIPED': {'img_height': 720,#720
|
| 262 |
+
'img_width': 1280,#1280
|
| 263 |
+
'test_list': 'test_rgb.lst',
|
| 264 |
+
'train_list': 'train_rgb.lst',
|
| 265 |
+
'data_dir': '../../dataset/BIPED/edges', # WIN: '../.../dataset/BIPED/edges'
|
| 266 |
+
'yita': 0.5},
|
| 267 |
+
'CLASSIC': {'img_height': 512,
|
| 268 |
+
'img_width': 512,
|
| 269 |
+
'test_list': None,
|
| 270 |
+
'train_list': None,
|
| 271 |
+
'data_dir': 'data', # mean_rgb
|
| 272 |
+
'yita': 0.5},
|
| 273 |
+
'DCD': {'img_height': 240,
|
| 274 |
+
'img_width': 360,
|
| 275 |
+
'test_list': 'test_pair.lst',
|
| 276 |
+
'data_dir': '/opt/dataset/DCD', # mean_rgb
|
| 277 |
+
'yita': 0.2}
|
| 278 |
+
}
|
| 279 |
+
data_info = config[dataset_name]
|
| 280 |
+
return data_info
|
DexiNed-TF2/mainTF.py
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/python3.7 python
|
| 2 |
+
"""
|
| 3 |
+
|
| 4 |
+
"""
|
| 5 |
+
__author__ = "Xavier Soria Poma"
|
| 6 |
+
__email__ = "[email protected] / [email protected]"
|
| 7 |
+
__homepage__="www.cvc.uab.cat/people/xsoria"
|
| 8 |
+
__credits__=["tensorflow_tutorial"]
|
| 9 |
+
__copyright__ = "Copyright 2020, CIMI"
|
| 10 |
+
|
| 11 |
+
import argparse
|
| 12 |
+
import platform
|
| 13 |
+
import tensorflow as tf
|
| 14 |
+
|
| 15 |
+
from run_model import run_DexiNed
|
| 16 |
+
from dataset_manager import dataset_info
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
# Testing settings
|
| 20 |
+
|
| 21 |
+
in_linux=True if platform.system()=="Linux" else False
|
| 22 |
+
|
| 23 |
+
DATASET_NAME= ['BIPED','MBIPED','BSDS','BSDS300','CID','DCD','MULTICUE',
|
| 24 |
+
'PASCAL','NYUD','CLASSIC'] # 8
|
| 25 |
+
TEST_DATA = DATASET_NAME[-1] # MULTICUE=6
|
| 26 |
+
TRAIN_DATA = DATASET_NAME[0]
|
| 27 |
+
test_data_inf = dataset_info(TEST_DATA, is_linux=in_linux)
|
| 28 |
+
train_data_inf = dataset_info(TRAIN_DATA, is_linux=in_linux)
|
| 29 |
+
test_model=False
|
| 30 |
+
is_testing ="test" if test_model else "train"
|
| 31 |
+
# training settings
|
| 32 |
+
|
| 33 |
+
parser = argparse.ArgumentParser(description='Edge detection parameters for feeding the model')
|
| 34 |
+
parser.add_argument("--train_dir",default=train_data_inf['data_dir'], help="path to folder containing images")
|
| 35 |
+
parser.add_argument("--test_dir",default=test_data_inf['data_dir'], help="path to folder containing images")
|
| 36 |
+
parser.add_argument("--data4train",default=TRAIN_DATA, type=str)
|
| 37 |
+
parser.add_argument("--data4test",default=TEST_DATA, type=str)
|
| 38 |
+
parser.add_argument('--train_list', default=train_data_inf['train_list'], type=str) # SSMIHD: train_rgb_pair.lst, others train_pair.lst
|
| 39 |
+
parser.add_argument('--test_list', default=test_data_inf['test_list'], type=str) # SSMIHD: train_rgb_pair.lst, others train_pair.lst
|
| 40 |
+
parser.add_argument("--model_state",default=is_testing , choices=["train", "test", "export"])
|
| 41 |
+
parser.add_argument("--output_dir", default='results', help="where to put output files")
|
| 42 |
+
parser.add_argument("--checkpoint_dir", default='checkpoints', help="directory with checkpoint to resume training from or use for testing")
|
| 43 |
+
|
| 44 |
+
parser.add_argument('--model_name', default='DexiNed', choices=['DexiNed'])
|
| 45 |
+
parser.add_argument('--continue_training', default=False, type=bool)
|
| 46 |
+
parser.add_argument("--max_epochs", type=int,default=24, help="number of training epochs")#24
|
| 47 |
+
parser.add_argument("--summary_freq", type=int, default=100, help="update summaries every summary_freq steps")
|
| 48 |
+
parser.add_argument("--progress_freq", type=int, default=50, help="display progress every progress_freq steps")
|
| 49 |
+
parser.add_argument("--display_freq", type=int, default=10, help="write current training images every display_freq steps")
|
| 50 |
+
parser.add_argument("--scale", type=float, default=None, help="scale image before fed DexiNed.0.5, 1.5 ")
|
| 51 |
+
|
| 52 |
+
parser.add_argument('--adjust_lr', default=[10, 15],type=int,
|
| 53 |
+
help='Learning rate step size.') # [5,10]BIRND [10,15]BIPED/BRIND
|
| 54 |
+
parser.add_argument("--batch_size", type=int, default=8, help="number of images in batch")
|
| 55 |
+
parser.add_argument("--test_bs", type=int, default=1, help="number of images in test batch")
|
| 56 |
+
parser.add_argument("--batch_normalization", type=bool, default=True, help=" use batch norm")
|
| 57 |
+
parser.add_argument("--image_height", type=int, default=352, help="scale images to this size before cropping to 256x256")
|
| 58 |
+
parser.add_argument("--image_width", type=int, default=352, help="scale images to this size before cropping to 256x256")
|
| 59 |
+
parser.add_argument("--crop_img", type=bool, default=False,
|
| 60 |
+
help="4Training: True crop image, False resize image")
|
| 61 |
+
parser.add_argument("--test_img_height", type=int, default=test_data_inf["img_height"],
|
| 62 |
+
help="network input height size")
|
| 63 |
+
parser.add_argument("--test_img_width", type=int, default=test_data_inf["img_width"],
|
| 64 |
+
help="network input height size")
|
| 65 |
+
|
| 66 |
+
parser.add_argument("--lr", type=float, default=0.0001, help=" learning rate for adam 1e-4")
|
| 67 |
+
parser.add_argument("--beta1", type=float, default=0.5, help="momentum term of adam")
|
| 68 |
+
parser.add_argument("--l1_weight", type=float, default=100.0, help="weight on L1 term for generator gradient")
|
| 69 |
+
parser.add_argument("--gan_weight", type=float, default=1.0, help="weight on GAN term for generator gradient")
|
| 70 |
+
parser.add_argument("--rgbn_mean", type=float, default=[103.939,116.779,123.68, 137.86], help="pixels mean")
|
| 71 |
+
parser.add_argument("--checkpoint", type=str, default='DexiNed19_model.h5', help="checkpoint Name")
|
| 72 |
+
|
| 73 |
+
arg = parser.parse_args()
|
| 74 |
+
def main(args):
|
| 75 |
+
tf.debugging.set_log_device_placement(True)
|
| 76 |
+
gpus = tf.config.list_physical_devices('GPU')
|
| 77 |
+
if gpus:
|
| 78 |
+
# Restrict TensorFlow to only allocate 1GB of memory on the first GPU
|
| 79 |
+
try:
|
| 80 |
+
tf.config.set_logical_device_configuration(
|
| 81 |
+
gpus[0],
|
| 82 |
+
[tf.config.LogicalDeviceConfiguration(memory_limit=1024)])
|
| 83 |
+
logical_gpus = tf.config.list_logical_devices('GPU')
|
| 84 |
+
print(len(gpus), "Physical GPUs,", len(logical_gpus), "Logical GPUs")
|
| 85 |
+
except RuntimeError as e:
|
| 86 |
+
# Virtual devices must be set before GPUs have been initialized
|
| 87 |
+
print(e)
|
| 88 |
+
|
| 89 |
+
model = run_DexiNed(args=args)
|
| 90 |
+
if args.model_state=='train':
|
| 91 |
+
model.train()
|
| 92 |
+
elif args.model_state =='test':
|
| 93 |
+
model.test()
|
| 94 |
+
else:
|
| 95 |
+
raise NotImplementedError('Sorry you just can test or train the model, please set in '
|
| 96 |
+
'args.model_state=')
|
| 97 |
+
|
| 98 |
+
if __name__=='__main__':
|
| 99 |
+
main(args=arg)
|
DexiNed-TF2/model.py
ADDED
|
@@ -0,0 +1,346 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from tensorflow.keras import callbacks
|
| 2 |
+
from tensorflow.keras import layers, regularizers
|
| 3 |
+
from tensorflow.keras import optimizers, metrics, losses
|
| 4 |
+
from tensorflow.keras.models import Model
|
| 5 |
+
from tensorflow.keras.models import load_model
|
| 6 |
+
from tensorflow.keras import backend as K
|
| 7 |
+
from tensorflow import keras
|
| 8 |
+
import tensorflow as tf
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
l2 = regularizers.l2
|
| 12 |
+
w_decay=1e-8 #0.0#2e-4#1e-3, 2e-4 # please define weight decay
|
| 13 |
+
K.clear_session()
|
| 14 |
+
# weight_init = tf.initializers.RandomNormal(mean=0.,stddev=0.01)
|
| 15 |
+
# weight_init = tf.initializers.glorot_normal()
|
| 16 |
+
weight_init = tf.initializers.glorot_normal()
|
| 17 |
+
|
| 18 |
+
class _DenseLayer(layers.Layer):
|
| 19 |
+
"""_DenseBlock model.
|
| 20 |
+
|
| 21 |
+
Arguments:
|
| 22 |
+
out_features: number of output features
|
| 23 |
+
"""
|
| 24 |
+
|
| 25 |
+
def __init__(self, out_features,**kwargs):
|
| 26 |
+
super(_DenseLayer, self).__init__(**kwargs)
|
| 27 |
+
k_reg = None if w_decay is None else l2(w_decay)
|
| 28 |
+
self.layers = []
|
| 29 |
+
self.layers.append(tf.keras.Sequential(
|
| 30 |
+
[
|
| 31 |
+
layers.ReLU(),
|
| 32 |
+
layers.Conv2D(
|
| 33 |
+
filters=out_features, kernel_size=(3,3), strides=(1,1), padding='same',
|
| 34 |
+
use_bias=True, kernel_initializer=weight_init,
|
| 35 |
+
kernel_regularizer=k_reg),
|
| 36 |
+
layers.BatchNormalization(),
|
| 37 |
+
layers.ReLU(),
|
| 38 |
+
layers.Conv2D(
|
| 39 |
+
filters=out_features, kernel_size=(3,3), strides=(1,1), padding='same',
|
| 40 |
+
use_bias=True, kernel_initializer=weight_init,
|
| 41 |
+
kernel_regularizer=k_reg),
|
| 42 |
+
layers.BatchNormalization(),
|
| 43 |
+
])) # first relu can be not needed
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def call(self, inputs):
|
| 47 |
+
x1, x2 = tuple(inputs)
|
| 48 |
+
new_features = x1
|
| 49 |
+
for layer in self.layers:
|
| 50 |
+
new_features = layer(new_features)
|
| 51 |
+
|
| 52 |
+
return 0.5 * (new_features + x2), x2
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
class _DenseBlock(layers.Layer):
|
| 56 |
+
"""DenseBlock layer.
|
| 57 |
+
|
| 58 |
+
Arguments:
|
| 59 |
+
num_layers: number of _DenseLayer's per block
|
| 60 |
+
out_features: number of output features
|
| 61 |
+
"""
|
| 62 |
+
|
| 63 |
+
def __init__(self,
|
| 64 |
+
num_layers,
|
| 65 |
+
out_features,**kwargs):
|
| 66 |
+
super(_DenseBlock, self).__init__(**kwargs)
|
| 67 |
+
self.layers = [_DenseLayer(out_features) for i in range(num_layers)]
|
| 68 |
+
|
| 69 |
+
def call(self, inputs):
|
| 70 |
+
for layer in self.layers:
|
| 71 |
+
inputs = layer(inputs)
|
| 72 |
+
|
| 73 |
+
return inputs
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
class UpConvBlock(layers.Layer):
|
| 77 |
+
"""UpConvDeconvBlock layer.
|
| 78 |
+
|
| 79 |
+
Arguments:
|
| 80 |
+
up_scale: int
|
| 81 |
+
"""
|
| 82 |
+
|
| 83 |
+
def __init__(self, up_scale,**kwargs):
|
| 84 |
+
super(UpConvBlock, self).__init__(**kwargs)
|
| 85 |
+
constant_features = 16
|
| 86 |
+
k_reg = None if w_decay is None else l2(w_decay)
|
| 87 |
+
features = []
|
| 88 |
+
total_up_scale = 2 ** up_scale
|
| 89 |
+
for i in range(up_scale):
|
| 90 |
+
out_features = 1 if i == up_scale-1 else constant_features
|
| 91 |
+
if i==up_scale-1:
|
| 92 |
+
features.append(layers.Conv2D(
|
| 93 |
+
filters=out_features, kernel_size=(1,1), strides=(1,1), padding='same',
|
| 94 |
+
activation='relu', kernel_initializer=tf.initializers.RandomNormal(mean=0.),
|
| 95 |
+
kernel_regularizer=k_reg,use_bias=True)) #tf.initializers.TruncatedNormal(mean=0.)
|
| 96 |
+
features.append(layers.Conv2DTranspose(
|
| 97 |
+
out_features, kernel_size=(total_up_scale,total_up_scale),
|
| 98 |
+
strides=(2,2), padding='same',
|
| 99 |
+
kernel_initializer=tf.initializers.RandomNormal(stddev=0.1),
|
| 100 |
+
kernel_regularizer=k_reg,use_bias=True)) # stddev=0.1
|
| 101 |
+
else:
|
| 102 |
+
|
| 103 |
+
features.append(layers.Conv2D(
|
| 104 |
+
filters=out_features, kernel_size=(1,1), strides=(1,1), padding='same',
|
| 105 |
+
activation='relu',kernel_initializer=weight_init,
|
| 106 |
+
kernel_regularizer=k_reg,use_bias=True))
|
| 107 |
+
features.append(layers.Conv2DTranspose(
|
| 108 |
+
out_features, kernel_size=(total_up_scale,total_up_scale),
|
| 109 |
+
strides=(2,2), padding='same', use_bias=True,
|
| 110 |
+
kernel_initializer=weight_init, kernel_regularizer=k_reg))
|
| 111 |
+
|
| 112 |
+
self.features = keras.Sequential(features)
|
| 113 |
+
|
| 114 |
+
def call(self, inputs):
|
| 115 |
+
return self.features(inputs)
|
| 116 |
+
|
| 117 |
+
|
| 118 |
+
class SingleConvBlock(layers.Layer):
|
| 119 |
+
"""SingleConvBlock layer.
|
| 120 |
+
|
| 121 |
+
Arguments:
|
| 122 |
+
out_features: number of output features
|
| 123 |
+
stride: stride per convolution
|
| 124 |
+
"""
|
| 125 |
+
|
| 126 |
+
def __init__(self, out_features, k_size=(1,1),stride=(1,1),
|
| 127 |
+
use_bs=False, use_act=False,w_init=None,**kwargs): # bias_init=tf.constant_initializer(0.0)
|
| 128 |
+
super(SingleConvBlock, self).__init__(**kwargs)
|
| 129 |
+
self.use_bn = use_bs
|
| 130 |
+
self.use_act = use_act
|
| 131 |
+
k_reg = None if w_decay is None else l2(w_decay)
|
| 132 |
+
self.conv = layers.Conv2D(
|
| 133 |
+
filters=out_features, kernel_size=k_size, strides=stride,
|
| 134 |
+
padding='same',kernel_initializer=w_init,
|
| 135 |
+
kernel_regularizer=k_reg)#, use_bias=True, bias_initializer=bias_init
|
| 136 |
+
if self.use_bn:
|
| 137 |
+
self.bn = layers.BatchNormalization()
|
| 138 |
+
if self.use_act:
|
| 139 |
+
self.relu = layers.ReLU()
|
| 140 |
+
|
| 141 |
+
def call(self, inputs):
|
| 142 |
+
x =self.conv(inputs)
|
| 143 |
+
if self.use_bn:
|
| 144 |
+
x = self.bn(x)
|
| 145 |
+
if self.use_act:
|
| 146 |
+
x = self.relu(x)
|
| 147 |
+
return x
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
class DoubleConvBlock(layers.Layer):
|
| 151 |
+
"""DoubleConvBlock layer.
|
| 152 |
+
|
| 153 |
+
Arguments:
|
| 154 |
+
mid_features: number of middle features
|
| 155 |
+
out_features: number of output features
|
| 156 |
+
stride: stride per mid-layer convolution
|
| 157 |
+
"""
|
| 158 |
+
|
| 159 |
+
def __init__(self, mid_features, out_features=None, stride=(1,1),
|
| 160 |
+
use_bn=True,use_act=True,**kwargs):
|
| 161 |
+
super(DoubleConvBlock, self).__init__(**kwargs)
|
| 162 |
+
self.use_bn =use_bn
|
| 163 |
+
self.use_act =use_act
|
| 164 |
+
out_features = mid_features if out_features is None else out_features
|
| 165 |
+
k_reg = None if w_decay is None else l2(w_decay)
|
| 166 |
+
|
| 167 |
+
self.conv1 = layers.Conv2D(
|
| 168 |
+
filters=mid_features, kernel_size=(3, 3), strides=stride, padding='same',
|
| 169 |
+
use_bias=True, kernel_initializer=weight_init,
|
| 170 |
+
kernel_regularizer=k_reg)
|
| 171 |
+
self.bn1 = layers.BatchNormalization()
|
| 172 |
+
|
| 173 |
+
self.conv2 = layers.Conv2D(
|
| 174 |
+
filters=out_features, kernel_size=(3, 3), padding='same',strides=(1,1),
|
| 175 |
+
use_bias=True, kernel_initializer=weight_init,
|
| 176 |
+
kernel_regularizer=k_reg)
|
| 177 |
+
self.bn2 = layers.BatchNormalization()
|
| 178 |
+
self.relu = layers.ReLU()
|
| 179 |
+
|
| 180 |
+
def call(self, inputs):
|
| 181 |
+
x = self.conv1(inputs)
|
| 182 |
+
x = self.bn1(x)
|
| 183 |
+
x = self.relu(x)
|
| 184 |
+
x = self.conv2(x)
|
| 185 |
+
x = self.bn2(x)
|
| 186 |
+
if self.use_act:
|
| 187 |
+
x = self.relu(x)
|
| 188 |
+
return x
|
| 189 |
+
|
| 190 |
+
|
| 191 |
+
class DexiNed(tf.keras.Model):
|
| 192 |
+
"""DexiNet model."""
|
| 193 |
+
|
| 194 |
+
def __init__(self,rgb_mean=None,
|
| 195 |
+
**kwargs):
|
| 196 |
+
super(DexiNed, self).__init__(**kwargs)
|
| 197 |
+
|
| 198 |
+
self.rgbn_mean = rgb_mean
|
| 199 |
+
self.block_1 = DoubleConvBlock(32, 64, stride=(2,2),use_act=False)
|
| 200 |
+
self.block_2 = DoubleConvBlock(128,use_act=False)
|
| 201 |
+
self.dblock_3 = _DenseBlock(2, 256)
|
| 202 |
+
self.dblock_4 = _DenseBlock(3, 512)
|
| 203 |
+
self.dblock_5 = _DenseBlock(3, 512)
|
| 204 |
+
self.dblock_6 = _DenseBlock(3, 256)
|
| 205 |
+
self.maxpool = layers.MaxPool2D(pool_size=(3, 3), strides=2, padding='same')
|
| 206 |
+
|
| 207 |
+
# left skip connections, figure in Journal
|
| 208 |
+
self.side_1 = SingleConvBlock(128,k_size=(1,1),stride=(2,2),use_bs=True,
|
| 209 |
+
w_init=weight_init)
|
| 210 |
+
self.side_2 = SingleConvBlock(256,k_size=(1,1),stride=(2,2),use_bs=True,
|
| 211 |
+
w_init=weight_init)
|
| 212 |
+
self.side_3 = SingleConvBlock(512,k_size=(1,1),stride=(2,2),use_bs=True,
|
| 213 |
+
w_init=weight_init)
|
| 214 |
+
self.side_4 = SingleConvBlock(512,k_size=(1,1),stride=(1,1),use_bs=True,
|
| 215 |
+
w_init=weight_init)
|
| 216 |
+
# self.side_5 = SingleConvBlock(256,k_size=(1,1),stride=(1,1),use_bs=True,
|
| 217 |
+
# w_init=weight_init)
|
| 218 |
+
|
| 219 |
+
# right skip connections, figure in Journal paper
|
| 220 |
+
self.pre_dense_2 = SingleConvBlock(256,k_size=(1,1),stride=(2,2),
|
| 221 |
+
w_init=weight_init) # use_bn=True
|
| 222 |
+
self.pre_dense_3 = SingleConvBlock(256,k_size=(1,1),stride=(1,1),use_bs=True,
|
| 223 |
+
w_init=weight_init)
|
| 224 |
+
self.pre_dense_4 = SingleConvBlock(512,k_size=(1,1),stride=(1,1),use_bs=True,
|
| 225 |
+
w_init=weight_init)
|
| 226 |
+
# self.pre_dense_5_0 = SingleConvBlock(512, k_size=(1,1),stride=(2,2),
|
| 227 |
+
# w_init=weight_init) # use_bn=True
|
| 228 |
+
self.pre_dense_5 = SingleConvBlock(512,k_size=(1,1),stride=(1,1),use_bs=True,
|
| 229 |
+
w_init=weight_init)
|
| 230 |
+
self.pre_dense_6 = SingleConvBlock(256,k_size=(1,1),stride=(1,1),use_bs=True,
|
| 231 |
+
w_init=weight_init)
|
| 232 |
+
# USNet
|
| 233 |
+
self.up_block_1 = UpConvBlock(1)
|
| 234 |
+
self.up_block_2 = UpConvBlock(1)
|
| 235 |
+
self.up_block_3 = UpConvBlock(2)
|
| 236 |
+
self.up_block_4 = UpConvBlock(3)
|
| 237 |
+
self.up_block_5 = UpConvBlock(4)
|
| 238 |
+
self.up_block_6 = UpConvBlock(4)
|
| 239 |
+
|
| 240 |
+
self.block_cat = SingleConvBlock(
|
| 241 |
+
1,k_size=(1,1),stride=(1,1),
|
| 242 |
+
w_init=tf.constant_initializer(1/5))
|
| 243 |
+
|
| 244 |
+
|
| 245 |
+
def slice(self, tensor, slice_shape):
|
| 246 |
+
height, width = slice_shape
|
| 247 |
+
return tensor[..., :height, :width]
|
| 248 |
+
|
| 249 |
+
|
| 250 |
+
def call(self, x):
|
| 251 |
+
# Block 1
|
| 252 |
+
x = x-self.rgbn_mean[:-1]
|
| 253 |
+
block_1 = self.block_1(x)
|
| 254 |
+
block_1_side = self.side_1(block_1)
|
| 255 |
+
|
| 256 |
+
# Block 2
|
| 257 |
+
block_2 = self.block_2(block_1)
|
| 258 |
+
block_2_down = self.maxpool(block_2) # the key for the second skip connec...
|
| 259 |
+
block_2_add = block_2_down + block_1_side
|
| 260 |
+
block_2_side = self.side_2(block_2_add) #
|
| 261 |
+
|
| 262 |
+
# Block 3
|
| 263 |
+
block_3_pre_dense = self.pre_dense_3(block_2_down)
|
| 264 |
+
block_3, _ = self.dblock_3([block_2_add, block_3_pre_dense])
|
| 265 |
+
block_3_down = self.maxpool(block_3)
|
| 266 |
+
block_3_add = block_3_down + block_2_side
|
| 267 |
+
block_3_side = self.side_3(block_3_add)
|
| 268 |
+
|
| 269 |
+
# Block 4
|
| 270 |
+
block_4_pre_dense_256 = self.pre_dense_2(block_2_down)
|
| 271 |
+
block_4_pre_dense = self.pre_dense_4(block_4_pre_dense_256 + block_3_down)
|
| 272 |
+
block_4, _ = self.dblock_4([block_3_add, block_4_pre_dense])
|
| 273 |
+
block_4_down = self.maxpool(block_4)
|
| 274 |
+
block_4_add = block_4_down + block_3_side
|
| 275 |
+
block_4_side = self.side_4(block_4_add)
|
| 276 |
+
|
| 277 |
+
# Block 5
|
| 278 |
+
# block_5_pre_dense_512 = self.pre_dense_5_0(block_4_pre_dense_256)
|
| 279 |
+
block_5_pre_dense = self.pre_dense_5(block_4_down )
|
| 280 |
+
block_5, _ = self.dblock_5([block_4_add, block_5_pre_dense])
|
| 281 |
+
block_5_add = block_5 + block_4_side
|
| 282 |
+
|
| 283 |
+
# Block 6
|
| 284 |
+
block_6_pre_dense = self.pre_dense_6(block_5)
|
| 285 |
+
block_6, _ = self.dblock_6([block_5_add, block_6_pre_dense])
|
| 286 |
+
|
| 287 |
+
# upsampling blocks
|
| 288 |
+
height, width = x.shape[1:3]
|
| 289 |
+
slice_shape = (height, width)
|
| 290 |
+
out_1 = self.up_block_1(block_1) # self.slice(, slice_shape)
|
| 291 |
+
out_2 = self.up_block_2(block_2)
|
| 292 |
+
out_3 = self.up_block_3(block_3)
|
| 293 |
+
out_4 = self.up_block_4(block_4)
|
| 294 |
+
out_5 = self.up_block_5(block_5)
|
| 295 |
+
out_6 = self.up_block_6(block_6)
|
| 296 |
+
results = [out_1, out_2, out_3, out_4, out_5, out_6]
|
| 297 |
+
|
| 298 |
+
# concatenate multiscale outputs
|
| 299 |
+
block_cat = tf.concat(results, 3) # BxHxWX6
|
| 300 |
+
block_cat = self.block_cat(block_cat) # BxHxWX1
|
| 301 |
+
|
| 302 |
+
results.append(block_cat)
|
| 303 |
+
|
| 304 |
+
return results
|
| 305 |
+
|
| 306 |
+
def weighted_cross_entropy_loss(input, label):
|
| 307 |
+
y = tf.cast(label,dtype=tf.float32)
|
| 308 |
+
negatives = tf.math.reduce_sum(1.-y)
|
| 309 |
+
positives = tf.math.reduce_sum(y)
|
| 310 |
+
|
| 311 |
+
beta = negatives/(negatives + positives)
|
| 312 |
+
pos_w = beta/(1-beta)
|
| 313 |
+
cost = tf.nn.weighted_cross_entropy_with_logits(
|
| 314 |
+
labels=label, logits=input, pos_weight=pos_w, name=None)
|
| 315 |
+
cost = tf.reduce_sum(cost*(1-beta))
|
| 316 |
+
return tf.where(tf.equal(positives, 0.0), 0.0, cost)
|
| 317 |
+
|
| 318 |
+
|
| 319 |
+
def pre_process_binary_cross_entropy(bc_loss,input, label,arg, use_tf_loss=False):
|
| 320 |
+
# preprocess data
|
| 321 |
+
y = label
|
| 322 |
+
loss = 0
|
| 323 |
+
w_loss=1.0
|
| 324 |
+
preds = []
|
| 325 |
+
for tmp_p in input:
|
| 326 |
+
# tmp_p = input[i]
|
| 327 |
+
|
| 328 |
+
# loss processing
|
| 329 |
+
tmp_y = tf.cast(y, dtype=tf.float32)
|
| 330 |
+
mask = tf.dtypes.cast(tmp_y > 0., tf.float32)
|
| 331 |
+
b,h,w,c=mask.get_shape()
|
| 332 |
+
positives = tf.math.reduce_sum(mask, axis=[1, 2, 3], keepdims=True)
|
| 333 |
+
negatives = h*w*c-positives
|
| 334 |
+
|
| 335 |
+
beta2 = (1.*positives) / (negatives + positives) # negatives in hed
|
| 336 |
+
beta = (1.1*negatives)/ (positives + negatives) # positives in hed
|
| 337 |
+
pos_w = tf.where(tf.equal(y, 0.0), beta2, beta)
|
| 338 |
+
logits = tf.sigmoid(tmp_p)
|
| 339 |
+
|
| 340 |
+
l_cost = bc_loss(y_true=tmp_y, y_pred=logits,
|
| 341 |
+
sample_weight=pos_w)
|
| 342 |
+
|
| 343 |
+
preds.append(logits)
|
| 344 |
+
loss += (l_cost*w_loss)
|
| 345 |
+
|
| 346 |
+
return preds, loss
|
DexiNed-TF2/run_model.py
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import absolute_import, division, print_function
|
| 2 |
+
|
| 3 |
+
import time, os
|
| 4 |
+
import numpy as np
|
| 5 |
+
from os.path import join
|
| 6 |
+
import cv2 as cv
|
| 7 |
+
|
| 8 |
+
from model import *
|
| 9 |
+
from utls import image_normalization,visualize_result, tensor2image, cv_imshow,h5_writer
|
| 10 |
+
from dataset_manager import DataLoader
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
BUFFER_SIZE = 448
|
| 14 |
+
|
| 15 |
+
# tf.set_random_seed(1)
|
| 16 |
+
class run_DexiNed():
|
| 17 |
+
|
| 18 |
+
def __init__(self, args):
|
| 19 |
+
self.model_state= args.model_state
|
| 20 |
+
self.args = args
|
| 21 |
+
self.img_width=args.image_width
|
| 22 |
+
self.img_height = args.image_height
|
| 23 |
+
self.epochs = args.max_epochs
|
| 24 |
+
self.bs = args.batch_size
|
| 25 |
+
|
| 26 |
+
def train(self):
|
| 27 |
+
# Validation and Train dataset generation
|
| 28 |
+
|
| 29 |
+
train_data = DataLoader(data_name=self.args.data4train, arg=self.args)
|
| 30 |
+
n_train =train_data.indices.size #data_cache["n_files"]
|
| 31 |
+
val_data = DataLoader(data_name=self.args.data4train,
|
| 32 |
+
arg=self.args, is_val=True)
|
| 33 |
+
val_idcs = np.arange(val_data.indices.size)
|
| 34 |
+
# Summary and checkpoint manager
|
| 35 |
+
model_dir =self.args.model_name+'2'+self.args.data4train
|
| 36 |
+
summary_dir = os.path.join('logs',model_dir)
|
| 37 |
+
train_log_dir=os.path.join(summary_dir,'train')
|
| 38 |
+
val_log_dir =os.path.join(summary_dir,'test')
|
| 39 |
+
|
| 40 |
+
checkpoint_dir = os.path.join(self.args.checkpoint_dir,model_dir)
|
| 41 |
+
epoch_ckpt_dir = checkpoint_dir + 'epochs'
|
| 42 |
+
os.makedirs(epoch_ckpt_dir, exist_ok=True)
|
| 43 |
+
os.makedirs(train_log_dir,exist_ok=True)
|
| 44 |
+
os.makedirs(val_log_dir,exist_ok=True)
|
| 45 |
+
os.makedirs(checkpoint_dir, exist_ok=True)
|
| 46 |
+
|
| 47 |
+
train_writer = tf.summary.create_file_writer(train_log_dir)
|
| 48 |
+
val_writer = tf.summary.create_file_writer(val_log_dir)
|
| 49 |
+
|
| 50 |
+
my_model = DexiNed(rgb_mean=self.args.rgbn_mean)#rgb_mean=self.args.rgbn_mean
|
| 51 |
+
|
| 52 |
+
# accuracy = metrics.SparseCategoricalAccuracy()
|
| 53 |
+
accuracy = metrics.BinaryAccuracy()
|
| 54 |
+
accuracy_val = metrics.BinaryAccuracy()
|
| 55 |
+
loss_bc = losses.BinaryCrossentropy()
|
| 56 |
+
optimizer = optimizers.Adam(
|
| 57 |
+
learning_rate=self.args.lr, beta_1=self.args.beta1)
|
| 58 |
+
iter = 0
|
| 59 |
+
|
| 60 |
+
imgs_res_folder = os.path.join(self.args.output_dir, "current_training")
|
| 61 |
+
os.makedirs(imgs_res_folder, exist_ok=True)
|
| 62 |
+
global_loss = 1000.
|
| 63 |
+
t_loss = []
|
| 64 |
+
ckpt_save_mode = "h5"
|
| 65 |
+
tmp_lr = self.args.lr
|
| 66 |
+
for epoch in range(self.args.max_epochs):
|
| 67 |
+
# training
|
| 68 |
+
t_loss = []
|
| 69 |
+
# if epoch in self.args.adjust_lr:
|
| 70 |
+
tmp_lr=tmp_lr*0.1
|
| 71 |
+
optimizer.lr.assign(tmp_lr)
|
| 72 |
+
for step, (x, y) in enumerate(train_data):
|
| 73 |
+
|
| 74 |
+
with tf.GradientTape() as tape:
|
| 75 |
+
pred = my_model(x, training=True)
|
| 76 |
+
|
| 77 |
+
preds, loss = pre_process_binary_cross_entropy(
|
| 78 |
+
loss_bc, pred, y, self.args, use_tf_loss=False)
|
| 79 |
+
|
| 80 |
+
accuracy.update_state(y_true=y, y_pred=preds[-1])
|
| 81 |
+
gradients = tape.gradient(loss, my_model.trainable_variables)
|
| 82 |
+
optimizer.apply_gradients(zip(gradients, my_model.trainable_variables))
|
| 83 |
+
|
| 84 |
+
# logging the current accuracy value so far.
|
| 85 |
+
t_loss.append(loss.numpy())
|
| 86 |
+
if step % 10 == 0:
|
| 87 |
+
print("Epoch:", epoch, "Step:", step, "Loss: %.4f" % loss.numpy(),
|
| 88 |
+
"Accuracy: %.4f" % accuracy.result(), time.ctime())
|
| 89 |
+
|
| 90 |
+
if step % 10 == 0:
|
| 91 |
+
# visualize preds
|
| 92 |
+
img_test = 'Epoch: {0} Sample {1}/{2} Loss: {3}' \
|
| 93 |
+
.format(epoch, step, n_train // self.args.batch_size, loss.numpy())
|
| 94 |
+
vis_imgs = visualize_result(
|
| 95 |
+
x=x[2], y=y[2], p=preds, img_title=img_test)
|
| 96 |
+
cv.imwrite(os.path.join(imgs_res_folder, 'results.png'), vis_imgs)
|
| 97 |
+
if step % 20 == 0 and loss < global_loss: # 500
|
| 98 |
+
if epoch==0 and step==0:
|
| 99 |
+
tmp_loss = np.array(t_loss)
|
| 100 |
+
with train_writer.as_default():
|
| 101 |
+
tf.summary.scalar('loss', tmp_loss.mean(), step=epoch)
|
| 102 |
+
tf.summary.scalar('accuracy', accuracy.result(), step=epoch)
|
| 103 |
+
|
| 104 |
+
save_ckpt_path = os.path.join(checkpoint_dir, "DexiNedL_model.h5")
|
| 105 |
+
Model.save_weights(my_model, save_ckpt_path, save_format='h5')
|
| 106 |
+
|
| 107 |
+
global_loss = loss
|
| 108 |
+
print("Model saved in: ", save_ckpt_path, "Current loss:", global_loss.numpy())
|
| 109 |
+
|
| 110 |
+
iter += 1 # global iteration
|
| 111 |
+
|
| 112 |
+
t_loss = np.array(t_loss)
|
| 113 |
+
# train summary
|
| 114 |
+
if epoch!=0:
|
| 115 |
+
with train_writer.as_default():
|
| 116 |
+
tf.summary.scalar('loss', t_loss.mean(), step=epoch)
|
| 117 |
+
tf.summary.scalar('accuracy', accuracy.result(), step=epoch)
|
| 118 |
+
|
| 119 |
+
Model.save_weights(my_model, os.path.join(epoch_ckpt_dir, "DexiNed{}_model.h5".format(str(epoch))),
|
| 120 |
+
save_format=ckpt_save_mode)
|
| 121 |
+
print("Epoch:", epoch, "Model saved in Loss: ", t_loss.mean())
|
| 122 |
+
|
| 123 |
+
# validation
|
| 124 |
+
t_val_loss = []
|
| 125 |
+
for i, (x_val, y_val) in enumerate(val_data):
|
| 126 |
+
|
| 127 |
+
pred_val = my_model(x_val)
|
| 128 |
+
v_logits, V_loss = pre_process_binary_cross_entropy(
|
| 129 |
+
loss_bc, pred_val, y_val, self.args, use_tf_loss=False)
|
| 130 |
+
accuracy_val.update_state(y_true=y_val, y_pred=v_logits[-1])
|
| 131 |
+
t_val_loss.append(V_loss.numpy())
|
| 132 |
+
if i == 7:
|
| 133 |
+
break
|
| 134 |
+
val_acc = accuracy_val.result()
|
| 135 |
+
t_val_loss = np.array(t_val_loss)
|
| 136 |
+
print("Epoch(validation):", epoch, "Val loss: ", t_val_loss.mean(),
|
| 137 |
+
"Accuracy: ", val_acc.numpy())
|
| 138 |
+
# validation summary
|
| 139 |
+
with val_writer.as_default():
|
| 140 |
+
tf.summary.scalar('loss', t_val_loss.mean(), step=epoch)
|
| 141 |
+
tf.summary.scalar('accuracy', val_acc.numpy(), step=epoch)
|
| 142 |
+
|
| 143 |
+
# Reset metrics every epoch
|
| 144 |
+
accuracy.reset_states()
|
| 145 |
+
accuracy_val.reset_states()
|
| 146 |
+
|
| 147 |
+
my_model.summary()
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
def test(self):
|
| 151 |
+
# Test dataset generation
|
| 152 |
+
|
| 153 |
+
test_data = DataLoader(data_name=self.args.data4test, arg=self.args)
|
| 154 |
+
n_test = test_data.indices.size # data_cache["n_files"]
|
| 155 |
+
|
| 156 |
+
optimizer = tf.keras.optimizers.Adam(
|
| 157 |
+
learning_rate=self.args.lr, beta_1=self.args.beta1)
|
| 158 |
+
|
| 159 |
+
my_model = DexiNed(rgb_mean=self.args.rgbn_mean)
|
| 160 |
+
input_shape = test_data.input_shape
|
| 161 |
+
my_model.build(input_shape=input_shape) # rgb_mean=self.args.rgbn_mean
|
| 162 |
+
|
| 163 |
+
checkpoit_dir = os.path.join(self.args.checkpoint_dir,
|
| 164 |
+
self.args.model_name + "2" + self.args.data4train)
|
| 165 |
+
|
| 166 |
+
my_model.load_weights(os.path.join(checkpoit_dir, self.args.checkpoint))
|
| 167 |
+
|
| 168 |
+
result_dir = os.path.join(
|
| 169 |
+
self.args.output_dir,
|
| 170 |
+
self.args.model_name + '-' + self.args.data4train + "2" + self.args.data4test)
|
| 171 |
+
os.makedirs(result_dir, exist_ok=True)
|
| 172 |
+
if self.args.scale is not None:
|
| 173 |
+
scl = self.args.scale
|
| 174 |
+
save_dir = ['fuse_'+str(scl), 'avrg_'+str(scl), 'h5_'+str(scl)]
|
| 175 |
+
else:
|
| 176 |
+
save_dir = ['fuse', 'avrg', 'h5']
|
| 177 |
+
save_dirs = []
|
| 178 |
+
for tmp_dir in save_dir:
|
| 179 |
+
os.makedirs(os.path.join(result_dir, tmp_dir), exist_ok=True)
|
| 180 |
+
save_dirs.append(os.path.join(result_dir, tmp_dir))
|
| 181 |
+
|
| 182 |
+
total_time = []
|
| 183 |
+
data_names = test_data.imgs_name
|
| 184 |
+
data_shape = test_data.imgs_shape
|
| 185 |
+
k = 0
|
| 186 |
+
for step, (x, y) in enumerate(test_data):
|
| 187 |
+
|
| 188 |
+
start_time = time.time()
|
| 189 |
+
preds = my_model(x, training=False)
|
| 190 |
+
tmp_time = time.time() - start_time
|
| 191 |
+
total_time.append(tmp_time)
|
| 192 |
+
|
| 193 |
+
preds = [tf.sigmoid(i).numpy() for i in preds]
|
| 194 |
+
all_preds = np.array(preds)
|
| 195 |
+
for i in range(all_preds.shape[1]):
|
| 196 |
+
tmp_name = data_names[k]
|
| 197 |
+
tmp_name, _ = os.path.splitext(tmp_name)
|
| 198 |
+
tmp_shape = data_shape[k]
|
| 199 |
+
|
| 200 |
+
tmp_preds = all_preds[:, i, ...]
|
| 201 |
+
tmp_av = np.expand_dims(tmp_preds.mean(axis=0), axis=0)
|
| 202 |
+
tmp_preds = np.concatenate((tmp_preds, tmp_av), axis=0)
|
| 203 |
+
res_preds = []
|
| 204 |
+
for j in range(tmp_preds.shape[0]):
|
| 205 |
+
tmp_pred = tmp_preds[j, ...]
|
| 206 |
+
tmp_pred[tmp_pred < 0.0] = 0.0
|
| 207 |
+
tmp_pred = cv.bitwise_not(np.uint8(image_normalization(tmp_pred)))
|
| 208 |
+
h, w = tmp_pred.shape[:2]
|
| 209 |
+
if h != tmp_shape[0] or w != tmp_shape[1]:
|
| 210 |
+
tmp_pred = cv.resize(tmp_pred, (tmp_shape[1], tmp_shape[0]))
|
| 211 |
+
res_preds.append(tmp_pred)
|
| 212 |
+
n_save =len(tmp_preds)-2
|
| 213 |
+
for idx in range(len(save_dirs) - 1):
|
| 214 |
+
s_dir = save_dirs[idx]
|
| 215 |
+
tmp = res_preds[n_save + idx]
|
| 216 |
+
cv.imwrite(join(s_dir, tmp_name + '.png'), tmp)
|
| 217 |
+
h5_writer(path=join(save_dirs[-1], tmp_name + '.h5'),
|
| 218 |
+
vars=np.squeeze(res_preds))
|
| 219 |
+
print("saved:", join(save_dirs[-1], tmp_name + '.h5'), tmp_preds.shape)
|
| 220 |
+
k += 1
|
| 221 |
+
|
| 222 |
+
# tmp_name = data_names[step][:-3]+"png"
|
| 223 |
+
# tmp_shape = data_shape[step]
|
| 224 |
+
# tmp_path = os.path.join(result_dir,tmp_name)
|
| 225 |
+
# tensor2image(preds[-1].numpy(), img_path =tmp_path,img_shape=tmp_shape)
|
| 226 |
+
|
| 227 |
+
total_time = np.array(total_time)
|
| 228 |
+
|
| 229 |
+
print('-------------------------------------------------')
|
| 230 |
+
print("End testing in: ", self.args.data4test)
|
| 231 |
+
print("Batch size: ", self.args.test_bs)
|
| 232 |
+
print("Time average per image: ", total_time.mean(), "secs")
|
| 233 |
+
print("Total time: ", total_time.sum(), "secs")
|
| 234 |
+
print('-------------------------------------------------')
|
DexiNed-TF2/utls.py
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
import numpy as np
|
| 3 |
+
import os
|
| 4 |
+
import cv2 as cv
|
| 5 |
+
import h5py
|
| 6 |
+
|
| 7 |
+
def image_normalization(img, img_min=0, img_max=255):
|
| 8 |
+
"""This is a typical image normalization function
|
| 9 |
+
where the minimum and maximum of the image is needed
|
| 10 |
+
source: https://en.wikipedia.org/wiki/Normalization_(image_processing)
|
| 11 |
+
:param img: an image could be gray scale or color
|
| 12 |
+
:param img_min: for default is 0
|
| 13 |
+
:param img_max: for default is 255
|
| 14 |
+
:return: a normalized image, if max is 255 the dtype is uint8
|
| 15 |
+
"""
|
| 16 |
+
img = np.float32(img)
|
| 17 |
+
epsilon=1e-12 # whenever an inconsistent image
|
| 18 |
+
img = (img-np.min(img))*(img_max-img_min)/((np.max(img)-np.min(img))+epsilon)+img_min
|
| 19 |
+
return img
|
| 20 |
+
|
| 21 |
+
def make_dirs(paths): # make path or paths dirs
|
| 22 |
+
if not os.path.exists(paths):
|
| 23 |
+
os.makedirs(paths)
|
| 24 |
+
print("Directories have been created: ",paths)
|
| 25 |
+
return True
|
| 26 |
+
else:
|
| 27 |
+
print("Directories already exists: ", paths)
|
| 28 |
+
return False
|
| 29 |
+
|
| 30 |
+
def read_files_list(list_path,dataset_name=None):
|
| 31 |
+
mfiles = open(list_path)
|
| 32 |
+
file_names = mfiles.readlines()
|
| 33 |
+
mfiles.close()
|
| 34 |
+
|
| 35 |
+
file_names = [f.strip() for f in file_names] # this is for delete '\n'
|
| 36 |
+
return file_names
|
| 37 |
+
|
| 38 |
+
def data_parser(dataset_dir,dataset_name, list_name=None,training=True):
|
| 39 |
+
|
| 40 |
+
if dataset_name.upper()!="CLASSIC":
|
| 41 |
+
files_name = list_name # dataset base dir
|
| 42 |
+
list_path = os.path.join(dataset_dir, files_name)
|
| 43 |
+
data_list = read_files_list(list_path)
|
| 44 |
+
tmp_list = data_list[0]
|
| 45 |
+
tmp_list = tmp_list.split(' ')
|
| 46 |
+
n_lists = len(tmp_list)
|
| 47 |
+
if dataset_name.upper()=='BIPED':
|
| 48 |
+
in_dir = os.path.join(dataset_dir,'imgs','train') if training else \
|
| 49 |
+
os.path.join(dataset_dir, 'imgs', 'test')
|
| 50 |
+
gt_dir = os.path.join(dataset_dir,'edge_maps','train') if training else \
|
| 51 |
+
os.path.join(dataset_dir, 'edge_maps', 'test')
|
| 52 |
+
elif dataset_name.upper()=="CLASSIC":
|
| 53 |
+
list_path= dataset_dir
|
| 54 |
+
data_list = os.listdir(dataset_dir)
|
| 55 |
+
data_list = [os.path.join(dataset_dir,i)for i in data_list]
|
| 56 |
+
n_lists = None
|
| 57 |
+
else:
|
| 58 |
+
|
| 59 |
+
in_dir = dataset_dir
|
| 60 |
+
gt_dir = dataset_dir
|
| 61 |
+
|
| 62 |
+
if n_lists==1:
|
| 63 |
+
data_list = [c.split(' ') for c in data_list]
|
| 64 |
+
data_list = [(os.path.join(in_dir, c[0])) for c in data_list]
|
| 65 |
+
elif n_lists==2:
|
| 66 |
+
data_list = [c.split(' ') for c in data_list]
|
| 67 |
+
data_list = [(os.path.join(in_dir, c[0]),
|
| 68 |
+
os.path.join(gt_dir, c[1])) for c in data_list]
|
| 69 |
+
else:
|
| 70 |
+
print('There are just two entry files, dataset:', dataset_name)
|
| 71 |
+
|
| 72 |
+
num_data = len(data_list)
|
| 73 |
+
print(" Enterely training set-up from {}, size: {}".format(list_path, num_data))
|
| 74 |
+
|
| 75 |
+
all_train_ids = np.arange(num_data)
|
| 76 |
+
np.random.shuffle(all_train_ids)
|
| 77 |
+
if training:
|
| 78 |
+
|
| 79 |
+
train_ids = all_train_ids[:int(0.9 * len(data_list))]
|
| 80 |
+
valid_ids = all_train_ids[int(0.9 * len(data_list)):]
|
| 81 |
+
|
| 82 |
+
print("Training set-up from {}, size: {}".format(list_path, len(train_ids)))
|
| 83 |
+
print("Validation set-up from {}, size: {}".format(list_path, len(valid_ids)))
|
| 84 |
+
train_list = [data_list[i] for i in train_ids]
|
| 85 |
+
val_list = [data_list[i] for i in valid_ids]
|
| 86 |
+
cache_info = {
|
| 87 |
+
"files_path": data_list,
|
| 88 |
+
"train_paths":train_list,
|
| 89 |
+
"val_paths": val_list,
|
| 90 |
+
"n_files": num_data,
|
| 91 |
+
"train_indices": train_ids,
|
| 92 |
+
"val_indices": valid_ids
|
| 93 |
+
}
|
| 94 |
+
else:
|
| 95 |
+
data_shape = []
|
| 96 |
+
data_name=[]
|
| 97 |
+
for tmp_path in data_list:
|
| 98 |
+
tmp_img = cv.imread(tmp_path[0]) if len(tmp_path)<4 else cv.imread(tmp_path)
|
| 99 |
+
tmp_name = os.path.basename(tmp_path[0])if len(tmp_path)<4 else\
|
| 100 |
+
os.path.basename(tmp_path)
|
| 101 |
+
tmp_shape = tmp_img.shape[:2]
|
| 102 |
+
data_shape.append(tmp_shape)
|
| 103 |
+
data_name.append(tmp_name)
|
| 104 |
+
is_gt = True if len(tmp_path)<4 else False
|
| 105 |
+
|
| 106 |
+
print("Testing set-up from {}, size: {}".format(list_path, len(all_train_ids)))
|
| 107 |
+
cache_info = {
|
| 108 |
+
"files_path": data_list,
|
| 109 |
+
"n_files": num_data,
|
| 110 |
+
"is_gt":is_gt,
|
| 111 |
+
"data_name": data_name,
|
| 112 |
+
"data_shape":data_shape
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
+
return cache_info
|
| 116 |
+
|
| 117 |
+
def cv_imshow(title='image',img=None):
|
| 118 |
+
|
| 119 |
+
cv.imshow(title,img)
|
| 120 |
+
cv.waitKey(0)
|
| 121 |
+
cv.destroyAllWindows()
|
| 122 |
+
|
| 123 |
+
def image_normalization(img, img_min=0, img_max=255):
|
| 124 |
+
"""This is a typical image normalization function
|
| 125 |
+
where the minimum and maximum of the image is needed
|
| 126 |
+
source: https://en.wikipedia.org/wiki/Normalization_(image_processing)
|
| 127 |
+
:param img: an image could be gray scale or color
|
| 128 |
+
:param img_min: for default is 0
|
| 129 |
+
:param img_max: for default is 255
|
| 130 |
+
:return: a normalized image, if max is 255 the dtype is uint8
|
| 131 |
+
"""
|
| 132 |
+
img = np.float32(img)
|
| 133 |
+
epsilon=1e-12 # whenever an inconsistent image
|
| 134 |
+
img = (img-np.min(img))*(img_max-img_min)/((np.max(img)-np.min(img))+epsilon)+img_min
|
| 135 |
+
return img
|
| 136 |
+
|
| 137 |
+
def restore_rgb(config,I, restore_rgb=False):
|
| 138 |
+
"""
|
| 139 |
+
:param config: [args.channel_swap, args.mean_pixel_value]
|
| 140 |
+
:param I: and image or a set of images
|
| 141 |
+
:return: an image or a set of images restored
|
| 142 |
+
"""
|
| 143 |
+
|
| 144 |
+
if len(I)>3 and not type(I)==np.ndarray:
|
| 145 |
+
I =np.array(I)
|
| 146 |
+
I = I[:,:,:,0:3]
|
| 147 |
+
n = I.shape[0]
|
| 148 |
+
for i in range(n):
|
| 149 |
+
x = I[i,...]
|
| 150 |
+
x = np.array(x, dtype=np.float32)
|
| 151 |
+
x += config[1]
|
| 152 |
+
if restore_rgb:
|
| 153 |
+
x = x[:, :, config[0]]
|
| 154 |
+
x = image_normalization(x)
|
| 155 |
+
I[i,:,:,:]=x
|
| 156 |
+
elif len(I.shape)==3 and I.shape[-1]==3:
|
| 157 |
+
I = np.array(I, dtype=np.float32)
|
| 158 |
+
I += config[1]
|
| 159 |
+
if restore_rgb:
|
| 160 |
+
I = I[:, :, config[0]]
|
| 161 |
+
I = image_normalization(I)
|
| 162 |
+
else:
|
| 163 |
+
print("Sorry the input data size is out of our configuration")
|
| 164 |
+
# print("The enterely I data {} restored".format(I.shape))
|
| 165 |
+
return I
|
| 166 |
+
|
| 167 |
+
def visualize_result(x,y,p, img_title):
|
| 168 |
+
"""
|
| 169 |
+
function for tensorflow results
|
| 170 |
+
:param imgs_list: a list of prediction, gt and input data
|
| 171 |
+
:param arg:
|
| 172 |
+
:return: one image with the whole of imgs_list data
|
| 173 |
+
"""
|
| 174 |
+
imgs_list = []
|
| 175 |
+
imgs_list.append(x)
|
| 176 |
+
imgs_list.append(y)
|
| 177 |
+
for i in p:
|
| 178 |
+
tmp = i.numpy()[2]
|
| 179 |
+
imgs_list.append(tmp)
|
| 180 |
+
|
| 181 |
+
n_imgs = len(imgs_list)
|
| 182 |
+
data_list =[]
|
| 183 |
+
for i in range(n_imgs):
|
| 184 |
+
tmp = imgs_list[i]
|
| 185 |
+
if tmp.shape[-1]==3:
|
| 186 |
+
# tmp = np.transpose(np.squeeze(tmp),[1,2,0])
|
| 187 |
+
# tmp=restore_rgb([arg.channel_swap,arg.mean_pixel_values[:3]],tmp)
|
| 188 |
+
tmp = tmp[:,:,[2,1,0]]
|
| 189 |
+
tmp = np.uint8(image_normalization(tmp))
|
| 190 |
+
else:
|
| 191 |
+
tmp= np.squeeze(tmp)
|
| 192 |
+
if len(tmp.shape) == 2:
|
| 193 |
+
tmp = np.uint8(image_normalization(tmp))
|
| 194 |
+
tmp = cv.bitwise_not(tmp)
|
| 195 |
+
tmp = cv.cvtColor(tmp, cv.COLOR_GRAY2BGR)
|
| 196 |
+
else:
|
| 197 |
+
tmp = np.uint8(image_normalization(tmp))
|
| 198 |
+
|
| 199 |
+
|
| 200 |
+
data_list.append(tmp)
|
| 201 |
+
img = data_list[0]
|
| 202 |
+
if n_imgs % 2 == 0:
|
| 203 |
+
imgs = np.zeros((img.shape[0] * 2 + 10, img.shape[1] * (n_imgs // 2) + ((n_imgs // 2 - 1) * 5), 3))
|
| 204 |
+
else:
|
| 205 |
+
imgs = np.zeros((img.shape[0] * 2 + 10, img.shape[1] * ((1 + n_imgs) // 2) + ((n_imgs // 2) * 5), 3))
|
| 206 |
+
n_imgs += 1
|
| 207 |
+
|
| 208 |
+
k=0
|
| 209 |
+
imgs = np.uint8(imgs)
|
| 210 |
+
i_step = img.shape[0]+10
|
| 211 |
+
j_step = img.shape[1]+5
|
| 212 |
+
for i in range(2):
|
| 213 |
+
for j in range(n_imgs//2):
|
| 214 |
+
if k<len(data_list):
|
| 215 |
+
imgs[i*i_step:i*i_step+img.shape[0],j*j_step:j*j_step+img.shape[1],:]=data_list[k]
|
| 216 |
+
k+=1
|
| 217 |
+
else:
|
| 218 |
+
pass
|
| 219 |
+
|
| 220 |
+
# last processing, resize and add title
|
| 221 |
+
vis_imgs = cv.resize(imgs, (int(imgs.shape[1] * 0.8), int(imgs.shape[0] * 0.8)))
|
| 222 |
+
BLACK = (0, 0, 255)
|
| 223 |
+
font = cv.FONT_HERSHEY_SIMPLEX
|
| 224 |
+
font_size = 1.1
|
| 225 |
+
font_color = BLACK
|
| 226 |
+
font_thickness = 2
|
| 227 |
+
x, y = 30, 30
|
| 228 |
+
vis_imgs = cv.putText(vis_imgs, img_title, (x, y), font, font_size, font_color, font_thickness,
|
| 229 |
+
cv.LINE_AA)
|
| 230 |
+
return vis_imgs
|
| 231 |
+
|
| 232 |
+
def tensor2image(image, img_path =None,img_shape=None):
|
| 233 |
+
tmp_img = np.squeeze(image_normalization(image))
|
| 234 |
+
tmp_img = np.uint8(cv.resize(tmp_img,(img_shape[1],img_shape[0])))
|
| 235 |
+
tmp_img = cv.bitwise_not(tmp_img)
|
| 236 |
+
cv.imwrite(img_path,tmp_img)
|
| 237 |
+
print("Prediction saved in:",img_path)
|
| 238 |
+
|
| 239 |
+
def tensor2image(image, img_path =None,img_shape=None):
|
| 240 |
+
tmp_img = np.squeeze(image_normalization(image))
|
| 241 |
+
tmp_img = np.uint8(cv.resize(tmp_img,(img_shape[1],img_shape[0])))
|
| 242 |
+
tmp_img = cv.bitwise_not(tmp_img)
|
| 243 |
+
cv.imwrite(img_path,tmp_img)
|
| 244 |
+
print("Prediction saved in:",img_path)
|
| 245 |
+
|
| 246 |
+
def h5_writer(vars,path, is_multivar=False):
|
| 247 |
+
# vars is a single variable o a list of multiple variables
|
| 248 |
+
|
| 249 |
+
with h5py.File(path, 'w') as hf:
|
| 250 |
+
if is_multivar:
|
| 251 |
+
assert isinstance(vars, list)
|
| 252 |
+
for idx, var in enumerate(vars):
|
| 253 |
+
hf.create_dataset('data'+str(idx+1), data=var)
|
| 254 |
+
# print('Set of data',len(vars),'saved in ', path)
|
| 255 |
+
else:
|
| 256 |
+
hf.create_dataset('data', data=vars)
|
| 257 |
+
# print("Data [", len(vars), "] saved in: ", path)
|
LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2019 Xavier Soria Poma
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 6 |
+
of this software and associated documentation files (the "Software"), to deal
|
| 7 |
+
in the Software without restriction, including without limitation the rights
|
| 8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 9 |
+
copies of the Software, and to permit persons to whom the Software is
|
| 10 |
+
furnished to do so, subject to the following conditions:
|
| 11 |
+
|
| 12 |
+
The above copyright notice and this permission notice shall be included in all
|
| 13 |
+
copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 21 |
+
SOFTWARE.
|
README.md
CHANGED
|
@@ -1,19 +1,204 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[](https://paperswithcode.com/sota/edge-detection-on-biped-1?p=dense-extreme-inception-network-for-edge)
|
| 2 |
+
[](https://paperswithcode.com/sota/edge-detection-on-mdbd?p=dense-extreme-inception-network-for-edge)
|
| 3 |
+
# DexiNed: Dense Extreme Inception Network for Edge Detection (Extended version)
|
| 4 |
+
|
| 5 |
+
```diff
|
| 6 |
+
- We have just updated the last version of DexiNed in Pytorch.
|
| 7 |
+
- The implementation with TF1 is fransfered to the "legacy" dir.
|
| 8 |
+
- These days we are going to updated minor changes but the model,
|
| 9 |
+
loss function, and the testing and training procedures does not need changes,
|
| 10 |
+
hopefully :), if you have time please check errors and let me know
|
| 11 |
+
in Issues.
|
| 12 |
+
|
| 13 |
+
```
|
| 14 |
+
|
| 15 |
+
This is the extended work from DexiNed presented in WACV2020.
|
| 16 |
+
We have improved the architecture and the dataset. Unlike of the state-of-the-art CNN
|
| 17 |
+
based edge detectors, this models has a single training stage,
|
| 18 |
+
but it is still able to overcome those models in edge detection datasets. Moreover,
|
| 19 |
+
Dexined does not need pre-trained weights, and it is trained from the scratch
|
| 20 |
+
with fewer parameters tunning. To know more about DexiNed, read our first
|
| 21 |
+
version of Dexined in [ieeexplore](https://ieeexplore.ieee.org/document/9093290),
|
| 22 |
+
and its extended version in [arXiv](https://arxiv.org/abs/2112.02250).
|
| 23 |
+
The last version of DexiNed is implemented in Pytorch, in TF2 it
|
| 24 |
+
will be available soon. If to want our preliminary version, please check legacy DIR.
|
| 25 |
+
|
| 26 |
+
We have prepared a basic intro to DexiNed in a video, [check it in YouTube](https://youtu.be/Hz0uU04B3U8)
|
| 27 |
+
|
| 28 |
+
<div style="text-align:center"><img src='figs/DexiNed_banner.png' width=800>
|
| 29 |
+
</div>
|
| 30 |
+
|
| 31 |
+
## Table of Contents
|
| 32 |
+
* [DexiNed-v1](#dexiNed-v1)
|
| 33 |
+
* [TensorFlow](#tensorflow2)
|
| 34 |
+
* [Datasets](#datasets)
|
| 35 |
+
* [Performance](#performance)
|
| 36 |
+
* [Citation](#citation)
|
| 37 |
+
|
| 38 |
+
# DexiNed-v1
|
| 39 |
+
|
| 40 |
+
This version was presented in WACV2020, this is the base DexiNed model [implemented in TensorFlow 1](https://github.com/xavysp/DexiNed/tree/master/legacy)
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
# TensorFlow2
|
| 44 |
+
|
| 45 |
+
Dexined version on TF 2 is not ready
|
| 46 |
+
## Requirements
|
| 47 |
+
|
| 48 |
+
* [Python 3.7](https://www.python.org/downloads/release/python-370/g)
|
| 49 |
+
* [Pytorch >=1.4](https://pytorch.org/) (Last test 1.9)
|
| 50 |
+
* [OpenCV](https://pypi.org/project/opencv-python/)
|
| 51 |
+
* [Matplotlib](https://matplotlib.org/3.1.1/users/installing.html)
|
| 52 |
+
* [Kornia](https://kornia.github.io/)
|
| 53 |
+
* Other package like Numpy, h5py, PIL, json.
|
| 54 |
+
|
| 55 |
+
Once the packages are installed, clone this repo as follow:
|
| 56 |
+
|
| 57 |
+
git clone https://github.com/xavysp/DexiNed.git
|
| 58 |
+
cd DexiNed
|
| 59 |
+
|
| 60 |
+
## Project Architecture
|
| 61 |
+
|
| 62 |
+
```
|
| 63 |
+
├── data # Sample images for testing (paste your image here)
|
| 64 |
+
| ├── lena_std.tif # Sample 1
|
| 65 |
+
├── DexiNed-TF2 # DexiNed in TensorFlow2 (in construction)
|
| 66 |
+
├── figs # Images used in README.md
|
| 67 |
+
| └── DexiNed_banner.png # DexiNed banner
|
| 68 |
+
├── legacy # DexiNed in TensorFlow1 (presented in WACV2020)
|
| 69 |
+
├── utls # A series of tools used in this repo
|
| 70 |
+
| └── image.py # Miscellaneous tool functions
|
| 71 |
+
├── datasets.py # Tools for dataset managing
|
| 72 |
+
├── dexi_utils.py # New functions still not used in the currecnt version
|
| 73 |
+
├── losses.py # Loss function used to train DexiNed (BDCNloss2)
|
| 74 |
+
├── main.py # The main python file with main functions and parameter settings
|
| 75 |
+
# here you can test and train
|
| 76 |
+
├── model.py # DexiNed class in pythorch
|
| 77 |
+
```
|
| 78 |
+
|
| 79 |
+
Before to start please check dataset.py, from the first line of code you can see the datasets used for training/testing. The main.py, line 194, call the data for the training or testing, see the example of the code below:
|
| 80 |
+
```
|
| 81 |
+
parser = argparse.ArgumentParser(description='DexiNed trainer.')
|
| 82 |
+
parser.add_argument('--choose_test_data',
|
| 83 |
+
type=int,
|
| 84 |
+
default=1,
|
| 85 |
+
help='Already set the dataset for testing choice: 0 - 8')
|
| 86 |
+
# ----------- test -------0--
|
| 87 |
+
|
| 88 |
+
TEST_DATA = DATASET_NAMES[parser.parse_args().choose_test_data] # max 8
|
| 89 |
+
test_inf = dataset_info(TEST_DATA, is_linux=IS_LINUX)
|
| 90 |
+
test_dir = test_inf['data_dir']
|
| 91 |
+
is_testing = True# current test -352-SM-NewGT-2AugmenPublish
|
| 92 |
+
|
| 93 |
+
# Training settings
|
| 94 |
+
TRAIN_DATA = DATASET_NAMES[0] # BIPED=0
|
| 95 |
+
train_inf = dataset_info(TRAIN_DATA, is_linux=IS_LINUX)
|
| 96 |
+
train_dir = train_inf['data_dir']
|
| 97 |
+
```
|
| 98 |
+
|
| 99 |
+
## Test
|
| 100 |
+
As previously mentioned, the datasets.py has, among other things, the whole datasets configurations used in DexiNed for testing and training:
|
| 101 |
+
```
|
| 102 |
+
DATASET_NAMES = [
|
| 103 |
+
'BIPED',
|
| 104 |
+
'BSDS',
|
| 105 |
+
'BSDS300',
|
| 106 |
+
'CID',
|
| 107 |
+
'DCD',
|
| 108 |
+
'MULTICUE', #5
|
| 109 |
+
'PASCAL',
|
| 110 |
+
'NYUD',
|
| 111 |
+
'CLASSIC'
|
| 112 |
+
]
|
| 113 |
+
```
|
| 114 |
+
For example, if want to test your own dataset or image choose "CLASSIC" and save your test data in "data" dir.
|
| 115 |
+
Before test the DexiNed model, it is necesarry to download the checkpoint here [Checkpoint Pytorch](https://drive.google.com/file/d/1V56vGTsu7GYiQouCIKvTWl5UKCZ6yCNu/view?usp=sharing) and save this file into the DexiNed folder like: checkpoints/BIPED/10/(here the checkpoints from Drive), then run as follow:
|
| 116 |
+
|
| 117 |
+
```python main.py --choose_test_data=-1 ```
|
| 118 |
+
Make sure that in main.py the test setting be as:
|
| 119 |
+
```parser.add_argument('--is_testing', default=True, help='Script in testing mode.')```
|
| 120 |
+
DexiNed downsample the input image till 16 scales, please make sure that, in dataset_info fucn (datasets.py), the image width and height be multiple of 16, like 512, 960, and etc. **In the Checkpoint from Drive you will find the last trained checkpoint, which has been trained in the last version of BIPED dataset that will be updated soon in Kaggle **
|
| 121 |
+
|
| 122 |
+
## Train
|
| 123 |
+
|
| 124 |
+
python main.py
|
| 125 |
+
Make sure that in main.py the train setting be as:
|
| 126 |
+
```parser.add_argument('--is_testing', default=False, help='Script in testing mode.')```
|
| 127 |
+
|
| 128 |
+
# Datasets
|
| 129 |
+
|
| 130 |
+
## Dataset used for Training
|
| 131 |
+
```diff
|
| 132 |
+
- The BIPED dataset has been updated to the last version and it can be download from Kaggle
|
| 133 |
+
|
| 134 |
+
```
|
| 135 |
+
|
| 136 |
+
BIPED (Barcelona Images for Perceptual Edge Detection): This dataset is collected and annotated in the edge level for this work. **See more details, augmentation script, and download** in: [Option1](https://xavysp.github.io/MBIPED/), [Option2 kaggle](https://www.kaggle.com/xavysp/biped). The BIPED dataset has been updated, adding more annotations and correcting few mistakes, so those links have the renewed version of BIPED, if you want the older version you may ask us by email. The last performance (table below) will be updated soon.
|
| 137 |
+
|
| 138 |
+
## Datasets used for Testing
|
| 139 |
+
|
| 140 |
+
Edge detection datasets
|
| 141 |
+
* [BIPED](https://xavysp.github.io/MBIPED/) and [MDBD](http://serre-lab.clps.brown.edu/resource/multicue/)
|
| 142 |
+
|
| 143 |
+
Non-edge detection datasets
|
| 144 |
+
|
| 145 |
+
* [CID](http://www.cs.rug.nl/~imaging/databases/contour_database/contour_database.html) <!-- * [DCD](http://www.cs.cmu.edu/~mengtial/proj/sketch/)-->, [BSDS300](https://www2.eecs.berkeley.edu/Research/Projects/CS/vision/bsds/), [BSDS500](https://www2.eecs.berkeley.edu/Research/Projects/CS/vision/bsds/), [NYUD](https://cs.nyu.edu/~silberman/datasets/nyu_depth_v2.html), and [PASCAL-context](https://cs.stanford.edu/~roozbeh/pascal-context/)
|
| 146 |
+
|
| 147 |
+
# Performance
|
| 148 |
+
|
| 149 |
+
The results below are from the last version of BIPEP (BIPEDv2, we leave as BIPED because this is the default version).
|
| 150 |
+
After WACV20, the BIPED images have been checked again and added more annotations. All of those models have been trained again.
|
| 151 |
+
|
| 152 |
+
<center>
|
| 153 |
+
|
| 154 |
+
| Methods | ODS | ODS | AP |
|
| 155 |
+
| -------------- | ---------| -------- | -------- |
|
| 156 |
+
| [RCF](https://github.com/yun-liu/rcf) | `.849` | `.861` | `.906` |
|
| 157 |
+
| [BDCN](https://github.com/pkuCactus/BDCN) | `.890` | `.899` | `.934` |
|
| 158 |
+
| [CATS](https://github.com/WHUHLX/CATS) | `.887` | `.892` | `.817` |
|
| 159 |
+
| DexiNed-f(Ours)| `.895` | `.900` | `.927` |
|
| 160 |
+
| DexiNed-a(Ours)| `.893` | `.897` | `.940` |
|
| 161 |
+
|
| 162 |
+
</center>
|
| 163 |
+
|
| 164 |
+
|
| 165 |
+
# Citation
|
| 166 |
+
|
| 167 |
+
If you like DexiNed, why not starring the project on GitHub!
|
| 168 |
+
|
| 169 |
+
[](https://GitHub.com/xavysp/DexiNed/stargazers/)
|
| 170 |
+
|
| 171 |
+
Please cite our paper if you find helpful in your academic/scientific publication,
|
| 172 |
+
```
|
| 173 |
+
@INPROCEEDINGS {xsoria2020dexined,
|
| 174 |
+
author = {X. Soria and E. Riba and A. Sappa},
|
| 175 |
+
booktitle = {2020 IEEE Winter Conference on Applications of Computer Vision (WACV)},
|
| 176 |
+
title = {Dense Extreme Inception Network: Towards a Robust CNN Model for Edge Detection},
|
| 177 |
+
year = {2020},
|
| 178 |
+
volume = {},
|
| 179 |
+
issn = {},
|
| 180 |
+
pages = {1912-1921},
|
| 181 |
+
keywords = {image edge detection;convolution;training;feeds;machine learning;task analysis;kernel},
|
| 182 |
+
doi = {10.1109/WACV45572.2020.9093290},
|
| 183 |
+
url = {https://doi.ieeecomputersociety.org/10.1109/WACV45572.2020.9093290},
|
| 184 |
+
publisher = {IEEE Computer Society},
|
| 185 |
+
address = {Los Alamitos, CA, USA},
|
| 186 |
+
month = {mar}
|
| 187 |
+
}
|
| 188 |
+
```
|
| 189 |
+
Extended version.
|
| 190 |
+
```
|
| 191 |
+
@article{soria2023dexined_ext,
|
| 192 |
+
title = {Dense extreme inception network for edge detection},
|
| 193 |
+
journal = {Pattern Recognition},
|
| 194 |
+
volume = {139},
|
| 195 |
+
pages = {109461},
|
| 196 |
+
year = {2023},
|
| 197 |
+
issn = {0031-3203},
|
| 198 |
+
doi = {https://doi.org/10.1016/j.patcog.2023.109461},
|
| 199 |
+
url = {https://www.sciencedirect.com/science/article/pii/S0031320323001619},
|
| 200 |
+
author = {Xavier Soria and Angel Sappa and Patricio Humanante and Arash Akbarinia},
|
| 201 |
+
keywords = {Edge detection, Deep learning, CNN, Contour detection, Boundary detection, Segmentation}
|
| 202 |
+
}
|
| 203 |
+
```
|
| 204 |
+
|
__pycache__/datasets.cpython-312.pyc
ADDED
|
Binary file (16.8 kB). View file
|
|
|
__pycache__/dexi_utils.cpython-312.pyc
ADDED
|
Binary file (2.11 kB). View file
|
|
|
__pycache__/losses.cpython-312.pyc
ADDED
|
Binary file (8.96 kB). View file
|
|
|
__pycache__/model.cpython-312.pyc
ADDED
|
Binary file (15.3 kB). View file
|
|
|
app.py
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import glob
|
| 3 |
+
import subprocess
|
| 4 |
+
import streamlit as st
|
| 5 |
+
from PIL import Image
|
| 6 |
+
|
| 7 |
+
# ————————————————————————————————
|
| 8 |
+
# 1) Setup direktori dan session state
|
| 9 |
+
# ————————————————————————————————
|
| 10 |
+
DATA_DIR = "data"
|
| 11 |
+
FUSED_DIR = os.path.join("result", "BIPED2CLASSIC", "fused")
|
| 12 |
+
|
| 13 |
+
os.makedirs(DATA_DIR, exist_ok=True)
|
| 14 |
+
os.makedirs(FUSED_DIR, exist_ok=True)
|
| 15 |
+
|
| 16 |
+
# Inisialisasi flag supaya hasil hanya tampil setelah proses
|
| 17 |
+
if "processed" not in st.session_state:
|
| 18 |
+
st.session_state.processed = False
|
| 19 |
+
|
| 20 |
+
st.title("Deteksi jalan berlubang menggunakan DexiNed Egde Detection")
|
| 21 |
+
|
| 22 |
+
# ————————————————————————————————
|
| 23 |
+
# 2) Upload input
|
| 24 |
+
# ————————————————————————————————
|
| 25 |
+
upload = st.file_uploader("Unggah satu gambar jalan", type=["jpg","jpeg","png"])
|
| 26 |
+
if upload:
|
| 27 |
+
st.session_state.uploaded_file = upload
|
| 28 |
+
else:
|
| 29 |
+
# reset kalau user hapus input
|
| 30 |
+
st.session_state.processed = False
|
| 31 |
+
|
| 32 |
+
# ————————————————————————————————
|
| 33 |
+
# 3) Tombol Proses
|
| 34 |
+
# ————————————————————————————————
|
| 35 |
+
if st.button("Memproses Gambar"):
|
| 36 |
+
|
| 37 |
+
# 3.0 Validasi apakah gambar sudah diupload
|
| 38 |
+
if not upload and "uploaded_file" not in st.session_state:
|
| 39 |
+
st.error("❌ Silakan upload gambar terlebih dahulu sebelum memproses!")
|
| 40 |
+
elif not upload and st.session_state.get("uploaded_file") is None:
|
| 41 |
+
st.error("❌ Silakan upload gambar terlebih dahulu sebelum memproses!")
|
| 42 |
+
else:
|
| 43 |
+
# 3.1 Hapus semua file lama di DATA_DIR
|
| 44 |
+
for f in glob.glob(os.path.join(DATA_DIR, "*")):
|
| 45 |
+
os.remove(f)
|
| 46 |
+
|
| 47 |
+
# 3.2 Simpan ulang file input (seharusnya hanya 1)
|
| 48 |
+
input_path = os.path.join(DATA_DIR, st.session_state.uploaded_file.name)
|
| 49 |
+
with open(input_path, "wb") as f:
|
| 50 |
+
f.write(st.session_state.uploaded_file.getvalue())
|
| 51 |
+
|
| 52 |
+
# 3.3 Hapus semua file lama di FUSED_DIR
|
| 53 |
+
for f in glob.glob(os.path.join(FUSED_DIR, "*")):
|
| 54 |
+
os.remove(f)
|
| 55 |
+
|
| 56 |
+
# 3.4 Jalankan main.py (sesuaikan args jika perlu)
|
| 57 |
+
with st.spinner("Sedang memproses gambar..."):
|
| 58 |
+
result = subprocess.run(
|
| 59 |
+
["python", "main.py"],
|
| 60 |
+
capture_output=True, text=True
|
| 61 |
+
)
|
| 62 |
+
|
| 63 |
+
if result.returncode == 0:
|
| 64 |
+
st.success("Proses selesai 🎉")
|
| 65 |
+
st.session_state.processed = True
|
| 66 |
+
else:
|
| 67 |
+
st.error("Proses gagal:")
|
| 68 |
+
st.code(result.stderr)
|
| 69 |
+
st.session_state.processed = False
|
| 70 |
+
|
| 71 |
+
# ————————————————————————————————
|
| 72 |
+
# 4) Tampilkan hasil jika sudah diproses
|
| 73 |
+
# ————————————————————————————————
|
| 74 |
+
if st.session_state.processed:
|
| 75 |
+
# Cari file di fused (harusnya 1 file output)
|
| 76 |
+
outputs = glob.glob(os.path.join(FUSED_DIR, "*.*"))
|
| 77 |
+
if len(outputs) == 1:
|
| 78 |
+
out_img = Image.open(outputs[0])
|
| 79 |
+
st.subheader("Gambar Hasil")
|
| 80 |
+
st.image(out_img, caption=os.path.basename(outputs[0]), use_container_width=True)
|
| 81 |
+
elif len(outputs) > 1:
|
| 82 |
+
st.warning(f"Ditemukan {len(outputs)} file, seharusnya hanya 1.")
|
| 83 |
+
else:
|
| 84 |
+
st.error("Tidak ada file output di folder fused.")
|
checkpoints/BIPED/10/10_model.pth
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:bd4c603ef71113b447bffb72a73b9a54ca890e78f4bc8f34cb73f1efb2681e74
|
| 3 |
+
size 141069187
|
data/1739757991209.png
ADDED
|
Git LFS Details
|
dataset-lists/MDBD/test_pair.lst
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
test/imgs/4100_left_2268.png test/edge-maps/4100_left_2268.png
|
| 2 |
+
test/imgs/4101_left_0382.png test/edge-maps/4101_left_0382.png
|
| 3 |
+
test/imgs/4108_left_0082.png test/edge-maps/4108_left_0082.png
|
| 4 |
+
test/imgs/4113_left_0082.png test/edge-maps/4113_left_0082.png
|
| 5 |
+
test/imgs/4114_left_0611.png test/edge-maps/4114_left_0611.png
|
| 6 |
+
test/imgs/4176_left_0273.png test/edge-maps/4176_left_0273.png
|
| 7 |
+
test/imgs/4178_left_0052.png test/edge-maps/4178_left_0052.png
|
| 8 |
+
test/imgs/4179_left_0315.png test/edge-maps/4179_left_0315.png
|
| 9 |
+
test/imgs/4187_left_0071.png test/edge-maps/4187_left_0071.png
|
| 10 |
+
test/imgs/4209_left_0034.png test/edge-maps/4209_left_0034.png
|
| 11 |
+
test/imgs/4377_left_0016.png test/edge-maps/4377_left_0016.png
|
| 12 |
+
test/imgs/4386_left_0020.png test/edge-maps/4386_left_0020.png
|
| 13 |
+
test/imgs/4406_left_0030.png test/edge-maps/4406_left_0030.png
|
| 14 |
+
test/imgs/4523_left_0070.png test/edge-maps/4523_left_0070.png
|
| 15 |
+
test/imgs/4558_left_0260.png test/edge-maps/4558_left_0260.png
|
| 16 |
+
test/imgs/4580_left_0165.png test/edge-maps/4580_left_0165.png
|
| 17 |
+
test/imgs/4603_left_0050.png test/edge-maps/4603_left_0050.png
|
| 18 |
+
test/imgs/4663_left_0010.png test/edge-maps/4663_left_0010.png
|
| 19 |
+
test/imgs/4684_left_0010.png test/edge-maps/4684_left_0010.png
|
| 20 |
+
test/imgs/4685_left_0045.png test/edge-maps/4685_left_0045.png
|
datasets.py
ADDED
|
@@ -0,0 +1,490 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import random
|
| 3 |
+
|
| 4 |
+
import cv2
|
| 5 |
+
import numpy as np
|
| 6 |
+
import torch
|
| 7 |
+
from torch.utils.data import Dataset
|
| 8 |
+
import json
|
| 9 |
+
|
| 10 |
+
DATASET_NAMES = [
|
| 11 |
+
'BIPED',
|
| 12 |
+
'BSDS',
|
| 13 |
+
'BRIND',
|
| 14 |
+
'BSDS300',
|
| 15 |
+
'CID',
|
| 16 |
+
'DCD',
|
| 17 |
+
'MDBD', #5
|
| 18 |
+
'PASCAL',
|
| 19 |
+
'NYUD',
|
| 20 |
+
'CLASSIC'
|
| 21 |
+
] # 8
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
def dataset_info(dataset_name, is_linux=True):
|
| 25 |
+
if is_linux:
|
| 26 |
+
|
| 27 |
+
config = {
|
| 28 |
+
'BSDS': {
|
| 29 |
+
'img_height': 512, #321
|
| 30 |
+
'img_width': 512, #481
|
| 31 |
+
'train_list': 'train_pair.lst',
|
| 32 |
+
'test_list': 'test_pair.lst',
|
| 33 |
+
'data_dir': '/opt/dataset/BSDS', # mean_rgb
|
| 34 |
+
'yita': 0.5
|
| 35 |
+
},
|
| 36 |
+
'BRIND': {
|
| 37 |
+
'img_height': 512, # 321
|
| 38 |
+
'img_width': 512, # 481
|
| 39 |
+
'train_list': 'train_pair2.lst',
|
| 40 |
+
'test_list': 'test_pair.lst',
|
| 41 |
+
'data_dir': '/opt/dataset/BRIND', # mean_rgb
|
| 42 |
+
'yita': 0.5
|
| 43 |
+
},
|
| 44 |
+
'BSDS300': {
|
| 45 |
+
'img_height': 512, #321
|
| 46 |
+
'img_width': 512, #481
|
| 47 |
+
'test_list': 'test_pair.lst',
|
| 48 |
+
'train_list': None,
|
| 49 |
+
'data_dir': '/opt/dataset/BSDS300', # NIR
|
| 50 |
+
'yita': 0.5
|
| 51 |
+
},
|
| 52 |
+
'PASCAL': {
|
| 53 |
+
'img_height': 416, # 375
|
| 54 |
+
'img_width': 512, #500
|
| 55 |
+
'test_list': 'test_pair.lst',
|
| 56 |
+
'train_list': None,
|
| 57 |
+
'data_dir': '/opt/dataset/PASCAL', # mean_rgb
|
| 58 |
+
'yita': 0.3
|
| 59 |
+
},
|
| 60 |
+
'CID': {
|
| 61 |
+
'img_height': 512,
|
| 62 |
+
'img_width': 512,
|
| 63 |
+
'test_list': 'test_pair.lst',
|
| 64 |
+
'train_list': None,
|
| 65 |
+
'data_dir': '/opt/dataset/CID', # mean_rgb
|
| 66 |
+
'yita': 0.3
|
| 67 |
+
},
|
| 68 |
+
'NYUD': {
|
| 69 |
+
'img_height': 448,#425
|
| 70 |
+
'img_width': 560,#560
|
| 71 |
+
'test_list': 'test_pair.lst',
|
| 72 |
+
'train_list': None,
|
| 73 |
+
'data_dir': '/opt/dataset/NYUD', # mean_rgb
|
| 74 |
+
'yita': 0.5
|
| 75 |
+
},
|
| 76 |
+
'MDBD': {
|
| 77 |
+
'img_height': 720,
|
| 78 |
+
'img_width': 1280,
|
| 79 |
+
'test_list': 'test_pair.lst',
|
| 80 |
+
'train_list': 'train_pair.lst',
|
| 81 |
+
'data_dir': '/opt/dataset/MDBD', # mean_rgb
|
| 82 |
+
'yita': 0.3
|
| 83 |
+
},
|
| 84 |
+
'BIPED': {
|
| 85 |
+
'img_height': 720, #720 # 1088
|
| 86 |
+
'img_width': 1280, # 1280 5 1920
|
| 87 |
+
'test_list': 'test_pair.lst',
|
| 88 |
+
'train_list': 'train_rgb.lst',
|
| 89 |
+
'data_dir': '/opt/dataset/BIPED', # mean_rgb
|
| 90 |
+
'yita': 0.5
|
| 91 |
+
},
|
| 92 |
+
'CLASSIC': {
|
| 93 |
+
'img_height': 512,
|
| 94 |
+
'img_width': 512,
|
| 95 |
+
'test_list': None,
|
| 96 |
+
'train_list': None,
|
| 97 |
+
'data_dir': 'data', # mean_rgb
|
| 98 |
+
'yita': 0.5
|
| 99 |
+
},
|
| 100 |
+
'DCD': {
|
| 101 |
+
'img_height': 352, #240
|
| 102 |
+
'img_width': 480,# 360
|
| 103 |
+
'test_list': 'test_pair.lst',
|
| 104 |
+
'train_list': None,
|
| 105 |
+
'data_dir': '/opt/dataset/DCD', # mean_rgb
|
| 106 |
+
'yita': 0.2
|
| 107 |
+
}
|
| 108 |
+
}
|
| 109 |
+
else:
|
| 110 |
+
config = {
|
| 111 |
+
'BSDS': {'img_height': 512, # 321
|
| 112 |
+
'img_width': 512, # 481
|
| 113 |
+
'test_list': 'test_pair.lst',
|
| 114 |
+
'train_list': 'train_pair.lst',
|
| 115 |
+
'data_dir': 'C:/Users/xavysp/dataset/BSDS', # mean_rgb
|
| 116 |
+
'yita': 0.5},
|
| 117 |
+
'BSDS300': {'img_height': 512, # 321
|
| 118 |
+
'img_width': 512, # 481
|
| 119 |
+
'test_list': 'test_pair.lst',
|
| 120 |
+
'data_dir': 'C:/Users/xavysp/dataset/BSDS300', # NIR
|
| 121 |
+
'yita': 0.5},
|
| 122 |
+
'PASCAL': {'img_height': 375,
|
| 123 |
+
'img_width': 500,
|
| 124 |
+
'test_list': 'test_pair.lst',
|
| 125 |
+
'data_dir': 'C:/Users/xavysp/dataset/PASCAL', # mean_rgb
|
| 126 |
+
'yita': 0.3},
|
| 127 |
+
'CID': {'img_height': 512,
|
| 128 |
+
'img_width': 512,
|
| 129 |
+
'test_list': 'test_pair.lst',
|
| 130 |
+
'data_dir': 'C:/Users/xavysp/dataset/CID', # mean_rgb
|
| 131 |
+
'yita': 0.3},
|
| 132 |
+
'NYUD': {'img_height': 425,
|
| 133 |
+
'img_width': 560,
|
| 134 |
+
'test_list': 'test_pair.lst',
|
| 135 |
+
'data_dir': 'C:/Users/xavysp/dataset/NYUD', # mean_rgb
|
| 136 |
+
'yita': 0.5},
|
| 137 |
+
'MDBD': {'img_height': 720,
|
| 138 |
+
'img_width': 1280,
|
| 139 |
+
'test_list': 'test_pair.lst',
|
| 140 |
+
'train_list': 'train_pair.lst',
|
| 141 |
+
'data_dir': 'C:/Users/xavysp/dataset/MDBD', # mean_rgb
|
| 142 |
+
'yita': 0.3},
|
| 143 |
+
'BIPED': {'img_height': 720, # 720
|
| 144 |
+
'img_width': 1280, # 1280
|
| 145 |
+
'test_list': 'test_pair.lst',
|
| 146 |
+
'train_list': 'train_rgb.lst',
|
| 147 |
+
'data_dir': 'C:/Users/xavysp/dataset/BIPED', # WIN: '../.../dataset/BIPED/edges'
|
| 148 |
+
'yita': 0.5},
|
| 149 |
+
'CLASSIC': {'img_height': 512,
|
| 150 |
+
'img_width': 512,
|
| 151 |
+
'test_list': None,
|
| 152 |
+
'train_list': None,
|
| 153 |
+
'data_dir': 'data', # mean_rgb
|
| 154 |
+
'yita': 0.5},
|
| 155 |
+
'DCD': {'img_height': 240,
|
| 156 |
+
'img_width': 360,
|
| 157 |
+
'test_list': 'test_pair.lst',
|
| 158 |
+
'data_dir': 'C:/Users/xavysp/dataset/DCD', # mean_rgb
|
| 159 |
+
'yita': 0.2}
|
| 160 |
+
}
|
| 161 |
+
return config[dataset_name]
|
| 162 |
+
|
| 163 |
+
|
| 164 |
+
class TestDataset(Dataset):
|
| 165 |
+
def __init__(self,
|
| 166 |
+
data_root,
|
| 167 |
+
test_data,
|
| 168 |
+
mean_bgr,
|
| 169 |
+
img_height,
|
| 170 |
+
img_width,
|
| 171 |
+
test_list=None,
|
| 172 |
+
arg=None
|
| 173 |
+
):
|
| 174 |
+
if test_data not in DATASET_NAMES:
|
| 175 |
+
raise ValueError(f"Unsupported dataset: {test_data}")
|
| 176 |
+
|
| 177 |
+
self.data_root = data_root
|
| 178 |
+
self.test_data = test_data
|
| 179 |
+
self.test_list = test_list
|
| 180 |
+
self.args=arg
|
| 181 |
+
# self.arg = arg
|
| 182 |
+
# self.mean_bgr = arg.mean_pixel_values[0:3] if len(arg.mean_pixel_values) == 4 \
|
| 183 |
+
# else arg.mean_pixel_values
|
| 184 |
+
self.mean_bgr = mean_bgr
|
| 185 |
+
self.img_height = img_height
|
| 186 |
+
self.img_width = img_width
|
| 187 |
+
self.data_index = self._build_index()
|
| 188 |
+
|
| 189 |
+
print(f"mean_bgr: {self.mean_bgr}")
|
| 190 |
+
|
| 191 |
+
def _build_index(self):
|
| 192 |
+
sample_indices = []
|
| 193 |
+
if self.test_data == "CLASSIC":
|
| 194 |
+
# for single image testing
|
| 195 |
+
images_path = os.listdir(self.data_root)
|
| 196 |
+
labels_path = None
|
| 197 |
+
sample_indices = [images_path, labels_path]
|
| 198 |
+
else:
|
| 199 |
+
# image and label paths are located in a list file
|
| 200 |
+
|
| 201 |
+
if not self.test_list:
|
| 202 |
+
raise ValueError(
|
| 203 |
+
f"Test list not provided for dataset: {self.test_data}")
|
| 204 |
+
|
| 205 |
+
list_name = os.path.join(self.data_root, self.test_list)
|
| 206 |
+
if self.test_data.upper()=='BIPED':
|
| 207 |
+
|
| 208 |
+
with open(list_name) as f:
|
| 209 |
+
files = json.load(f)
|
| 210 |
+
for pair in files:
|
| 211 |
+
tmp_img = pair[0]
|
| 212 |
+
tmp_gt = pair[1]
|
| 213 |
+
sample_indices.append(
|
| 214 |
+
(os.path.join(self.data_root, tmp_img),
|
| 215 |
+
os.path.join(self.data_root, tmp_gt),))
|
| 216 |
+
else:
|
| 217 |
+
with open(list_name, 'r') as f:
|
| 218 |
+
files = f.readlines()
|
| 219 |
+
files = [line.strip() for line in files]
|
| 220 |
+
pairs = [line.split() for line in files]
|
| 221 |
+
|
| 222 |
+
for pair in pairs:
|
| 223 |
+
tmp_img = pair[0]
|
| 224 |
+
tmp_gt = pair[1]
|
| 225 |
+
sample_indices.append(
|
| 226 |
+
(os.path.join(self.data_root, tmp_img),
|
| 227 |
+
os.path.join(self.data_root, tmp_gt),))
|
| 228 |
+
return sample_indices
|
| 229 |
+
|
| 230 |
+
def __len__(self):
|
| 231 |
+
return len(self.data_index[0]) if self.test_data.upper()=='CLASSIC' else len(self.data_index)
|
| 232 |
+
|
| 233 |
+
def __getitem__(self, idx):
|
| 234 |
+
# get data sample
|
| 235 |
+
# image_path, label_path = self.data_index[idx]
|
| 236 |
+
if self.data_index[1] is None:
|
| 237 |
+
image_path = self.data_index[0][idx]
|
| 238 |
+
else:
|
| 239 |
+
image_path = self.data_index[idx][0]
|
| 240 |
+
label_path = None if self.test_data == "CLASSIC" else self.data_index[idx][1]
|
| 241 |
+
img_name = os.path.basename(image_path)
|
| 242 |
+
file_name = os.path.splitext(img_name)[0] + ".png"
|
| 243 |
+
|
| 244 |
+
# base dir
|
| 245 |
+
if self.test_data.upper() == 'BIPED':
|
| 246 |
+
img_dir = os.path.join(self.data_root, 'imgs', 'test')
|
| 247 |
+
gt_dir = os.path.join(self.data_root, 'edge_maps', 'test')
|
| 248 |
+
elif self.test_data.upper() == 'CLASSIC':
|
| 249 |
+
img_dir = self.data_root
|
| 250 |
+
gt_dir = None
|
| 251 |
+
else:
|
| 252 |
+
img_dir = self.data_root
|
| 253 |
+
gt_dir = self.data_root
|
| 254 |
+
|
| 255 |
+
# load data
|
| 256 |
+
image = cv2.imread(os.path.join(img_dir, image_path), cv2.IMREAD_COLOR)
|
| 257 |
+
if not self.test_data == "CLASSIC":
|
| 258 |
+
label = cv2.imread(os.path.join(
|
| 259 |
+
gt_dir, label_path), cv2.IMREAD_COLOR)
|
| 260 |
+
else:
|
| 261 |
+
label = None
|
| 262 |
+
|
| 263 |
+
im_shape = [image.shape[0], image.shape[1]]
|
| 264 |
+
image, label = self.transform(img=image, gt=label)
|
| 265 |
+
|
| 266 |
+
return dict(images=image, labels=label, file_names=file_name, image_shape=im_shape)
|
| 267 |
+
|
| 268 |
+
def transform(self, img, gt):
|
| 269 |
+
# gt[gt< 51] = 0 # test without gt discrimination
|
| 270 |
+
if self.test_data == "CLASSIC":
|
| 271 |
+
img_height = self.img_height
|
| 272 |
+
img_width = self.img_width
|
| 273 |
+
print(
|
| 274 |
+
f"actual size: {img.shape}, target size: {( img_height,img_width,)}")
|
| 275 |
+
# img = cv2.resize(img, (self.img_width, self.img_height))
|
| 276 |
+
img = cv2.resize(img, (img_width,img_height))
|
| 277 |
+
gt = None
|
| 278 |
+
|
| 279 |
+
# Make images and labels at least 512 by 512
|
| 280 |
+
elif img.shape[0] < 512 or img.shape[1] < 512:
|
| 281 |
+
img = cv2.resize(img, (self.args.test_img_width, self.args.test_img_height)) # 512
|
| 282 |
+
gt = cv2.resize(gt, (self.args.test_img_width, self.args.test_img_height)) # 512
|
| 283 |
+
|
| 284 |
+
# Make sure images and labels are divisible by 2^4=16
|
| 285 |
+
elif img.shape[0] % 16 != 0 or img.shape[1] % 16 != 0:
|
| 286 |
+
img_width = ((img.shape[1] // 16) + 1) * 16
|
| 287 |
+
img_height = ((img.shape[0] // 16) + 1) * 16
|
| 288 |
+
img = cv2.resize(img, (img_width, img_height))
|
| 289 |
+
gt = cv2.resize(gt, (img_width, img_height))
|
| 290 |
+
else:
|
| 291 |
+
img_width =self.args.test_img_width
|
| 292 |
+
img_height =self.args.test_img_height
|
| 293 |
+
img = cv2.resize(img, (img_width, img_height))
|
| 294 |
+
gt = cv2.resize(gt, (img_width, img_height))
|
| 295 |
+
|
| 296 |
+
# if self.yita is not None:
|
| 297 |
+
# gt[gt >= self.yita] = 1
|
| 298 |
+
img = np.array(img, dtype=np.float32)
|
| 299 |
+
# if self.rgb:
|
| 300 |
+
# img = img[:, :, ::-1] # RGB->BGR
|
| 301 |
+
# img=cv2.resize(img, (400, 464))
|
| 302 |
+
img -= self.mean_bgr
|
| 303 |
+
img = img.transpose((2, 0, 1))
|
| 304 |
+
img = torch.from_numpy(img.copy()).float()
|
| 305 |
+
|
| 306 |
+
if self.test_data == "CLASSIC":
|
| 307 |
+
gt = np.zeros((img.shape[:2]))
|
| 308 |
+
gt = torch.from_numpy(np.array([gt])).float()
|
| 309 |
+
else:
|
| 310 |
+
gt = np.array(gt, dtype=np.float32)
|
| 311 |
+
if len(gt.shape) == 3:
|
| 312 |
+
gt = gt[:, :, 0]
|
| 313 |
+
gt /= 255.
|
| 314 |
+
gt = torch.from_numpy(np.array([gt])).float()
|
| 315 |
+
|
| 316 |
+
return img, gt
|
| 317 |
+
|
| 318 |
+
|
| 319 |
+
class BipedDataset(Dataset):
|
| 320 |
+
train_modes = ['train', 'test', ]
|
| 321 |
+
dataset_types = ['rgbr', ]
|
| 322 |
+
data_types = ['aug', ]
|
| 323 |
+
|
| 324 |
+
def __init__(self,
|
| 325 |
+
data_root,
|
| 326 |
+
img_height,
|
| 327 |
+
img_width,
|
| 328 |
+
mean_bgr,
|
| 329 |
+
train_mode='train',
|
| 330 |
+
dataset_type='rgbr',
|
| 331 |
+
# is_scaling=None,
|
| 332 |
+
# Whether to crop image or otherwise resize image to match image height and width.
|
| 333 |
+
crop_img=False,
|
| 334 |
+
arg=None
|
| 335 |
+
):
|
| 336 |
+
self.data_root = data_root
|
| 337 |
+
self.train_mode = train_mode
|
| 338 |
+
self.dataset_type = dataset_type
|
| 339 |
+
self.data_type = 'aug' # be aware that this might change in the future
|
| 340 |
+
self.img_height = img_height
|
| 341 |
+
self.img_width = img_width
|
| 342 |
+
self.mean_bgr = mean_bgr
|
| 343 |
+
self.crop_img = crop_img
|
| 344 |
+
self.arg = arg
|
| 345 |
+
|
| 346 |
+
self.data_index = self._build_index()
|
| 347 |
+
|
| 348 |
+
def _build_index(self):
|
| 349 |
+
assert self.train_mode in self.train_modes, self.train_mode
|
| 350 |
+
assert self.dataset_type in self.dataset_types, self.dataset_type
|
| 351 |
+
assert self.data_type in self.data_types, self.data_type
|
| 352 |
+
|
| 353 |
+
data_root = os.path.abspath(self.data_root)
|
| 354 |
+
sample_indices = []
|
| 355 |
+
if self.arg.train_data.lower()=='biped':
|
| 356 |
+
|
| 357 |
+
images_path = os.path.join(data_root,
|
| 358 |
+
'edges/imgs',
|
| 359 |
+
self.train_mode,
|
| 360 |
+
self.dataset_type,
|
| 361 |
+
self.data_type)
|
| 362 |
+
labels_path = os.path.join(data_root,
|
| 363 |
+
'edges/edge_maps',
|
| 364 |
+
self.train_mode,
|
| 365 |
+
self.dataset_type,
|
| 366 |
+
self.data_type)
|
| 367 |
+
|
| 368 |
+
for directory_name in os.listdir(images_path):
|
| 369 |
+
image_directories = os.path.join(images_path, directory_name)
|
| 370 |
+
for file_name_ext in os.listdir(image_directories):
|
| 371 |
+
file_name = os.path.splitext(file_name_ext)[0]
|
| 372 |
+
sample_indices.append(
|
| 373 |
+
(os.path.join(images_path, directory_name, file_name + '.jpg'),
|
| 374 |
+
os.path.join(labels_path, directory_name, file_name + '.png'),)
|
| 375 |
+
)
|
| 376 |
+
else:
|
| 377 |
+
file_path = os.path.join(data_root, self.arg.train_list)
|
| 378 |
+
if self.arg.train_data.lower()=='bsds':
|
| 379 |
+
|
| 380 |
+
with open(file_path, 'r') as f:
|
| 381 |
+
files = f.readlines()
|
| 382 |
+
files = [line.strip() for line in files]
|
| 383 |
+
|
| 384 |
+
pairs = [line.split() for line in files]
|
| 385 |
+
for pair in pairs:
|
| 386 |
+
tmp_img = pair[0]
|
| 387 |
+
tmp_gt = pair[1]
|
| 388 |
+
sample_indices.append(
|
| 389 |
+
(os.path.join(data_root,tmp_img),
|
| 390 |
+
os.path.join(data_root,tmp_gt),))
|
| 391 |
+
else:
|
| 392 |
+
with open(file_path) as f:
|
| 393 |
+
files = json.load(f)
|
| 394 |
+
for pair in files:
|
| 395 |
+
tmp_img = pair[0]
|
| 396 |
+
tmp_gt = pair[1]
|
| 397 |
+
sample_indices.append(
|
| 398 |
+
(os.path.join(data_root, tmp_img),
|
| 399 |
+
os.path.join(data_root, tmp_gt),))
|
| 400 |
+
|
| 401 |
+
return sample_indices
|
| 402 |
+
|
| 403 |
+
def __len__(self):
|
| 404 |
+
return len(self.data_index)
|
| 405 |
+
|
| 406 |
+
def __getitem__(self, idx):
|
| 407 |
+
# get data sample
|
| 408 |
+
image_path, label_path = self.data_index[idx]
|
| 409 |
+
|
| 410 |
+
# load data
|
| 411 |
+
image = cv2.imread(image_path, cv2.IMREAD_COLOR)
|
| 412 |
+
label = cv2.imread(label_path, cv2.IMREAD_GRAYSCALE)
|
| 413 |
+
image, label = self.transform(img=image, gt=label)
|
| 414 |
+
return dict(images=image, labels=label)
|
| 415 |
+
|
| 416 |
+
def transform(self, img, gt):
|
| 417 |
+
gt = np.array(gt, dtype=np.float32)
|
| 418 |
+
if len(gt.shape) == 3:
|
| 419 |
+
gt = gt[:, :, 0]
|
| 420 |
+
|
| 421 |
+
gt /= 255. # for DexiNed input and BDCN
|
| 422 |
+
|
| 423 |
+
img = np.array(img, dtype=np.float32)
|
| 424 |
+
img -= self.mean_bgr
|
| 425 |
+
i_h, i_w,_ = img.shape
|
| 426 |
+
# data = []
|
| 427 |
+
# if self.scale is not None:
|
| 428 |
+
# for scl in self.scale:
|
| 429 |
+
# img_scale = cv2.resize(img, None, fx=scl, fy=scl, interpolation=cv2.INTER_LINEAR)
|
| 430 |
+
# data.append(torch.from_numpy(img_scale.transpose((2, 0, 1))).float())
|
| 431 |
+
# return data, gt
|
| 432 |
+
# 400 for BIPEd and 352 for BSDS check with 384
|
| 433 |
+
crop_size = self.img_height if self.img_height == self.img_width else None#448# MDBD=480 BIPED=480/400 BSDS=352
|
| 434 |
+
|
| 435 |
+
# for BSDS 352/BRIND
|
| 436 |
+
if i_w> crop_size and i_h>crop_size:
|
| 437 |
+
i = random.randint(0, i_h - crop_size)
|
| 438 |
+
j = random.randint(0, i_w - crop_size)
|
| 439 |
+
img = img[i:i + crop_size , j:j + crop_size ]
|
| 440 |
+
gt = gt[i:i + crop_size , j:j + crop_size ]
|
| 441 |
+
|
| 442 |
+
# # for BIPED/MDBD
|
| 443 |
+
# if np.random.random() > 0.4: #l
|
| 444 |
+
# h,w = gt.shape
|
| 445 |
+
# if i_w> 500 and i_h>500:
|
| 446 |
+
#
|
| 447 |
+
# LR_img_size = crop_size #l BIPED=256, 240 200 # MDBD= 352 BSDS= 176
|
| 448 |
+
# i = random.randint(0, h - LR_img_size)
|
| 449 |
+
# j = random.randint(0, w - LR_img_size)
|
| 450 |
+
# # if img.
|
| 451 |
+
# img = img[i:i + LR_img_size , j:j + LR_img_size ]
|
| 452 |
+
# gt = gt[i:i + LR_img_size , j:j + LR_img_size ]
|
| 453 |
+
# else:
|
| 454 |
+
# LR_img_size = 352#256 # l BIPED=208-352, # MDBD= 352-480- BSDS= 176-320
|
| 455 |
+
# i = random.randint(0, h - LR_img_size)
|
| 456 |
+
# j = random.randint(0, w - LR_img_size)
|
| 457 |
+
# # if img.
|
| 458 |
+
# img = img[i:i + LR_img_size, j:j + LR_img_size]
|
| 459 |
+
# gt = gt[i:i + LR_img_size, j:j + LR_img_size]
|
| 460 |
+
# img = cv2.resize(img, dsize=(crop_size, crop_size), )
|
| 461 |
+
# gt = cv2.resize(gt, dsize=(crop_size, crop_size))
|
| 462 |
+
|
| 463 |
+
else:
|
| 464 |
+
# New addidings
|
| 465 |
+
img = cv2.resize(img, dsize=(crop_size, crop_size))
|
| 466 |
+
gt = cv2.resize(gt, dsize=(crop_size, crop_size))
|
| 467 |
+
# BRIND
|
| 468 |
+
gt[gt > 0.1] +=0.2#0.4
|
| 469 |
+
gt = np.clip(gt, 0., 1.)
|
| 470 |
+
# gt[gt > 0.1] =1#0.4
|
| 471 |
+
# gt = np.clip(gt, 0., 1.)
|
| 472 |
+
# # for BIPED
|
| 473 |
+
# gt[gt > 0.2] += 0.6# 0.5 for BIPED
|
| 474 |
+
# gt = np.clip(gt, 0., 1.) # BIPED
|
| 475 |
+
# # for MDBD
|
| 476 |
+
# gt[gt > 0.1] +=0.7
|
| 477 |
+
# gt = np.clip(gt, 0., 1.)
|
| 478 |
+
# # For RCF input
|
| 479 |
+
# # -----------------------------------
|
| 480 |
+
# gt[gt==0]=0.
|
| 481 |
+
# gt[np.logical_and(gt>0.,gt<0.5)] = 2.
|
| 482 |
+
# gt[gt>=0.5]=1.
|
| 483 |
+
#
|
| 484 |
+
# gt = gt.astype('float32')
|
| 485 |
+
# ----------------------------------
|
| 486 |
+
|
| 487 |
+
img = img.transpose((2, 0, 1))
|
| 488 |
+
img = torch.from_numpy(img.copy()).float()
|
| 489 |
+
gt = torch.from_numpy(np.array([gt])).float()
|
| 490 |
+
return img, gt
|
dexi_utils.py
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import cv2 as cv
|
| 2 |
+
import numpy as np
|
| 3 |
+
import torch
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
def image_normalization(img, img_min=0, img_max=255):
|
| 7 |
+
"""This is a typical image normalization function
|
| 8 |
+
where the minimum and maximum of the image is needed
|
| 9 |
+
source: https://en.wikipedia.org/wiki/Normalization_(image_processing)
|
| 10 |
+
:param img: an image could be gray scale or color
|
| 11 |
+
:param img_min: for default is 0
|
| 12 |
+
:param img_max: for default is 255
|
| 13 |
+
:return: a normalized image, if max is 255 the dtype is uint8
|
| 14 |
+
"""
|
| 15 |
+
img = np.float32(img)
|
| 16 |
+
epsilon = 1e-12 # whenever an inconsistent image
|
| 17 |
+
img = (img-np.min(img))*(img_max-img_min) / \
|
| 18 |
+
((np.max(img)-np.min(img))+epsilon)+img_min
|
| 19 |
+
return img
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
# def visualize_result(imgs_list, arg):
|
| 23 |
+
# """
|
| 24 |
+
# function for tensorflow results
|
| 25 |
+
# :param imgs_list: a list of prediction, gt and input data
|
| 26 |
+
# :param arg:
|
| 27 |
+
# :return: one image with the whole of imgs_list data
|
| 28 |
+
# """
|
| 29 |
+
# n_imgs = len(imgs_list)
|
| 30 |
+
# data_list = []
|
| 31 |
+
# for i in range(n_imgs):
|
| 32 |
+
# tmp = imgs_list[i]
|
| 33 |
+
|
| 34 |
+
# if tmp.shape[1] == 3:
|
| 35 |
+
# tmp = np.transpose(np.squeeze(tmp), [1, 2, 0])
|
| 36 |
+
# tmp = restore_rgb(
|
| 37 |
+
# [arg.channel_swap, arg.mean_pixel_values[:3]], tmp)
|
| 38 |
+
# tmp = np.uint8(image_normalization(tmp))
|
| 39 |
+
# else:
|
| 40 |
+
# tmp = np.squeeze(tmp)
|
| 41 |
+
# if len(tmp.shape) == 2:
|
| 42 |
+
# tmp = np.uint8(image_normalization(tmp))
|
| 43 |
+
# tmp = cv.bitwise_not(tmp)
|
| 44 |
+
# tmp = cv.cvtColor(tmp, cv.COLOR_GRAY2BGR)
|
| 45 |
+
# else:
|
| 46 |
+
# tmp = np.uint8(image_normalization(tmp))
|
| 47 |
+
# data_list.append(tmp)
|
| 48 |
+
# img = data_list[0]
|
| 49 |
+
# if n_imgs % 2 == 0:
|
| 50 |
+
# imgs = np.zeros((img.shape[0] * 2 + 10, img.shape[1]
|
| 51 |
+
# * (n_imgs // 2) + ((n_imgs // 2 - 1) * 5), 3))
|
| 52 |
+
# else:
|
| 53 |
+
# imgs = np.zeros((img.shape[0] * 2 + 10, img.shape[1]
|
| 54 |
+
# * ((1 + n_imgs) // 2) + ((n_imgs // 2) * 5), 3))
|
| 55 |
+
# n_imgs += 1
|
| 56 |
+
|
| 57 |
+
# k = 0
|
| 58 |
+
# imgs = np.uint8(imgs)
|
| 59 |
+
# i_step = img.shape[0]+10
|
| 60 |
+
# j_step = img.shape[1]+5
|
| 61 |
+
# for i in range(2):
|
| 62 |
+
# for j in range(n_imgs//2):
|
| 63 |
+
# if k < len(data_list):
|
| 64 |
+
# imgs[i*i_step:i*i_step+img.shape[0], j*j_step:j *
|
| 65 |
+
# j_step+img.shape[1], :] = data_list[k]
|
| 66 |
+
# k += 1
|
| 67 |
+
# else:
|
| 68 |
+
# pass
|
| 69 |
+
# return imgs
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
# def cv_imshow(title='image', img=None):
|
| 73 |
+
# cv.imshow(title, img)
|
| 74 |
+
# cv.waitKey(0)
|
| 75 |
+
# cv.destroyAllWindows()
|
| 76 |
+
def tensor2edge(tensor):
|
| 77 |
+
print(tensor.shape)
|
| 78 |
+
tensor =torch.squeeze(tensor) if len(tensor.shape)>2 else tensor
|
| 79 |
+
tmp = torch.sigmoid(tensor)
|
| 80 |
+
tmp = tmp.cpu().detach().numpy()
|
| 81 |
+
# tmp = np.transpose(np.squeeze(tmp[1]), [1, 2, 0])
|
| 82 |
+
tmp = np.uint8(image_normalization(tmp))
|
| 83 |
+
tmp = cv.bitwise_not(tmp)
|
| 84 |
+
tmp = cv.cvtColor(tmp, cv.COLOR_GRAY2BGR)
|
| 85 |
+
cv.imshow('test_img', tmp)
|
| 86 |
+
cv.waitKey(0)
|
| 87 |
+
cv.destroyAllWindows()
|
figs/DexiNed_banner.png
ADDED
|
Git LFS Details
|
legacy/README.md
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[](https://paperswithcode.com/sota/edge-detection-on-biped?p=dense-extreme-inception-network-towards-a)
|
| 2 |
+
|
| 3 |
+
# Dense Extreme Inception Network: Towards a Robust CNN Model for Edge Detection (DexiNed)
|
| 4 |
+
|
| 5 |
+
<!-- ```diff
|
| 6 |
+
- Sorry for any inconvenience, we are updating the repo
|
| 7 |
+
``` -->
|
| 8 |
+
|
| 9 |
+
This work presents a new Convolutional Neural Network (CNN) arquitecture for edge detection. Unlike of the state-of-the-art CNN based edge detectors, this models has a single training stage, but it is still able to overcome those models in the edge detection datasets. Moreover, Dexined does not need pre-trained weights, and it is trained from the scratch with fewer parameters tunning. To know more about DexiNed, read our first version of Dexined in [arxiv](https://arxiv.org/abs/1909.01955), the last version will be uploaded after the camera-ready deadline of WACV2020.
|
| 10 |
+
|
| 11 |
+
<div style="text-align:center"><img src='figs/DexiNed_banner.png' width=800>
|
| 12 |
+
<div/>
|
| 13 |
+
|
| 14 |
+
## Table of Contents
|
| 15 |
+
* [Datasets](#datasets)
|
| 16 |
+
* [Performance](#performance)
|
| 17 |
+
* [Citation](#citation)
|
| 18 |
+
|
| 19 |
+
This is the first version of DexiNed presented in WACV2020, so it can run on TensorFlow 1.15.4. The last version of DexiNed has been implemented on Pytorch and you can see in the main path of this repo.
|
| 20 |
+
## Requirements
|
| 21 |
+
|
| 22 |
+
* [Python 3.7](https://www.python.org/downloads/release/python-370/g)
|
| 23 |
+
* [TensorFlow>=1.8 <=1.15.4](https://www.tensorflow.org) (tested on such versions)
|
| 24 |
+
* [OpenCV](https://pypi.org/project/opencv-python/)
|
| 25 |
+
* [Matplotlib](https://matplotlib.org/3.1.1/users/installing.html)
|
| 26 |
+
* Other package like Numpy, h5py, PIL.
|
| 27 |
+
|
| 28 |
+
Once the packages are installed, clone this repo as follow:
|
| 29 |
+
|
| 30 |
+
git clone https://github.com/xavysp/DexiNed.git
|
| 31 |
+
cd DexiNed
|
| 32 |
+
|
| 33 |
+
## Project Architecture
|
| 34 |
+
|
| 35 |
+
```
|
| 36 |
+
├── data # sample images for testing
|
| 37 |
+
| ├── lena_std.tif # sample 1
|
| 38 |
+
| └── stonehengeuk.jpg # sample 2
|
| 39 |
+
├── figs # Images used in README.md
|
| 40 |
+
| └── DexiNed_banner.png # DexiNed banner
|
| 41 |
+
├── models # tensorflow model file
|
| 42 |
+
| └── dexined.py # DexiNed class
|
| 43 |
+
├── utls # a series of tools used in this repo
|
| 44 |
+
| └── dataset_manager.py # tools for dataset managing
|
| 45 |
+
| └── losses.py # Loss function used to train DexiNed
|
| 46 |
+
| └── utls.py # miscellaneous tool functions
|
| 47 |
+
├── run_model.py # the main python file with main functions and parameter settings
|
| 48 |
+
└── test.py # the script to run the test experiment
|
| 49 |
+
└── train.py # the script to run the train experiment
|
| 50 |
+
```
|
| 51 |
+
|
| 52 |
+
As described above, run_model.py has the parameters settings, whether DexiNed is used for training or testing, before those processes the parameters need to be set. As highlighted, DexiNed is trained just one time with our proposed dataset BIPED, so in "--train_dataset" as the default setting is BIDEP; however, in the testing stage (--test_dataset), any dataset can be used, even CLASSIC, which is an arbitrary image downloaded from the internet. However, to evaluate with single images or CLASSIC "--use_dataset" has to be in FALSE mode. Whenever a dataset is used to test or train on DexiNed the arguments have to have the list of training or testing files (--train_list, --test_list). Pay attention in the parameters' settings, and change whatever you want, like ''--image_width'' or ''--image_height''. To test the Lena image I set 512x51 (see "test" section).
|
| 53 |
+
```
|
| 54 |
+
parser.add_argument('--train_dataset', default='BIPED', choices=['BIPED','BSDS'])
|
| 55 |
+
parser.add_argument('--test_dataset', default='CLASSIC', choices=['BIPED', 'BSDS','MULTICUE','NYUD','PASCAL','CID'])
|
| 56 |
+
parser.add_argument('--dataset_dir',default=None,type=str)
|
| 57 |
+
parser.add_argument('--dataset_augmented', default=True,type=bool)
|
| 58 |
+
parser.add_argument('--train_list',default='train_rgb.lst', type=str)
|
| 59 |
+
parser.add_argument('--test_list', default='test_pair.lst',type=str)
|
| 60 |
+
```
|
| 61 |
+
|
| 62 |
+
## Test
|
| 63 |
+
Before test the DexiNed model, it is necesarry to download the checkpoint here [Checkpoint from Drive](https://drive.google.com/open?id=1fLBpOrSXC2VOWUvDtNGyrHcuB2IB-4_D) and save those files into the DexiNed folder like: checkpoints/DXN_BIPED/train/(here the checkpoints from Drive), then run as follow:
|
| 64 |
+
|
| 65 |
+
python run_model.py --image_width=512 --image_height=512
|
| 66 |
+
Make sure that in run_model.py the test setting be as:
|
| 67 |
+
```parser.add_argument('--model_state', default='test', choices=['train','test','None'])```
|
| 68 |
+
DexiNed downsample the input image till 16 scales, please make sure that the image width and height be multiple of 16, like 512, 960, and etc. **In the Checkpoint from Drive you will get data_list.zip, train_1.zip, and train_2.zip. The train_2 contains our last checkpoint trained with the updated BIPED; train_1 has checkpoints with the results presented in WACV'20, and data_list has a list of MDBD dataset images used for testing, if you choose another random list of images, you probably get a better or worst result, I think is not fair.**
|
| 69 |
+
|
| 70 |
+
## Train
|
| 71 |
+
|
| 72 |
+
python run_model.py
|
| 73 |
+
Make sure that in run_model.py the train setting be as:
|
| 74 |
+
```parser.add_argument('--model_state', default='train', choices=['train','test','None'])```
|
| 75 |
+
|
| 76 |
+
# Datasets
|
| 77 |
+
|
| 78 |
+
## Dataset used for Training
|
| 79 |
+
|
| 80 |
+
BIPED (Barcelona Images for Perceptual Edge Detection): This dataset is collected and annotated in the edge level for this work. See more details and download in: [Option1](https://xavysp.github.io/MBIPED/), [Option2 kaggle](https://www.kaggle.com/xavysp/biped). The BIPED dataset has been updated, adding more annotations and correcting few mistakes, so those links have the renewed version of BIPED, if you want the older version you may ask us by email. The last performance (table below) will be updated soon.
|
| 81 |
+
|
| 82 |
+
## Datasets used for Testing
|
| 83 |
+
|
| 84 |
+
Edge detection datasets
|
| 85 |
+
* [BIPED](https://xavysp.github.io/MBIPED/) and [MDBD](http://serre-lab.clps.brown.edu/resource/multicue/)
|
| 86 |
+
|
| 87 |
+
Non-edge detection datasets
|
| 88 |
+
|
| 89 |
+
* [CID](http://www.cs.rug.nl/~imaging/databases/contour_database/contour_database.html) <!-- * [DCD](http://www.cs.cmu.edu/~mengtial/proj/sketch/)-->, [BSDS300](https://www2.eecs.berkeley.edu/Research/Projects/CS/vision/bsds/), [BSDS500](https://www2.eecs.berkeley.edu/Research/Projects/CS/vision/bsds/), [NYUD](https://cs.nyu.edu/~silberman/datasets/nyu_depth_v2.html), and [PASCAL-context](https://cs.stanford.edu/~roozbeh/pascal-context/)
|
| 90 |
+
|
| 91 |
+
# Performance
|
| 92 |
+
|
| 93 |
+
The results below are from the last version of BIPEP. After WACV20, the BIPED images have been again checked and added annotations. All of those models have been trained again.
|
| 94 |
+
|
| 95 |
+
<center>
|
| 96 |
+
|
| 97 |
+
| Methods | ODS | ODS | AP |
|
| 98 |
+
| -------------- | ---------| -------- | -------- |
|
| 99 |
+
| [SED](https://github.com/ArashAkbarinia/BoundaryDetection) | `.717` | `.731` | `.756` |
|
| 100 |
+
| [HED](https://github.com/s9xie/hed) | `.823` | `.847` | `.869` |
|
| 101 |
+
| [RCF](https://github.com/yun-liu/rcf) | `.843` | `.859` | `.882` |
|
| 102 |
+
| [BDCN](https://github.com/pkuCactus/BDCN) | `.839` | `.854` | `.887` |
|
| 103 |
+
| DexiNed(WACV'20)| `.859` | `.867` | `.905` |
|
| 104 |
+
</center>
|
| 105 |
+
Evaluation performed to BIPED dataset. We will update the result soon.
|
| 106 |
+
|
| 107 |
+
# Citation
|
| 108 |
+
|
| 109 |
+
If you like DexiNed, why not starring the project on GitHub!
|
| 110 |
+
|
| 111 |
+
[](https://GitHub.com/xavysp/DexiNed/stargazers/)
|
| 112 |
+
|
| 113 |
+
Please cite our paper if you find helpful in your academic/scientific publication,
|
| 114 |
+
```
|
| 115 |
+
@InProceedings{soria2020dexined,
|
| 116 |
+
title={Dense Extreme Inception Network: Towards a Robust CNN Model for Edge Detection},
|
| 117 |
+
author={Xavier Soria and Edgar Riba and Angel Sappa},
|
| 118 |
+
booktitle={The IEEE Winter Conference on Applications of Computer Vision (WACV '20)},
|
| 119 |
+
year={2020}
|
| 120 |
+
}
|
| 121 |
+
```
|
| 122 |
+
|
| 123 |
+
<!--```
|
| 124 |
+
@misc{soria2020dexined_ext,
|
| 125 |
+
title={Towards a Robust Deep Learning Model for Edge Detection},
|
| 126 |
+
author={Xavier Soria and Edgar Riba and Angel Sappa},
|
| 127 |
+
year={2020},
|
| 128 |
+
eprint={000000000},
|
| 129 |
+
archivePrefix={arXiv},
|
| 130 |
+
primaryClass={cs.CV}
|
| 131 |
+
```-->
|
| 132 |
+
|
legacy/figs/DexiNed_banner.png
ADDED
|
Git LFS Details
|
legacy/models/dexined.py
ADDED
|
@@ -0,0 +1,503 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
""" DexiNed architecture description
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
Created by: Xavier Soria Poma
|
| 5 |
+
Modified from: https://github.com/machrisaa/tensorflow-vgg
|
| 6 |
+
Autonomous University of Barcelona-Computer Vision Center
|
| 7 | |
| 8 |
+
"""
|
| 9 |
+
|
| 10 |
+
import time
|
| 11 |
+
import os
|
| 12 |
+
import numpy as np
|
| 13 |
+
|
| 14 |
+
from legacy.utls.losses import *
|
| 15 |
+
from legacy.utls.utls import print_info, print_warning
|
| 16 |
+
|
| 17 |
+
slim = tf.contrib.slim
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
class dexined():
|
| 21 |
+
|
| 22 |
+
def __init__(self, args):
|
| 23 |
+
|
| 24 |
+
self.args = args
|
| 25 |
+
self.utw = self.args.use_trained_model
|
| 26 |
+
self.img_height =args.image_height
|
| 27 |
+
self.img_width =args.image_width
|
| 28 |
+
if args.model_state=='test':
|
| 29 |
+
self.images = tf.placeholder(tf.float32, [None, self.args.image_height,
|
| 30 |
+
self.args.image_width, self.args.n_channels])
|
| 31 |
+
else:
|
| 32 |
+
self.images = tf.compat.v1.placeholder(tf.float32, [None, self.args.image_height,
|
| 33 |
+
self.args.image_width, self.args.n_channels])
|
| 34 |
+
self.edgemaps = tf.compat.v1.placeholder(tf.float32, [None, self.args.image_height,
|
| 35 |
+
self.args.image_width, 1])
|
| 36 |
+
self.define_model()
|
| 37 |
+
|
| 38 |
+
def define_model(self, is_training=True):
|
| 39 |
+
""" DexiNed architecture
|
| 40 |
+
DexiNed is composed by six blocks, the two first blocks have two convolutional layers
|
| 41 |
+
the rest of the blocks is composed by sub blocks and they have 2, 3, 3, 3 sub blocks
|
| 42 |
+
"""
|
| 43 |
+
start_time = time.time()
|
| 44 |
+
use_subpixel=self.args.use_subpixel
|
| 45 |
+
weight_init =tf.random_normal_initializer(mean=0.0, stddev=0.01)
|
| 46 |
+
with tf.compat.v1.variable_scope('Xpt') as sc:
|
| 47 |
+
|
| 48 |
+
# ------------------------- Block1 ----------------------------------------
|
| 49 |
+
self.conv1_1 = tf.layers.conv2d(self.images, filters=32, kernel_size=[3, 3],
|
| 50 |
+
strides=(2, 2), bias_initializer=tf.constant_initializer(0.0),
|
| 51 |
+
padding='SAME', name="conv1_1", kernel_initializer=weight_init) # bx200x200x32, b=batch size
|
| 52 |
+
self.conv1_1 = slim.batch_norm(self.conv1_1)
|
| 53 |
+
self.conv1_1 = tf.nn.relu(self.conv1_1)
|
| 54 |
+
|
| 55 |
+
self.conv1_2 = tf.layers.conv2d(self.conv1_1, filters=64, kernel_size=[3,3],
|
| 56 |
+
strides=(1,1), bias_initializer=tf.constant_initializer(0.0),
|
| 57 |
+
padding='SAME', name="conv1_2", kernel_initializer=weight_init) # bx200x200x64
|
| 58 |
+
self.conv1_2 = slim.batch_norm(self.conv1_2)
|
| 59 |
+
self.conv1_2 = tf.nn.relu(self.conv1_2)
|
| 60 |
+
|
| 61 |
+
self.output1 = self.side_layer(self.conv1_2,name='output1',filters=1, upscale=int(2 ** 1),
|
| 62 |
+
strides=(1,1),kernel_size=[1,1],sub_pixel=use_subpixel,
|
| 63 |
+
kernel_init=weight_init) # bx400x400x1
|
| 64 |
+
self.rconv1 = tf.layers.conv2d(
|
| 65 |
+
self.conv1_2,filters=128, kernel_size=[1,1], activation=None,
|
| 66 |
+
strides=(2,2), bias_initializer=tf.constant_initializer(0.0),
|
| 67 |
+
padding='SAME', name="rconv1", kernel_initializer=weight_init) # bx100x100x128 --Skip left
|
| 68 |
+
self.rconv1 =slim.batch_norm(self.rconv1) # bx100x100x128 --Skip left
|
| 69 |
+
|
| 70 |
+
# ------------------------- Block2 ----------------------------------------
|
| 71 |
+
self.block2_xcp = self.conv1_2
|
| 72 |
+
for k in range(1):
|
| 73 |
+
self.block2_xcp = tf.layers.conv2d(
|
| 74 |
+
self.block2_xcp, filters=128, kernel_size=[3, 3],
|
| 75 |
+
strides=(1, 1), padding='same', name='conv_block2_{}'.format(k + 1),
|
| 76 |
+
kernel_initializer=weight_init) # bx200x200x128
|
| 77 |
+
self.block2_xcp = slim.batch_norm(self.block2_xcp)
|
| 78 |
+
self.block2_xcp = tf.nn.relu(self.block2_xcp)
|
| 79 |
+
|
| 80 |
+
self.block2_xcp = tf.layers.conv2d(
|
| 81 |
+
self.block2_xcp, filters=128, kernel_size=[3, 3],
|
| 82 |
+
strides=(1, 1), padding='same', name='conv2_block2_{}'.format(k + 1),
|
| 83 |
+
kernel_initializer=weight_init) # bx200x200x128
|
| 84 |
+
self.block2_xcp= slim.batch_norm(self.block2_xcp)
|
| 85 |
+
|
| 86 |
+
self.maxpool2_1=slim.max_pool2d(self.block2_xcp,kernel_size=[3,3],stride=2, padding='same',
|
| 87 |
+
scope='maxpool2_1') # bx100x100x128
|
| 88 |
+
self.add2_1 = tf.add(self.maxpool2_1, self.rconv1)# with skip left
|
| 89 |
+
self.output2 = self.side_layer(self.block2_xcp,filters=1,name='output2', upscale=int(2 ** 1),
|
| 90 |
+
strides=(1,1),kernel_size=[1,1],sub_pixel=use_subpixel,
|
| 91 |
+
kernel_init=weight_init) # bx400x400x1
|
| 92 |
+
self.rconv2= tf.layers.conv2d(
|
| 93 |
+
self.add2_1,filters=256, kernel_size=[1,1], activation=None,
|
| 94 |
+
kernel_initializer=weight_init, strides=(2,2), bias_initializer=tf.constant_initializer(0.0),
|
| 95 |
+
padding='SAME', name="rconv2") # bx50x50x256 # skip left
|
| 96 |
+
self.rconv2 = slim.batch_norm(self.rconv2) # skip left
|
| 97 |
+
|
| 98 |
+
# ------------------------- Block3 ----------------------------------------
|
| 99 |
+
self.block3_xcp = self.add2_1
|
| 100 |
+
self.addb2_4b3 = tf.layers.conv2d(
|
| 101 |
+
self.maxpool2_1,filters=256, kernel_size=[1, 1], activation=None,
|
| 102 |
+
kernel_initializer=weight_init, strides=(1, 1), bias_initializer=tf.constant_initializer(0.0),
|
| 103 |
+
padding='SAME', name="add2conv_4b3") # 100x100x256 # skip right
|
| 104 |
+
self.addb2_4b3 = slim.batch_norm(self.addb2_4b3) # skip right
|
| 105 |
+
for k in range(2):
|
| 106 |
+
|
| 107 |
+
self.block3_xcp=tf.nn.relu(self.block3_xcp)
|
| 108 |
+
self.block3_xcp = tf.layers.conv2d(
|
| 109 |
+
self.block3_xcp, filters=256, kernel_size=[3, 3],
|
| 110 |
+
strides=(1, 1), padding='same', name='con1v_block3_{}'.format(k + 1),
|
| 111 |
+
kernel_initializer=weight_init) # bx100x100x256
|
| 112 |
+
self.block3_xcp = slim.batch_norm(self.block3_xcp)
|
| 113 |
+
self.block3_xcp = tf.nn.relu(self.block3_xcp)
|
| 114 |
+
|
| 115 |
+
self.block3_xcp = tf.layers.conv2d(
|
| 116 |
+
self.block3_xcp, filters=256, kernel_size=[3, 3],
|
| 117 |
+
strides=(1,1),padding='same',name='conv2_block3_{}'.format(k+1),
|
| 118 |
+
kernel_initializer=weight_init) # bx100x100x256
|
| 119 |
+
self.block3_xcp = slim.batch_norm(self.block3_xcp)
|
| 120 |
+
self.block3_xcp = tf.add(self.block3_xcp, self.addb2_4b3)/2 # with right skip
|
| 121 |
+
|
| 122 |
+
self.maxpool3_1 = slim.max_pool2d(self.block3_xcp, kernel_size=[3, 3],stride=2, padding='same',
|
| 123 |
+
scope='maxpool3_1') # bx50x50x256
|
| 124 |
+
self.add3_1 = tf.add(self.maxpool3_1, self.rconv2) # with before skip left
|
| 125 |
+
self.rconv3 = tf.layers.conv2d(
|
| 126 |
+
self.add3_1, filters=512, kernel_size=[1, 1], activation=None,
|
| 127 |
+
kernel_initializer=weight_init, strides=(2, 2), bias_initializer=tf.constant_initializer(0.0),
|
| 128 |
+
padding='SAME', name="rconv3") # bx25x25x512 # skip left
|
| 129 |
+
self.rconv3 = slim.batch_norm(self.rconv3) # skip left
|
| 130 |
+
self.output3 = self.side_layer(self.block3_xcp, filters=1,name='output3', upscale=int(2 ** 2),
|
| 131 |
+
strides=(1,1),kernel_size=[1,1],sub_pixel=use_subpixel,
|
| 132 |
+
kernel_init=weight_init) # bx400x400x1
|
| 133 |
+
|
| 134 |
+
# ------------------------- Block4 ----------------------------------------
|
| 135 |
+
self.conv_b2b4 = tf.layers.conv2d(
|
| 136 |
+
self.maxpool2_1, filters=256, kernel_size=[1, 1], activation=None,
|
| 137 |
+
kernel_initializer=weight_init, strides=(2, 2), bias_initializer=tf.constant_initializer(0.0),
|
| 138 |
+
padding='SAME', name="conv_b2b4") # bx50x50x256 # skip right
|
| 139 |
+
self.block4_xcp= self.add3_1
|
| 140 |
+
self.addb2b3 = tf.add(self.conv_b2b4, self.maxpool3_1)# skip right
|
| 141 |
+
self.addb3_4b4 = tf.layers.conv2d(
|
| 142 |
+
self.addb2b3, filters=512, kernel_size=[1, 1], activation=None,
|
| 143 |
+
kernel_initializer=weight_init, strides=(1, 1), bias_initializer=tf.constant_initializer(0.0),
|
| 144 |
+
padding='SAME', name="add3conv_4b4") # bx50x50x512 # skip right
|
| 145 |
+
self.addb3_4b4 = slim.batch_norm(self.addb3_4b4)# skip right
|
| 146 |
+
for k in range(3):
|
| 147 |
+
self.block4_xcp= tf.nn.relu(self.block4_xcp)
|
| 148 |
+
self.block4_xcp = tf.layers.conv2d(
|
| 149 |
+
self.block4_xcp, filters=512, kernel_size=[3, 3], strides=(1, 1),
|
| 150 |
+
padding='same', name='conv1_block4_{}'.format(k + 1), kernel_initializer=weight_init) # bx50x50x512
|
| 151 |
+
self.block4_xcp = slim.batch_norm(self.block4_xcp)
|
| 152 |
+
self.block4_xcp = tf.nn.relu(self.block4_xcp)
|
| 153 |
+
|
| 154 |
+
self.block4_xcp = tf.layers.conv2d(
|
| 155 |
+
self.block4_xcp, filters=512, kernel_size=[3, 3], strides=(1, 1),
|
| 156 |
+
padding='same', name='conv2_block4_{}'.format(k+1), kernel_initializer=weight_init) # bx50x50x512
|
| 157 |
+
self.block4_xcp = slim.batch_norm(self.block4_xcp)
|
| 158 |
+
self.block4_xcp = tf.add(self.block4_xcp, self.addb3_4b4)/2 # with right skip
|
| 159 |
+
|
| 160 |
+
self.maxpool4_1 = slim.max_pool2d(self.block4_xcp, kernel_size=[3, 3], stride=2, padding='same',
|
| 161 |
+
scope='maxpool3_1') # bx25x25x728, b=batch size
|
| 162 |
+
self.add4_1 = tf.add(self.maxpool4_1, self.rconv3) # with skip left
|
| 163 |
+
self.rconv4 = tf.layers.conv2d(
|
| 164 |
+
self.add4_1, filters=512, kernel_size=[1, 1], activation=None,
|
| 165 |
+
kernel_initializer=weight_init, strides=(1, 1), bias_initializer=tf.constant_initializer(0.0),
|
| 166 |
+
padding='SAME', name="rconv4") # bx25x25x512 # skip leff
|
| 167 |
+
self.rconv4 = slim.batch_norm(self.rconv4) # skip left
|
| 168 |
+
|
| 169 |
+
self.output4 = self.side_layer(self.block4_xcp, filters=1,name='output4', upscale=int(2 ** 3),
|
| 170 |
+
strides=(1,1),kernel_size=[1,1],sub_pixel=use_subpixel,
|
| 171 |
+
kernel_init=weight_init) # bx400x400x1
|
| 172 |
+
|
| 173 |
+
# ------------------------- Block5 ----------------------------------------
|
| 174 |
+
self.convb3_2ab4 = tf.layers.conv2d(
|
| 175 |
+
self.conv_b2b4, filters=512, kernel_size=[1, 1], activation=None,
|
| 176 |
+
kernel_initializer=weight_init, strides=(2, 2), bias_initializer=tf.constant_initializer(0.0),
|
| 177 |
+
padding='SAME', name="conv_b2b5") # bx25x25x512 # skip right
|
| 178 |
+
|
| 179 |
+
self.block5_xcp=self.add4_1
|
| 180 |
+
self.addb2b5 = tf.add(self.convb3_2ab4,self.maxpool4_1) # skip right
|
| 181 |
+
self.addb2b5 = tf.layers.conv2d(
|
| 182 |
+
self.addb2b5, filters=512, kernel_size=[1, 1], activation=None,
|
| 183 |
+
kernel_initializer=weight_init, strides=(1, 1), bias_initializer=tf.constant_initializer(0.0),
|
| 184 |
+
padding='SAME', name="addb2b5") # bx25x25x512# skip right
|
| 185 |
+
self.addb2b5 = slim.batch_norm(self.addb2b5)# skip right
|
| 186 |
+
for k in range(3):
|
| 187 |
+
self.block5_xcp=tf.nn.relu(self.block5_xcp)
|
| 188 |
+
self.block5_xcp= tf.layers.conv2d(
|
| 189 |
+
self.block5_xcp, filters=512, kernel_size=[3, 3],
|
| 190 |
+
strides=(1, 1),padding='SAME', name="conv1_block5{}".format(k+1),
|
| 191 |
+
kernel_initializer=weight_init) # bx25x25x512
|
| 192 |
+
self.block5_xcp = slim.batch_norm(self.block5_xcp)
|
| 193 |
+
self.block5_xcp=tf.nn.relu(self.block5_xcp)
|
| 194 |
+
|
| 195 |
+
self.block5_xcp= tf.layers.conv2d(
|
| 196 |
+
self.block5_xcp, filters=512, kernel_size=[3, 3],
|
| 197 |
+
strides=(1, 1),padding='SAME', name="conv2_block5{}".format(k+1),
|
| 198 |
+
kernel_initializer=weight_init) # bx25x25x728
|
| 199 |
+
self.block5_xcp = slim.batch_norm(self.block5_xcp)
|
| 200 |
+
self.block5_xcp=tf.add(self.block5_xcp,self.addb2b5)/2 # wwith right skip
|
| 201 |
+
|
| 202 |
+
self.add5_1 = tf.add(self.block5_xcp, self.rconv4) # with skip left
|
| 203 |
+
self.output5 = self.side_layer(self.block5_xcp, filters=1,name='output5', kernel_size=[1,1],
|
| 204 |
+
upscale=int(2 ** 4), sub_pixel=use_subpixel, strides=(1,1),
|
| 205 |
+
kernel_init=weight_init)
|
| 206 |
+
|
| 207 |
+
# ------------------------- Block6 ----------------------------------------
|
| 208 |
+
self.block6_xcp = self.add5_1
|
| 209 |
+
self.block6_xcp = tf.layers.conv2d(
|
| 210 |
+
self.block6_xcp, filters=256, kernel_size=[1, 1], activation=None,
|
| 211 |
+
kernel_initializer=weight_init, strides=(1, 1), bias_initializer=tf.constant_initializer(0.0),
|
| 212 |
+
padding='SAME', name="conv0_b6") # bx25x25x256
|
| 213 |
+
|
| 214 |
+
self.block6_xcp = slim.batch_norm(self.block6_xcp)
|
| 215 |
+
self.addb25_2b6 = tf.layers.conv2d(
|
| 216 |
+
self.block5_xcp, filters=256, kernel_size=[1, 1], activation=None,
|
| 217 |
+
kernel_initializer=weight_init, strides=(1, 1), bias_initializer=tf.constant_initializer(0.0),
|
| 218 |
+
padding='SAME', name="add2b6") # bx25x25x256# skip right
|
| 219 |
+
self.addb25_2b6 = slim.batch_norm(self.addb25_2b6)# skip right
|
| 220 |
+
for k in range(3):
|
| 221 |
+
self.block6_xcp = tf.nn.relu(self.block6_xcp)
|
| 222 |
+
self.block6_xcp = tf.layers.conv2d(
|
| 223 |
+
self.block6_xcp, filters=256, kernel_size=[3, 3],
|
| 224 |
+
strides=(1, 1), padding='SAME', name="conv1_block6{}".format(k + 1),
|
| 225 |
+
kernel_initializer=weight_init) # bx25x25x256
|
| 226 |
+
self.block6_xcp = slim.batch_norm(self.block6_xcp)
|
| 227 |
+
self.block6_xcp = tf.nn.relu(self.block6_xcp)
|
| 228 |
+
|
| 229 |
+
self.block6_xcp = tf.layers.conv2d(
|
| 230 |
+
self.block6_xcp, filters=256, kernel_size=[3, 3],
|
| 231 |
+
strides=(1, 1), padding='SAME', name="conv2_block6{}".format(k + 1),
|
| 232 |
+
kernel_initializer=weight_init) # bx25x25x256
|
| 233 |
+
self.block6_xcp = slim.batch_norm(self.block6_xcp)
|
| 234 |
+
self.block6_xcp = tf.add(self.block6_xcp, self.addb25_2b6) / 2 # with right skip
|
| 235 |
+
|
| 236 |
+
self.output6 = self.side_layer(self.block6_xcp, filters=1, name='output6', kernel_size=[1, 1],
|
| 237 |
+
upscale=int(2 ** 4), sub_pixel=use_subpixel, strides=(1, 1),
|
| 238 |
+
kernel_init=weight_init)
|
| 239 |
+
# ******************** End blocks *****************************************
|
| 240 |
+
|
| 241 |
+
self.side_outputs = [self.output1, self.output2, self.output3,
|
| 242 |
+
self.output4, self.output5,self.output6]
|
| 243 |
+
|
| 244 |
+
self.fuse = tf.layers.conv2d(tf.concat(self.side_outputs, axis=3),filters=1,
|
| 245 |
+
kernel_size=[1,1], name='fuse_1',strides=(1,1),padding='same',
|
| 246 |
+
kernel_initializer=tf.constant_initializer(1 / len(self.side_outputs)))
|
| 247 |
+
self.outputs = self.side_outputs + [self.fuse]
|
| 248 |
+
|
| 249 |
+
print_info("Build model finished: {:.4f}s".format(time.time() - start_time))
|
| 250 |
+
|
| 251 |
+
def max_pool(self, bottom, name):
|
| 252 |
+
return tf.nn.max_pool(bottom, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME', name=name)
|
| 253 |
+
|
| 254 |
+
def conv_layer(self, inputs, filters=None,kernel_size=None, depth_multiplier=None,
|
| 255 |
+
padding='same', activation=None, name=None,
|
| 256 |
+
kernel_initializer=None, strides=(1,1), separable_conv=False):
|
| 257 |
+
|
| 258 |
+
if separable_conv:
|
| 259 |
+
conv = tf.layers.separable_conv2d(
|
| 260 |
+
inputs, filters=filters, kernel_size=kernel_size,
|
| 261 |
+
depth_multiplier=depth_multiplier, padding=padding, name=name)
|
| 262 |
+
else:
|
| 263 |
+
conv= tf.layers.conv2d(inputs, filters=filters, kernel_size=kernel_size,
|
| 264 |
+
strides=strides,padding=padding, kernel_initializer=kernel_initializer, name=name)
|
| 265 |
+
return conv
|
| 266 |
+
|
| 267 |
+
def side_layer(self, inputs, filters=None,kernel_size=None, strides=(1,1),
|
| 268 |
+
name=None, upscale=None, sub_pixel=False,kernel_init=None):
|
| 269 |
+
"""
|
| 270 |
+
https://github.com/s9xie/hed/blob/9e74dd710773d8d8a469ad905c76f4a7fa08f945/examples/hed/train_val.prototxt#L122
|
| 271 |
+
1x1 conv followed with Deconvoltion layer to upscale the size of input image sans color
|
| 272 |
+
"""
|
| 273 |
+
def upsample_block(inputs, filters=None,kernel_size=None, strides=(1,1),
|
| 274 |
+
name=None, upscale=None, sub_pixel=False):
|
| 275 |
+
i=1
|
| 276 |
+
scale=2
|
| 277 |
+
sub_net=inputs
|
| 278 |
+
output_filters=16
|
| 279 |
+
if sub_pixel is None:
|
| 280 |
+
# Upsampling by transpose_convolution
|
| 281 |
+
while (scale<=upscale):
|
| 282 |
+
if scale==upscale:
|
| 283 |
+
|
| 284 |
+
sub_net = self.conv_layer(sub_net, filters=filters, kernel_size=kernel_size,
|
| 285 |
+
strides=strides,kernel_initializer=tf.truncated_normal_initializer(mean=0.0),
|
| 286 |
+
name=name + '_conv_{}'.format(i)) # bx100x100x64
|
| 287 |
+
biases = tf.Variable(tf.constant(0.0, shape=[filters], dtype=tf.float32),
|
| 288 |
+
name=name + '_biases_{}'.format(i))
|
| 289 |
+
sub_net = tf.nn.bias_add(sub_net, biases)
|
| 290 |
+
sub_net = tf.nn.relu(sub_net)
|
| 291 |
+
|
| 292 |
+
sub_net = tf.layers.conv2d_transpose(
|
| 293 |
+
sub_net, filters=filters, kernel_size=[(upscale), (upscale)],
|
| 294 |
+
strides=(2, 2), padding="SAME", kernel_initializer=tf.truncated_normal_initializer(stddev=0.1),
|
| 295 |
+
name='{}_deconv_{}_{}'.format(name, upscale, i)) # upscale/2
|
| 296 |
+
else:
|
| 297 |
+
|
| 298 |
+
sub_net = self.conv_layer(sub_net, filters=output_filters,
|
| 299 |
+
kernel_size=kernel_size,kernel_initializer=kernel_init,
|
| 300 |
+
strides=strides, name=name + '_conv_{}'.format(i)) # bx100x100x64 tf.truncated_normal_initializer(mean=0.0, stddev=0.15)
|
| 301 |
+
biases = tf.Variable(tf.constant(0.0, shape=[output_filters], dtype=tf.float32),
|
| 302 |
+
name=name + '_biases_{}'.format(i))
|
| 303 |
+
|
| 304 |
+
sub_net = tf.nn.bias_add(sub_net, biases)
|
| 305 |
+
sub_net = tf.nn.relu(sub_net)
|
| 306 |
+
# *
|
| 307 |
+
sub_net = tf.layers.conv2d_transpose(
|
| 308 |
+
sub_net, filters=output_filters, kernel_size=[(upscale), (upscale)],
|
| 309 |
+
strides=(2, 2), padding="SAME", kernel_initializer=kernel_init,
|
| 310 |
+
name='{}_deconv_{}_{}'.format(name, upscale, i))
|
| 311 |
+
i += 1
|
| 312 |
+
scale=2**i
|
| 313 |
+
|
| 314 |
+
elif sub_pixel is False:
|
| 315 |
+
# Upsampling by bilinear interpolation
|
| 316 |
+
while (scale <= upscale):
|
| 317 |
+
|
| 318 |
+
if scale == upscale:
|
| 319 |
+
cur_shape = sub_net.get_shape().as_list()
|
| 320 |
+
sub_net = self.conv_layer(sub_net, filters=1,
|
| 321 |
+
kernel_size=3, kernel_initializer=kernel_init,
|
| 322 |
+
strides=strides, name=name + '_conv'+str(i)) # bx100x100x64 tf.truncated_normal_initializer(mean=0.0, stddev=0.15)
|
| 323 |
+
biases = tf.Variable(tf.constant(0.0, shape=[1], dtype=tf.float32),
|
| 324 |
+
name=name + '_conv_b'+str(i))
|
| 325 |
+
sub_net = tf.nn.bias_add(sub_net, biases)
|
| 326 |
+
sub_net = tf.nn.relu(sub_net)
|
| 327 |
+
if cur_shape[1]== self.img_height and cur_shape[2]==self.img_width:
|
| 328 |
+
pass
|
| 329 |
+
else:
|
| 330 |
+
sub_net = self._upscore_layer(input=sub_net,n_outputs=1,stride=upscale,ksize=upscale,
|
| 331 |
+
name=name+'_bdconv'+str(i))
|
| 332 |
+
else:
|
| 333 |
+
cur_shape = sub_net.get_shape().as_list()
|
| 334 |
+
sub_net = self.conv_layer(sub_net, filters=output_filters,
|
| 335 |
+
kernel_size=3, kernel_initializer=kernel_init,
|
| 336 |
+
strides=strides, name=name + '_conv' + str(
|
| 337 |
+
i)) # bx100x100x64 tf.truncated_normal_initializer(mean=0.0, stddev=0.15)
|
| 338 |
+
biases = tf.Variable(tf.constant(0.0, shape=[output_filters], dtype=tf.float32),
|
| 339 |
+
name=name + '_conv_b' + str(i))
|
| 340 |
+
sub_net = tf.nn.bias_add(sub_net, biases)
|
| 341 |
+
sub_net = tf.nn.relu(sub_net)
|
| 342 |
+
if cur_shape[1] == self.img_height and cur_shape[2] == self.img_width:
|
| 343 |
+
pass
|
| 344 |
+
else:
|
| 345 |
+
sub_net = self._upscore_layer(input=sub_net, n_outputs=output_filters, stride=upscale, ksize=upscale,
|
| 346 |
+
name=name + '_bdconv' + str(i))
|
| 347 |
+
i += 1
|
| 348 |
+
scale = 2 ** i
|
| 349 |
+
|
| 350 |
+
elif sub_pixel is True:
|
| 351 |
+
# Upsampling by subPixel convolution
|
| 352 |
+
while (scale <= upscale):
|
| 353 |
+
if scale == upscale:
|
| 354 |
+
sub_net = self.conv_layer(sub_net, filters=4,
|
| 355 |
+
kernel_size=3, kernel_initializer=kernel_init,
|
| 356 |
+
strides=strides, name=name + '_conv'+str(i)) # bx100x100x64 tf.truncated_normal_initializer(mean=0.0, stddev=0.15)
|
| 357 |
+
biases = tf.Variable(tf.constant(0.0, shape=[4], dtype=tf.float32),
|
| 358 |
+
name=name + '_conv_b'+str(i))
|
| 359 |
+
sub_net = tf.nn.bias_add(sub_net, biases)
|
| 360 |
+
sub_net = tf.nn.relu(sub_net)
|
| 361 |
+
_err_log = "SubpixelConv2d: The number of input channels == (scale x scale)" \
|
| 362 |
+
" x The number of output channels"
|
| 363 |
+
r = 2
|
| 364 |
+
if filters >= 1:
|
| 365 |
+
if int(sub_net.get_shape()[-1]) != int(r ** 2 * filters):
|
| 366 |
+
raise Exception(_err_log)
|
| 367 |
+
sub_net = tf.depth_to_space(sub_net, r)
|
| 368 |
+
else:
|
| 369 |
+
raise Exception(' the output channel is not setted')
|
| 370 |
+
else:
|
| 371 |
+
|
| 372 |
+
sub_net = self.conv_layer(
|
| 373 |
+
sub_net, filters=32, kernel_size=3, kernel_initializer=kernel_init,
|
| 374 |
+
strides=strides, name=name + '_conv' + str(i)) # bx100x100x32
|
| 375 |
+
biases = tf.Variable(tf.constant(0.0, shape=[32], dtype=tf.float32),
|
| 376 |
+
name=name + '_conv_b' + str(i))
|
| 377 |
+
sub_net = tf.nn.bias_add(sub_net, biases)
|
| 378 |
+
sub_net = tf.nn.relu(sub_net)
|
| 379 |
+
_err_log = "SubpixelConv2d: The number of input channels == (scale x scale)" \
|
| 380 |
+
" x The number of output channels"
|
| 381 |
+
r = 2
|
| 382 |
+
sp_filter =8
|
| 383 |
+
if sp_filter >= 1:
|
| 384 |
+
if int(sub_net.get_shape()[-1]) != int(r ** 2 * sp_filter):
|
| 385 |
+
raise Exception(_err_log)
|
| 386 |
+
sub_net = tf.nn.depth_to_space(sub_net, r)
|
| 387 |
+
else:
|
| 388 |
+
raise Exception(' the output channel is not setted')
|
| 389 |
+
i += 1
|
| 390 |
+
scale = 2 ** i
|
| 391 |
+
else:
|
| 392 |
+
raise NotImplementedError
|
| 393 |
+
return sub_net
|
| 394 |
+
classifier = upsample_block(inputs, filters=filters, kernel_size=kernel_size, strides=strides,
|
| 395 |
+
name=name, upscale=upscale, sub_pixel=sub_pixel)
|
| 396 |
+
return classifier
|
| 397 |
+
|
| 398 |
+
def _upscore_layer(self, input, n_outputs, name,
|
| 399 |
+
ksize=4, stride=2,shape=None):
|
| 400 |
+
strides = [1, stride, stride, 1]
|
| 401 |
+
in_features = input.get_shape().as_list()[3]
|
| 402 |
+
|
| 403 |
+
if shape is None:
|
| 404 |
+
# Compute shape out of Bottom
|
| 405 |
+
in_shape = tf.shape(input)
|
| 406 |
+
ot_shape = input.get_shape().as_list()
|
| 407 |
+
|
| 408 |
+
h = ((ot_shape[1] - 1) * stride) + 1
|
| 409 |
+
w = ((ot_shape[2] - 1) * stride) + 1
|
| 410 |
+
# new_shape = [in_shape[0], h, w, n_outputs]
|
| 411 |
+
new_shape = [in_shape[0], self.img_height, self.img_width, n_outputs] #output_shape=[,]
|
| 412 |
+
else:
|
| 413 |
+
new_shape = [shape[0], shape[1], shape[2], n_outputs]
|
| 414 |
+
output_shape = tf.stack(new_shape)
|
| 415 |
+
|
| 416 |
+
f_shape = [ksize, ksize, n_outputs, in_features]
|
| 417 |
+
# create
|
| 418 |
+
num_input = ksize * ksize * in_features / stride
|
| 419 |
+
stddev = (2 / num_input) ** 0.5
|
| 420 |
+
weights = self.get_deconv_filter(f_shape,name=name+'_Wb')
|
| 421 |
+
deconv = tf.nn.conv2d_transpose(input,weights, output_shape,
|
| 422 |
+
strides=strides, padding='SAME', name=name)
|
| 423 |
+
# _activation_summary(deconv)
|
| 424 |
+
return deconv
|
| 425 |
+
|
| 426 |
+
def get_deconv_filter(self, f_shape,name=''):
|
| 427 |
+
width = f_shape[0]
|
| 428 |
+
heigh = f_shape[0]
|
| 429 |
+
f = np.ceil(width / 2.0)
|
| 430 |
+
c = (2 * f - 1 - f % 2) / (2.0 * f)
|
| 431 |
+
bilinear = np.zeros([f_shape[0], f_shape[1]])
|
| 432 |
+
for x in range(width):
|
| 433 |
+
for y in range(heigh):
|
| 434 |
+
value = (1 - abs(x / f - c)) * (1 - abs(y / f - c))
|
| 435 |
+
bilinear[x, y] = value
|
| 436 |
+
weights = np.zeros(f_shape)
|
| 437 |
+
for i in range(f_shape[2]):
|
| 438 |
+
weights[:, :, i, i] = bilinear
|
| 439 |
+
|
| 440 |
+
init = tf.constant_initializer(value=weights,
|
| 441 |
+
dtype=tf.float32)
|
| 442 |
+
|
| 443 |
+
return tf.get_variable(name=name, initializer=init, shape=weights.shape)
|
| 444 |
+
|
| 445 |
+
def setup_testing(self, session):
|
| 446 |
+
"""
|
| 447 |
+
Apply sigmoid non-linearity to side layer ouputs + fuse layer outputs for predictions
|
| 448 |
+
"""
|
| 449 |
+
self.predictions = []
|
| 450 |
+
|
| 451 |
+
for idx, b in enumerate(self.outputs):
|
| 452 |
+
output = tf.nn.sigmoid(b, name='output_{}'.format(idx))
|
| 453 |
+
self.predictions.append(output)
|
| 454 |
+
|
| 455 |
+
def setup_training(self, session):
|
| 456 |
+
"""
|
| 457 |
+
Apply sigmoid non-linearity to side layer ouputs + fuse layer outputs
|
| 458 |
+
Compute total loss := side_layer_loss + fuse_layer_loss
|
| 459 |
+
Compute predicted edge maps from fuse layer as pseudo performance metric to track
|
| 460 |
+
"""
|
| 461 |
+
self.predictions = []
|
| 462 |
+
self.loss = 0
|
| 463 |
+
self.fuse_output = []
|
| 464 |
+
self.losses=[]
|
| 465 |
+
|
| 466 |
+
print_warning('Deep supervision application set to {}'.format(self.args.deep_supervision))
|
| 467 |
+
ci=np.arange(len(self.side_outputs))
|
| 468 |
+
for idx, b in enumerate(self.side_outputs):
|
| 469 |
+
output = tf.nn.sigmoid(b, name='output_{}'.format(idx))
|
| 470 |
+
if self.args.deep_supervision and idx in ci:
|
| 471 |
+
cost = sigmoid_cross_entropy_balanced(b, self.edgemaps, name='cross_entropy{}'.format(idx)) # Deep supervision
|
| 472 |
+
self.loss += (self.args.loss_weights * cost) # Deep supervision
|
| 473 |
+
self.predictions.append(output)
|
| 474 |
+
else:
|
| 475 |
+
self.predictions.append(output)
|
| 476 |
+
|
| 477 |
+
# loss for the last side
|
| 478 |
+
self.fuse_output = tf.nn.sigmoid(self.fuse, name='fuse') # self by me
|
| 479 |
+
fuse_cost = sigmoid_cross_entropy_balanced(self.fuse, self.edgemaps, name='cross_entropy_fuse')
|
| 480 |
+
|
| 481 |
+
self.predictions.append(self.fuse_output)
|
| 482 |
+
self.loss += (self.args.loss_weights * fuse_cost) if self.args.deep_supervision else fuse_cost# deep supervision
|
| 483 |
+
|
| 484 |
+
pred = tf.cast(tf.greater(self.fuse_output, 0.5), tf.int32, name='predictions')
|
| 485 |
+
error = tf.cast(tf.not_equal(pred, tf.cast(self.edgemaps, tf.int32)), tf.float32)
|
| 486 |
+
self.error = tf.reduce_mean(error, name='pixel_error')
|
| 487 |
+
|
| 488 |
+
tf.compat.v1.summary.scalar('Training', self.loss)
|
| 489 |
+
tf.compat.v1.summary.scalar('Validation', self.error)
|
| 490 |
+
|
| 491 |
+
self.merged_summary = tf.compat.v1.summary.merge_all()
|
| 492 |
+
|
| 493 |
+
self.train_log_dir = os.path.join(self.args.logs_dir,
|
| 494 |
+
os.path.join(self.args.model_name+'_'+self.args.train_dataset,'train'))
|
| 495 |
+
self.val_log_dir = os.path.join(self.args.logs_dir,
|
| 496 |
+
os.path.join(self.args.model_name+'_'+self.args.train_dataset, 'val'))
|
| 497 |
+
|
| 498 |
+
if not os.path.exists(self.train_log_dir):
|
| 499 |
+
os.makedirs(self.train_log_dir)
|
| 500 |
+
if not os.path.exists(self.val_log_dir):
|
| 501 |
+
os.makedirs(self.val_log_dir)
|
| 502 |
+
self.train_writer = tf.compat.v1.summary.FileWriter(self.train_log_dir, session.graph)
|
| 503 |
+
self.val_writer = tf.compat.v1.summary.FileWriter(self.val_log_dir)
|
legacy/requirements.txt
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
absl-py==0.9.0
|
| 2 |
+
cachetools==4.1.0
|
| 3 |
+
certifi==2020.4.5.1
|
| 4 |
+
chardet==3.0.4
|
| 5 |
+
cycler==0.10.0
|
| 6 |
+
gast==0.2.2
|
| 7 |
+
google-auth==1.14.1
|
| 8 |
+
google-auth-oauthlib==0.4.1
|
| 9 |
+
google-pasta==0.1.8
|
| 10 |
+
grpcio==1.26.0
|
| 11 |
+
h5py==2.10.0
|
| 12 |
+
idna==2.9
|
| 13 |
+
Keras-Applications==1.0.8
|
| 14 |
+
Keras-Preprocessing==1.1.0
|
| 15 |
+
Markdown==3.1.1
|
| 16 |
+
matplotlib==3.1.2
|
| 17 |
+
mock==4.0.2
|
| 18 |
+
numpy==1.22
|
| 19 |
+
oauthlib==3.1.0
|
| 20 |
+
opencv-python==4.4.0
|
| 21 |
+
opt-einsum==3.2.1
|
| 22 |
+
pkg-resources==0.0.0
|
| 23 |
+
protobuf==3.15.0
|
| 24 |
+
pyasn1==0.4.8
|
| 25 |
+
pyasn1-modules==0.2.8
|
| 26 |
+
pyparsing==2.4.6
|
| 27 |
+
python-dateutil==2.8.1
|
| 28 |
+
requests==2.23.0
|
| 29 |
+
requests-oauthlib==1.3.0
|
| 30 |
+
six==1.14.0
|
| 31 |
+
termcolor==1.1.0
|
| 32 |
+
Werkzeug==0.16.1
|
| 33 |
+
wrapt==1.11.2
|
legacy/run_model.py
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
""" DexiNed main script
|
| 2 |
+
|
| 3 |
+
This code is based on DexiNed (Dense Extreme Inception Network for Edge Detection),
|
| 4 |
+
Please pay attention in the function config_model() to set any parameter before training or
|
| 5 |
+
testing the model.
|
| 6 |
+
"""
|
| 7 |
+
__author__ = "Xavier Soria Poma, CVC-UAB"
|
| 8 |
+
__email__ = "[email protected] / [email protected]"
|
| 9 |
+
__homepage__="www.cvc.uab.cat/people/xsoria"
|
| 10 |
+
__credits__=['DexiNed']
|
| 11 |
+
__copyright__ = "MIT License [see LICENSE for details]"#"Copyright 2019, CIMI"
|
| 12 |
+
|
| 13 |
+
import sys
|
| 14 |
+
import argparse
|
| 15 |
+
import tensorflow as tf
|
| 16 |
+
|
| 17 |
+
import utls.dataset_manager as dm
|
| 18 |
+
from train import m_trainer
|
| 19 |
+
from test import m_tester
|
| 20 |
+
import platform
|
| 21 |
+
|
| 22 |
+
def config_model():
|
| 23 |
+
in_linux = True if platform.system() == "Linux" else False
|
| 24 |
+
base_dir = "/opt/dataset/" if in_linux else "../../dataset/"
|
| 25 |
+
parser = argparse.ArgumentParser(description='Basic details to run HED')
|
| 26 |
+
# dataset config
|
| 27 |
+
parser.add_argument('--train_dataset', default='BIPED', choices=['BIPED','BSDS'])
|
| 28 |
+
parser.add_argument('--test_dataset', default='CLASSIC', choices=['BIPED', 'BSDS','MULTICUE','NYUD','PASCAL','CID','DCD'])
|
| 29 |
+
parser.add_argument('--dataset_dir',default=base_dir,type=str) # default:'/opt/dataset/'
|
| 30 |
+
parser.add_argument('--dataset_augmented', default=True,type=bool)
|
| 31 |
+
parser.add_argument('--train_list',default='train_rgb.lst', type=str) # BSDS train_pair.lst, SSMIHD train_rgb_pair.lst/train_rgbn_pair.lst
|
| 32 |
+
parser.add_argument('--test_list', default='test_rgb.lst',type=str) # for NYUD&BSDS:test_pair.lst, biped msi_test.lst/test_rgb.lst
|
| 33 |
+
parser.add_argument('--trained_model_dir', default='train',type=str) # 'trainV2_RN'
|
| 34 |
+
# SSMIHD_RGBN msi_valid_list.txt and msi_test_list.txt is for unified test
|
| 35 |
+
parser.add_argument('--use_nir', default=False, type=bool)
|
| 36 |
+
parser.add_argument('--use_dataset', default=False, type=bool) # test: dataset=True single image=FALSE
|
| 37 |
+
# model config
|
| 38 |
+
parser.add_argument('--model_state', default='train', choices=['train','test','None']) # always in None
|
| 39 |
+
parser.add_argument('--model_name', default='DXN',choices=['DXN','XCP','None'])
|
| 40 |
+
parser.add_argument('--use_v1', default=False,type=bool)
|
| 41 |
+
parser.add_argument('--model_purpose', default='edges',choices=['edges','restoration','None'])
|
| 42 |
+
parser.add_argument('--batch_size_train',default=8,type=int)
|
| 43 |
+
parser.add_argument('--batch_size_val',default=8, type=int)
|
| 44 |
+
parser.add_argument('--batch_size_test',default=1,type=int)
|
| 45 |
+
parser.add_argument('--checkpoint_dir', default='checkpoints',type=str)
|
| 46 |
+
parser.add_argument('--logs_dir', default='logs',type=str)
|
| 47 |
+
parser.add_argument('--learning_rate',default=1e-4, type=float) # 1e-4=0.0001
|
| 48 |
+
parser.add_argument('--lr_scheduler',default=None,choices=[None,'asce','desc']) # check here
|
| 49 |
+
parser.add_argument('--learning_rate_decay', default=0.1,type=float)
|
| 50 |
+
parser.add_argument('--weight_decay', default=0.0002, type=float)
|
| 51 |
+
parser.add_argument('--model_weights_path', default='vgg16_.npy')
|
| 52 |
+
parser.add_argument('--train_split', default=0.9, type=float) # default 0.8
|
| 53 |
+
parser.add_argument('--max_iterations', default=180000, type=int) # 100000
|
| 54 |
+
parser.add_argument('--learning_decay_interval',default=25000, type=int) # 25000
|
| 55 |
+
parser.add_argument('--loss_weights', default=1.0, type=float)
|
| 56 |
+
parser.add_argument('--save_interval', default=20000, type=int) # 50000
|
| 57 |
+
parser.add_argument('--val_interval', default=30, type=int)
|
| 58 |
+
parser.add_argument('--use_subpixel', default=None, type=bool) # None=upsampling with transp conv
|
| 59 |
+
parser.add_argument('--deep_supervision', default=True, type= bool)
|
| 60 |
+
parser.add_argument('--target_regression',default=True, type=bool) # true
|
| 61 |
+
parser.add_argument('--mean_pixel_values', default=[103.939,116.779,123.68, 137.86], type=float)# [103.939,116.779,123.68]
|
| 62 |
+
# for Nir pixels mean [103.939,116.779,123.68, 137.86]
|
| 63 |
+
parser.add_argument('--channel_swap', default=[2,1,0], type=int)
|
| 64 |
+
parser.add_argument('--gpu-limit',default=1.0, type= float, )
|
| 65 |
+
parser.add_argument('--use_trained_model', default=True, type=bool) # for vvg16
|
| 66 |
+
parser.add_argument('--use_previous_trained', default=False, type=bool) # for training
|
| 67 |
+
# image configuration
|
| 68 |
+
parser.add_argument('--image_width', default=512, type=int) # 480 NYUD=560 BIPED=1280 default 400 other 448
|
| 69 |
+
parser.add_argument('--image_height', default=512, type=int) # 480 for NYUD 425 BIPED=720 default 400
|
| 70 |
+
parser.add_argument('--n_channels', default=3, type=int) # last ssmihd_xcp trained in 512
|
| 71 |
+
# test config
|
| 72 |
+
parser.add_argument('--test_snapshot', default=149999, type=int) # BIPED: 149736 BSDS:101179
|
| 73 |
+
#DexiNedv1=149736,DexiNedv2=149999
|
| 74 |
+
parser.add_argument('--testing_threshold', default=0.0, type=float)
|
| 75 |
+
parser.add_argument('--base_dir_results',default='results/edges',type=str) # default: '/opt/results/edges'
|
| 76 |
+
# single image default=None
|
| 77 |
+
args = parser.parse_args()
|
| 78 |
+
return args
|
| 79 |
+
|
| 80 |
+
def get_session(gpu_fraction):
|
| 81 |
+
|
| 82 |
+
num_threads = False
|
| 83 |
+
gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=gpu_fraction)
|
| 84 |
+
|
| 85 |
+
if num_threads:
|
| 86 |
+
return tf.compat.v1.Session(config=tf.compat.v1.ConfigProto(gpu_options=gpu_options, intra_op_parallelism_threads=num_threads))
|
| 87 |
+
else:
|
| 88 |
+
return tf.compat.v1.Session(config=tf.compat.v1.ConfigProto())
|
| 89 |
+
|
| 90 |
+
|
| 91 |
+
def main(args):
|
| 92 |
+
|
| 93 |
+
if not args.dataset_augmented:
|
| 94 |
+
# Only for BIPED dataset
|
| 95 |
+
# dm.augment_data(args)
|
| 96 |
+
print("Please visit the webpage of BIPED in:")
|
| 97 |
+
print("https://xavysp.github.io/MBIPED/")
|
| 98 |
+
print("and run the code")
|
| 99 |
+
sys.exit()
|
| 100 |
+
|
| 101 |
+
if args.model_state =='train' or args.model_state=='test':
|
| 102 |
+
sess = get_session(args.gpu_limit)
|
| 103 |
+
# sess =tf.Session()
|
| 104 |
+
else:
|
| 105 |
+
print("The model state is None, so it will exit...")
|
| 106 |
+
sys.exit()
|
| 107 |
+
|
| 108 |
+
if args.model_state=='train':
|
| 109 |
+
trainer = m_trainer(args)
|
| 110 |
+
trainer.setup()
|
| 111 |
+
trainer.run(sess)
|
| 112 |
+
sess.close()
|
| 113 |
+
|
| 114 |
+
if args.model_state=='test':
|
| 115 |
+
|
| 116 |
+
if args.test_dataset=="BIPED":
|
| 117 |
+
if args.image_width >700:
|
| 118 |
+
pass
|
| 119 |
+
else:
|
| 120 |
+
print(' image size is not set in non augmented data')
|
| 121 |
+
sys.exit()
|
| 122 |
+
tester = m_tester(args)
|
| 123 |
+
tester.setup(sess)
|
| 124 |
+
tester.run(sess)
|
| 125 |
+
sess.close()
|
| 126 |
+
|
| 127 |
+
if args.model_state=="None":
|
| 128 |
+
print("Sorry the model state is {}".format(args.model_state))
|
| 129 |
+
sys.exit()
|
| 130 |
+
|
| 131 |
+
if __name__=='__main__':
|
| 132 |
+
|
| 133 |
+
args = config_model()
|
| 134 |
+
main(args=args)
|
legacy/test.py
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
|
| 3 |
+
import tensorflow as tf
|
| 4 |
+
from PIL import Image
|
| 5 |
+
|
| 6 |
+
from models.dexined import dexined
|
| 7 |
+
# from models.dexinedBs import dexined
|
| 8 |
+
from utls.utls import *
|
| 9 |
+
from utls.dataset_manager import data_parser,get_single_image,\
|
| 10 |
+
get_testing_batch
|
| 11 |
+
|
| 12 |
+
class m_tester():
|
| 13 |
+
|
| 14 |
+
def __init__(self, args):
|
| 15 |
+
self.args = args
|
| 16 |
+
|
| 17 |
+
def setup(self, session):
|
| 18 |
+
|
| 19 |
+
try:
|
| 20 |
+
if self.args.model_name=='DXN':
|
| 21 |
+
self.model = dexined(self.args)
|
| 22 |
+
else:
|
| 23 |
+
print_error("Error setting model, {}".format(self.args.model_name))
|
| 24 |
+
if self.args.trained_model_dir is None:
|
| 25 |
+
meta_model_file = os.path.join(
|
| 26 |
+
self.args.checkpoint_dir, os.path.join(
|
| 27 |
+
self.args.model_name + '_' + self.args.train_dataset,
|
| 28 |
+
os.path.join('train',
|
| 29 |
+
'{}-{}'.format(self.args.model_name, self.args.test_snapshot))))
|
| 30 |
+
else:
|
| 31 |
+
meta_model_file = os.path.join(
|
| 32 |
+
self.args.checkpoint_dir, os.path.join(
|
| 33 |
+
self.args.model_name + '_' + self.args.train_dataset,
|
| 34 |
+
os.path.join(self.args.trained_model_dir,
|
| 35 |
+
'{}-{}'.format(self.args.model_name, self.args.test_snapshot))))
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
saver = tf.train.Saver()
|
| 39 |
+
saver.restore(session, meta_model_file)
|
| 40 |
+
print_info('Done restoring DexiNed model from {}'.format(meta_model_file))
|
| 41 |
+
|
| 42 |
+
except Exception as err:
|
| 43 |
+
|
| 44 |
+
print_error('Error setting up DexiNed traied model, {}'.format(err))
|
| 45 |
+
|
| 46 |
+
def run(self, session):
|
| 47 |
+
|
| 48 |
+
self.model.setup_testing(session)
|
| 49 |
+
if self.args.use_dataset:
|
| 50 |
+
test_data= data_parser(self.args)
|
| 51 |
+
n_data = len(test_data[1])
|
| 52 |
+
else:
|
| 53 |
+
test_data=get_single_image(self.args)
|
| 54 |
+
n_data = len(test_data)
|
| 55 |
+
print_info('Writing PNGs at {}'.format(self.args.base_dir_results))
|
| 56 |
+
|
| 57 |
+
if self.args.batch_size_test==1 and self.args.use_dataset:
|
| 58 |
+
for i in range(n_data):
|
| 59 |
+
im, em, file_name = get_testing_batch(self.args,
|
| 60 |
+
[test_data[0][test_data[1][i]], test_data[1][i]], use_batch=False)
|
| 61 |
+
self.img_info = file_name
|
| 62 |
+
edgemap = session.run(self.model.predictions, feed_dict={self.model.images: [im]})
|
| 63 |
+
|
| 64 |
+
self.save_egdemaps(edgemap, single_image=True)
|
| 65 |
+
print_info('Done testing {}, {}'.format(self.img_info[0], self.img_info[1]))
|
| 66 |
+
|
| 67 |
+
# for individual images
|
| 68 |
+
elif self.args.batch_size_test==1 and not self.args.use_dataset:
|
| 69 |
+
for i in range(n_data):
|
| 70 |
+
im, file_name = get_single_image(self.args,file_path=test_data[i])
|
| 71 |
+
self.img_info = file_name
|
| 72 |
+
edgemap = session.run(self.model.predictions, feed_dict={self.model.images: [im]})
|
| 73 |
+
self.save_egdemaps(edgemap, single_image=True)
|
| 74 |
+
print_info('Done testing {}, {}'.format(self.img_info[0], self.img_info[1]))
|
| 75 |
+
|
| 76 |
+
def save_egdemaps(self, em_maps, single_image=False):
|
| 77 |
+
""" save_edgemaps descriptios
|
| 78 |
+
|
| 79 |
+
:param em_maps:
|
| 80 |
+
:param single_image:
|
| 81 |
+
save predicted edge maps
|
| 82 |
+
"""
|
| 83 |
+
result_dir = 'DexiNed_'+self.args.train_dataset+'2'+self.args.test_dataset
|
| 84 |
+
if self.args.base_dir_results is None:
|
| 85 |
+
res_dir = os.path.join('../results', result_dir)
|
| 86 |
+
else:
|
| 87 |
+
res_dir = os.path.join(self.args.base_dir_results,result_dir)
|
| 88 |
+
gt_dir = os.path.join(res_dir,'gt')
|
| 89 |
+
all_dir = os.path.join(res_dir,'pred-h5')
|
| 90 |
+
resf_dir = os.path.join(res_dir,'pred-f')
|
| 91 |
+
resa_dir = os.path.join(res_dir,'pred-a')
|
| 92 |
+
|
| 93 |
+
os.makedirs(resf_dir, exist_ok=True)
|
| 94 |
+
os.makedirs(resa_dir, exist_ok=True)
|
| 95 |
+
os.makedirs(gt_dir, exist_ok=True)
|
| 96 |
+
os.makedirs(all_dir, exist_ok=True)
|
| 97 |
+
|
| 98 |
+
if single_image:
|
| 99 |
+
em_maps = [e[0] for e in em_maps]
|
| 100 |
+
em_a = np.mean(np.array(em_maps), axis=0)
|
| 101 |
+
em_maps = em_maps + [em_a ]
|
| 102 |
+
|
| 103 |
+
em = em_maps[len(em_maps)-2]
|
| 104 |
+
em[em < self.args.testing_threshold] = 0.0
|
| 105 |
+
em_a[em_a < self.args.testing_threshold] = 0.0
|
| 106 |
+
em = 255.0 * (1.0 - em)
|
| 107 |
+
em_a = 255.0 * (1.0 - em_a)
|
| 108 |
+
em = np.tile(em, [1, 1, 3])
|
| 109 |
+
em_a = np.tile(em_a, [1, 1, 3])
|
| 110 |
+
|
| 111 |
+
em = Image.fromarray(np.uint8(em))
|
| 112 |
+
em_a = Image.fromarray(np.uint8(em_a))
|
| 113 |
+
|
| 114 |
+
tmp_name = os.path.basename(self.img_info[0])
|
| 115 |
+
tmp_name = tmp_name[:-4]
|
| 116 |
+
tmp_size = self.img_info[-1][:2]
|
| 117 |
+
tmp_size = (tmp_size[1],tmp_size[0])
|
| 118 |
+
|
| 119 |
+
em_f = em.resize(tmp_size)
|
| 120 |
+
em_a = em_a.resize(tmp_size)
|
| 121 |
+
|
| 122 |
+
em_f.save(os.path.join(resf_dir, tmp_name + '.png'))
|
| 123 |
+
em_a.save(os.path.join(resa_dir, tmp_name + '.png'))
|
| 124 |
+
em_maps =tensor_norm_01(em_maps)
|
| 125 |
+
save_variable_h5(os.path.join(all_dir, tmp_name + '.h5'), np.float16(em_maps))
|
| 126 |
+
|
| 127 |
+
|
| 128 |
+
else:
|
| 129 |
+
pass
|
legacy/train.py
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
|
| 3 |
+
import tensorflow as tf
|
| 4 |
+
import matplotlib.pyplot as plt
|
| 5 |
+
|
| 6 |
+
from models.dexined import dexined
|
| 7 |
+
# from models.dexinedBs import dexined
|
| 8 |
+
from utls.utls import *
|
| 9 |
+
from utls.dataset_manager import (data_parser,
|
| 10 |
+
get_training_batch,get_validation_batch, visualize_result)
|
| 11 |
+
|
| 12 |
+
class m_trainer():
|
| 13 |
+
|
| 14 |
+
def __init__(self,args ):
|
| 15 |
+
self.init = True
|
| 16 |
+
self.args = args
|
| 17 |
+
|
| 18 |
+
def setup(self):
|
| 19 |
+
try:
|
| 20 |
+
if self.args.model_name=='DXN':
|
| 21 |
+
self.model = dexined(self.args)
|
| 22 |
+
else:
|
| 23 |
+
print_error("Error setting model, {}".format(self.args.model_name))
|
| 24 |
+
|
| 25 |
+
print_info("DL model Set")
|
| 26 |
+
except Exception as err:
|
| 27 |
+
print_error("Error setting up DL model, {}".format(err))
|
| 28 |
+
self.init=False
|
| 29 |
+
|
| 30 |
+
def run(self, sess):
|
| 31 |
+
if not self.init:
|
| 32 |
+
return
|
| 33 |
+
train_data = data_parser(self.args)
|
| 34 |
+
|
| 35 |
+
self.model.setup_training(sess)
|
| 36 |
+
if self.args.lr_scheduler is not None:
|
| 37 |
+
global_step = tf.Variable(0, trainable=False, dtype=tf.int64)
|
| 38 |
+
if self.args.lr_scheduler is None:
|
| 39 |
+
learning_rate = tf.constant(self.args.learning_rate, dtype=tf.float16)
|
| 40 |
+
else:
|
| 41 |
+
raise NotImplementedError('Learning rate scheduler type [%s] is not implemented',
|
| 42 |
+
self.args.lr_scheduler)
|
| 43 |
+
opt = tf.compat.v1.train.AdamOptimizer(learning_rate)
|
| 44 |
+
trainG = opt.minimize(self.model.loss)# like hed
|
| 45 |
+
saver = tf.compat.v1.train.Saver(max_to_keep=7)
|
| 46 |
+
|
| 47 |
+
sess.run(tf.compat.v1.global_variables_initializer())
|
| 48 |
+
# here to recovery previous training
|
| 49 |
+
if self.args.use_previous_trained:
|
| 50 |
+
if self.args.dataset_name.lower()!='biped': # using biped pretrained to use in other dataset
|
| 51 |
+
model_path = os.path.join(self.args.checkpoint_dir,self.args.model_name+
|
| 52 |
+
'_'+self.args.train_dataset,'train')
|
| 53 |
+
else:
|
| 54 |
+
model_path = os.path.join(self.args.checkpoint_dir, self.args.model_name + '_' + self.args.train_dataset)
|
| 55 |
+
model_path = os.path.join(model_path, 'train')
|
| 56 |
+
if not os.path.exists(model_path) or len(os.listdir(model_path))==0: # :
|
| 57 |
+
ini = 0
|
| 58 |
+
maxi = self.args.max_iterations+1
|
| 59 |
+
print_warning('There is not previous trained data for the current model... and')
|
| 60 |
+
print_warning('*** The training process is starting from scratch ***')
|
| 61 |
+
else:
|
| 62 |
+
# restoring using the last checkpoint
|
| 63 |
+
assert (len(os.listdir(model_path)) != 0),'There is not previous trained data for the current model...'
|
| 64 |
+
last_ckpt = tf.train.latest_checkpoint(model_path)
|
| 65 |
+
saver.restore(sess,last_ckpt)
|
| 66 |
+
ini=self.args.max_iterations
|
| 67 |
+
maxi=ini+self.args.max_iterations+1 # check
|
| 68 |
+
print_info('--> Previous model restored successfully: {}'.format(last_ckpt))
|
| 69 |
+
else:
|
| 70 |
+
print_warning('*** The training process is starting from scratch ***')
|
| 71 |
+
ini = 0
|
| 72 |
+
maxi = ini + self.args.max_iterations
|
| 73 |
+
prev_loss=1000.
|
| 74 |
+
prev_val = None
|
| 75 |
+
# directories for checkpoints
|
| 76 |
+
checkpoint_dir = os.path.join(
|
| 77 |
+
self.args.checkpoint_dir, self.args.model_name + '_' + self.args.train_dataset,
|
| 78 |
+
self.args.model_state)
|
| 79 |
+
os.makedirs(checkpoint_dir,exist_ok=True)
|
| 80 |
+
|
| 81 |
+
fig = plt.figure()
|
| 82 |
+
for idx in range(ini, maxi):
|
| 83 |
+
|
| 84 |
+
x_batch, y_batch,_ = get_training_batch(self.args, train_data)
|
| 85 |
+
run_metadata = tf.compat.v1.RunMetadata()
|
| 86 |
+
|
| 87 |
+
_, summary, loss,pred_maps= sess.run(
|
| 88 |
+
[trainG, self.model.merged_summary, self.model.loss, self.model.predictions],
|
| 89 |
+
feed_dict={self.model.images: x_batch, self.model.edgemaps: y_batch})
|
| 90 |
+
if idx%5==0:
|
| 91 |
+
self.model.train_writer.add_run_metadata(run_metadata,
|
| 92 |
+
'step{:06}'.format(idx))
|
| 93 |
+
self.model.train_writer.add_summary(summary, idx)
|
| 94 |
+
print(time.ctime(), '[{}/{}]'.format(idx, maxi), ' TRAINING loss: %.5f' % loss,
|
| 95 |
+
'prev_loss: %.5f' % prev_loss)
|
| 96 |
+
|
| 97 |
+
# saving trained parameters
|
| 98 |
+
save_inter = ini+self.args.save_interval
|
| 99 |
+
if prev_loss>loss:
|
| 100 |
+
saver.save(sess, os.path.join(checkpoint_dir, self.args.model_name), global_step=idx)
|
| 101 |
+
prev_loss = loss
|
| 102 |
+
print("Weights saved in the lowest loss",idx, " Current Loss",prev_loss)
|
| 103 |
+
|
| 104 |
+
if idx % self.args.save_interval == 0:
|
| 105 |
+
saver.save(sess, os.path.join(checkpoint_dir, self.args.model_name), global_step=idx)
|
| 106 |
+
prev_loss = loss
|
| 107 |
+
print("Weights saved in the interval", idx, " Current Loss",prev_loss)
|
| 108 |
+
|
| 109 |
+
# ********* for validation **********
|
| 110 |
+
if (idx+1) % self.args.val_interval== 0:
|
| 111 |
+
pause_show=0.01
|
| 112 |
+
imgs_list = []
|
| 113 |
+
img = x_batch[2][:,:,0:3]
|
| 114 |
+
gt_mp= y_batch[2]
|
| 115 |
+
imgs_list.append(img)
|
| 116 |
+
imgs_list.append(gt_mp)
|
| 117 |
+
for i in range(len(pred_maps)):
|
| 118 |
+
tmp=pred_maps[i][2,...]
|
| 119 |
+
imgs_list.append(tmp)
|
| 120 |
+
vis_imgs = visualize_result(imgs_list, self.args)
|
| 121 |
+
fig.suptitle("Iterac:" + str(idx + 1) + " Loss:" + '%.5f' % loss + " training")
|
| 122 |
+
fig.add_subplot(1,1,1)
|
| 123 |
+
plt.imshow(np.uint8(vis_imgs))
|
| 124 |
+
|
| 125 |
+
print("Evaluation in progress...")
|
| 126 |
+
plt.draw()
|
| 127 |
+
plt.pause(pause_show)
|
| 128 |
+
|
| 129 |
+
im, em, _ = get_validation_batch(self.args, train_data)
|
| 130 |
+
summary, error, pred_val = sess.run(
|
| 131 |
+
[self.model.merged_summary, self.model.error, self.model.fuse_output],
|
| 132 |
+
feed_dict={self.model.images: im, self.model.edgemaps: em})
|
| 133 |
+
if error<=0.08:
|
| 134 |
+
saver.save(sess, os.path.join(checkpoint_dir, self.args.model_name), global_step=idx)
|
| 135 |
+
prev_loss = loss
|
| 136 |
+
print("Parameters saved in the validation stage when its error is <=0.08::", error)
|
| 137 |
+
|
| 138 |
+
self.model.val_writer.add_summary(summary, idx)
|
| 139 |
+
print_info(('[{}/{}]'.format(idx, self.args.max_iterations),'VALIDATION error: %0.5f'%error,
|
| 140 |
+
'pError: %.5f'%prev_loss))
|
| 141 |
+
if (idx+1) % (self.args.val_interval*150)== 0:
|
| 142 |
+
print('updating visualisation')
|
| 143 |
+
plt.close()
|
| 144 |
+
fig = plt.figure()
|
| 145 |
+
|
| 146 |
+
saver.save(sess, os.path.join(checkpoint_dir, self.args.model_name), global_step=idx)
|
| 147 |
+
print("Final Weights saved", idx, " Current Loss", loss)
|
| 148 |
+
self.model.train_writer.close()
|
| 149 |
+
sess.close()
|
| 150 |
+
|
legacy/utls/dataset_manager.py
ADDED
|
@@ -0,0 +1,1336 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
|
| 3 |
+
"""
|
| 4 |
+
import sys
|
| 5 |
+
import cv2 as cv
|
| 6 |
+
from PIL import Image
|
| 7 |
+
|
| 8 |
+
from legacy.utls.utls import *
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
def cv_imshow(title='default',img=None):
|
| 12 |
+
print(img.shape)
|
| 13 |
+
cv.imshow(title,img)
|
| 14 |
+
cv.waitKey(0)
|
| 15 |
+
cv.destroyAllWindows()
|
| 16 |
+
|
| 17 |
+
def rotated_img_extractor(x=None, gt=None,img_width=None, img_height=None,i=None, two_data=False):
|
| 18 |
+
if two_data:
|
| 19 |
+
if img_width==img_height:
|
| 20 |
+
# for images whose sizes are the same
|
| 21 |
+
|
| 22 |
+
if i % 90 == 0:
|
| 23 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 24 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height, img_width))
|
| 25 |
+
rot_gt = cv.warpAffine(gt, adjus_M, (img_height, img_width))
|
| 26 |
+
elif i % 19 == 0:
|
| 27 |
+
if i == 57:
|
| 28 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 29 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height, img_width))
|
| 30 |
+
rot_gt = cv.warpAffine(gt, adjus_M, (img_height, img_width))
|
| 31 |
+
# cv.rectangle(rot_x, (100, 100), (720 - 100, 720 - 100), (0, 0, 255), (2))
|
| 32 |
+
rot_x = rot_x[100:720 - 100, 100:720 - 100, :]
|
| 33 |
+
rot_gt = rot_gt[100:720 - 100, 100:720 - 100]
|
| 34 |
+
# print("just for check 19: ", i, rot_x.shape)
|
| 35 |
+
elif i == 285:
|
| 36 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 37 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height, img_width))
|
| 38 |
+
rot_gt = cv.warpAffine(gt, adjus_M, (img_height, img_width))
|
| 39 |
+
rot_x = rot_x[75:720 - 75, 75:720 - 75, :]
|
| 40 |
+
rot_gt = rot_gt[75:720 - 75, 75:720 - 75]
|
| 41 |
+
else:
|
| 42 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 43 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height, img_width))
|
| 44 |
+
rot_gt = cv.warpAffine(gt, adjus_M, (img_height, img_width))
|
| 45 |
+
rot_x = rot_x[95:720 - 95, 95:720 - 95, :]
|
| 46 |
+
rot_gt = rot_gt[95:720 - 95, 95:720 - 95]
|
| 47 |
+
elif i % 23 == 0:
|
| 48 |
+
if i == 161:
|
| 49 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 50 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height, img_width))
|
| 51 |
+
rot_gt = cv.warpAffine(gt, adjus_M, (img_height, img_width))
|
| 52 |
+
rot_x = rot_x[85:720 - 85, 85:720 - 85, :]
|
| 53 |
+
rot_gt = rot_gt[85:720 - 85, 85:720 - 85]
|
| 54 |
+
else:
|
| 55 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 56 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height, img_width))
|
| 57 |
+
rot_gt = cv.warpAffine(gt, adjus_M, (img_height, img_width))
|
| 58 |
+
# cv.rectangle(rot_x, (105, 105), (720 - 105, 720 - 105), (0, 0, 255), (2))
|
| 59 |
+
rot_x = rot_x[105:720 - 105, 105:720 - 105, :]
|
| 60 |
+
rot_gt = rot_gt[105:720 - 105, 105:720 - 105]
|
| 61 |
+
# print("just for check 23:", i, rot_x.shape)
|
| 62 |
+
|
| 63 |
+
return rot_x, rot_gt
|
| 64 |
+
else:
|
| 65 |
+
# # for images whose sizes are ***not*** the same *********************************
|
| 66 |
+
img_size = img_width if img_width < img_height else img_height
|
| 67 |
+
if i % 90 == 0:
|
| 68 |
+
if i==180:
|
| 69 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 70 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height+250, img_width))
|
| 71 |
+
rot_gt = cv.warpAffine(gt, adjus_M, (img_height+250, img_width))
|
| 72 |
+
# a = np.copy(rot_x)
|
| 73 |
+
rot_x = rot_x[10:img_size-90, 10:img_size+110, :]
|
| 74 |
+
rot_gt = rot_gt[10:img_size-90, 10:img_size+110]
|
| 75 |
+
else:
|
| 76 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 77 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height + 450, img_width))
|
| 78 |
+
rot_gt = cv.warpAffine(gt, adjus_M, (img_height + 450, img_width))
|
| 79 |
+
# a = np.copy(rot_x)
|
| 80 |
+
rot_x = rot_x[100:img_size + 200, 300:img_size + 200, :]
|
| 81 |
+
rot_gt = rot_gt[100:img_size + 200, 300:img_size + 200]
|
| 82 |
+
elif i % 19 == 0:
|
| 83 |
+
if i == 57:
|
| 84 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 85 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height+i+5, img_width))
|
| 86 |
+
rot_gt = cv.warpAffine(gt, adjus_M, (img_height+i+5, img_width))
|
| 87 |
+
# a = np.copy(rot_x)
|
| 88 |
+
# # x y x y
|
| 89 |
+
# cv.rectangle(a, (275, 275), (img_size+55, img_size+55), (0, 0, 255), (2))
|
| 90 |
+
# y x
|
| 91 |
+
rot_x = rot_x[275:img_size+55, 275:img_size+55, :]
|
| 92 |
+
rot_gt = rot_gt[275:img_size+55, 275:img_size+55]
|
| 93 |
+
# print("just for check 19: ", i, rot_x.shape)
|
| 94 |
+
elif i == 285:
|
| 95 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 96 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height+i, img_width))
|
| 97 |
+
rot_gt = cv.warpAffine(gt, adjus_M, (img_height+i, img_width))
|
| 98 |
+
rot_x = rot_x[100:img_size-50,355:img_size+205, :]
|
| 99 |
+
rot_gt = rot_gt[100:img_size-50,355:img_size+205]
|
| 100 |
+
# print("just for check 19: ", i, rot_x.shape)
|
| 101 |
+
elif i==19:
|
| 102 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 103 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height+200, img_width))
|
| 104 |
+
rot_gt = cv.warpAffine(gt, adjus_M, (img_height+200, img_width))
|
| 105 |
+
# a = np.copy(rot_x)
|
| 106 |
+
# cv.rectangle(a, (150, 150), (img_size+30, img_size-70), (0, 0, 255), (2))
|
| 107 |
+
rot_x = rot_x[150:img_size-70, 150:img_size+30, :]
|
| 108 |
+
rot_gt = rot_gt[150:img_size-70, 150:img_size+30]
|
| 109 |
+
# print("just for check 19: ", i, rot_x.shape)
|
| 110 |
+
|
| 111 |
+
else:
|
| 112 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 113 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height+250, img_width))
|
| 114 |
+
rot_gt = cv.warpAffine(gt, adjus_M, (img_height+250, img_width))
|
| 115 |
+
# a = np.copy(rot_x)
|
| 116 |
+
# cv.rectangle(a, (400, 115), (img_size+180, img_size-105), (0, 0, 255), (2))
|
| 117 |
+
rot_x = rot_x[115:img_size-105, 400:img_size+180, :]
|
| 118 |
+
rot_gt = rot_gt[115:img_size-105, 400:img_size+180]
|
| 119 |
+
# print("just for check 19: ", i, rot_x.shape)
|
| 120 |
+
|
| 121 |
+
elif i % 23 == 0:
|
| 122 |
+
if i == 161:
|
| 123 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 124 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height+i+200, img_width))
|
| 125 |
+
rot_gt = cv.warpAffine(gt, adjus_M, (img_height+i, img_width))
|
| 126 |
+
# a = rot_x
|
| 127 |
+
# cv.rectangle(a, (95, 50), (img_size+75, img_size-170), (0, 0, 255), (2))
|
| 128 |
+
rot_x = rot_x[50:img_size-170, 95:img_size+75, :]
|
| 129 |
+
rot_gt = rot_gt[50:img_size-170, 95:img_size+75]
|
| 130 |
+
# print("just for check 23: ", i, rot_x.shape)
|
| 131 |
+
elif i==207:
|
| 132 |
+
|
| 133 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 134 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height + 250, img_width))
|
| 135 |
+
rot_gt = cv.warpAffine(gt, adjus_M, (img_height + 250, img_width))
|
| 136 |
+
# a = np.copy(rot_x)
|
| 137 |
+
# cv.rectangle(a, (200, 185), (img_size + 160, img_size - 95), (0, 0, 255), (2))
|
| 138 |
+
rot_x = rot_x[185:img_size - 95, 200:img_size + 160, :]
|
| 139 |
+
rot_gt = rot_gt[185:img_size - 95, 200:img_size + 160]
|
| 140 |
+
|
| 141 |
+
else:
|
| 142 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 143 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height+250, img_width))
|
| 144 |
+
rot_gt = cv.warpAffine(gt, adjus_M, (img_height+250, img_width))
|
| 145 |
+
# a = np.copy(rot_x)
|
| 146 |
+
# cv.rectangle(a, (390, 115), (img_size+170, img_size-105), (0, 0, 255), (2))
|
| 147 |
+
rot_x = rot_x[115:img_size-105, 390:img_size+170, :]
|
| 148 |
+
rot_gt = rot_gt[115:img_size-105, 390:img_size+170]
|
| 149 |
+
return rot_x,rot_gt
|
| 150 |
+
else:
|
| 151 |
+
# For NIR imagel but just NIR (ONE data)
|
| 152 |
+
if img_height==img_width:
|
| 153 |
+
|
| 154 |
+
if i % 90 == 0:
|
| 155 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 156 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height, img_width))
|
| 157 |
+
# print("just for check 90: ", i)
|
| 158 |
+
elif i % 19 == 0:
|
| 159 |
+
if i == 57:
|
| 160 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 161 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height, img_width))
|
| 162 |
+
# cv.rectangle(rot_x, (100, 100), (720 - 100, 720 - 100), (0, 0, 255), (2))
|
| 163 |
+
rot_x = rot_x[100:720 - 100, 100:720 - 100, :]
|
| 164 |
+
# print("just for check 19: ", i, rot_x.shape)
|
| 165 |
+
elif i == 285:
|
| 166 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 167 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height, img_width))
|
| 168 |
+
# cv.rectangle(rot_x, (75, 75), (720 - 75, 720 - 75), (0, 0, 255), (2))
|
| 169 |
+
rot_x = rot_x[75:720 - 75, 75:720 - 75, :]
|
| 170 |
+
# print("just for check 19: ", i, rot_x.shape)
|
| 171 |
+
else:
|
| 172 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 173 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height, img_width))
|
| 174 |
+
# cv.rectangle(rot_x,(95,95),(720-95,720-95),(0,0,255),(2) )
|
| 175 |
+
rot_x = rot_x[95:720 - 95, 95:720 - 95, :]
|
| 176 |
+
# print("just for check 19: ", i, rot_x.shape)
|
| 177 |
+
elif i % 23 == 0:
|
| 178 |
+
if i == 161:
|
| 179 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 180 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height, img_width))
|
| 181 |
+
# cv.rectangle(rot_x,(85,85),(720-85,720-85),(0,0,255),(2) )
|
| 182 |
+
rot_x = rot_x[85:720 - 85, 85:720 - 85, :]
|
| 183 |
+
# print("just for check 23: ", i, rot_x.shape)
|
| 184 |
+
elif i==207:
|
| 185 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 186 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height, img_width))
|
| 187 |
+
# cv.rectangle(rot_x, (105, 105), (720 - 105, 720 - 105), (0, 0, 255), (2))
|
| 188 |
+
rot_x = rot_x[105:720 - 105, 105:720 - 105, :]
|
| 189 |
+
# print("just for check 23:", i, rot_x.shape)
|
| 190 |
+
else:
|
| 191 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 192 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height, img_width))
|
| 193 |
+
# cv.rectangle(rot_x, (105, 105), (720 - 105, 720 - 105), (0, 0, 255), (2))
|
| 194 |
+
rot_x = rot_x[105:720 - 105, 105:720 - 105, :]
|
| 195 |
+
# print("just for check 23:", i, rot_x.shape)
|
| 196 |
+
else:
|
| 197 |
+
print("Error line 221 in dataset_manager")
|
| 198 |
+
sys.exit()
|
| 199 |
+
else:
|
| 200 |
+
img_size = img_width if img_width < img_height else img_height
|
| 201 |
+
if i % 90 == 0:
|
| 202 |
+
if i == 180:
|
| 203 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 204 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height + 250, img_width))
|
| 205 |
+
rot_x = rot_x[10:img_size - 90, 10:img_size + 110, :]
|
| 206 |
+
|
| 207 |
+
else:
|
| 208 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 209 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height + 450, img_width))
|
| 210 |
+
rot_x = rot_x[100:img_size + 200, 300:img_size + 200, :]
|
| 211 |
+
|
| 212 |
+
elif i % 19 == 0:
|
| 213 |
+
if i == 57:
|
| 214 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 215 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height + i + 5, img_width))
|
| 216 |
+
# # x y x y
|
| 217 |
+
# cv.rectangle(a, (275, 275), (img_size+55, img_size+55), (0, 0, 255), (2))
|
| 218 |
+
# y x
|
| 219 |
+
rot_x = rot_x[275:img_size + 55, 275:img_size + 55, :]
|
| 220 |
+
elif i == 285:
|
| 221 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 222 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height + i, img_width))
|
| 223 |
+
# a = np.copy(rot_x)
|
| 224 |
+
# cv.rectangle(a, (355, 100), (img_size+205, img_size-50), (0, 0, 255), (2))
|
| 225 |
+
rot_x = rot_x[100:img_size - 50, 355:img_size + 205, :]
|
| 226 |
+
elif i == 19:
|
| 227 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 228 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height + 200, img_width))
|
| 229 |
+
# a = np.copy(rot_x)
|
| 230 |
+
# cv.rectangle(a, (150, 150), (img_size+30, img_size-70), (0, 0, 255), (2))
|
| 231 |
+
rot_x = rot_x[150:img_size - 70, 150:img_size + 30, :]
|
| 232 |
+
|
| 233 |
+
else:
|
| 234 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 235 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height + 250, img_width))
|
| 236 |
+
# a = np.copy(rot_x)
|
| 237 |
+
# cv.rectangle(a, (400, 115), (img_size+180, img_size-105), (0, 0, 255), (2))
|
| 238 |
+
rot_x = rot_x[115:img_size - 105, 400:img_size + 180, :]
|
| 239 |
+
|
| 240 |
+
elif i % 23 == 0:
|
| 241 |
+
if i == 161:
|
| 242 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 243 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height + i + 200, img_width))
|
| 244 |
+
# a = rot_x
|
| 245 |
+
# cv.rectangle(a, (95, 50), (img_size+75, img_size-170), (0, 0, 255), (2))
|
| 246 |
+
rot_x = rot_x[50:img_size - 170, 95:img_size + 75, :]
|
| 247 |
+
elif i == 207:
|
| 248 |
+
|
| 249 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 250 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height + 250, img_width))
|
| 251 |
+
# a = np.copy(rot_x)
|
| 252 |
+
# cv.rectangle(a, (200, 185), (img_size + 160, img_size - 95), (0, 0, 255), (2))
|
| 253 |
+
rot_x = rot_x[185:img_size - 95, 200:img_size + 160, :]
|
| 254 |
+
|
| 255 |
+
else:
|
| 256 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 257 |
+
rot_x = cv.warpAffine(x, adjus_M, (img_height + 250, img_width))
|
| 258 |
+
# a = np.copy(rot_x)
|
| 259 |
+
# cv.rectangle(a, (390, 115), (img_size+170, img_size-105), (0, 0, 255), (2))
|
| 260 |
+
rot_x = rot_x[115:img_size - 105, 390:img_size + 170, :]
|
| 261 |
+
return rot_x
|
| 262 |
+
|
| 263 |
+
def augment_data(args):
|
| 264 |
+
|
| 265 |
+
data_for = 'train' # choice [train validation, test]
|
| 266 |
+
imgs_splitted = True
|
| 267 |
+
imgs_rotated = True
|
| 268 |
+
imgs_flipped = True
|
| 269 |
+
imgs_gamma_corrected = True
|
| 270 |
+
|
| 271 |
+
# degrees
|
| 272 |
+
# [19, 46, 57, 90, 114, 138, 161, 180, 207, 230, 247 270, 285, 322, 342]
|
| 273 |
+
degrees = [19, 23*2, 19*3, 90, 19*6, 23*6,23*7,180, 23*9, 23*10,19*13, 270, 19*15,23*14,19*18]
|
| 274 |
+
# if data_for=='train':
|
| 275 |
+
# **************** training data ************************#
|
| 276 |
+
if data_for=='train' and not args.use_nir:
|
| 277 |
+
base_dataset_dir = args.dataset_dir.lower() + args.train_dataset + '/edges'
|
| 278 |
+
GT_dir = os.path.join(base_dataset_dir, 'edge_maps/train/rgbr/aug')
|
| 279 |
+
X_dir = os.path.join(base_dataset_dir, 'imgs/train/rgbr/aug')
|
| 280 |
+
# this implementation is just for BIPED dataset
|
| 281 |
+
gt_list = os.listdir(os.path.join(GT_dir,'real')) #
|
| 282 |
+
gt_list.sort()
|
| 283 |
+
x_list = os.listdir(os.path.join(X_dir,'real'))
|
| 284 |
+
x_list.sort()
|
| 285 |
+
n = len(gt_list) if len(x_list)==len(gt_list) else 0
|
| 286 |
+
if n==0:
|
| 287 |
+
print('there is some inconsistence in the size of lists')
|
| 288 |
+
sys.exit()
|
| 289 |
+
|
| 290 |
+
# making 720x720 image size (splitting) ******************
|
| 291 |
+
# ********************************************************
|
| 292 |
+
if not imgs_splitted:
|
| 293 |
+
tmp_img = cv.imread(os.path.join(
|
| 294 |
+
os.path.join(X_dir, 'real'), x_list[0]))
|
| 295 |
+
img_width = tmp_img.shape[1]
|
| 296 |
+
img_height = tmp_img.shape[0]
|
| 297 |
+
if not os.path.exists(os.path.join(GT_dir, 'p1')):
|
| 298 |
+
os.makedirs(os.path.join(GT_dir, 'p1'))
|
| 299 |
+
if not os.path.exists(os.path.join(GT_dir, 'p2')):
|
| 300 |
+
os.makedirs(os.path.join(GT_dir, 'p2'))
|
| 301 |
+
if not os.path.exists(os.path.join(X_dir, 'p1')):
|
| 302 |
+
os.makedirs(os.path.join(X_dir, 'p1'))
|
| 303 |
+
if not os.path.exists(os.path.join(X_dir, 'p2')):
|
| 304 |
+
os.makedirs(os.path.join(X_dir, 'p2'))
|
| 305 |
+
|
| 306 |
+
for i in range(n):
|
| 307 |
+
x_tmp = cv.imread(os.path.join(
|
| 308 |
+
os.path.join(X_dir,'real'), x_list[i]))
|
| 309 |
+
gt_tmp = cv.imread(os.path.join(
|
| 310 |
+
os.path.join(GT_dir,'real'),gt_list[i]))
|
| 311 |
+
x_tmp1 = x_tmp[:,0:img_height,:]
|
| 312 |
+
x_tmp2 = x_tmp[:,img_width-img_height:img_width,:]
|
| 313 |
+
|
| 314 |
+
gt_tmp1 = gt_tmp[:,0:img_height]
|
| 315 |
+
gt_tmp2 = gt_tmp[:,img_width-img_height:img_width]
|
| 316 |
+
|
| 317 |
+
cv.imwrite(os.path.join(X_dir,os.path.join('p1',x_list[i])), x_tmp1)
|
| 318 |
+
cv.imwrite(os.path.join(X_dir, os.path.join('p2', x_list[i])), x_tmp2)
|
| 319 |
+
cv.imwrite(os.path.join(GT_dir, os.path.join('p1', gt_list[i])), gt_tmp1)
|
| 320 |
+
cv.imwrite(os.path.join(GT_dir, os.path.join('p2', gt_list[i])), gt_tmp2)
|
| 321 |
+
print('saved image: ', x_list[i], gt_list[i])
|
| 322 |
+
print('...split done')
|
| 323 |
+
|
| 324 |
+
# *************** image rotation *******************************
|
| 325 |
+
if not imgs_rotated:
|
| 326 |
+
|
| 327 |
+
# for p1 ***********
|
| 328 |
+
folder_name='real' # choice [p1,p2,real] which are the source of files previously prepared
|
| 329 |
+
# folder_name_x = 'real'
|
| 330 |
+
if folder_name=='p1':
|
| 331 |
+
x_aug_list = os.listdir(os.path.join(X_dir, 'p1'))
|
| 332 |
+
x_aug_list.sort()
|
| 333 |
+
gt_aug_list = os.listdir(os.path.join(GT_dir, 'p1'))
|
| 334 |
+
gt_aug_list.sort()
|
| 335 |
+
elif folder_name == 'p2':
|
| 336 |
+
x_aug_list = os.listdir(os.path.join(X_dir, 'p2'))
|
| 337 |
+
x_aug_list.sort()
|
| 338 |
+
gt_aug_list = os.listdir(os.path.join(GT_dir, 'p2'))
|
| 339 |
+
gt_aug_list.sort()
|
| 340 |
+
elif folder_name=='real':
|
| 341 |
+
x_aug_list = os.listdir(os.path.join(X_dir, 'real'))
|
| 342 |
+
x_aug_list.sort()
|
| 343 |
+
gt_aug_list = os.listdir(os.path.join(GT_dir, 'real'))
|
| 344 |
+
gt_aug_list.sort()
|
| 345 |
+
else:
|
| 346 |
+
print("error reading folder name")
|
| 347 |
+
sys.exit()
|
| 348 |
+
if n==len(x_aug_list) and n== len(gt_aug_list):
|
| 349 |
+
pass
|
| 350 |
+
else:
|
| 351 |
+
print("Error reading data. The is an inconsistency in the data ")
|
| 352 |
+
sys.exit()
|
| 353 |
+
|
| 354 |
+
tmp_img = cv.imread(os.path.join(X_dir,
|
| 355 |
+
os.path.join(folder_name,x_aug_list[1])))
|
| 356 |
+
img_width = tmp_img.shape[1]
|
| 357 |
+
img_height = tmp_img.shape[0]
|
| 358 |
+
|
| 359 |
+
for i in (degrees):
|
| 360 |
+
if folder_name=='p1':
|
| 361 |
+
current_X_dir = X_dir+'/p1_rot_'+str(i)
|
| 362 |
+
current_GT_dir = GT_dir+'/p1_rot_'+str(i)
|
| 363 |
+
elif folder_name=='p2':
|
| 364 |
+
|
| 365 |
+
current_X_dir = X_dir + '/p2_rot_' + str(i)
|
| 366 |
+
current_GT_dir = GT_dir + '/p2_rot_' + str(i)
|
| 367 |
+
elif folder_name=='real':
|
| 368 |
+
current_X_dir = X_dir + '/real_rot_' + str(i)
|
| 369 |
+
current_GT_dir = GT_dir + '/real_rot_' + str(i)
|
| 370 |
+
else:
|
| 371 |
+
print('error')
|
| 372 |
+
sys.exit()
|
| 373 |
+
if not os.path.exists(current_X_dir):
|
| 374 |
+
os.makedirs(current_X_dir)
|
| 375 |
+
if not os.path.exists(current_GT_dir):
|
| 376 |
+
os.makedirs(current_GT_dir)
|
| 377 |
+
|
| 378 |
+
for j in range(n):
|
| 379 |
+
# i = degrees[j]
|
| 380 |
+
if folder_name=='real':
|
| 381 |
+
tmp_x = cv.imread(os.path.join(X_dir,
|
| 382 |
+
os.path.join(folder_name, x_aug_list[j])))
|
| 383 |
+
tmp_gt = cv.imread(os.path.join(GT_dir,
|
| 384 |
+
os.path.join(folder_name, gt_aug_list[j])))
|
| 385 |
+
rot_x,rot_gt=rotated_img_extractor(tmp_x, tmp_gt,img_width, img_height,i, True)
|
| 386 |
+
# [19, 46, 90, 114, 138, 161, 180, 207, 230, 247, 270, 285, 322, 342]
|
| 387 |
+
|
| 388 |
+
else:
|
| 389 |
+
tmp_x = cv.imread(os.path.join(X_dir,
|
| 390 |
+
os.path.join(folder_name,x_aug_list[j])))
|
| 391 |
+
tmp_gt = cv.imread(os.path.join(GT_dir,
|
| 392 |
+
os.path.join(folder_name,gt_aug_list[j])))
|
| 393 |
+
rot_x, rot_gt = rotated_img_extractor(tmp_x, tmp_gt, img_width, img_height, i, True)
|
| 394 |
+
|
| 395 |
+
cv.imwrite(os.path.join(current_GT_dir,gt_aug_list[j]),rot_gt)
|
| 396 |
+
cv.imwrite(os.path.join(current_X_dir, x_aug_list[j]),rot_x)
|
| 397 |
+
tmp_imgs = np.concatenate((rot_x,rot_gt), axis=1)
|
| 398 |
+
cv.imshow("rotated", tmp_imgs)
|
| 399 |
+
cv.waitKey(400) # 1000= 1 seg
|
| 400 |
+
print("rotation with {} degrees fullfiled ".format(i))
|
| 401 |
+
cv.destroyAllWindows()
|
| 402 |
+
print("... rotation done in ", folder_name)
|
| 403 |
+
|
| 404 |
+
# **************** flipping horizontally ***********
|
| 405 |
+
if not imgs_flipped:
|
| 406 |
+
type_aug= '_flip'
|
| 407 |
+
dir_list = os.listdir(X_dir)
|
| 408 |
+
dir_list.sort()
|
| 409 |
+
|
| 410 |
+
for i in (dir_list):
|
| 411 |
+
X_list = os.listdir(os.path.join(X_dir,i))
|
| 412 |
+
X_list.sort()
|
| 413 |
+
GT_list = os.listdir(os.path.join(GT_dir,i))
|
| 414 |
+
GT_list.sort()
|
| 415 |
+
save_dir_x = X_dir+'/'+str(i)+type_aug
|
| 416 |
+
save_dir_gt = GT_dir+'/'+str(i)+type_aug
|
| 417 |
+
|
| 418 |
+
if not os.path.exists(save_dir_x):
|
| 419 |
+
os.makedirs(save_dir_x)
|
| 420 |
+
if not os.path.exists(save_dir_gt):
|
| 421 |
+
os.makedirs(save_dir_gt)
|
| 422 |
+
|
| 423 |
+
print("Working on the dir: ", os.path.join(X_dir,i),os.path.join(GT_dir,i) )
|
| 424 |
+
for j in range(n):
|
| 425 |
+
x_tmp = cv.imread(os.path.join(X_dir,os.path.join(i,X_list[j])))
|
| 426 |
+
gt_tmp = cv.imread(os.path.join(GT_dir, os.path.join(i, GT_list[j])))
|
| 427 |
+
flip_x = np.fliplr(x_tmp)
|
| 428 |
+
flip_gt = np.fliplr(gt_tmp)
|
| 429 |
+
|
| 430 |
+
tmp_imgs = np.concatenate((flip_x, flip_gt), axis=1)
|
| 431 |
+
cv.imshow("rotated", tmp_imgs)
|
| 432 |
+
cv.waitKey(350)
|
| 433 |
+
cv.imwrite(os.path.join(save_dir_gt,GT_list[j]),flip_gt)
|
| 434 |
+
cv.imwrite(os.path.join(save_dir_x, X_list[j]),flip_x)
|
| 435 |
+
|
| 436 |
+
print("End flipping file in {}".format(os.path.join(X_dir,i)))
|
| 437 |
+
cv.destroyAllWindows()
|
| 438 |
+
print("... Flipping data augmentation finished")
|
| 439 |
+
|
| 440 |
+
# ***********Data augmentation based on gamma correction **********
|
| 441 |
+
if not imgs_gamma_corrected:
|
| 442 |
+
gamma30 = '_ga30'
|
| 443 |
+
gamma60 = '_ga60'
|
| 444 |
+
dir_list = os.listdir(X_dir)
|
| 445 |
+
dir_list.sort()
|
| 446 |
+
for i in (dir_list):
|
| 447 |
+
X_list = os.listdir(os.path.join(X_dir,i))
|
| 448 |
+
X_list.sort()
|
| 449 |
+
GT_list = os.listdir(os.path.join(GT_dir,i))
|
| 450 |
+
GT_list.sort()
|
| 451 |
+
save_dir_x30 = X_dir+'/'+str(i)+gamma30
|
| 452 |
+
save_dir_gt30 = GT_dir+'/'+str(i)+gamma30
|
| 453 |
+
save_dir_x60 = X_dir + '/' + str(i)+ gamma60
|
| 454 |
+
save_dir_gt60 = GT_dir + '/' + str(i)+ gamma60
|
| 455 |
+
|
| 456 |
+
if not os.path.exists(save_dir_x30):
|
| 457 |
+
os.makedirs(save_dir_x30)
|
| 458 |
+
if not os.path.exists(save_dir_gt30):
|
| 459 |
+
os.makedirs(save_dir_gt30)
|
| 460 |
+
if not os.path.exists(save_dir_x60):
|
| 461 |
+
os.makedirs(save_dir_x60)
|
| 462 |
+
if not os.path.exists(save_dir_gt60):
|
| 463 |
+
os.makedirs(save_dir_gt60)
|
| 464 |
+
print("Working on the dir: ", os.path.join(X_dir, i), os.path.join(GT_dir, i))
|
| 465 |
+
for j in range(n):
|
| 466 |
+
x_tmp = cv.imread(os.path.join(X_dir, os.path.join(i, X_list[j])))
|
| 467 |
+
gt_tmp = cv.imread(os.path.join(GT_dir, os.path.join(i, GT_list[j])))
|
| 468 |
+
x_tmp = normalization_data_01(x_tmp)
|
| 469 |
+
x_tmp = gamma_correction(x_tmp,0.4040,False)
|
| 470 |
+
|
| 471 |
+
gam30_x = gamma_correction(x_tmp,0.3030,True)
|
| 472 |
+
gam60_x = gamma_correction(x_tmp,0.6060, True)
|
| 473 |
+
gam30_x = np.uint8(normalization_data_0255(gam30_x))
|
| 474 |
+
gam60_x = np.uint8(normalization_data_0255(gam60_x))
|
| 475 |
+
|
| 476 |
+
tmp_imgs1 = np.concatenate((gam30_x, gt_tmp), axis=1)
|
| 477 |
+
tmp_imgs2 = np.concatenate((gam60_x, gt_tmp), axis=1)
|
| 478 |
+
tmp_imgs = np.concatenate((tmp_imgs2,tmp_imgs1),axis=0)
|
| 479 |
+
|
| 480 |
+
cv.imshow("gamma ", tmp_imgs)
|
| 481 |
+
cv.waitKey(350)
|
| 482 |
+
cv.imwrite(os.path.join(save_dir_gt30, GT_list[j]), gt_tmp)
|
| 483 |
+
cv.imwrite(os.path.join(save_dir_x30, X_list[j]), gam30_x)
|
| 484 |
+
cv.imwrite(os.path.join(save_dir_gt60, GT_list[j]), gt_tmp)
|
| 485 |
+
cv.imwrite(os.path.join(save_dir_x60, X_list[j]), gam60_x)
|
| 486 |
+
|
| 487 |
+
print("End gamma correction, file in {}".format(os.path.join(X_dir, i)))
|
| 488 |
+
cv.destroyAllWindows()
|
| 489 |
+
print("... gamma correction data augmentation finished")
|
| 490 |
+
|
| 491 |
+
# ************** for validation ********************************
|
| 492 |
+
elif data_for=='validation' and not args.use_nir:
|
| 493 |
+
|
| 494 |
+
train_GT_dir = args.dataset_dir + args.train_dataset + '/valid'
|
| 495 |
+
train_X_dir = args.dataset_dir + args.train_dataset + '/valid'
|
| 496 |
+
|
| 497 |
+
gt_list = os.listdir(os.path.join(train_GT_dir, 'GT_un')) #
|
| 498 |
+
gt_list.sort()
|
| 499 |
+
x_list = os.listdir(os.path.join(train_X_dir, 'X_un'))
|
| 500 |
+
x_list.sort()
|
| 501 |
+
n = len(gt_list) if len(x_list) == len(gt_list) else 0
|
| 502 |
+
if n == 0:
|
| 503 |
+
print('there is some inconsistence in the size of lists')
|
| 504 |
+
sys.exit()
|
| 505 |
+
|
| 506 |
+
# making 720x720 image size (splitting) ******************
|
| 507 |
+
if not imgs_splitted:
|
| 508 |
+
tmp_img = cv.imread(os.path.join(
|
| 509 |
+
os.path.join(train_X_dir, 'X_un'), x_list[0]))
|
| 510 |
+
img_width = tmp_img.shape[1]
|
| 511 |
+
img_height = tmp_img.shape[0]
|
| 512 |
+
for i in range(n):
|
| 513 |
+
x_tmp = cv.imread(os.path.join(
|
| 514 |
+
os.path.join(train_X_dir, 'X_un'), x_list[i]))
|
| 515 |
+
gt_tmp = cv.imread(os.path.join(
|
| 516 |
+
os.path.join(train_GT_dir, 'GT_un'), gt_list[i]))
|
| 517 |
+
x_tmp1 = x_tmp[:, 0:img_height, :]
|
| 518 |
+
x_tmp2 = x_tmp[:, img_width - img_height:img_width, :]
|
| 519 |
+
|
| 520 |
+
gt_tmp1 = gt_tmp[:, 0:img_height]
|
| 521 |
+
gt_tmp2 = gt_tmp[:, img_width - img_height:img_width]
|
| 522 |
+
|
| 523 |
+
cv.imwrite(os.path.join(train_X_dir, os.path.join('X/p1', x_list[i])), x_tmp1)
|
| 524 |
+
cv.imwrite(os.path.join(train_X_dir, os.path.join('X/p2', x_list[i])), x_tmp2)
|
| 525 |
+
cv.imwrite(os.path.join(train_GT_dir, os.path.join('GT/p1', gt_list[i])), gt_tmp1)
|
| 526 |
+
cv.imwrite(os.path.join(train_GT_dir, os.path.join('GT/p2', gt_list[i])), gt_tmp2)
|
| 527 |
+
print('saved image: ', x_list[i], gt_list[i])
|
| 528 |
+
|
| 529 |
+
tmp_imgs = np.concatenate((x_tmp,gt_tmp), axis=1)
|
| 530 |
+
cv.imshow("rotated", tmp_imgs)
|
| 531 |
+
cv.waitKey(500)
|
| 532 |
+
cv.destroyAllWindows()
|
| 533 |
+
print('...split for validation finished')
|
| 534 |
+
|
| 535 |
+
# image rotation
|
| 536 |
+
if not imgs_rotated:
|
| 537 |
+
folder_name = 'p2' # choice [p1,p2,GT_u] which are the source of files previously prepared
|
| 538 |
+
X_dir = args.dataset_dir + args.train_dataset + '/valid'
|
| 539 |
+
GT_dir = args.dataset_dir + args.train_dataset + '/valid'
|
| 540 |
+
|
| 541 |
+
folder_name_x = 'X_un'
|
| 542 |
+
if folder_name == 'p1':
|
| 543 |
+
x_aug_list = os.listdir(os.path.join(X_dir, 'X/p1'))
|
| 544 |
+
x_aug_list.sort()
|
| 545 |
+
gt_aug_list = os.listdir(os.path.join(GT_dir, 'GT/p1'))
|
| 546 |
+
gt_aug_list.sort()
|
| 547 |
+
elif folder_name == 'p2':
|
| 548 |
+
x_aug_list = os.listdir(os.path.join(X_dir, 'X/p2'))
|
| 549 |
+
x_aug_list.sort()
|
| 550 |
+
gt_aug_list = os.listdir(os.path.join(GT_dir, 'GT/p2'))
|
| 551 |
+
gt_aug_list.sort()
|
| 552 |
+
elif folder_name == 'GT_u':
|
| 553 |
+
x_aug_list = os.listdir(os.path.join(X_dir, 'X_un'))
|
| 554 |
+
x_aug_list.sort()
|
| 555 |
+
gt_aug_list = os.listdir(os.path.join(GT_dir, 'GT_un'))
|
| 556 |
+
gt_aug_list.sort()
|
| 557 |
+
else:
|
| 558 |
+
print("error reading folder name")
|
| 559 |
+
sys.exit()
|
| 560 |
+
# image size
|
| 561 |
+
tmp_img = cv.imread(os.path.join(X_dir,
|
| 562 |
+
os.path.join('X/' + folder_name, x_aug_list[1])))
|
| 563 |
+
img_width = tmp_img.shape[1]
|
| 564 |
+
img_height = tmp_img.shape[0]
|
| 565 |
+
|
| 566 |
+
for i in (degrees):
|
| 567 |
+
if folder_name == 'p1':
|
| 568 |
+
current_X_dir = X_dir + '/X/p1_rot_' + str(i)
|
| 569 |
+
current_GT_dir = GT_dir + '/GT/p1_rot_' + str(i)
|
| 570 |
+
elif folder_name == 'p2':
|
| 571 |
+
|
| 572 |
+
current_X_dir = X_dir + '/X/p2_rot_' + str(i)
|
| 573 |
+
current_GT_dir = GT_dir + '/GT/p2_rot_' + str(i)
|
| 574 |
+
elif folder_name == 'GT_u':
|
| 575 |
+
current_X_dir = X_dir + 'X/un_rot_' + str(i)
|
| 576 |
+
current_GT_dir = GT_dir + 'GT/un_rot_' + str(i)
|
| 577 |
+
else:
|
| 578 |
+
print('error')
|
| 579 |
+
sys.exit()
|
| 580 |
+
if not os.path.exists(current_X_dir):
|
| 581 |
+
os.makedirs(current_X_dir)
|
| 582 |
+
if not os.path.exists(current_GT_dir):
|
| 583 |
+
os.makedirs(current_GT_dir)
|
| 584 |
+
|
| 585 |
+
for j in range(n):
|
| 586 |
+
if folder_name == 'GT_un':
|
| 587 |
+
tmp_x = cv.imread(os.path.join(X_dir,
|
| 588 |
+
os.path.join(folder_name_x, x_aug_list[j])))
|
| 589 |
+
tmp_gt = cv.imread(os.path.join(GT_dir,
|
| 590 |
+
os.path.join(folder_name, gt_aug_list[j])))
|
| 591 |
+
else:
|
| 592 |
+
tmp_x = cv.imread(os.path.join(X_dir,
|
| 593 |
+
os.path.join('X/' + folder_name, x_aug_list[j])))
|
| 594 |
+
tmp_gt = cv.imread(os.path.join(GT_dir,
|
| 595 |
+
os.path.join('GT/' + folder_name, gt_aug_list[j])))
|
| 596 |
+
if i % 90 == 0:
|
| 597 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 598 |
+
rot_x = cv.warpAffine(tmp_x, adjus_M, (img_height, img_width))
|
| 599 |
+
rot_gt = cv.warpAffine(tmp_gt, adjus_M, (img_height, img_width))
|
| 600 |
+
elif i % 19 == 0:
|
| 601 |
+
if i == 57:
|
| 602 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 603 |
+
rot_x = cv.warpAffine(tmp_x, adjus_M, (img_height, img_width))
|
| 604 |
+
rot_gt = cv.warpAffine(tmp_gt, adjus_M, (img_height, img_width))
|
| 605 |
+
# cv.rectangle(rot_x, (100, 100), (720 - 100, 720 - 100), (0, 0, 255), (2))
|
| 606 |
+
rot_x = rot_x[100:720 - 100, 100:720 - 100, :]
|
| 607 |
+
rot_gt = rot_gt[100:720 - 100, 100:720 - 100]
|
| 608 |
+
# print("just for check 19: ", i, rot_x.shape)
|
| 609 |
+
elif i == 285:
|
| 610 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 611 |
+
rot_x = cv.warpAffine(tmp_x, adjus_M, (img_height, img_width))
|
| 612 |
+
rot_gt = cv.warpAffine(tmp_gt, adjus_M, (img_height, img_width))
|
| 613 |
+
# cv.rectangle(rot_x, (75, 75), (720 - 75, 720 - 75), (0, 0, 255), (2))
|
| 614 |
+
rot_x = rot_x[75:720 - 75, 75:720 - 75, :]
|
| 615 |
+
rot_gt = rot_gt[75:720 - 75, 75:720 - 75]
|
| 616 |
+
else:
|
| 617 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 618 |
+
rot_x = cv.warpAffine(tmp_x, adjus_M, (img_height, img_width))
|
| 619 |
+
rot_gt = cv.warpAffine(tmp_gt, adjus_M, (img_height, img_width))
|
| 620 |
+
rot_x = rot_x[95:720 - 95, 95:720 - 95, :]
|
| 621 |
+
rot_gt = rot_gt[95:720 - 95, 95:720 - 95]
|
| 622 |
+
elif i % 23 == 0:
|
| 623 |
+
if i == 161:
|
| 624 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 625 |
+
rot_x = cv.warpAffine(tmp_x, adjus_M, (img_height, img_width))
|
| 626 |
+
rot_gt = cv.warpAffine(tmp_gt, adjus_M, (img_height, img_width))
|
| 627 |
+
# cv.rectangle(rot_x,(85,85),(720-85,720-85),(0,0,255),(2) )
|
| 628 |
+
rot_x = rot_x[85:720 - 85, 85:720 - 85, :]
|
| 629 |
+
rot_gt = rot_gt[85:720 - 85, 85:720 - 85]
|
| 630 |
+
# print("just for check 23: ", i, rot_x.shape)
|
| 631 |
+
else:
|
| 632 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 633 |
+
rot_x = cv.warpAffine(tmp_x, adjus_M, (img_height, img_width))
|
| 634 |
+
rot_gt = cv.warpAffine(tmp_gt, adjus_M, (img_height, img_width))
|
| 635 |
+
rot_x = rot_x[105:720 - 105, 105:720 - 105, :]
|
| 636 |
+
rot_gt = rot_gt[105:720 - 105, 105:720 - 105]
|
| 637 |
+
else:
|
| 638 |
+
print('Error using degrees for rotation')
|
| 639 |
+
sys.exit()
|
| 640 |
+
cv.imwrite(os.path.join(current_GT_dir, gt_aug_list[j]), rot_gt)
|
| 641 |
+
cv.imwrite(os.path.join(current_X_dir, x_aug_list[j]), rot_x)
|
| 642 |
+
tmp_imgs = np.concatenate((rot_x, rot_gt), axis=1)
|
| 643 |
+
cv.imshow("rotated", tmp_imgs)
|
| 644 |
+
cv.waitKey(1000)
|
| 645 |
+
print("rotation with {} degrees fullfiled ".format(i))
|
| 646 |
+
cv.destroyAllWindows()
|
| 647 |
+
|
| 648 |
+
print("... data rotation for validation finished ", folder_name)
|
| 649 |
+
# flipping horizontally
|
| 650 |
+
if not imgs_flipped:
|
| 651 |
+
type_aug = 'flip_'
|
| 652 |
+
X_dir = args.dataset_dir + args.train_dataset + '/valid/X'
|
| 653 |
+
GT_dir = args.dataset_dir + args.train_dataset + '/valid/GT'
|
| 654 |
+
dir_list = os.listdir(X_dir)
|
| 655 |
+
dir_list.sort()
|
| 656 |
+
|
| 657 |
+
for i in (dir_list):
|
| 658 |
+
X_list = os.listdir(os.path.join(X_dir, i))
|
| 659 |
+
X_list.sort()
|
| 660 |
+
GT_list = os.listdir(os.path.join(GT_dir, i))
|
| 661 |
+
GT_list.sort()
|
| 662 |
+
save_dir_x = X_dir + '/' + type_aug + str(i)
|
| 663 |
+
save_dir_gt = GT_dir + '/' + type_aug + str(i)
|
| 664 |
+
|
| 665 |
+
if not os.path.exists(save_dir_x):
|
| 666 |
+
os.makedirs(save_dir_x)
|
| 667 |
+
if not os.path.exists(save_dir_gt):
|
| 668 |
+
os.makedirs(save_dir_gt)
|
| 669 |
+
|
| 670 |
+
print("Working on the dir: ", os.path.join(X_dir, i), os.path.join(GT_dir, i))
|
| 671 |
+
for j in range(n):
|
| 672 |
+
x_tmp = cv.imread(os.path.join(X_dir, os.path.join(i, X_list[j])))
|
| 673 |
+
gt_tmp = cv.imread(os.path.join(GT_dir, os.path.join(i, GT_list[j])))
|
| 674 |
+
flip_x = np.fliplr(x_tmp)
|
| 675 |
+
flip_gt = np.fliplr(gt_tmp)
|
| 676 |
+
|
| 677 |
+
tmp_imgs = np.concatenate((flip_x, flip_gt), axis=1)
|
| 678 |
+
cv.imshow("rotated", tmp_imgs)
|
| 679 |
+
cv.waitKey(1000)
|
| 680 |
+
cv.imwrite(os.path.join(save_dir_gt, GT_list[j]), flip_gt)
|
| 681 |
+
cv.imwrite(os.path.join(save_dir_x, X_list[j]), flip_x)
|
| 682 |
+
|
| 683 |
+
print("End flipping file in {}".format(os.path.join(X_dir, i)))
|
| 684 |
+
|
| 685 |
+
cv.destroyAllWindows()
|
| 686 |
+
|
| 687 |
+
print("... Flipping validation stage data augmentation finished")
|
| 688 |
+
|
| 689 |
+
# ========================================================
|
| 690 |
+
# =====================Just for NIR ======================
|
| 691 |
+
# ========================================================
|
| 692 |
+
elif args.use_nir:
|
| 693 |
+
|
| 694 |
+
if data_for == 'train':
|
| 695 |
+
base_dataset_dir = args.dataset_dir + args.train_dataset + '/edges'
|
| 696 |
+
X_dir = os.path.join(base_dataset_dir, 'imgs/train/nir/aug')
|
| 697 |
+
|
| 698 |
+
x_list = os.listdir(os.path.join(X_dir, 'real'))
|
| 699 |
+
x_list.sort()
|
| 700 |
+
n = len(x_list)
|
| 701 |
+
if n == 0:
|
| 702 |
+
print('there is some inconsistence in the size of lists')
|
| 703 |
+
sys.exit()
|
| 704 |
+
|
| 705 |
+
# making 720x720 image size (splitting) ******************
|
| 706 |
+
if not imgs_splitted:
|
| 707 |
+
tmp_img = cv.imread(os.path.join(
|
| 708 |
+
os.path.join(X_dir, 'real'), x_list[0]))
|
| 709 |
+
img_width = tmp_img.shape[1]
|
| 710 |
+
img_height = tmp_img.shape[0]
|
| 711 |
+
|
| 712 |
+
for i in range(n):
|
| 713 |
+
x_tmp = cv.imread(os.path.join(
|
| 714 |
+
os.path.join(X_dir, 'real'), x_list[i]))
|
| 715 |
+
x_tmp1 = x_tmp[:, 0:img_height, :]
|
| 716 |
+
x_tmp2 = x_tmp[:, img_width - img_height:img_width, :]
|
| 717 |
+
|
| 718 |
+
cv.imwrite(os.path.join(X_dir, os.path.join('p1', x_list[i])), x_tmp1)
|
| 719 |
+
cv.imwrite(os.path.join(X_dir, os.path.join('p2', x_list[i])), x_tmp2)
|
| 720 |
+
print('saved image: ', x_list[i])
|
| 721 |
+
print('...split done')
|
| 722 |
+
|
| 723 |
+
# ***************** image rotation ******************
|
| 724 |
+
if not imgs_rotated:
|
| 725 |
+
|
| 726 |
+
# for p1 ***********
|
| 727 |
+
folder_name = 'real' # choice [p1,p2,real] which are the source of files previously prepared
|
| 728 |
+
# firstly X_un is not used
|
| 729 |
+
folder_name_x = 'real'
|
| 730 |
+
if folder_name == 'p1':
|
| 731 |
+
x_aug_list = os.listdir(os.path.join(X_dir, 'p1'))
|
| 732 |
+
x_aug_list.sort()
|
| 733 |
+
elif folder_name == 'p2':
|
| 734 |
+
x_aug_list = os.listdir(os.path.join(X_dir, 'p2'))
|
| 735 |
+
x_aug_list.sort()
|
| 736 |
+
elif folder_name == 'real':
|
| 737 |
+
x_aug_list = os.listdir(os.path.join(X_dir, 'real'))
|
| 738 |
+
x_aug_list.sort()
|
| 739 |
+
else:
|
| 740 |
+
print("error reading folder name")
|
| 741 |
+
sys.exit()
|
| 742 |
+
|
| 743 |
+
# image size
|
| 744 |
+
tmp_img = cv.imread(os.path.join(
|
| 745 |
+
X_dir, os.path.join(folder_name, x_aug_list[1])))
|
| 746 |
+
img_width = tmp_img.shape[1]
|
| 747 |
+
img_height = tmp_img.shape[0]
|
| 748 |
+
|
| 749 |
+
for i in (degrees):
|
| 750 |
+
if folder_name == 'p1':
|
| 751 |
+
current_X_dir = X_dir + '/p1_rot_' + str(i)
|
| 752 |
+
elif folder_name == 'p2':
|
| 753 |
+
current_X_dir = X_dir + '/p2_rot_' + str(i)
|
| 754 |
+
elif folder_name == 'real':
|
| 755 |
+
current_X_dir = X_dir + '/real_rot_' + str(i)
|
| 756 |
+
else:
|
| 757 |
+
print('error')
|
| 758 |
+
sys.exit()
|
| 759 |
+
if not os.path.exists(current_X_dir):
|
| 760 |
+
os.makedirs(current_X_dir)
|
| 761 |
+
|
| 762 |
+
for j in range(n):
|
| 763 |
+
# i = degrees[j]
|
| 764 |
+
if folder_name == 'real':
|
| 765 |
+
tmp_x = cv.imread(os.path.join(X_dir,
|
| 766 |
+
os.path.join(folder_name_x, x_aug_list[j])))
|
| 767 |
+
rot_x = rotated_img_extractor(x=tmp_x, gt=None, img_width=img_width,
|
| 768 |
+
img_height=img_height, i=i, two_data=False)
|
| 769 |
+
else:
|
| 770 |
+
tmp_x = cv.imread(os.path.join(X_dir,
|
| 771 |
+
os.path.join(folder_name, x_aug_list[j])))
|
| 772 |
+
rot_x = rotated_img_extractor(x=tmp_x, gt=None, img_width=img_width,
|
| 773 |
+
img_height=img_height, i=i, two_data=False)
|
| 774 |
+
|
| 775 |
+
cv.imwrite(os.path.join(current_X_dir, x_aug_list[j]), rot_x)
|
| 776 |
+
cv.imshow("rotated", rot_x)
|
| 777 |
+
cv.waitKey(450)
|
| 778 |
+
print("rotation with {} degrees fullfiled ".format(i))
|
| 779 |
+
cv.destroyAllWindows()
|
| 780 |
+
|
| 781 |
+
print("... rotation done in ", folder_name)
|
| 782 |
+
|
| 783 |
+
# flipping horizontally
|
| 784 |
+
if not imgs_flipped:
|
| 785 |
+
type_aug = '_flip'
|
| 786 |
+
dir_list = os.listdir(X_dir)
|
| 787 |
+
dir_list.sort()
|
| 788 |
+
|
| 789 |
+
for i in (dir_list):
|
| 790 |
+
X_list = os.listdir(os.path.join(X_dir, i))
|
| 791 |
+
X_list.sort()
|
| 792 |
+
save_dir_x = X_dir + '/' + str(i)+ type_aug
|
| 793 |
+
|
| 794 |
+
if not os.path.exists(save_dir_x):
|
| 795 |
+
os.makedirs(save_dir_x)
|
| 796 |
+
|
| 797 |
+
print("Working on the dir: ", os.path.join(X_dir, i), i)
|
| 798 |
+
for j in range(n):
|
| 799 |
+
x_tmp = cv.imread(os.path.join(X_dir, os.path.join(i, X_list[j])))
|
| 800 |
+
flip_x = np.fliplr(x_tmp)
|
| 801 |
+
|
| 802 |
+
cv.imshow("Flipping", x_tmp)
|
| 803 |
+
cv.waitKey(450)
|
| 804 |
+
cv.imwrite(os.path.join(save_dir_x, X_list[j]), flip_x)
|
| 805 |
+
|
| 806 |
+
print("End flipping file in {}".format(os.path.join(X_dir, i)))
|
| 807 |
+
|
| 808 |
+
cv.destroyAllWindows()
|
| 809 |
+
|
| 810 |
+
print("... Flipping data augmentation finished")
|
| 811 |
+
|
| 812 |
+
if not imgs_gamma_corrected:
|
| 813 |
+
gamma30 = '_ga30'
|
| 814 |
+
gamma60 = '_ga60'
|
| 815 |
+
dir_list = os.listdir(X_dir)
|
| 816 |
+
dir_list.sort()
|
| 817 |
+
for i in (dir_list):
|
| 818 |
+
X_list = os.listdir(os.path.join(X_dir, i))
|
| 819 |
+
X_list.sort()
|
| 820 |
+
save_dir_x30 = X_dir + '/' + str(i) + gamma30
|
| 821 |
+
save_dir_x60 = X_dir + '/' + str(i) + gamma60
|
| 822 |
+
|
| 823 |
+
if not os.path.exists(save_dir_x30):
|
| 824 |
+
os.makedirs(save_dir_x30)
|
| 825 |
+
if not os.path.exists(save_dir_x60):
|
| 826 |
+
os.makedirs(save_dir_x60)
|
| 827 |
+
|
| 828 |
+
print("Working on the dir: ", os.path.join(X_dir, i))
|
| 829 |
+
for j in range(n):
|
| 830 |
+
x_tmp = cv.imread(os.path.join(X_dir, os.path.join(i, X_list[j])))
|
| 831 |
+
x_tmp = normalization_data_01(x_tmp)
|
| 832 |
+
x_tmp = gamma_correction(x_tmp, 0.4040, False)
|
| 833 |
+
|
| 834 |
+
gam30_x = gamma_correction(x_tmp, 0.3030, True)
|
| 835 |
+
gam60_x = gamma_correction(x_tmp, 0.6060, True)
|
| 836 |
+
gam30_x = np.uint8(normalization_data_0255(gam30_x))
|
| 837 |
+
gam60_x = np.uint8(normalization_data_0255(gam60_x))
|
| 838 |
+
|
| 839 |
+
tmp_imgs = np.concatenate((gam30_x, gam60_x), axis=1)
|
| 840 |
+
|
| 841 |
+
cv.imshow("gamma ", tmp_imgs)
|
| 842 |
+
cv.waitKey(450)
|
| 843 |
+
cv.imwrite(os.path.join(save_dir_x30, X_list[j]), gam30_x)
|
| 844 |
+
cv.imwrite(os.path.join(save_dir_x60, X_list[j]), gam60_x)
|
| 845 |
+
|
| 846 |
+
print("End gamma correction, file in {}".format(os.path.join(X_dir, i)))
|
| 847 |
+
cv.destroyAllWindows()
|
| 848 |
+
print("... gamma correction data augmentation finished")
|
| 849 |
+
|
| 850 |
+
|
| 851 |
+
elif data_for == 'validation':
|
| 852 |
+
|
| 853 |
+
train_X_dir = args.dataset_dir + args.train_dataset + '/nir_valid'
|
| 854 |
+
|
| 855 |
+
x_list = os.listdir(os.path.join(train_X_dir, 'X_un'))
|
| 856 |
+
x_list.sort()
|
| 857 |
+
n = len(x_list)
|
| 858 |
+
if n == 0:
|
| 859 |
+
print('there is some inconsistence in the size of lists')
|
| 860 |
+
sys.exit()
|
| 861 |
+
# making 720x720 image size (splitting) ******************
|
| 862 |
+
if not imgs_splitted:
|
| 863 |
+
tmp_img = cv.imread(os.path.join(
|
| 864 |
+
os.path.join(train_X_dir, 'X_un'), x_list[0]))
|
| 865 |
+
img_width = tmp_img.shape[1]
|
| 866 |
+
img_height = tmp_img.shape[0]
|
| 867 |
+
|
| 868 |
+
for i in range(n):
|
| 869 |
+
x_tmp = cv.imread(os.path.join(
|
| 870 |
+
os.path.join(train_X_dir, 'X_un'), x_list[i]))
|
| 871 |
+
x_tmp1 = x_tmp[:, 0:img_height, :]
|
| 872 |
+
x_tmp2 = x_tmp[:, img_width - img_height:img_width, :]
|
| 873 |
+
|
| 874 |
+
cv.imwrite(os.path.join(train_X_dir, os.path.join('X/p1', x_list[i])), x_tmp1)
|
| 875 |
+
cv.imwrite(os.path.join(train_X_dir, os.path.join('X/p2', x_list[i])), x_tmp2)
|
| 876 |
+
print('saved image: ', x_list[i])
|
| 877 |
+
print('... validation split done')
|
| 878 |
+
|
| 879 |
+
# image rotation
|
| 880 |
+
if not imgs_rotated:
|
| 881 |
+
X_dir = args.dataset_dir + args.train_dataset + '/nir_valid'
|
| 882 |
+
|
| 883 |
+
# for p1 ***********
|
| 884 |
+
folder_name = 'p2' # choice [p1,p2,X_un] which are the source of files previously prepared
|
| 885 |
+
# firstly X_un is not used
|
| 886 |
+
folder_name_x = 'X_un'
|
| 887 |
+
if folder_name == 'p1':
|
| 888 |
+
x_aug_list = os.listdir(os.path.join(X_dir, 'X/p1'))
|
| 889 |
+
x_aug_list.sort()
|
| 890 |
+
elif folder_name == 'p2':
|
| 891 |
+
x_aug_list = os.listdir(os.path.join(X_dir, 'X/p2'))
|
| 892 |
+
x_aug_list.sort()
|
| 893 |
+
elif folder_name == 'X_un':
|
| 894 |
+
x_aug_list = os.listdir(os.path.join(X_dir, 'X_un'))
|
| 895 |
+
x_aug_list.sort()
|
| 896 |
+
else:
|
| 897 |
+
print("error reading folder name")
|
| 898 |
+
sys.exit()
|
| 899 |
+
|
| 900 |
+
# image size
|
| 901 |
+
tmp_img = cv.imread(os.path.join(X_dir,
|
| 902 |
+
os.path.join('X/' + folder_name, x_aug_list[1])))
|
| 903 |
+
img_width = tmp_img.shape[1]
|
| 904 |
+
img_height = tmp_img.shape[0]
|
| 905 |
+
|
| 906 |
+
for i in (degrees):
|
| 907 |
+
if folder_name == 'p1':
|
| 908 |
+
current_X_dir = X_dir + '/X/p1_rot_' + str(i)
|
| 909 |
+
elif folder_name == 'p2':
|
| 910 |
+
current_X_dir = X_dir + '/X/p2_rot_' + str(i)
|
| 911 |
+
elif folder_name == 'X_un':
|
| 912 |
+
current_X_dir = X_dir + 'X/un_rot_' + str(i)
|
| 913 |
+
else:
|
| 914 |
+
print('error')
|
| 915 |
+
sys.exit()
|
| 916 |
+
if not os.path.exists(current_X_dir):
|
| 917 |
+
os.makedirs(current_X_dir)
|
| 918 |
+
|
| 919 |
+
for j in range(n):
|
| 920 |
+
# i = degrees[j]
|
| 921 |
+
if folder_name == 'X_un':
|
| 922 |
+
tmp_x = cv.imread(
|
| 923 |
+
os.path.join(X_dir, os.path.join(folder_name_x, x_aug_list[j])))
|
| 924 |
+
else:
|
| 925 |
+
tmp_x = cv.imread(
|
| 926 |
+
os.path.join(X_dir, os.path.join('X/' + folder_name, x_aug_list[j])))
|
| 927 |
+
|
| 928 |
+
if i % 90 == 0:
|
| 929 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 930 |
+
rot_x = cv.warpAffine(tmp_x, adjus_M, (img_height, img_width))
|
| 931 |
+
|
| 932 |
+
elif i % 19 == 0:
|
| 933 |
+
if i == 57:
|
| 934 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 935 |
+
rot_x = cv.warpAffine(tmp_x, adjus_M, (img_height, img_width))
|
| 936 |
+
# cv.rectangle(rot_x, (100, 100), (720 - 100, 720 - 100), (0, 0, 255), (2))
|
| 937 |
+
rot_x = rot_x[100:720 - 100, 100:720 - 100, :]
|
| 938 |
+
# print("just for check 19: ", i, rot_x.shape)
|
| 939 |
+
elif i == 285:
|
| 940 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 941 |
+
rot_x = cv.warpAffine(tmp_x, adjus_M, (img_height, img_width))
|
| 942 |
+
# cv.rectangle(rot_x, (75, 75), (720 - 75, 720 - 75), (0, 0, 255), (2))
|
| 943 |
+
rot_x = rot_x[75:720 - 75, 75:720 - 75, :]
|
| 944 |
+
# print("just for check 19: ", i, rot_x.shape)
|
| 945 |
+
else:
|
| 946 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 947 |
+
rot_x = cv.warpAffine(tmp_x, adjus_M, (img_height, img_width))
|
| 948 |
+
# cv.rectangle(rot_x,(95,95),(720-95,720-95),(0,0,255),(2) )
|
| 949 |
+
rot_x = rot_x[95:720 - 95, 95:720 - 95, :]
|
| 950 |
+
# print("just for check 19: ", i, rot_x.shape)
|
| 951 |
+
|
| 952 |
+
elif i % 23 == 0:
|
| 953 |
+
if i == 161:
|
| 954 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 955 |
+
rot_x = cv.warpAffine(tmp_x, adjus_M, (img_height, img_width))
|
| 956 |
+
# cv.rectangle(rot_x,(85,85),(720-85,720-85),(0,0,255),(2) )
|
| 957 |
+
rot_x = rot_x[85:720 - 85, 85:720 - 85, :]
|
| 958 |
+
# print("just for check 23: ", i, rot_x.shape)
|
| 959 |
+
else:
|
| 960 |
+
adjus_M = cv.getRotationMatrix2D((img_width / 2, img_height / 2), i, 1)
|
| 961 |
+
rot_x = cv.warpAffine(tmp_x, adjus_M, (img_height, img_width))
|
| 962 |
+
# cv.rectangle(rot_x, (105, 105), (720 - 105, 720 - 105), (0, 0, 255), (2))
|
| 963 |
+
rot_x = rot_x[105:720 - 105, 105:720 - 105, :]
|
| 964 |
+
# print("just for check 23:", i, rot_x.shape)
|
| 965 |
+
else:
|
| 966 |
+
print('Error using degrees for rotation')
|
| 967 |
+
sys.exit()
|
| 968 |
+
cv.imwrite(os.path.join(current_X_dir, x_aug_list[j]), rot_x)
|
| 969 |
+
cv.imshow("rotated", rot_x)
|
| 970 |
+
cv.waitKey(350)
|
| 971 |
+
print("rotation with {} degrees fullfiled ".format(i))
|
| 972 |
+
cv.destroyAllWindows()
|
| 973 |
+
|
| 974 |
+
print("... rotation done in ", folder_name)
|
| 975 |
+
|
| 976 |
+
# flipping horizontally
|
| 977 |
+
if not imgs_flipped:
|
| 978 |
+
type_aug = 'flip_'
|
| 979 |
+
X_dir = args.dataset_dir + args.train_dataset + '/nir_valid/X'
|
| 980 |
+
dir_list = os.listdir(X_dir)
|
| 981 |
+
dir_list.sort()
|
| 982 |
+
|
| 983 |
+
for i in (dir_list):
|
| 984 |
+
X_list = os.listdir(os.path.join(X_dir, i))
|
| 985 |
+
X_list.sort()
|
| 986 |
+
save_dir_x = X_dir + '/' + type_aug + str(i)
|
| 987 |
+
|
| 988 |
+
if not os.path.exists(save_dir_x):
|
| 989 |
+
os.makedirs(save_dir_x)
|
| 990 |
+
|
| 991 |
+
print("Working on the dir: ", os.path.join(X_dir, i), i)
|
| 992 |
+
for j in range(n):
|
| 993 |
+
x_tmp = cv.imread(os.path.join(X_dir, os.path.join(i, X_list[j])))
|
| 994 |
+
flip_x = np.fliplr(x_tmp)
|
| 995 |
+
|
| 996 |
+
cv.imshow("rotated", x_tmp)
|
| 997 |
+
cv.waitKey(350)
|
| 998 |
+
cv.imwrite(os.path.join(save_dir_x, X_list[j]), flip_x)
|
| 999 |
+
|
| 1000 |
+
print("End flipping file in {}".format(os.path.join(X_dir, i)))
|
| 1001 |
+
|
| 1002 |
+
cv.destroyAllWindows()
|
| 1003 |
+
|
| 1004 |
+
print("... Flipping validation data augmentation finished")
|
| 1005 |
+
else:
|
| 1006 |
+
print("This part is not finished yet")
|
| 1007 |
+
else:
|
| 1008 |
+
|
| 1009 |
+
print("Error, just train and validation code have written")
|
| 1010 |
+
|
| 1011 |
+
def data_parser(args):
|
| 1012 |
+
|
| 1013 |
+
if args.model_state=='train':
|
| 1014 |
+
|
| 1015 |
+
train_files_name = args.train_list # dataset base dir
|
| 1016 |
+
|
| 1017 |
+
base_dir = os.path.join(args.dataset_dir, args.train_dataset,'edges') \
|
| 1018 |
+
if args.train_dataset.lower() == 'biped' else os.path.join(args.dataset_dir, args.train_dataset)
|
| 1019 |
+
|
| 1020 |
+
train_list_path = os.path.join(base_dir, train_files_name)
|
| 1021 |
+
|
| 1022 |
+
train_list = read_files_list(train_list_path)
|
| 1023 |
+
|
| 1024 |
+
train_samples = split_pair_names(args,train_list, base_dir=base_dir)
|
| 1025 |
+
n_train = len(train_samples)
|
| 1026 |
+
print_info(" Enterely training set-up from {}, size: {}".format(train_list_path, n_train))
|
| 1027 |
+
|
| 1028 |
+
all_train_ids = np.arange(n_train)
|
| 1029 |
+
np.random.shuffle(all_train_ids)
|
| 1030 |
+
|
| 1031 |
+
train_ids = all_train_ids[:int(args.train_split * len(train_list))]
|
| 1032 |
+
valid_ids = all_train_ids[int(args.train_split * len(train_list)):]
|
| 1033 |
+
|
| 1034 |
+
print_info("Training set-up from {}, size: {}".format(train_list_path, len(train_ids)))
|
| 1035 |
+
print_info("Validation set-up from {}, size: {}".format(train_list_path, len(valid_ids)))
|
| 1036 |
+
cache_info = {
|
| 1037 |
+
"files_path": train_samples,
|
| 1038 |
+
"n_files": n_train,
|
| 1039 |
+
"train_indices": train_ids,
|
| 1040 |
+
"validation_indices": valid_ids
|
| 1041 |
+
}
|
| 1042 |
+
return cache_info
|
| 1043 |
+
|
| 1044 |
+
# ************** for testing **********************
|
| 1045 |
+
elif args.model_state=='test':
|
| 1046 |
+
base_dir = os.path.join(args.dataset_dir,args.test_dataset,'edges')\
|
| 1047 |
+
if args.test_dataset.upper()=='BIPED' else os.path.join(args.dataset_dir,args.test_dataset)
|
| 1048 |
+
|
| 1049 |
+
if args.test_dataset.upper() == "BIPED":
|
| 1050 |
+
test_files_name = args.test_list
|
| 1051 |
+
test_list_path = os.path.join(base_dir,test_files_name)
|
| 1052 |
+
test_list = read_files_list(test_list_path)
|
| 1053 |
+
|
| 1054 |
+
test_samples = split_pair_names(args, test_list, base_dir)
|
| 1055 |
+
n_test = len(test_samples)
|
| 1056 |
+
print_info(" Enterely testing set-up from {}, size: {}".format(test_list_path, n_test))
|
| 1057 |
+
|
| 1058 |
+
test_ids = np.arange(n_test)
|
| 1059 |
+
# np.random.shuffle(test_ids)
|
| 1060 |
+
|
| 1061 |
+
print_info("testing set-up from {}, size: {}".format(test_list_path, len(test_ids)))
|
| 1062 |
+
cache_out = [test_samples, test_ids]
|
| 1063 |
+
|
| 1064 |
+
return cache_out
|
| 1065 |
+
|
| 1066 |
+
elif args.test_dataset == "BSDS":
|
| 1067 |
+
test_files_name = args.test_list
|
| 1068 |
+
test_list_path = os.path.join(args.dataset_dir + args.test_dataset,
|
| 1069 |
+
test_files_name)
|
| 1070 |
+
test_list = read_files_list(test_list_path)
|
| 1071 |
+
|
| 1072 |
+
test_samples = split_pair_names(args,test_list, args.dataset_dir + args.test_dataset)
|
| 1073 |
+
n_test = len(test_samples)
|
| 1074 |
+
print_info(" Enterely testing set-up from {}, size: {}".format(test_list_path, n_test))
|
| 1075 |
+
|
| 1076 |
+
test_ids = np.arange(n_test)
|
| 1077 |
+
# np.random.shuffle(test_ids)
|
| 1078 |
+
|
| 1079 |
+
print_info("testing set-up from {}, size: {}".format(test_list_path, len(test_ids)))
|
| 1080 |
+
cache_out = [test_samples, test_ids]
|
| 1081 |
+
return cache_out
|
| 1082 |
+
|
| 1083 |
+
else:
|
| 1084 |
+
# for NYUD
|
| 1085 |
+
test_files_name = args.test_list
|
| 1086 |
+
test_list_path = os.path.join(args.dataset_dir + args.test_dataset,
|
| 1087 |
+
test_files_name)
|
| 1088 |
+
test_list = read_files_list(test_list_path)
|
| 1089 |
+
|
| 1090 |
+
test_samples = split_pair_names(args,test_list, args.dataset_dir + args.test_dataset)
|
| 1091 |
+
n_test = len(test_samples)
|
| 1092 |
+
print_info(" Enterely testing set-up from {}, size: {}".format(test_list_path, n_test))
|
| 1093 |
+
|
| 1094 |
+
test_ids = np.arange(n_test)
|
| 1095 |
+
# np.random.shuffle(test_ids)
|
| 1096 |
+
|
| 1097 |
+
print_info("testing set-up from {}, size: {}".format(test_list_path, len(test_ids)))
|
| 1098 |
+
cache_out = [test_samples, test_ids]
|
| 1099 |
+
return cache_out
|
| 1100 |
+
else:
|
| 1101 |
+
print_error("The model state is just train and test")
|
| 1102 |
+
sys.exit()
|
| 1103 |
+
|
| 1104 |
+
# ___________batch management ___________
|
| 1105 |
+
def get_batch(arg,file_list, batch=None, use_batch=True):
|
| 1106 |
+
|
| 1107 |
+
if use_batch:
|
| 1108 |
+
file_names =[]
|
| 1109 |
+
images=[]
|
| 1110 |
+
edgemaps=[]
|
| 1111 |
+
for idx, b in enumerate(batch):
|
| 1112 |
+
x = cv.imread(file_list[b][0]) # Image.open(file_list[b][0])
|
| 1113 |
+
y = cv.imread(file_list[b][1]) # Image.open(file_list[b][1])
|
| 1114 |
+
if arg.model_state=='test':
|
| 1115 |
+
pass
|
| 1116 |
+
else:
|
| 1117 |
+
x = cv.resize(x, dsize=(arg.image_width,arg.image_height)) # x.resize((arg.image_width, arg.image_height))
|
| 1118 |
+
y = cv.resize(y,dsize=(arg.image_width, arg.image_height))# y.resize((arg.image_width, arg.image_height))
|
| 1119 |
+
# pay attention here
|
| 1120 |
+
x = np.array(x, dtype=np.float32)
|
| 1121 |
+
# x = x[:, :, arg.channel_swap] # while using opencv it is not necessary
|
| 1122 |
+
x -= arg.mean_pixel_values[0:3]
|
| 1123 |
+
|
| 1124 |
+
y = cv.cvtColor(y, cv.COLOR_BGR2GRAY)# np.array(y.convert('L'), dtype=np.float32)
|
| 1125 |
+
y = np.array(y, dtype=np.float32)
|
| 1126 |
+
if arg.train_dataset.lower()!='biped':
|
| 1127 |
+
y[y < 107] = 0 # first nothing second <50 third <30
|
| 1128 |
+
y[y >= 107] = 255.0
|
| 1129 |
+
# else:
|
| 1130 |
+
# y[y < 51] = 0 # first 100
|
| 1131 |
+
|
| 1132 |
+
if arg.target_regression:
|
| 1133 |
+
bin_y = y/255.0
|
| 1134 |
+
else:
|
| 1135 |
+
bin_y = np.zeros_like(y)
|
| 1136 |
+
bin_y[np.where(y)]=1
|
| 1137 |
+
|
| 1138 |
+
bin_y = bin_y if bin_y.ndim ==2 else bin_y[:,:,0]
|
| 1139 |
+
bin_y = np.expand_dims(bin_y,axis=2)
|
| 1140 |
+
|
| 1141 |
+
images.append(x)
|
| 1142 |
+
edgemaps.append(bin_y)
|
| 1143 |
+
file_names.append(file_list[b])
|
| 1144 |
+
|
| 1145 |
+
return images, edgemaps, file_names
|
| 1146 |
+
|
| 1147 |
+
else:
|
| 1148 |
+
# for testing re-coding is needed
|
| 1149 |
+
if arg.test_dataset=='BIPED' and (arg.model_state=='test' and arg.use_nir):
|
| 1150 |
+
x_nir = Image.open(file_list[0])
|
| 1151 |
+
x_rgb = Image.open(file_list[1])
|
| 1152 |
+
real_size = x_rgb.shape
|
| 1153 |
+
# y = Image.open(file_list[2])
|
| 1154 |
+
if not arg.image_width % 6 == 0 and arg.image_width > 1000:
|
| 1155 |
+
x_nir = x_nir.resize((arg.image_width, arg.image_height)) #--
|
| 1156 |
+
x_rgb = x_rgb.resize((arg.image_width, arg.image_height)) # --
|
| 1157 |
+
else:
|
| 1158 |
+
x_nir = x_nir.resize((arg.image_width, arg.image_height))
|
| 1159 |
+
x_rgb = x_rgb.resize((arg.image_width, arg.image_height))
|
| 1160 |
+
|
| 1161 |
+
# y = y.resize((arg.image_width, arg.image_height))
|
| 1162 |
+
|
| 1163 |
+
x_nir = x_nir.convert("L")
|
| 1164 |
+
# pay attention here
|
| 1165 |
+
x_nir = np.array(x_nir, dtype=np.float32)
|
| 1166 |
+
x_nir = np.expand_dims(x_nir, axis=2)
|
| 1167 |
+
x_rgb = np.array(x_rgb, dtype=np.float32)
|
| 1168 |
+
|
| 1169 |
+
x_rgb = x_rgb[:, :, arg.channel_swap]
|
| 1170 |
+
x = np.concatenate((x_rgb, x_nir), axis=2)
|
| 1171 |
+
x -= arg.mean_pixel_values
|
| 1172 |
+
# y = np.array(y.convert('L'), dtype=np.float32)
|
| 1173 |
+
# if arg.target_regression:
|
| 1174 |
+
# bin_y = y / 255.0
|
| 1175 |
+
# else:
|
| 1176 |
+
# bin_y = np.zeros_like(y)
|
| 1177 |
+
# bin_y[np.where(y)] = 1
|
| 1178 |
+
#
|
| 1179 |
+
# bin_y = bin_y if bin_y.ndim == 2 else bin_y[:, :, 0]
|
| 1180 |
+
# bin_y = np.expand_dims(bin_y, axis=2)
|
| 1181 |
+
images =x
|
| 1182 |
+
edgemaps = None
|
| 1183 |
+
file_info = (file_list[2], real_size)
|
| 1184 |
+
|
| 1185 |
+
else:
|
| 1186 |
+
x = cv.imread(file_list[0])
|
| 1187 |
+
y = cv.imread(file_list[1])
|
| 1188 |
+
real_size = x.shape
|
| 1189 |
+
|
| 1190 |
+
if arg.test_dataset.lower()=='biped' or arg.test_dataset.lower()=='multicue':
|
| 1191 |
+
pass
|
| 1192 |
+
else:
|
| 1193 |
+
x = cv.resize(x, dsize=(arg.image_width, arg.image_height))
|
| 1194 |
+
y = cv.resize(y, dsize=(arg.image_width, arg.image_height))
|
| 1195 |
+
x = np.array(x, dtype=np.float32)
|
| 1196 |
+
# x = x[:, :, arg.channel_swap] # while using opencv it is not necessary
|
| 1197 |
+
x -= arg.mean_pixel_values[:-1]
|
| 1198 |
+
y = cv.cvtColor(y, cv.COLOR_BGR2GRAY)
|
| 1199 |
+
y = np.array(y, dtype=np.float32)
|
| 1200 |
+
if arg.target_regression:
|
| 1201 |
+
bin_y = y / 255.0
|
| 1202 |
+
else:
|
| 1203 |
+
bin_y = np.zeros_like(y)
|
| 1204 |
+
bin_y[np.where(y)] = 1
|
| 1205 |
+
|
| 1206 |
+
bin_y = bin_y if bin_y.ndim == 2 else bin_y[:, :, 0]
|
| 1207 |
+
bin_y = np.expand_dims(bin_y, axis=2)
|
| 1208 |
+
|
| 1209 |
+
images = x
|
| 1210 |
+
edgemaps = bin_y
|
| 1211 |
+
file_info = (file_list[1],real_size)
|
| 1212 |
+
return images, edgemaps, file_info
|
| 1213 |
+
|
| 1214 |
+
def get_training_batch(arg, data_ids):
|
| 1215 |
+
train_ids = data_ids['train_indices']
|
| 1216 |
+
file_list= data_ids['files_path']
|
| 1217 |
+
batch_ids = np.random.choice(train_ids,arg.batch_size_train)
|
| 1218 |
+
|
| 1219 |
+
return get_batch(arg, file_list, batch_ids)
|
| 1220 |
+
|
| 1221 |
+
def get_validation_batch(arg, data_ids):
|
| 1222 |
+
if arg.use_nir:
|
| 1223 |
+
valid_ids = data_ids['validation_indices']
|
| 1224 |
+
file_list = data_ids['files_path']
|
| 1225 |
+
batch_ids = np.random.choice(valid_ids, arg.batch_size_val)
|
| 1226 |
+
else:
|
| 1227 |
+
valid_ids = data_ids['validation_indices']
|
| 1228 |
+
file_list= data_ids['files_path']
|
| 1229 |
+
batch_ids = np.random.choice(valid_ids,arg.batch_size_val)
|
| 1230 |
+
return get_batch(arg,file_list,batch_ids)
|
| 1231 |
+
|
| 1232 |
+
def get_testing_batch(arg,list_ids, use_batch=True, i=None):
|
| 1233 |
+
if use_batch:
|
| 1234 |
+
test_ids = list_ids[1]
|
| 1235 |
+
file_list = list_ids[0]
|
| 1236 |
+
batch_ids = test_ids[i:i + arg.batch_size_test]
|
| 1237 |
+
return get_batch(arg,file_list,batch_ids)
|
| 1238 |
+
else:
|
| 1239 |
+
return get_batch(arg, list_ids[0],list_ids[1], use_batch=False)
|
| 1240 |
+
|
| 1241 |
+
def open_images(file_list):
|
| 1242 |
+
if len(file_list)>2 and not len(file_list)==3:
|
| 1243 |
+
imgs=[]
|
| 1244 |
+
file_names = []
|
| 1245 |
+
for i in range(len(file_list)):
|
| 1246 |
+
tmp = Image.open(file_list[i])
|
| 1247 |
+
imgs.append(tmp)
|
| 1248 |
+
file_names.append(file_list[i])
|
| 1249 |
+
|
| 1250 |
+
elif len(file_list)>2 and len(file_list)==3:
|
| 1251 |
+
|
| 1252 |
+
imgs = Image.open(file_list[2])
|
| 1253 |
+
file_names = file_list
|
| 1254 |
+
else:
|
| 1255 |
+
imgs = Image.open(file_list[1])
|
| 1256 |
+
file_names= file_list
|
| 1257 |
+
|
| 1258 |
+
return imgs, file_names
|
| 1259 |
+
|
| 1260 |
+
# for testing on single images
|
| 1261 |
+
def get_single_image(args,file_path=None):
|
| 1262 |
+
|
| 1263 |
+
if file_path is None:
|
| 1264 |
+
imgs_name = ["CLASSIC", None]
|
| 1265 |
+
img_dir = 'data' if args.test_dataset in imgs_name else os.path.join(args.dataset_dir, args.test_dataset)
|
| 1266 |
+
file_list = os.listdir(img_dir)
|
| 1267 |
+
data =[]
|
| 1268 |
+
for i in file_list:
|
| 1269 |
+
data.append(os.path.join(img_dir,i))
|
| 1270 |
+
return data
|
| 1271 |
+
else:
|
| 1272 |
+
img = cv.imread(file_path)
|
| 1273 |
+
h,w,c=img.shape
|
| 1274 |
+
x = np.array(img, dtype=np.float32)
|
| 1275 |
+
if h==args.image_height and w==args.image_width:
|
| 1276 |
+
pass
|
| 1277 |
+
else:
|
| 1278 |
+
x = cv.resize(x, dsize=(args.image_width, args.image_height))
|
| 1279 |
+
# x = x[:, :, arg.channel_swap] # while using opencv it is not necessary
|
| 1280 |
+
x -= args.mean_pixel_values[:-1]
|
| 1281 |
+
img_info = (file_path,img.shape)
|
| 1282 |
+
return x, img_info
|
| 1283 |
+
|
| 1284 |
+
def visualize_result(imgs_list, arg):
|
| 1285 |
+
"""
|
| 1286 |
+
function for tensorflow results
|
| 1287 |
+
:param imgs_list: a list of prediction, gt and input data
|
| 1288 |
+
:param arg:
|
| 1289 |
+
:return: one image with the whole of imgs_list data
|
| 1290 |
+
"""
|
| 1291 |
+
n_imgs = len(imgs_list)
|
| 1292 |
+
data_list =[]
|
| 1293 |
+
for i in range(n_imgs):
|
| 1294 |
+
tmp = imgs_list[i]
|
| 1295 |
+
if len(tmp.shape)==3 or len(tmp.shape)==2:
|
| 1296 |
+
if len(tmp.shape)==2:
|
| 1297 |
+
tmp = np.uint8(image_normalization(tmp))
|
| 1298 |
+
tmp=cv.cvtColor(tmp, cv.COLOR_GRAY2BGR)
|
| 1299 |
+
tmp = cv.bitwise_not(tmp)
|
| 1300 |
+
else:
|
| 1301 |
+
if tmp.shape[-1]==3:
|
| 1302 |
+
tmp=restore_rgb([arg.channel_swap,arg.mean_pixel_values[:3]],tmp)
|
| 1303 |
+
tmp = np.uint8(image_normalization(tmp))
|
| 1304 |
+
else:
|
| 1305 |
+
tmp = np.squeeze(tmp)
|
| 1306 |
+
tmp = np.uint8(image_normalization(tmp))
|
| 1307 |
+
tmp = cv.cvtColor(tmp, cv.COLOR_GRAY2BGR)
|
| 1308 |
+
tmp = cv.bitwise_not(tmp)
|
| 1309 |
+
else:
|
| 1310 |
+
tmp= np.squeeze(tmp)
|
| 1311 |
+
if len(tmp.shape) == 2:
|
| 1312 |
+
tmp = np.uint8(image_normalization(tmp))
|
| 1313 |
+
tmp = cv.bitwise_not(tmp)
|
| 1314 |
+
tmp = cv.cvtColor(tmp, cv.COLOR_GRAY2BGR)
|
| 1315 |
+
else:
|
| 1316 |
+
tmp = np.uint8(image_normalization(tmp))
|
| 1317 |
+
data_list.append(tmp)
|
| 1318 |
+
img = data_list[0]
|
| 1319 |
+
if n_imgs % 2 == 0:
|
| 1320 |
+
imgs = np.zeros((img.shape[0] * 2 + 10, img.shape[1] * (n_imgs // 2) + ((n_imgs // 2 - 1) * 5), 3))
|
| 1321 |
+
else:
|
| 1322 |
+
imgs = np.zeros((img.shape[0] * 2 + 10, img.shape[1] * ((1 + n_imgs) // 2) + ((n_imgs // 2) * 5), 3))
|
| 1323 |
+
n_imgs += 1
|
| 1324 |
+
|
| 1325 |
+
k=0
|
| 1326 |
+
imgs = np.uint8(imgs)
|
| 1327 |
+
i_step = img.shape[0]+10
|
| 1328 |
+
j_step = img.shape[1]+5
|
| 1329 |
+
for i in range(2):
|
| 1330 |
+
for j in range(n_imgs//2):
|
| 1331 |
+
if k<len(data_list):
|
| 1332 |
+
imgs[i*i_step:i*i_step+img.shape[0],j*j_step:j*j_step+img.shape[1],:]=data_list[k]
|
| 1333 |
+
k+=1
|
| 1334 |
+
else:
|
| 1335 |
+
pass
|
| 1336 |
+
return imgs
|
legacy/utls/losses.py
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
import tensorflow as tf
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
def sigmoid_cross_entropy_balanced(logits, label, name='cross_entrony_loss'):
|
| 6 |
+
"""
|
| 7 |
+
Initially proposed in: 'Holistically-Nested Edge Detection (CVPR 15)'
|
| 8 |
+
Implements Equation [2] in https://arxiv.org/pdf/1504.06375.pdf
|
| 9 |
+
Compute edge pixels for each training sample and set as pos_weights to
|
| 10 |
+
tf.nn.weighted_cross_entropy_with_logits
|
| 11 |
+
"""
|
| 12 |
+
y = tf.cast(label, tf.float32)
|
| 13 |
+
|
| 14 |
+
count_neg = tf.reduce_sum(1.-y)
|
| 15 |
+
count_pos = tf.reduce_sum(y)
|
| 16 |
+
# Equation [2]
|
| 17 |
+
beta = count_neg / (count_neg + count_pos)
|
| 18 |
+
|
| 19 |
+
# Equation [2] divide by 1 - beta
|
| 20 |
+
pos_weight = beta / (1 - beta)
|
| 21 |
+
cost = tf.nn.weighted_cross_entropy_with_logits(logits=logits, targets=y, pos_weight=pos_weight)
|
| 22 |
+
# cost = tf.
|
| 23 |
+
# Multiply by 1 - beta
|
| 24 |
+
cost = tf.reduce_mean(cost * (1 - beta))
|
| 25 |
+
|
| 26 |
+
# check if image has no edge pixels return 0 else return complete error function
|
| 27 |
+
return tf.where(tf.equal(count_pos, 0.0), 0.0, cost, name=name)
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
# def class_balanced_cross_entropy_with_logits(logits,label,name='class_ballanced_cross_entropy'):
|
| 31 |
+
#
|
| 32 |
+
# # Initialy proposed in: 'Holistically-Nested Edge Detection (CVPR 15)'
|
| 33 |
+
# with tf.name_scope(name) as scope:
|
| 34 |
+
# logits= tf.cast(logits, tf.float32)
|
| 35 |
+
# label = tf.cast(label, tf.float32)
|
| 36 |
+
#
|
| 37 |
+
# n_positives = tf.reduce_sum(label)
|
| 38 |
+
# n_negatives = tf.reduce_sum(1.0-label)
|
| 39 |
+
#
|
| 40 |
+
# beta = n_negatives/(n_negatives+n_positives)
|
| 41 |
+
# pos_weight = beta / (1-beta)
|
| 42 |
+
# check_weight = tf.identity(beta,name='check')
|
| 43 |
+
#
|
| 44 |
+
# cost = tf.nn.weighted_cross_entropy_with_logits(targets=label,logits=logits,pos_weight=pos_weight)
|
| 45 |
+
# loss = tf.reduce_mean((1-beta)*cost)
|
| 46 |
+
#
|
| 47 |
+
# return tf.where(tf.equal(beta,1.0),0.0,loss)
|
legacy/utls/utls.py
ADDED
|
@@ -0,0 +1,385 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
""" Utilities
|
| 2 |
+
|
| 3 |
+
"""
|
| 4 |
+
import numpy as np
|
| 5 |
+
import time
|
| 6 |
+
from termcolor import colored
|
| 7 |
+
import os,glob
|
| 8 |
+
import h5py
|
| 9 |
+
|
| 10 |
+
def get_model_trained_name(sess=None,data_dir=None, last_update=True):
|
| 11 |
+
|
| 12 |
+
if sess is not None or data_dir is not None:
|
| 13 |
+
path = os.path.join(data_dir,'*.ckpt')
|
| 14 |
+
if last_update:
|
| 15 |
+
mfiles= glob.glob(path)
|
| 16 |
+
last_file=max(mfiles,key=os.path.getctime)
|
| 17 |
+
return os.path.join(path,last_file)
|
| 18 |
+
else:
|
| 19 |
+
print('Not performet yet')
|
| 20 |
+
|
| 21 |
+
def gamma_correction(i, g,gamma=True):
|
| 22 |
+
"""Gamma correction
|
| 23 |
+
This function is for gamma corrections and de-correction 0.4040 0.3030 0.6060
|
| 24 |
+
:param i: image data
|
| 25 |
+
:param g: gamma value
|
| 26 |
+
:param gamma: if true do gamma correction if does not degamma correction
|
| 27 |
+
:return:if gamma gamma corrected image else image without gamma correction
|
| 28 |
+
"""
|
| 29 |
+
i = np.float32(i)
|
| 30 |
+
if gamma:
|
| 31 |
+
img=i**g
|
| 32 |
+
else:
|
| 33 |
+
img=i**(1/g)
|
| 34 |
+
return img
|
| 35 |
+
|
| 36 |
+
def image_normalization(img, img_min=0, img_max=255):
|
| 37 |
+
""" Image normalization given a minimum and maximum
|
| 38 |
+
|
| 39 |
+
This is a typical image normalization function
|
| 40 |
+
where the minimum and maximum of the image is needed
|
| 41 |
+
source: https://en.wikipedia.org/wiki/Normalization_(image_processing)
|
| 42 |
+
:param img: an image could be gray scale or color
|
| 43 |
+
:param img_min: for default is 0
|
| 44 |
+
:param img_max: for default is 255
|
| 45 |
+
:return: a normalized image given a scale
|
| 46 |
+
"""
|
| 47 |
+
img = np.float32(img)
|
| 48 |
+
epsilon=1e-12 # whenever an inconsistent image
|
| 49 |
+
img = (img-np.min(img))*(img_max-img_min)/((np.max(img)-np.min(img))+epsilon)+img_min
|
| 50 |
+
return img
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
def normalization_data_0255(data):
|
| 54 |
+
"""
|
| 55 |
+
data normalization in 0 till 1 range
|
| 56 |
+
:param data:
|
| 57 |
+
:return:
|
| 58 |
+
"""
|
| 59 |
+
epsilon = 1e-12
|
| 60 |
+
if not len(data.shape)==2:
|
| 61 |
+
n_imgs = data.shape[0]
|
| 62 |
+
# data = np.float32(data)
|
| 63 |
+
if data.shape[-1]==3 and len(data.shape)==3:
|
| 64 |
+
data = ((data - np.min(data)) * 255 / ((np.max(data) - np.min(data)) + epsilon))
|
| 65 |
+
# data = ((data - np.min(data)) * 254 / (np.max(data) - np.min(data)))+1
|
| 66 |
+
|
| 67 |
+
elif data.shape[-1]==3 and len(data.shape)==4:
|
| 68 |
+
for i in range(n_imgs):
|
| 69 |
+
img = data[i,...]
|
| 70 |
+
data[i,:,:,:] = ((img - np.min(img)) * 255 / ((np.max(img) - np.min(img))+epsilon))
|
| 71 |
+
# print("Data normalized with:", data.shape[-1], "channels")
|
| 72 |
+
elif data.shape[-1]>3 or len(data.shape)>=4:
|
| 73 |
+
print('error normalizin 0-255 line 30')
|
| 74 |
+
else:
|
| 75 |
+
print('error normalizin 0-255 line 32')
|
| 76 |
+
|
| 77 |
+
return data
|
| 78 |
+
elif len(data.shape)==2:
|
| 79 |
+
# data = ((data-np.min(data))*255/(np.max(data)-np.min(data)))
|
| 80 |
+
data = ((data-np.min(data))*255/((np.max(data) - np.min(data)) + epsilon))
|
| 81 |
+
|
| 82 |
+
return data
|
| 83 |
+
else:
|
| 84 |
+
print('error normalization 0-255')
|
| 85 |
+
|
| 86 |
+
def normalization_data_01(data):
|
| 87 |
+
"""
|
| 88 |
+
data normalization in 0 till 1 range
|
| 89 |
+
:param data:
|
| 90 |
+
:return:
|
| 91 |
+
"""
|
| 92 |
+
epsilon = 1e-12
|
| 93 |
+
if np.sum(np.isnan(data))>0:
|
| 94 |
+
print('NaN detected before Normalization')
|
| 95 |
+
return 'variable has NaN values'
|
| 96 |
+
if len(data.shape)>3:
|
| 97 |
+
n_imgs = data.shape[0]
|
| 98 |
+
data = np.float32(data)
|
| 99 |
+
if data.shape[-1]==3:
|
| 100 |
+
for i in range(n_imgs):
|
| 101 |
+
img = data[i,:,:,:]
|
| 102 |
+
data[i,:,:,:] = ((img - np.min(img)) * 1 / ((np.max(img) - np.min(img))+epsilon))
|
| 103 |
+
|
| 104 |
+
elif data.shape[-1]==4:
|
| 105 |
+
print('it is a little naive, check it in line 64 seg utils.py')
|
| 106 |
+
for i in range(n_imgs):
|
| 107 |
+
nir = data[i, :, :, -1]
|
| 108 |
+
nir = ((nir - np.min(nir)) * 1 / ((np.max(nir) - np.min(nir)) + epsilon))
|
| 109 |
+
img = data[i, :, :, 0:3]
|
| 110 |
+
img = ((img - np.min(img)) * 1 / ((np.max(img) - np.min(img)) + epsilon))
|
| 111 |
+
data[i, :, :, 0:3] = img
|
| 112 |
+
data[i, :, :, -1] = nir
|
| 113 |
+
elif data.shape[-1]==2:
|
| 114 |
+
#normalization according to channels
|
| 115 |
+
print('check line 70 utils_seg.py')
|
| 116 |
+
for i in range(n_imgs):
|
| 117 |
+
im = data[i,:,:,0]
|
| 118 |
+
N = data[i,:,:,-1]
|
| 119 |
+
data[i,:,:,0]= ((im-np.min(im))*1/(np.max(im)-np.min(im)))
|
| 120 |
+
data[i, :, :, -1] = ((N - np.min(N)) * 1 / (np.max(N) - np.min(N)))
|
| 121 |
+
|
| 122 |
+
elif data.shape[-1]==1:
|
| 123 |
+
for i in range(n_imgs):
|
| 124 |
+
img = data[i, :, :, 0]
|
| 125 |
+
data[i, :, :, 0] = ((img - np.min(img)) * 1 / ((np.max(img) - np.min(img))+epsilon))
|
| 126 |
+
else:
|
| 127 |
+
print("error normalizing line 83")
|
| 128 |
+
if np.sum(np.isnan(data)) > 0:
|
| 129 |
+
print('NaN detected after normalization')
|
| 130 |
+
return 'variable has NaN values'
|
| 131 |
+
return data
|
| 132 |
+
|
| 133 |
+
else:
|
| 134 |
+
if np.max(data) ==0 and np.min(data)==0:
|
| 135 |
+
return data
|
| 136 |
+
if np.sum(np.isnan(data)) > 0:
|
| 137 |
+
print('NaN detected before normalization')
|
| 138 |
+
return 'variable has NaN values'
|
| 139 |
+
|
| 140 |
+
data = ((data - np.min(data)) * 1 / ((np.max(data) - np.min(data))+epsilon))
|
| 141 |
+
if np.sum(np.isnan(data)) > 0:
|
| 142 |
+
print('NaN detected after normalization')
|
| 143 |
+
return 'variable has NaN values'
|
| 144 |
+
return data
|
| 145 |
+
|
| 146 |
+
# _________ text visualization ____________
|
| 147 |
+
def get_local_time():
|
| 148 |
+
return time.strftime("%d %b %Y %Hh%Mm%Ss", time.localtime())
|
| 149 |
+
|
| 150 |
+
def print_info(info_string, quite=False):
|
| 151 |
+
|
| 152 |
+
info = '[{0}][INFO]{1}'.format(get_local_time(), info_string)
|
| 153 |
+
print(colored(info, 'green'))
|
| 154 |
+
|
| 155 |
+
def print_error(error_string):
|
| 156 |
+
|
| 157 |
+
error = '[{0}][ERROR] {1}'.format(get_local_time(), error_string)
|
| 158 |
+
print (colored(error, 'red'))
|
| 159 |
+
|
| 160 |
+
def print_warning(warning_string):
|
| 161 |
+
|
| 162 |
+
warning = '[{0}][WARNING] {1}'.format(get_local_time(), warning_string)
|
| 163 |
+
|
| 164 |
+
print (colored(warning, 'blue'))
|
| 165 |
+
# ___________ End text visualization
|
| 166 |
+
|
| 167 |
+
# ___________ read list of files
|
| 168 |
+
def read_files_list(list_path,dataset_name=None):
|
| 169 |
+
mfiles = open(list_path)
|
| 170 |
+
file_names = mfiles.readlines()
|
| 171 |
+
mfiles.close()
|
| 172 |
+
|
| 173 |
+
file_names = [f.strip() for f in file_names]
|
| 174 |
+
return file_names
|
| 175 |
+
|
| 176 |
+
def split_pair_names(opts, file_names, base_dir=None):
|
| 177 |
+
# If base_dir is None, it assume that the list have the complete image source
|
| 178 |
+
if opts.model_state=='train':
|
| 179 |
+
|
| 180 |
+
if base_dir==None:
|
| 181 |
+
file_names =[c.split(' ') for c in file_names]
|
| 182 |
+
else:
|
| 183 |
+
if opts.train_dataset.lower()=='biped':
|
| 184 |
+
x_base_dir=os.path.join(base_dir,'imgs',opts.model_state)
|
| 185 |
+
y_base_dir =os.path.join(base_dir,'edge_maps',opts.model_state)
|
| 186 |
+
file_names = [c.split(' ') for c in file_names]
|
| 187 |
+
file_names = [(os.path.join(x_base_dir, c[0]),
|
| 188 |
+
os.path.join(y_base_dir, c[1])) for c in file_names]
|
| 189 |
+
else:
|
| 190 |
+
file_names = [c.split(' ') for c in file_names]
|
| 191 |
+
file_names = [(os.path.join(base_dir, c[0]),
|
| 192 |
+
os.path.join(base_dir, c[1])) for c in file_names]
|
| 193 |
+
return file_names
|
| 194 |
+
else:
|
| 195 |
+
# ******************* for data testing ****************************
|
| 196 |
+
if base_dir == None:
|
| 197 |
+
file_names = [c.split(' ') for c in file_names]
|
| 198 |
+
else:
|
| 199 |
+
if opts.test_dataset.lower() == 'biped':
|
| 200 |
+
x_base_dir = os.path.join(base_dir,'imgs', opts.model_state)
|
| 201 |
+
y_base_dir = os.path.join(base_dir,'edge_maps', opts.model_state)
|
| 202 |
+
file_names = [c.split(' ') for c in file_names]
|
| 203 |
+
file_names = [(os.path.join(x_base_dir, c[0]),
|
| 204 |
+
os.path.join(y_base_dir, c[1])) for c in file_names]
|
| 205 |
+
else:
|
| 206 |
+
file_names = [c.split(' ') for c in file_names]
|
| 207 |
+
file_names = [(os.path.join(base_dir, c[0]),
|
| 208 |
+
os.path.join(base_dir, c[1])) for c in file_names]
|
| 209 |
+
|
| 210 |
+
return file_names
|
| 211 |
+
# ____________ End reading files list
|
| 212 |
+
|
| 213 |
+
# _____________ H5 file manager _________
|
| 214 |
+
|
| 215 |
+
def h5_reader(path):
|
| 216 |
+
""" Read H5 file
|
| 217 |
+
Read .h5 file format data h5py <<.File>>
|
| 218 |
+
:param path:file path of desired file
|
| 219 |
+
:return: dataset -> contain images data for training;
|
| 220 |
+
label -> contain training label values (ground truth)
|
| 221 |
+
"""
|
| 222 |
+
with h5py.File(path, 'r') as hf:
|
| 223 |
+
n_variables = len(list(hf.keys()))
|
| 224 |
+
# choice = True # write
|
| 225 |
+
if n_variables==3:
|
| 226 |
+
data = np.array(hf.get('data'))
|
| 227 |
+
label = np.array(hf.get('label'))
|
| 228 |
+
test = np.array(hf.get('test'))
|
| 229 |
+
elif n_variables==2:
|
| 230 |
+
|
| 231 |
+
data = np.array(hf.get('data'))
|
| 232 |
+
label = np.array(hf.get('label'))
|
| 233 |
+
test=None
|
| 234 |
+
elif n_variables == 1:
|
| 235 |
+
data = np.array(hf.get('data'))
|
| 236 |
+
label=None
|
| 237 |
+
test=None
|
| 238 |
+
else:
|
| 239 |
+
data = None
|
| 240 |
+
label = None
|
| 241 |
+
test = None
|
| 242 |
+
print("Error reading path: ",path)
|
| 243 |
+
|
| 244 |
+
print(n_variables, " vars opened from: ", path)
|
| 245 |
+
return data, label, test
|
| 246 |
+
|
| 247 |
+
def save_h5_data(savepath,data, label, predi = None, data_name=None,
|
| 248 |
+
label_name=None, predi_name=None):
|
| 249 |
+
if data_name==None or label_name==None:
|
| 250 |
+
if np.any(predi == None):
|
| 251 |
+
|
| 252 |
+
with h5py.File(savepath, 'w') as hf:
|
| 253 |
+
hf.create_dataset('data', data=data)
|
| 254 |
+
hf.create_dataset('label', data=label)
|
| 255 |
+
print("Data [", data.shape, "and label ", label.shape, "] saved in: ", savepath)
|
| 256 |
+
else:
|
| 257 |
+
with h5py.File(savepath, 'w') as hf:
|
| 258 |
+
hf.create_dataset('data', data=data)
|
| 259 |
+
hf.create_dataset('label', data=label)
|
| 260 |
+
hf.create_dataset('predi', data=predi)
|
| 261 |
+
print("Input data [", data.shape, ", label ", label.shape, "and predi ", predi.shape,"] saved in: ", savepath)
|
| 262 |
+
|
| 263 |
+
|
| 264 |
+
else:
|
| 265 |
+
with h5py.File(savepath, 'w') as hf:
|
| 266 |
+
hf.create_dataset(data_name, data=data)
|
| 267 |
+
hf.create_dataset(label_name, data=label)
|
| 268 |
+
hf.create_dataset(predi_name,data=predi)
|
| 269 |
+
print("[",data_name, data.shape, ", ",
|
| 270 |
+
label_name, label.shape," and ",predi_name, predi.shape, "] saved in: ", savepath)
|
| 271 |
+
|
| 272 |
+
def save_variable_h5(savepath, data):
|
| 273 |
+
|
| 274 |
+
with h5py.File(savepath, 'w') as hf:
|
| 275 |
+
hf.create_dataset('data', data=data)
|
| 276 |
+
|
| 277 |
+
print("Data [", len(data), "] saved in: ", savepath)
|
| 278 |
+
# ___________ End h5 file manager ____________
|
| 279 |
+
|
| 280 |
+
# ____________ Restoring RGB former values _______
|
| 281 |
+
|
| 282 |
+
def restore_rgb(config,I):
|
| 283 |
+
"""
|
| 284 |
+
:param config: [args.channel_swap, args.mean_pixel_value]
|
| 285 |
+
:param I: and image or a set of images
|
| 286 |
+
:return: an image or a set of images restored
|
| 287 |
+
"""
|
| 288 |
+
if len(I)>3 and not type(I)==np.ndarray:
|
| 289 |
+
I =np.array(I)
|
| 290 |
+
I = I[:,:,:,0:3]
|
| 291 |
+
n = I.shape[0]
|
| 292 |
+
for i in range(n):
|
| 293 |
+
x = I[i,...]
|
| 294 |
+
x = np.array(x, dtype=np.float32)
|
| 295 |
+
x += config[1]
|
| 296 |
+
x = x[:, :, config[0]]
|
| 297 |
+
x = normalization_data_0255(x)
|
| 298 |
+
I[i,:,:,:]=x
|
| 299 |
+
elif len(I.shape)==3 and I.shape[-1]==3:
|
| 300 |
+
I = np.array(I, dtype=np.float32)
|
| 301 |
+
I += config[1]
|
| 302 |
+
I = I[:, :, config[0]]
|
| 303 |
+
I = normalization_data_0255(I)
|
| 304 |
+
else:
|
| 305 |
+
print_error("Sorry the input data size is out of our configuration")
|
| 306 |
+
print_info("The enterely I data {} restored".format(I.shape))
|
| 307 |
+
return I
|
| 308 |
+
|
| 309 |
+
def restore_edgemap(config,I):
|
| 310 |
+
""" Not finished coding ***
|
| 311 |
+
:param config: args.target_regression = True or False
|
| 312 |
+
:param I: input image data
|
| 313 |
+
:return: restored image data
|
| 314 |
+
"""
|
| 315 |
+
print_error("Sorry this function is not ready")
|
| 316 |
+
if len(I.shape)>3 and I.shape[3]==1:
|
| 317 |
+
n = I.shape[0]
|
| 318 |
+
for i in range(n):
|
| 319 |
+
y=I[i,...]
|
| 320 |
+
elif len(I.shape)==3 and I.shape[-1]==1:
|
| 321 |
+
|
| 322 |
+
I = np.array(I.convert('L'), dtype=np.float32)
|
| 323 |
+
if config:
|
| 324 |
+
bin_I = I / 255.0
|
| 325 |
+
else:
|
| 326 |
+
bin_I = np.zeros_like(I)
|
| 327 |
+
bin_I[np.where(I)] = 1
|
| 328 |
+
|
| 329 |
+
bin_I = bin_I if bin_I.ndim == 2 else bin_I[:, :, 0]
|
| 330 |
+
bin_y = np.expand_dims(bin_I, axis=2)
|
| 331 |
+
else:
|
| 332 |
+
print_error("Sorry the input data size is out of our configuration")
|
| 333 |
+
return I
|
| 334 |
+
|
| 335 |
+
def tensor_norm_01(data):
|
| 336 |
+
"""
|
| 337 |
+
tensor means that the size image is [batch-size,img_width, img_height, num_channels]
|
| 338 |
+
:param data:
|
| 339 |
+
:return:
|
| 340 |
+
"""
|
| 341 |
+
data = np.array(data)
|
| 342 |
+
if np.sum(np.isnan(data))>0:
|
| 343 |
+
print('NaN detected before Normalization')
|
| 344 |
+
return 'variable has NaN values'
|
| 345 |
+
if len(data.shape)>3:
|
| 346 |
+
n_imgs = data.shape[0]
|
| 347 |
+
data = np.float32(data)
|
| 348 |
+
if data.shape[-1]==3:
|
| 349 |
+
for i in range(n_imgs):
|
| 350 |
+
img = data[i,:,:,:]
|
| 351 |
+
data[i,:,:,:] = image_normalization(img,img_min=0,img_max=1)
|
| 352 |
+
|
| 353 |
+
elif data.shape[-1]==4:
|
| 354 |
+
print('it is a little naive, check it in line 64 seg utils.py')
|
| 355 |
+
for i in range(n_imgs):
|
| 356 |
+
nir = data[i, :, :, -1]
|
| 357 |
+
nir = image_normalization(nir,img_min=0,img_max=1)
|
| 358 |
+
img = data[i, :, :, 0:3]
|
| 359 |
+
img = image_normalization(img,img_min=0,img_max=1)
|
| 360 |
+
data[i, :, :, 0:3] = img
|
| 361 |
+
data[i, :, :, -1] = nir
|
| 362 |
+
elif data.shape[-1]==2:
|
| 363 |
+
#normalization according to channels
|
| 364 |
+
print('check line 70 utils_seg.py')
|
| 365 |
+
for i in range(n_imgs):
|
| 366 |
+
im = data[i,:,:,0]
|
| 367 |
+
N = data[i,:,:,-1]
|
| 368 |
+
data[i,:,:,0]= image_normalization(im,img_min=0,img_max=1)
|
| 369 |
+
data[i, :, :, -1] = image_normalization(N,img_min=0,img_max=1)
|
| 370 |
+
|
| 371 |
+
elif data.shape[-1]==1:
|
| 372 |
+
x=[]
|
| 373 |
+
for i in range(n_imgs):
|
| 374 |
+
img = data[i, :, :, 0]
|
| 375 |
+
img= image_normalization(img,img_min=0,img_max=1)
|
| 376 |
+
x.append(img)
|
| 377 |
+
data=x
|
| 378 |
+
else:
|
| 379 |
+
print("error normalizing line 83")
|
| 380 |
+
if np.sum(np.isnan(data)) > 0:
|
| 381 |
+
print('NaN detected after normalization')
|
| 382 |
+
return 'variable has NaN values'
|
| 383 |
+
return data
|
| 384 |
+
else:
|
| 385 |
+
print('Please use image_normalization() function')
|
losses.py
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
import torch.nn.functional as F
|
| 3 |
+
from dexi_utils import *
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
def hed_loss2(inputs, targets, l_weight=1.1):
|
| 7 |
+
# bdcn loss with the rcf approach
|
| 8 |
+
targets = targets.long()
|
| 9 |
+
mask = targets.float()
|
| 10 |
+
num_positive = torch.sum((mask > 0.1).float()).float()
|
| 11 |
+
num_negative = torch.sum((mask <= 0.).float()).float()
|
| 12 |
+
|
| 13 |
+
mask[mask > 0.1] = 1.0 * num_negative / (num_positive + num_negative)
|
| 14 |
+
mask[mask <= 0.] = 1.1 * num_positive / (num_positive + num_negative)
|
| 15 |
+
inputs= torch.sigmoid(inputs)
|
| 16 |
+
cost = torch.nn.BCELoss(mask, reduction='sum')(inputs.float(), targets.float())
|
| 17 |
+
|
| 18 |
+
return l_weight*torch.sum(cost)
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def bdcn_loss2(inputs, targets, l_weight=1.1):
|
| 22 |
+
# bdcn loss with the rcf approach
|
| 23 |
+
targets = targets.long()
|
| 24 |
+
# mask = (targets > 0.1).float()
|
| 25 |
+
mask = targets.float()
|
| 26 |
+
num_positive = torch.sum((mask > 0.0).float()).float() # >0.1
|
| 27 |
+
num_negative = torch.sum((mask <= 0.0).float()).float() # <= 0.1
|
| 28 |
+
|
| 29 |
+
mask[mask > 0.] = 1.0 * num_negative / (num_positive + num_negative) #0.1
|
| 30 |
+
mask[mask <= 0.] = 1.1 * num_positive / (num_positive + num_negative) # before mask[mask <= 0.1]
|
| 31 |
+
# mask[mask == 2] = 0
|
| 32 |
+
inputs= torch.sigmoid(inputs)
|
| 33 |
+
cost = torch.nn.BCELoss(mask, reduction='none')(inputs, targets.float())
|
| 34 |
+
# cost = torch.mean(cost.float().mean((1, 2, 3))) # before sum
|
| 35 |
+
cost = torch.sum(cost.float().mean((1, 2, 3))) # before sum
|
| 36 |
+
return l_weight*cost
|
| 37 |
+
|
| 38 |
+
def bdcn_lossORI(inputs, targets, l_weigts=1.1,cuda=False):
|
| 39 |
+
"""
|
| 40 |
+
:param inputs: inputs is a 4 dimensional data nx1xhxw
|
| 41 |
+
:param targets: targets is a 3 dimensional data nx1xhxw
|
| 42 |
+
:return:
|
| 43 |
+
"""
|
| 44 |
+
n, c, h, w = inputs.size()
|
| 45 |
+
# print(cuda)
|
| 46 |
+
weights = np.zeros((n, c, h, w))
|
| 47 |
+
for i in range(n):
|
| 48 |
+
t = targets[i, :, :, :].cpu().data.numpy()
|
| 49 |
+
pos = (t == 1).sum()
|
| 50 |
+
neg = (t == 0).sum()
|
| 51 |
+
valid = neg + pos
|
| 52 |
+
weights[i, t == 1] = neg * 1. / valid
|
| 53 |
+
weights[i, t == 0] = pos * 1.1 / valid # balance = 1.1
|
| 54 |
+
weights = torch.Tensor(weights)
|
| 55 |
+
# if cuda:
|
| 56 |
+
weights = weights.cuda()
|
| 57 |
+
inputs = torch.sigmoid(inputs)
|
| 58 |
+
loss = torch.nn.BCELoss(weights, reduction='sum')(inputs.float(), targets.float())
|
| 59 |
+
return l_weigts*loss
|
| 60 |
+
|
| 61 |
+
def rcf_loss(inputs, label):
|
| 62 |
+
|
| 63 |
+
label = label.long()
|
| 64 |
+
mask = label.float()
|
| 65 |
+
num_positive = torch.sum((mask > 0.5).float()).float() # ==1.
|
| 66 |
+
num_negative = torch.sum((mask == 0).float()).float()
|
| 67 |
+
|
| 68 |
+
mask[mask == 1] = 1.0 * num_negative / (num_positive + num_negative)
|
| 69 |
+
mask[mask == 0] = 1.1 * num_positive / (num_positive + num_negative)
|
| 70 |
+
mask[mask == 2] = 0.
|
| 71 |
+
inputs= torch.sigmoid(inputs)
|
| 72 |
+
cost = torch.nn.BCELoss(mask, reduction='sum')(inputs.float(), label.float())
|
| 73 |
+
|
| 74 |
+
return 1.*torch.sum(cost)
|
| 75 |
+
|
| 76 |
+
# ------------ cats losses ----------
|
| 77 |
+
|
| 78 |
+
def bdrloss(prediction, label, radius,device='cpu'):
|
| 79 |
+
'''
|
| 80 |
+
The boundary tracing loss that handles the confusing pixels.
|
| 81 |
+
'''
|
| 82 |
+
|
| 83 |
+
filt = torch.ones(1, 1, 2*radius+1, 2*radius+1)
|
| 84 |
+
filt.requires_grad = False
|
| 85 |
+
filt = filt.to(device)
|
| 86 |
+
|
| 87 |
+
bdr_pred = prediction * label
|
| 88 |
+
pred_bdr_sum = label * F.conv2d(bdr_pred, filt, bias=None, stride=1, padding=radius)
|
| 89 |
+
texture_mask = F.conv2d(label.float(), filt, bias=None, stride=1, padding=radius)
|
| 90 |
+
mask = (texture_mask != 0).float()
|
| 91 |
+
mask[label == 1] = 0
|
| 92 |
+
pred_texture_sum = F.conv2d(prediction * (1-label) * mask, filt, bias=None, stride=1, padding=radius)
|
| 93 |
+
|
| 94 |
+
softmax_map = torch.clamp(pred_bdr_sum / (pred_texture_sum + pred_bdr_sum + 1e-10), 1e-10, 1 - 1e-10)
|
| 95 |
+
cost = -label * torch.log(softmax_map)
|
| 96 |
+
cost[label == 0] = 0
|
| 97 |
+
|
| 98 |
+
return cost.sum()
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
def textureloss(prediction, label, mask_radius, device='cpu'):
|
| 103 |
+
'''
|
| 104 |
+
The texture suppression loss that smooths the texture regions.
|
| 105 |
+
'''
|
| 106 |
+
filt1 = torch.ones(1, 1, 3, 3)
|
| 107 |
+
filt1.requires_grad = False
|
| 108 |
+
filt1 = filt1.to(device)
|
| 109 |
+
filt2 = torch.ones(1, 1, 2*mask_radius+1, 2*mask_radius+1)
|
| 110 |
+
filt2.requires_grad = False
|
| 111 |
+
filt2 = filt2.to(device)
|
| 112 |
+
|
| 113 |
+
pred_sums = F.conv2d(prediction.float(), filt1, bias=None, stride=1, padding=1)
|
| 114 |
+
label_sums = F.conv2d(label.float(), filt2, bias=None, stride=1, padding=mask_radius)
|
| 115 |
+
|
| 116 |
+
mask = 1 - torch.gt(label_sums, 0).float()
|
| 117 |
+
|
| 118 |
+
loss = -torch.log(torch.clamp(1-pred_sums/9, 1e-10, 1-1e-10))
|
| 119 |
+
loss[mask == 0] = 0
|
| 120 |
+
|
| 121 |
+
return torch.sum(loss)
|
| 122 |
+
|
| 123 |
+
|
| 124 |
+
def cats_loss(prediction, label, l_weight=[0.,0.], device='cpu'):
|
| 125 |
+
# tracingLoss
|
| 126 |
+
tex_factor,bdr_factor = l_weight
|
| 127 |
+
balanced_w = 1.1
|
| 128 |
+
label = label.float()
|
| 129 |
+
prediction = prediction.float()
|
| 130 |
+
with torch.no_grad():
|
| 131 |
+
mask = label.clone()
|
| 132 |
+
|
| 133 |
+
num_positive = torch.sum((mask == 1).float()).float()
|
| 134 |
+
num_negative = torch.sum((mask == 0).float()).float()
|
| 135 |
+
beta = num_negative / (num_positive + num_negative)
|
| 136 |
+
mask[mask == 1] = beta
|
| 137 |
+
mask[mask == 0] = balanced_w * (1 - beta)
|
| 138 |
+
mask[mask == 2] = 0
|
| 139 |
+
prediction = torch.sigmoid(prediction)
|
| 140 |
+
# print('bce')
|
| 141 |
+
cost = torch.sum(torch.nn.functional.binary_cross_entropy(
|
| 142 |
+
prediction.float(), label.float(), weight=mask, reduce=False))
|
| 143 |
+
label_w = (label != 0).float()
|
| 144 |
+
# print('tex')
|
| 145 |
+
textcost = textureloss(prediction.float(), label_w.float(), mask_radius=4, device=device)
|
| 146 |
+
bdrcost = bdrloss(prediction.float(), label_w.float(), radius=4, device=device)
|
| 147 |
+
|
| 148 |
+
return cost + bdr_factor * bdrcost + tex_factor * textcost
|
main.py
ADDED
|
@@ -0,0 +1,481 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
from __future__ import print_function
|
| 3 |
+
|
| 4 |
+
import argparse
|
| 5 |
+
import os
|
| 6 |
+
import time, platform
|
| 7 |
+
|
| 8 |
+
import cv2
|
| 9 |
+
import torch.optim as optim
|
| 10 |
+
from torch.utils.data import DataLoader
|
| 11 |
+
|
| 12 |
+
from datasets import DATASET_NAMES, BipedDataset, TestDataset, dataset_info
|
| 13 |
+
from losses import *
|
| 14 |
+
from model import DexiNed
|
| 15 |
+
from utils import (image_normalization, save_image_batch_to_disk,
|
| 16 |
+
visualize_result,count_parameters)
|
| 17 |
+
|
| 18 |
+
IS_LINUX = True if platform.system()=="Linux" else False
|
| 19 |
+
def train_one_epoch(epoch, dataloader, model, criterion, optimizer, device,
|
| 20 |
+
log_interval_vis, tb_writer, args=None):
|
| 21 |
+
imgs_res_folder = os.path.join(args.output_dir, 'current_res')
|
| 22 |
+
os.makedirs(imgs_res_folder,exist_ok=True)
|
| 23 |
+
|
| 24 |
+
# Put model in training mode
|
| 25 |
+
model.train()
|
| 26 |
+
# l_weight = [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1.1] # for bdcn ori loss
|
| 27 |
+
# before [0.6,0.6,1.1,1.1,0.4,0.4,1.3] [0.4,0.4,1.1,1.1,0.6,0.6,1.3],[0.4,0.4,1.1,1.1,0.8,0.8,1.3]
|
| 28 |
+
l_weight = [0.7,0.7,1.1,1.1,0.3,0.3,1.3] # New BDCN loss
|
| 29 |
+
# l_weight = [[0.05, 2.], [0.05, 2.], [0.05, 2.],
|
| 30 |
+
# [0.1, 1.], [0.1, 1.], [0.1, 1.],
|
| 31 |
+
# [0.01, 4.]] # for cats loss
|
| 32 |
+
loss_avg =[]
|
| 33 |
+
for batch_id, sample_batched in enumerate(dataloader):
|
| 34 |
+
images = sample_batched['images'].to(device) # BxCxHxW
|
| 35 |
+
labels = sample_batched['labels'].to(device) # BxHxW
|
| 36 |
+
preds_list = model(images)
|
| 37 |
+
# loss = sum([criterion(preds, labels, l_w, device) for preds, l_w in zip(preds_list, l_weight)]) # cats_loss
|
| 38 |
+
loss = sum([criterion(preds, labels,l_w) for preds, l_w in zip(preds_list,l_weight)]) # bdcn_loss
|
| 39 |
+
# loss = sum([criterion(preds, labels) for preds in preds_list]) #HED loss, rcf_loss
|
| 40 |
+
optimizer.zero_grad()
|
| 41 |
+
loss.backward()
|
| 42 |
+
optimizer.step()
|
| 43 |
+
loss_avg.append(loss.item())
|
| 44 |
+
if epoch==0 and (batch_id==100 and tb_writer is not None):
|
| 45 |
+
tmp_loss = np.array(loss_avg).mean()
|
| 46 |
+
tb_writer.add_scalar('loss', tmp_loss,epoch)
|
| 47 |
+
|
| 48 |
+
if batch_id % 5 == 0:
|
| 49 |
+
print(time.ctime(), 'Epoch: {0} Sample {1}/{2} Loss: {3}'
|
| 50 |
+
.format(epoch, batch_id, len(dataloader), loss.item()))
|
| 51 |
+
if batch_id % log_interval_vis == 0:
|
| 52 |
+
res_data = []
|
| 53 |
+
|
| 54 |
+
img = images.cpu().numpy()
|
| 55 |
+
res_data.append(img[2])
|
| 56 |
+
|
| 57 |
+
ed_gt = labels.cpu().numpy()
|
| 58 |
+
res_data.append(ed_gt[2])
|
| 59 |
+
|
| 60 |
+
# tmp_pred = tmp_preds[2,...]
|
| 61 |
+
for i in range(len(preds_list)):
|
| 62 |
+
tmp = preds_list[i]
|
| 63 |
+
tmp = tmp[2]
|
| 64 |
+
# print(tmp.shape)
|
| 65 |
+
tmp = torch.sigmoid(tmp).unsqueeze(dim=0)
|
| 66 |
+
tmp = tmp.cpu().detach().numpy()
|
| 67 |
+
res_data.append(tmp)
|
| 68 |
+
|
| 69 |
+
vis_imgs = visualize_result(res_data, arg=args)
|
| 70 |
+
del tmp, res_data
|
| 71 |
+
|
| 72 |
+
vis_imgs = cv2.resize(vis_imgs,
|
| 73 |
+
(int(vis_imgs.shape[1]*0.8), int(vis_imgs.shape[0]*0.8)))
|
| 74 |
+
img_test = 'Epoch: {0} Sample {1}/{2} Loss: {3}' \
|
| 75 |
+
.format(epoch, batch_id, len(dataloader), loss.item())
|
| 76 |
+
|
| 77 |
+
BLACK = (0, 0, 255)
|
| 78 |
+
font = cv2.FONT_HERSHEY_SIMPLEX
|
| 79 |
+
font_size = 1.1
|
| 80 |
+
font_color = BLACK
|
| 81 |
+
font_thickness = 2
|
| 82 |
+
x, y = 30, 30
|
| 83 |
+
vis_imgs = cv2.putText(vis_imgs,
|
| 84 |
+
img_test,
|
| 85 |
+
(x, y),
|
| 86 |
+
font, font_size, font_color, font_thickness, cv2.LINE_AA)
|
| 87 |
+
cv2.imwrite(os.path.join(imgs_res_folder, 'results.png'), vis_imgs)
|
| 88 |
+
loss_avg = np.array(loss_avg).mean()
|
| 89 |
+
return loss_avg
|
| 90 |
+
|
| 91 |
+
|
| 92 |
+
def validate_one_epoch(epoch, dataloader, model, device, output_dir, arg=None):
|
| 93 |
+
# XXX This is not really validation, but testing
|
| 94 |
+
|
| 95 |
+
# Put model in eval mode
|
| 96 |
+
model.eval()
|
| 97 |
+
|
| 98 |
+
with torch.no_grad():
|
| 99 |
+
for _, sample_batched in enumerate(dataloader):
|
| 100 |
+
images = sample_batched['images'].to(device)
|
| 101 |
+
# labels = sample_batched['labels'].to(device)
|
| 102 |
+
file_names = sample_batched['file_names']
|
| 103 |
+
image_shape = sample_batched['image_shape']
|
| 104 |
+
preds = model(images)
|
| 105 |
+
# print('pred shape', preds[0].shape)
|
| 106 |
+
save_image_batch_to_disk(preds[-1],
|
| 107 |
+
output_dir,
|
| 108 |
+
file_names,img_shape=image_shape,
|
| 109 |
+
arg=arg)
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
def test(checkpoint_path, dataloader, model, device, output_dir, args):
|
| 113 |
+
if not os.path.isfile(checkpoint_path):
|
| 114 |
+
raise FileNotFoundError(
|
| 115 |
+
f"Checkpoint filte note found: {checkpoint_path}")
|
| 116 |
+
print(f"Restoring weights from: {checkpoint_path}")
|
| 117 |
+
model.load_state_dict(torch.load(checkpoint_path,
|
| 118 |
+
map_location=device))
|
| 119 |
+
|
| 120 |
+
# Put model in evaluation mode
|
| 121 |
+
model.eval()
|
| 122 |
+
|
| 123 |
+
with torch.no_grad():
|
| 124 |
+
total_duration = []
|
| 125 |
+
for batch_id, sample_batched in enumerate(dataloader):
|
| 126 |
+
images = sample_batched['images'].to(device)
|
| 127 |
+
if not args.test_data == "CLASSIC":
|
| 128 |
+
labels = sample_batched['labels'].to(device)
|
| 129 |
+
file_names = sample_batched['file_names']
|
| 130 |
+
image_shape = sample_batched['image_shape']
|
| 131 |
+
print(f"input tensor shape: {images.shape}")
|
| 132 |
+
# images = images[:, [2, 1, 0], :, :]
|
| 133 |
+
|
| 134 |
+
end = time.perf_counter()
|
| 135 |
+
if device.type == 'cuda':
|
| 136 |
+
torch.cuda.synchronize()
|
| 137 |
+
preds = model(images)
|
| 138 |
+
if device.type == 'cuda':
|
| 139 |
+
torch.cuda.synchronize()
|
| 140 |
+
tmp_duration = time.perf_counter() - end
|
| 141 |
+
total_duration.append(tmp_duration)
|
| 142 |
+
|
| 143 |
+
save_image_batch_to_disk(preds,
|
| 144 |
+
output_dir,
|
| 145 |
+
file_names,
|
| 146 |
+
image_shape,
|
| 147 |
+
arg=args)
|
| 148 |
+
torch.cuda.empty_cache()
|
| 149 |
+
|
| 150 |
+
total_duration = np.sum(np.array(total_duration))
|
| 151 |
+
print("******** Testing finished in", args.test_data, "dataset. *****")
|
| 152 |
+
print("FPS: %f.4" % (len(dataloader)/total_duration))
|
| 153 |
+
|
| 154 |
+
def testPich(checkpoint_path, dataloader, model, device, output_dir, args):
|
| 155 |
+
# a test model plus the interganged channels
|
| 156 |
+
if not os.path.isfile(checkpoint_path):
|
| 157 |
+
raise FileNotFoundError(
|
| 158 |
+
f"Checkpoint filte note found: {checkpoint_path}")
|
| 159 |
+
print(f"Restoring weights from: {checkpoint_path}")
|
| 160 |
+
model.load_state_dict(torch.load(checkpoint_path,
|
| 161 |
+
map_location=device))
|
| 162 |
+
|
| 163 |
+
# Put model in evaluation mode
|
| 164 |
+
model.eval()
|
| 165 |
+
|
| 166 |
+
with torch.no_grad():
|
| 167 |
+
total_duration = []
|
| 168 |
+
for batch_id, sample_batched in enumerate(dataloader):
|
| 169 |
+
images = sample_batched['images'].to(device)
|
| 170 |
+
if not args.test_data == "CLASSIC":
|
| 171 |
+
labels = sample_batched['labels'].to(device)
|
| 172 |
+
file_names = sample_batched['file_names']
|
| 173 |
+
image_shape = sample_batched['image_shape']
|
| 174 |
+
print(f"input tensor shape: {images.shape}")
|
| 175 |
+
start_time = time.time()
|
| 176 |
+
# images2 = images[:, [1, 0, 2], :, :] #GBR
|
| 177 |
+
images2 = images[:, [2, 1, 0], :, :] # RGB
|
| 178 |
+
preds = model(images)
|
| 179 |
+
preds2 = model(images2)
|
| 180 |
+
tmp_duration = time.time() - start_time
|
| 181 |
+
total_duration.append(tmp_duration)
|
| 182 |
+
save_image_batch_to_disk([preds,preds2],
|
| 183 |
+
output_dir,
|
| 184 |
+
file_names,
|
| 185 |
+
image_shape,
|
| 186 |
+
arg=args, is_inchannel=True)
|
| 187 |
+
torch.cuda.empty_cache()
|
| 188 |
+
|
| 189 |
+
total_duration = np.array(total_duration)
|
| 190 |
+
print("******** Testing finished in", args.test_data, "dataset. *****")
|
| 191 |
+
print("Average time per image: %f.4" % total_duration.mean(), "seconds")
|
| 192 |
+
print("Time spend in the Dataset: %f.4" % total_duration.sum(), "seconds")
|
| 193 |
+
|
| 194 |
+
|
| 195 |
+
def parse_args():
|
| 196 |
+
"""Parse command line arguments."""
|
| 197 |
+
parser = argparse.ArgumentParser(description='DexiNed trainer.')
|
| 198 |
+
parser.add_argument('--choose_test_data',
|
| 199 |
+
type=int,
|
| 200 |
+
default=-1,
|
| 201 |
+
help='Already set the dataset for testing choice: 0 - 8')
|
| 202 |
+
# ----------- test -------0--
|
| 203 |
+
|
| 204 |
+
|
| 205 |
+
TEST_DATA = DATASET_NAMES[parser.parse_args().choose_test_data] # max 8
|
| 206 |
+
test_inf = dataset_info(TEST_DATA, is_linux=IS_LINUX)
|
| 207 |
+
test_dir = test_inf['data_dir']
|
| 208 |
+
is_testing =True# current test -352-SM-NewGT-2AugmenPublish
|
| 209 |
+
|
| 210 |
+
# Training settings
|
| 211 |
+
TRAIN_DATA = DATASET_NAMES[0] # BIPED=0, MDBD=6
|
| 212 |
+
train_inf = dataset_info(TRAIN_DATA, is_linux=IS_LINUX)
|
| 213 |
+
train_dir = train_inf['data_dir']
|
| 214 |
+
|
| 215 |
+
|
| 216 |
+
# Data parameters
|
| 217 |
+
parser.add_argument('--input_dir',
|
| 218 |
+
type=str,
|
| 219 |
+
default=train_dir,
|
| 220 |
+
help='the path to the directory with the input data.')
|
| 221 |
+
parser.add_argument('--input_val_dir',
|
| 222 |
+
type=str,
|
| 223 |
+
default=test_inf['data_dir'],
|
| 224 |
+
help='the path to the directory with the input data for validation.')
|
| 225 |
+
parser.add_argument('--output_dir',
|
| 226 |
+
type=str,
|
| 227 |
+
default='checkpoints',
|
| 228 |
+
help='the path to output the results.')
|
| 229 |
+
parser.add_argument('--train_data',
|
| 230 |
+
type=str,
|
| 231 |
+
choices=DATASET_NAMES,
|
| 232 |
+
default=TRAIN_DATA,
|
| 233 |
+
help='Name of the dataset.')
|
| 234 |
+
parser.add_argument('--test_data',
|
| 235 |
+
type=str,
|
| 236 |
+
choices=DATASET_NAMES,
|
| 237 |
+
default=TEST_DATA,
|
| 238 |
+
help='Name of the dataset.')
|
| 239 |
+
parser.add_argument('--test_list',
|
| 240 |
+
type=str,
|
| 241 |
+
default=test_inf['test_list'],
|
| 242 |
+
help='Dataset sample indices list.')
|
| 243 |
+
parser.add_argument('--train_list',
|
| 244 |
+
type=str,
|
| 245 |
+
default=train_inf['train_list'],
|
| 246 |
+
help='Dataset sample indices list.')
|
| 247 |
+
parser.add_argument('--is_testing',type=bool,
|
| 248 |
+
default=is_testing,
|
| 249 |
+
help='Script in testing mode.')
|
| 250 |
+
parser.add_argument('--double_img',
|
| 251 |
+
type=bool,
|
| 252 |
+
default=False,
|
| 253 |
+
help='True: use same 2 imgs changing channels') # Just for test
|
| 254 |
+
parser.add_argument('--resume',
|
| 255 |
+
type=bool,
|
| 256 |
+
default=False,
|
| 257 |
+
help='use previous trained data') # Just for test
|
| 258 |
+
parser.add_argument('--checkpoint_data',
|
| 259 |
+
type=str,
|
| 260 |
+
default='10/10_model.pth',# 4 6 7 9 14
|
| 261 |
+
help='Checkpoint path from which to restore model weights from.')
|
| 262 |
+
parser.add_argument('--test_img_width',
|
| 263 |
+
type=int,
|
| 264 |
+
default=test_inf['img_width'],
|
| 265 |
+
help='Image width for testing.')
|
| 266 |
+
parser.add_argument('--test_img_height',
|
| 267 |
+
type=int,
|
| 268 |
+
default=test_inf['img_height'],
|
| 269 |
+
help='Image height for testing.')
|
| 270 |
+
parser.add_argument('--res_dir',
|
| 271 |
+
type=str,
|
| 272 |
+
default='result',
|
| 273 |
+
help='Result directory')
|
| 274 |
+
parser.add_argument('--log_interval_vis',
|
| 275 |
+
type=int,
|
| 276 |
+
default=50,
|
| 277 |
+
help='The number of batches to wait before printing test predictions.')
|
| 278 |
+
|
| 279 |
+
parser.add_argument('--epochs',
|
| 280 |
+
type=int,
|
| 281 |
+
default=17,
|
| 282 |
+
metavar='N',
|
| 283 |
+
help='Number of training epochs (default: 25).')
|
| 284 |
+
parser.add_argument('--lr',
|
| 285 |
+
default=1e-4,
|
| 286 |
+
type=float,
|
| 287 |
+
help='Initial learning rate.')
|
| 288 |
+
parser.add_argument('--wd',
|
| 289 |
+
type=float,
|
| 290 |
+
default=1e-8,
|
| 291 |
+
metavar='WD',
|
| 292 |
+
help='weight decay (Good 1e-8) in TF1=0') # 1e-8 -> BIRND/MDBD, 0.0 -> BIPED
|
| 293 |
+
parser.add_argument('--adjust_lr',
|
| 294 |
+
default=[10,15],
|
| 295 |
+
type=int,
|
| 296 |
+
help='Learning rate step size.') #[5,10]BIRND [10,15]BIPED/BRIND
|
| 297 |
+
parser.add_argument('--batch_size',
|
| 298 |
+
type=int,
|
| 299 |
+
default=8,
|
| 300 |
+
metavar='B',
|
| 301 |
+
help='the mini-batch size (default: 8)')
|
| 302 |
+
parser.add_argument('--workers',
|
| 303 |
+
default=16,
|
| 304 |
+
type=int,
|
| 305 |
+
help='The number of workers for the dataloaders.')
|
| 306 |
+
parser.add_argument('--tensorboard',type=bool,
|
| 307 |
+
default=True,
|
| 308 |
+
help='Use Tensorboard for logging.'),
|
| 309 |
+
parser.add_argument('--img_width',
|
| 310 |
+
type=int,
|
| 311 |
+
default=352,
|
| 312 |
+
help='Image width for training.') # BIPED 400 BSDS 352/320 MDBD 480
|
| 313 |
+
parser.add_argument('--img_height',
|
| 314 |
+
type=int,
|
| 315 |
+
default=352,
|
| 316 |
+
help='Image height for training.') # BIPED 480 BSDS 352/320
|
| 317 |
+
parser.add_argument('--channel_swap',
|
| 318 |
+
default=[2, 1, 0],
|
| 319 |
+
type=int)
|
| 320 |
+
parser.add_argument('--crop_img',
|
| 321 |
+
default=True,
|
| 322 |
+
type=bool,
|
| 323 |
+
help='If true crop training images, else resize images to match image width and height.')
|
| 324 |
+
parser.add_argument('--mean_pixel_values',
|
| 325 |
+
default=[103.939,116.779,123.68, 137.86],
|
| 326 |
+
type=float) # [103.939,116.779,123.68] [104.00699, 116.66877, 122.67892]
|
| 327 |
+
args = parser.parse_args()
|
| 328 |
+
return args
|
| 329 |
+
|
| 330 |
+
|
| 331 |
+
def main(args):
|
| 332 |
+
"""Main function."""
|
| 333 |
+
|
| 334 |
+
print(f"Number of GPU's available: {torch.cuda.device_count()}")
|
| 335 |
+
print(f"Pytorch version: {torch.__version__}")
|
| 336 |
+
|
| 337 |
+
# Tensorboard summary writer
|
| 338 |
+
|
| 339 |
+
tb_writer = None
|
| 340 |
+
training_dir = os.path.join(args.output_dir,args.train_data)
|
| 341 |
+
os.makedirs(training_dir,exist_ok=True)
|
| 342 |
+
checkpoint_path = os.path.join(args.output_dir, args.train_data, args.checkpoint_data)
|
| 343 |
+
if args.tensorboard and not args.is_testing:
|
| 344 |
+
from torch.utils.tensorboard import SummaryWriter # for torch 1.4 or greather
|
| 345 |
+
tb_writer = SummaryWriter(log_dir=training_dir)
|
| 346 |
+
# saving Model training settings
|
| 347 |
+
training_notes = ['DexiNed, Xavier Normal Init, LR= ' + str(args.lr) + ' WD= '
|
| 348 |
+
+ str(args.wd) + ' image size = ' + str(args.img_width)
|
| 349 |
+
+ ' adjust LR='+ str(args.adjust_lr) + ' Loss Function= BDCNloss2. '
|
| 350 |
+
+'Trained on> '+args.train_data+' Tested on> '
|
| 351 |
+
+args.test_data+' Batch size= '+str(args.batch_size)+' '+str(time.asctime())]
|
| 352 |
+
info_txt = open(os.path.join(training_dir, 'training_settings.txt'), 'w')
|
| 353 |
+
info_txt.write(str(training_notes))
|
| 354 |
+
info_txt.close()
|
| 355 |
+
|
| 356 |
+
# Get computing device
|
| 357 |
+
device = torch.device('cpu' if torch.cuda.device_count() == 0
|
| 358 |
+
else 'cuda')
|
| 359 |
+
|
| 360 |
+
# Instantiate model and move it to the computing device
|
| 361 |
+
model = DexiNed().to(device)
|
| 362 |
+
# model = nn.DataParallel(model)
|
| 363 |
+
ini_epoch =0
|
| 364 |
+
if not args.is_testing:
|
| 365 |
+
if args.resume:
|
| 366 |
+
ini_epoch=11
|
| 367 |
+
model.load_state_dict(torch.load(checkpoint_path,
|
| 368 |
+
map_location=device))
|
| 369 |
+
print('Training restarted from> ',checkpoint_path)
|
| 370 |
+
dataset_train = BipedDataset(args.input_dir,
|
| 371 |
+
img_width=args.img_width,
|
| 372 |
+
img_height=args.img_height,
|
| 373 |
+
mean_bgr=args.mean_pixel_values[0:3] if len(
|
| 374 |
+
args.mean_pixel_values) == 4 else args.mean_pixel_values,
|
| 375 |
+
train_mode='train',
|
| 376 |
+
arg=args
|
| 377 |
+
)
|
| 378 |
+
dataloader_train = DataLoader(dataset_train,
|
| 379 |
+
batch_size=args.batch_size,
|
| 380 |
+
shuffle=True,
|
| 381 |
+
num_workers=args.workers)
|
| 382 |
+
|
| 383 |
+
dataset_val = TestDataset(args.input_val_dir,
|
| 384 |
+
test_data=args.test_data,
|
| 385 |
+
img_width=args.test_img_width,
|
| 386 |
+
img_height=args.test_img_height,
|
| 387 |
+
mean_bgr=args.mean_pixel_values[0:3] if len(
|
| 388 |
+
args.mean_pixel_values) == 4 else args.mean_pixel_values,
|
| 389 |
+
test_list=args.test_list, arg=args
|
| 390 |
+
)
|
| 391 |
+
dataloader_val = DataLoader(dataset_val,
|
| 392 |
+
batch_size=1,
|
| 393 |
+
shuffle=False,
|
| 394 |
+
num_workers=args.workers)
|
| 395 |
+
# Testing
|
| 396 |
+
if args.is_testing:
|
| 397 |
+
|
| 398 |
+
output_dir = os.path.join(args.res_dir, args.train_data+"2"+ args.test_data)
|
| 399 |
+
print(f"output_dir: {output_dir}")
|
| 400 |
+
if args.double_img:
|
| 401 |
+
# predict twice an image changing channels, then mix those results
|
| 402 |
+
testPich(checkpoint_path, dataloader_val, model, device, output_dir, args)
|
| 403 |
+
else:
|
| 404 |
+
test(checkpoint_path, dataloader_val, model, device, output_dir, args)
|
| 405 |
+
|
| 406 |
+
num_param = count_parameters(model)
|
| 407 |
+
print('-------------------------------------------------------')
|
| 408 |
+
print('DexiNed # of Parameters:')
|
| 409 |
+
print(num_param)
|
| 410 |
+
print('-------------------------------------------------------')
|
| 411 |
+
return
|
| 412 |
+
|
| 413 |
+
criterion = bdcn_loss2 # hed_loss2 #bdcn_loss2
|
| 414 |
+
|
| 415 |
+
optimizer = optim.Adam(model.parameters(),
|
| 416 |
+
lr=args.lr,
|
| 417 |
+
weight_decay=args.wd)
|
| 418 |
+
|
| 419 |
+
# Main training loop
|
| 420 |
+
seed=1021
|
| 421 |
+
adjust_lr = args.adjust_lr
|
| 422 |
+
lr2= args.lr
|
| 423 |
+
for epoch in range(ini_epoch,args.epochs):
|
| 424 |
+
if epoch%7==0:
|
| 425 |
+
|
| 426 |
+
seed = seed+1000
|
| 427 |
+
np.random.seed(seed)
|
| 428 |
+
torch.manual_seed(seed)
|
| 429 |
+
torch.cuda.manual_seed(seed)
|
| 430 |
+
print("------ Random seed applied-------------")
|
| 431 |
+
# Create output directories
|
| 432 |
+
if adjust_lr is not None:
|
| 433 |
+
if epoch in adjust_lr:
|
| 434 |
+
lr2 = lr2*0.1
|
| 435 |
+
for param_group in optimizer.param_groups:
|
| 436 |
+
param_group['lr'] = lr2
|
| 437 |
+
|
| 438 |
+
output_dir_epoch = os.path.join(args.output_dir,args.train_data, str(epoch))
|
| 439 |
+
img_test_dir = os.path.join(output_dir_epoch, args.test_data + '_res')
|
| 440 |
+
os.makedirs(output_dir_epoch,exist_ok=True)
|
| 441 |
+
os.makedirs(img_test_dir,exist_ok=True)
|
| 442 |
+
validate_one_epoch(epoch,
|
| 443 |
+
dataloader_val,
|
| 444 |
+
model,
|
| 445 |
+
device,
|
| 446 |
+
img_test_dir,
|
| 447 |
+
arg=args)
|
| 448 |
+
|
| 449 |
+
avg_loss =train_one_epoch(epoch,
|
| 450 |
+
dataloader_train,
|
| 451 |
+
model,
|
| 452 |
+
criterion,
|
| 453 |
+
optimizer,
|
| 454 |
+
device,
|
| 455 |
+
args.log_interval_vis,
|
| 456 |
+
tb_writer,
|
| 457 |
+
args=args)
|
| 458 |
+
validate_one_epoch(epoch,
|
| 459 |
+
dataloader_val,
|
| 460 |
+
model,
|
| 461 |
+
device,
|
| 462 |
+
img_test_dir,
|
| 463 |
+
arg=args)
|
| 464 |
+
|
| 465 |
+
# Save model after end of every epoch
|
| 466 |
+
torch.save(model.module.state_dict() if hasattr(model, "module") else model.state_dict(),
|
| 467 |
+
os.path.join(output_dir_epoch, '{0}_model.pth'.format(epoch)))
|
| 468 |
+
if tb_writer is not None:
|
| 469 |
+
tb_writer.add_scalar('loss',
|
| 470 |
+
avg_loss,
|
| 471 |
+
epoch+1)
|
| 472 |
+
print('Current learning rate> ', optimizer.param_groups[0]['lr'])
|
| 473 |
+
num_param = count_parameters(model)
|
| 474 |
+
print('-------------------------------------------------------')
|
| 475 |
+
print('DexiNed, # of Parameters:')
|
| 476 |
+
print(num_param)
|
| 477 |
+
print('-------------------------------------------------------')
|
| 478 |
+
|
| 479 |
+
if __name__ == '__main__':
|
| 480 |
+
args = parse_args()
|
| 481 |
+
main(args)
|
model.py
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
import torch.nn as nn
|
| 3 |
+
import torch.nn.functional as F
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
def weight_init(m):
|
| 7 |
+
if isinstance(m, (nn.Conv2d,)):
|
| 8 |
+
# torch.nn.init.xavier_uniform_(m.weight, gain=1.0)
|
| 9 |
+
torch.nn.init.xavier_normal_(m.weight, gain=1.0)
|
| 10 |
+
# torch.nn.init.normal_(m.weight, mean=0.0, std=0.01)
|
| 11 |
+
if m.weight.data.shape[1] == torch.Size([1]):
|
| 12 |
+
torch.nn.init.normal_(m.weight, mean=0.0)
|
| 13 |
+
|
| 14 |
+
if m.bias is not None:
|
| 15 |
+
torch.nn.init.zeros_(m.bias)
|
| 16 |
+
|
| 17 |
+
# for fusion layer
|
| 18 |
+
if isinstance(m, (nn.ConvTranspose2d,)):
|
| 19 |
+
# torch.nn.init.xavier_uniform_(m.weight, gain=1.0)
|
| 20 |
+
torch.nn.init.xavier_normal_(m.weight, gain=1.0)
|
| 21 |
+
# torch.nn.init.normal_(m.weight, mean=0.0, std=0.01)
|
| 22 |
+
|
| 23 |
+
if m.weight.data.shape[1] == torch.Size([1]):
|
| 24 |
+
torch.nn.init.normal_(m.weight, std=0.1)
|
| 25 |
+
if m.bias is not None:
|
| 26 |
+
torch.nn.init.zeros_(m.bias)
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
class CoFusion(nn.Module):
|
| 30 |
+
|
| 31 |
+
def __init__(self, in_ch, out_ch):
|
| 32 |
+
super(CoFusion, self).__init__()
|
| 33 |
+
self.conv1 = nn.Conv2d(in_ch, 64, kernel_size=3,
|
| 34 |
+
stride=1, padding=1)
|
| 35 |
+
self.conv2 = nn.Conv2d(64, 64, kernel_size=3,
|
| 36 |
+
stride=1, padding=1)
|
| 37 |
+
self.conv3 = nn.Conv2d(64, out_ch, kernel_size=3,
|
| 38 |
+
stride=1, padding=1)
|
| 39 |
+
self.relu = nn.ReLU()
|
| 40 |
+
|
| 41 |
+
self.norm_layer1 = nn.GroupNorm(4, 64)
|
| 42 |
+
self.norm_layer2 = nn.GroupNorm(4, 64)
|
| 43 |
+
|
| 44 |
+
def forward(self, x):
|
| 45 |
+
# fusecat = torch.cat(x, dim=1)
|
| 46 |
+
attn = self.relu(self.norm_layer1(self.conv1(x)))
|
| 47 |
+
attn = self.relu(self.norm_layer2(self.conv2(attn)))
|
| 48 |
+
attn = F.softmax(self.conv3(attn), dim=1)
|
| 49 |
+
|
| 50 |
+
# return ((fusecat * attn).sum(1)).unsqueeze(1)
|
| 51 |
+
return ((x * attn).sum(1)).unsqueeze(1)
|
| 52 |
+
|
| 53 |
+
class _DenseLayer(nn.Sequential):
|
| 54 |
+
def __init__(self, input_features, out_features):
|
| 55 |
+
super(_DenseLayer, self).__init__()
|
| 56 |
+
|
| 57 |
+
# self.add_module('relu2', nn.ReLU(inplace=True)),
|
| 58 |
+
self.add_module('conv1', nn.Conv2d(input_features, out_features,
|
| 59 |
+
kernel_size=3, stride=1, padding=2, bias=True)),
|
| 60 |
+
self.add_module('norm1', nn.BatchNorm2d(out_features)),
|
| 61 |
+
self.add_module('relu1', nn.ReLU(inplace=True)),
|
| 62 |
+
self.add_module('conv2', nn.Conv2d(out_features, out_features,
|
| 63 |
+
kernel_size=3, stride=1, bias=True)),
|
| 64 |
+
self.add_module('norm2', nn.BatchNorm2d(out_features))
|
| 65 |
+
|
| 66 |
+
def forward(self, x):
|
| 67 |
+
x1, x2 = x
|
| 68 |
+
|
| 69 |
+
new_features = super(_DenseLayer, self).forward(F.relu(x1)) # F.relu()
|
| 70 |
+
# if new_features.shape[-1]!=x2.shape[-1]:
|
| 71 |
+
# new_features =F.interpolate(new_features,size=(x2.shape[2],x2.shape[-1]), mode='bicubic',
|
| 72 |
+
# align_corners=False)
|
| 73 |
+
return 0.5 * (new_features + x2), x2
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
class _DenseBlock(nn.Sequential):
|
| 77 |
+
def __init__(self, num_layers, input_features, out_features):
|
| 78 |
+
super(_DenseBlock, self).__init__()
|
| 79 |
+
for i in range(num_layers):
|
| 80 |
+
layer = _DenseLayer(input_features, out_features)
|
| 81 |
+
self.add_module('denselayer%d' % (i + 1), layer)
|
| 82 |
+
input_features = out_features
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
class UpConvBlock(nn.Module):
|
| 86 |
+
def __init__(self, in_features, up_scale):
|
| 87 |
+
super(UpConvBlock, self).__init__()
|
| 88 |
+
self.up_factor = 2
|
| 89 |
+
self.constant_features = 16
|
| 90 |
+
|
| 91 |
+
layers = self.make_deconv_layers(in_features, up_scale)
|
| 92 |
+
assert layers is not None, layers
|
| 93 |
+
self.features = nn.Sequential(*layers)
|
| 94 |
+
|
| 95 |
+
def make_deconv_layers(self, in_features, up_scale):
|
| 96 |
+
layers = []
|
| 97 |
+
all_pads=[0,0,1,3,7]
|
| 98 |
+
for i in range(up_scale):
|
| 99 |
+
kernel_size = 2 ** up_scale
|
| 100 |
+
pad = all_pads[up_scale] # kernel_size-1
|
| 101 |
+
out_features = self.compute_out_features(i, up_scale)
|
| 102 |
+
layers.append(nn.Conv2d(in_features, out_features, 1))
|
| 103 |
+
layers.append(nn.ReLU(inplace=True))
|
| 104 |
+
layers.append(nn.ConvTranspose2d(
|
| 105 |
+
out_features, out_features, kernel_size, stride=2, padding=pad))
|
| 106 |
+
in_features = out_features
|
| 107 |
+
return layers
|
| 108 |
+
|
| 109 |
+
def compute_out_features(self, idx, up_scale):
|
| 110 |
+
return 1 if idx == up_scale - 1 else self.constant_features
|
| 111 |
+
|
| 112 |
+
def forward(self, x):
|
| 113 |
+
return self.features(x)
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
class SingleConvBlock(nn.Module):
|
| 117 |
+
def __init__(self, in_features, out_features, stride,
|
| 118 |
+
use_bs=True
|
| 119 |
+
):
|
| 120 |
+
super(SingleConvBlock, self).__init__()
|
| 121 |
+
self.use_bn = use_bs
|
| 122 |
+
self.conv = nn.Conv2d(in_features, out_features, 1, stride=stride,
|
| 123 |
+
bias=True)
|
| 124 |
+
self.bn = nn.BatchNorm2d(out_features)
|
| 125 |
+
|
| 126 |
+
def forward(self, x):
|
| 127 |
+
x = self.conv(x)
|
| 128 |
+
if self.use_bn:
|
| 129 |
+
x = self.bn(x)
|
| 130 |
+
return x
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
class DoubleConvBlock(nn.Module):
|
| 134 |
+
def __init__(self, in_features, mid_features,
|
| 135 |
+
out_features=None,
|
| 136 |
+
stride=1,
|
| 137 |
+
use_act=True):
|
| 138 |
+
super(DoubleConvBlock, self).__init__()
|
| 139 |
+
|
| 140 |
+
self.use_act = use_act
|
| 141 |
+
if out_features is None:
|
| 142 |
+
out_features = mid_features
|
| 143 |
+
self.conv1 = nn.Conv2d(in_features, mid_features,
|
| 144 |
+
3, padding=1, stride=stride)
|
| 145 |
+
self.bn1 = nn.BatchNorm2d(mid_features)
|
| 146 |
+
self.conv2 = nn.Conv2d(mid_features, out_features, 3, padding=1)
|
| 147 |
+
self.bn2 = nn.BatchNorm2d(out_features)
|
| 148 |
+
self.relu = nn.ReLU(inplace=True)
|
| 149 |
+
|
| 150 |
+
def forward(self, x):
|
| 151 |
+
x = self.conv1(x)
|
| 152 |
+
x = self.bn1(x)
|
| 153 |
+
x = self.relu(x)
|
| 154 |
+
x = self.conv2(x)
|
| 155 |
+
x = self.bn2(x)
|
| 156 |
+
if self.use_act:
|
| 157 |
+
x = self.relu(x)
|
| 158 |
+
return x
|
| 159 |
+
|
| 160 |
+
|
| 161 |
+
class DexiNed(nn.Module):
|
| 162 |
+
""" Definition of the DXtrem network. """
|
| 163 |
+
|
| 164 |
+
def __init__(self):
|
| 165 |
+
super(DexiNed, self).__init__()
|
| 166 |
+
self.block_1 = DoubleConvBlock(3, 32, 64, stride=2,)
|
| 167 |
+
self.block_2 = DoubleConvBlock(64, 128, use_act=False)
|
| 168 |
+
self.dblock_3 = _DenseBlock(2, 128, 256) # [128,256,100,100]
|
| 169 |
+
self.dblock_4 = _DenseBlock(3, 256, 512)
|
| 170 |
+
self.dblock_5 = _DenseBlock(3, 512, 512)
|
| 171 |
+
self.dblock_6 = _DenseBlock(3, 512, 256)
|
| 172 |
+
self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
|
| 173 |
+
|
| 174 |
+
# left skip connections, figure in Journal
|
| 175 |
+
self.side_1 = SingleConvBlock(64, 128, 2)
|
| 176 |
+
self.side_2 = SingleConvBlock(128, 256, 2)
|
| 177 |
+
self.side_3 = SingleConvBlock(256, 512, 2)
|
| 178 |
+
self.side_4 = SingleConvBlock(512, 512, 1)
|
| 179 |
+
self.side_5 = SingleConvBlock(512, 256, 1) # Sory I forget to comment this line :(
|
| 180 |
+
|
| 181 |
+
# right skip connections, figure in Journal paper
|
| 182 |
+
self.pre_dense_2 = SingleConvBlock(128, 256, 2)
|
| 183 |
+
self.pre_dense_3 = SingleConvBlock(128, 256, 1)
|
| 184 |
+
self.pre_dense_4 = SingleConvBlock(256, 512, 1)
|
| 185 |
+
self.pre_dense_5 = SingleConvBlock(512, 512, 1)
|
| 186 |
+
self.pre_dense_6 = SingleConvBlock(512, 256, 1)
|
| 187 |
+
|
| 188 |
+
|
| 189 |
+
self.up_block_1 = UpConvBlock(64, 1)
|
| 190 |
+
self.up_block_2 = UpConvBlock(128, 1)
|
| 191 |
+
self.up_block_3 = UpConvBlock(256, 2)
|
| 192 |
+
self.up_block_4 = UpConvBlock(512, 3)
|
| 193 |
+
self.up_block_5 = UpConvBlock(512, 4)
|
| 194 |
+
self.up_block_6 = UpConvBlock(256, 4)
|
| 195 |
+
self.block_cat = SingleConvBlock(6, 1, stride=1, use_bs=False) # hed fusion method
|
| 196 |
+
# self.block_cat = CoFusion(6,6)# cats fusion method
|
| 197 |
+
|
| 198 |
+
|
| 199 |
+
self.apply(weight_init)
|
| 200 |
+
|
| 201 |
+
def slice(self, tensor, slice_shape):
|
| 202 |
+
t_shape = tensor.shape
|
| 203 |
+
height, width = slice_shape
|
| 204 |
+
if t_shape[-1]!=slice_shape[-1]:
|
| 205 |
+
new_tensor = F.interpolate(
|
| 206 |
+
tensor, size=(height, width), mode='bicubic',align_corners=False)
|
| 207 |
+
else:
|
| 208 |
+
new_tensor=tensor
|
| 209 |
+
# tensor[..., :height, :width]
|
| 210 |
+
return new_tensor
|
| 211 |
+
|
| 212 |
+
def forward(self, x):
|
| 213 |
+
assert x.ndim == 4, x.shape
|
| 214 |
+
|
| 215 |
+
# Block 1
|
| 216 |
+
block_1 = self.block_1(x)
|
| 217 |
+
block_1_side = self.side_1(block_1)
|
| 218 |
+
|
| 219 |
+
# Block 2
|
| 220 |
+
block_2 = self.block_2(block_1)
|
| 221 |
+
block_2_down = self.maxpool(block_2)
|
| 222 |
+
block_2_add = block_2_down + block_1_side
|
| 223 |
+
block_2_side = self.side_2(block_2_add)
|
| 224 |
+
|
| 225 |
+
# Block 3
|
| 226 |
+
block_3_pre_dense = self.pre_dense_3(block_2_down)
|
| 227 |
+
block_3, _ = self.dblock_3([block_2_add, block_3_pre_dense])
|
| 228 |
+
block_3_down = self.maxpool(block_3) # [128,256,50,50]
|
| 229 |
+
block_3_add = block_3_down + block_2_side
|
| 230 |
+
block_3_side = self.side_3(block_3_add)
|
| 231 |
+
|
| 232 |
+
# Block 4
|
| 233 |
+
block_2_resize_half = self.pre_dense_2(block_2_down)
|
| 234 |
+
block_4_pre_dense = self.pre_dense_4(block_3_down+block_2_resize_half)
|
| 235 |
+
block_4, _ = self.dblock_4([block_3_add, block_4_pre_dense])
|
| 236 |
+
block_4_down = self.maxpool(block_4)
|
| 237 |
+
block_4_add = block_4_down + block_3_side
|
| 238 |
+
block_4_side = self.side_4(block_4_add)
|
| 239 |
+
|
| 240 |
+
# Block 5
|
| 241 |
+
block_5_pre_dense = self.pre_dense_5(
|
| 242 |
+
block_4_down) #block_5_pre_dense_512 +block_4_down
|
| 243 |
+
block_5, _ = self.dblock_5([block_4_add, block_5_pre_dense])
|
| 244 |
+
block_5_add = block_5 + block_4_side
|
| 245 |
+
|
| 246 |
+
# Block 6
|
| 247 |
+
block_6_pre_dense = self.pre_dense_6(block_5)
|
| 248 |
+
block_6, _ = self.dblock_6([block_5_add, block_6_pre_dense])
|
| 249 |
+
|
| 250 |
+
# upsampling blocks
|
| 251 |
+
out_1 = self.up_block_1(block_1)
|
| 252 |
+
out_2 = self.up_block_2(block_2)
|
| 253 |
+
out_3 = self.up_block_3(block_3)
|
| 254 |
+
out_4 = self.up_block_4(block_4)
|
| 255 |
+
out_5 = self.up_block_5(block_5)
|
| 256 |
+
out_6 = self.up_block_6(block_6)
|
| 257 |
+
results = [out_1, out_2, out_3, out_4, out_5, out_6]
|
| 258 |
+
|
| 259 |
+
# concatenate multiscale outputs
|
| 260 |
+
block_cat = torch.cat(results, dim=1) # Bx6xHxW
|
| 261 |
+
block_cat = self.block_cat(block_cat) # Bx1xHxW
|
| 262 |
+
|
| 263 |
+
# return results
|
| 264 |
+
results.append(block_cat)
|
| 265 |
+
return results
|
| 266 |
+
|
| 267 |
+
|
| 268 |
+
if __name__ == '__main__':
|
| 269 |
+
batch_size = 8
|
| 270 |
+
img_height = 352
|
| 271 |
+
img_width = 352
|
| 272 |
+
|
| 273 |
+
# device = "cuda" if torch.cuda.is_available() else "cpu"
|
| 274 |
+
device = "cpu"
|
| 275 |
+
input = torch.rand(batch_size, 3, img_height, img_width).to(device)
|
| 276 |
+
# target = torch.rand(batch_size, 1, img_height, img_width).to(device)
|
| 277 |
+
print(f"input shape: {input.shape}")
|
| 278 |
+
model = DexiNed().to(device)
|
| 279 |
+
output = model(input)
|
| 280 |
+
print(f"output shapes: {[t.shape for t in output]}")
|
| 281 |
+
|
| 282 |
+
# for i in range(20000):
|
| 283 |
+
# print(i)
|
| 284 |
+
# output = model(input)
|
| 285 |
+
# loss = nn.MSELoss()(output[-1], target)
|
| 286 |
+
# loss.backward()
|
requirements.txt
CHANGED
|
@@ -1,3 +1,8 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
streamlit>=1.0
|
| 2 |
+
torch>=1.4
|
| 3 |
+
opencv-python-headless>=4.5
|
| 4 |
+
matplotlib
|
| 5 |
+
kornia
|
| 6 |
+
numpy
|
| 7 |
+
h5py
|
| 8 |
+
Pillow
|
res/BIPED/DexiNed-a/eval_bdry.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
0.68 0.893704 0.891902 0.892802 0.8983 0.89665 0.897474 0.93966
|
res/BIPED/DexiNed-a/eval_bdry_img.txt
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
1 0.67 0.918017 0.921663 0.919836
|
| 2 |
+
2 0.67 0.924182 0.884619 0.903968
|
| 3 |
+
3 0.68 0.829315 0.817614 0.823423
|
| 4 |
+
4 0.7 0.936372 0.90522 0.920533
|
| 5 |
+
5 0.72 0.893542 0.864391 0.878725
|
| 6 |
+
6 0.7 0.879453 0.88686 0.883141
|
| 7 |
+
7 0.67 0.929135 0.856629 0.89141
|
| 8 |
+
8 0.67 0.913886 0.87818 0.895677
|
| 9 |
+
9 0.71 0.873921 0.895068 0.884368
|
| 10 |
+
10 0.7 0.916716 0.915163 0.915939
|
| 11 |
+
11 0.67 0.920275 0.888373 0.904043
|
| 12 |
+
12 0.65 0.875954 0.905624 0.890542
|
| 13 |
+
13 0.656061 0.941063 0.890717 0.915198
|
| 14 |
+
14 0.703737 0.887589 0.883706 0.885643
|
| 15 |
+
15 0.62 0.945175 0.912697 0.928652
|
| 16 |
+
16 0.72 0.904389 0.892603 0.898457
|
| 17 |
+
17 0.73 0.932328 0.898245 0.914969
|
| 18 |
+
18 0.647374 0.911589 0.891872 0.901623
|
| 19 |
+
19 0.69 0.94388 0.946975 0.945425
|
| 20 |
+
20 0.663939 0.941802 0.921463 0.931521
|
| 21 |
+
21 0.73 0.973881 0.853938 0.909974
|
| 22 |
+
22 0.68 0.921542 0.927196 0.92436
|
| 23 |
+
23 0.62 0.924614 0.937149 0.930839
|
| 24 |
+
24 0.69 0.936955 0.843424 0.887733
|
| 25 |
+
25 0.7 0.912016 0.920638 0.916307
|
| 26 |
+
26 0.68 0.905477 0.888534 0.896925
|
| 27 |
+
27 0.66 0.865637 0.915651 0.889942
|
| 28 |
+
28 0.75 0.892646 0.908084 0.900299
|
| 29 |
+
29 0.68 0.935828 0.915717 0.925663
|
| 30 |
+
30 0.71 0.913648 0.890326 0.901836
|
| 31 |
+
31 0.74 0.904806 0.863486 0.883664
|
| 32 |
+
32 0.59 0.68313 0.921634 0.784658
|
| 33 |
+
33 0.71 0.838473 0.873585 0.855669
|
| 34 |
+
34 0.65 0.902898 0.914365 0.908595
|
| 35 |
+
35 0.68 0.913161 0.910422 0.911789
|
| 36 |
+
36 0.63 0.90569 0.893079 0.89934
|
| 37 |
+
37 0.69 0.887816 0.892947 0.890374
|
| 38 |
+
38 0.59 0.845585 0.914471 0.87868
|
| 39 |
+
39 0.71 0.908513 0.906695 0.907603
|
| 40 |
+
40 0.67 0.94974 0.88582 0.916667
|
| 41 |
+
41 0.71 0.889896 0.949489 0.918727
|
| 42 |
+
42 0.41 0.849084 0.874457 0.861584
|
| 43 |
+
43 0.6 0.805666 0.862249 0.832998
|
| 44 |
+
44 0.7 0.900068 0.908481 0.904255
|
| 45 |
+
45 0.78 0.844644 0.915197 0.878506
|
| 46 |
+
46 0.76 0.891072 0.889334 0.890202
|
| 47 |
+
47 0.59 0.940304 0.940185 0.940244
|
| 48 |
+
48 0.55 0.916852 0.905893 0.91134
|
| 49 |
+
49 0.56 0.930273 0.875427 0.902018
|
| 50 |
+
50 0.5 0.883004 0.914133 0.898299
|
res/BIPED/DexiNed-a/eval_bdry_thr.txt
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
0.01 0.988175 0.207782 0.343366
|
| 2 |
+
0.02 0.986216 0.253632 0.403495
|
| 3 |
+
0.03 0.98531 0.280848 0.437106
|
| 4 |
+
0.04 0.984197 0.317963 0.480644
|
| 5 |
+
0.05 0.98361 0.34075 0.506154
|
| 6 |
+
0.06 0.98274 0.372731 0.540473
|
| 7 |
+
0.07 0.982081 0.392988 0.561348
|
| 8 |
+
0.08 0.980956 0.421624 0.589762
|
| 9 |
+
0.09 0.980192 0.439719 0.607093
|
| 10 |
+
0.1 0.979071 0.465276 0.630788
|
| 11 |
+
0.11 0.978019 0.489119 0.65211
|
| 12 |
+
0.12 0.977452 0.504122 0.665178
|
| 13 |
+
0.13 0.976534 0.525536 0.683329
|
| 14 |
+
0.14 0.975905 0.538951 0.69441
|
| 15 |
+
0.15 0.975019 0.557785 0.709616
|
| 16 |
+
0.16 0.974403 0.569401 0.718777
|
| 17 |
+
0.17 0.973414 0.585647 0.731308
|
| 18 |
+
0.18 0.972738 0.595669 0.738877
|
| 19 |
+
0.19 0.971748 0.609387 0.749045
|
| 20 |
+
0.2 0.971205 0.617662 0.7551
|
| 21 |
+
0.21 0.970467 0.629194 0.763426
|
| 22 |
+
0.22 0.969727 0.639676 0.770859
|
| 23 |
+
0.23 0.969201 0.646257 0.775449
|
| 24 |
+
0.24 0.968419 0.655424 0.781757
|
| 25 |
+
0.25 0.9679 0.661159 0.785651
|
| 26 |
+
0.26 0.967156 0.669391 0.791185
|
| 27 |
+
0.27 0.966609 0.674612 0.794635
|
| 28 |
+
0.28 0.965865 0.681981 0.79947
|
| 29 |
+
0.29 0.965355 0.686676 0.80251
|
| 30 |
+
0.3 0.964581 0.693399 0.806813
|
| 31 |
+
0.31 0.963723 0.699708 0.810764
|
| 32 |
+
0.32 0.963135 0.703819 0.813307
|
| 33 |
+
0.33 0.962263 0.709873 0.81702
|
| 34 |
+
0.34 0.961615 0.713707 0.819319
|
| 35 |
+
0.35 0.960661 0.719355 0.822678
|
| 36 |
+
0.36 0.959952 0.723046 0.824826
|
| 37 |
+
0.37 0.958813 0.728583 0.827991
|
| 38 |
+
0.38 0.958129 0.732161 0.83004
|
| 39 |
+
0.39 0.957105 0.737354 0.83298
|
| 40 |
+
0.4 0.956477 0.74065 0.83484
|
| 41 |
+
0.41 0.955464 0.745614 0.837595
|
| 42 |
+
0.42 0.95444 0.75057 0.840316
|
| 43 |
+
0.43 0.953731 0.753903 0.842125
|
| 44 |
+
0.44 0.95268 0.758965 0.844861
|
| 45 |
+
0.45 0.951934 0.762367 0.846669
|
| 46 |
+
0.46 0.950701 0.767516 0.849343
|
| 47 |
+
0.47 0.94986 0.77107 0.851177
|
| 48 |
+
0.48 0.948544 0.776395 0.853879
|
| 49 |
+
0.49 0.947588 0.780009 0.855671
|
| 50 |
+
0.5 0.946131 0.78556 0.858401
|
| 51 |
+
0.51 0.944459 0.791298 0.861122
|
| 52 |
+
0.52 0.9432 0.795149 0.86287
|
| 53 |
+
0.53 0.941287 0.801239 0.865635
|
| 54 |
+
0.54 0.939963 0.80534 0.867459
|
| 55 |
+
0.55 0.937768 0.811506 0.87008
|
| 56 |
+
0.56 0.936222 0.815705 0.871818
|
| 57 |
+
0.57 0.933742 0.822284 0.874476
|
| 58 |
+
0.58 0.932102 0.826791 0.876294
|
| 59 |
+
0.59 0.929411 0.833635 0.878921
|
| 60 |
+
0.6 0.927518 0.8385 0.880766
|
| 61 |
+
0.61 0.924376 0.845633 0.883253
|
| 62 |
+
0.62 0.920763 0.85294 0.885555
|
| 63 |
+
0.63 0.918176 0.857962 0.887049
|
| 64 |
+
0.64 0.913762 0.865697 0.889081
|
| 65 |
+
0.65 0.910492 0.870926 0.890269
|
| 66 |
+
0.66 0.904977 0.878862 0.891729
|
| 67 |
+
0.67 0.900806 0.884203 0.892427
|
| 68 |
+
0.68 0.893704 0.891902 0.892802
|
| 69 |
+
0.69 0.88838 0.897135 0.892736
|
| 70 |
+
0.7 0.879576 0.904908 0.892062
|
| 71 |
+
0.71 0.869423 0.9122 0.890298
|
| 72 |
+
0.72 0.861751 0.917011 0.888523
|
| 73 |
+
0.73 0.849116 0.924042 0.884996
|
| 74 |
+
0.74 0.839958 0.928623 0.882068
|
| 75 |
+
0.75 0.824696 0.935411 0.876572
|
| 76 |
+
0.76 0.81359 0.939705 0.872111
|
| 77 |
+
0.77 0.795146 0.945445 0.863806
|
| 78 |
+
0.78 0.782052 0.949373 0.857628
|
| 79 |
+
0.79 0.759937 0.954739 0.846272
|
| 80 |
+
0.8 0.743715 0.958184 0.837436
|
| 81 |
+
0.81 0.717211 0.962967 0.822116
|
| 82 |
+
0.82 0.687891 0.967594 0.804114
|
| 83 |
+
0.83 0.66603 0.970528 0.789952
|
| 84 |
+
0.84 0.630251 0.975011 0.765609
|
| 85 |
+
0.85 0.603783 0.977975 0.746618
|
| 86 |
+
0.86 0.559587 0.982141 0.712958
|
| 87 |
+
0.87 0.526596 0.985282 0.686359
|
| 88 |
+
0.88 0.470019 0.98926 0.637261
|
| 89 |
+
0.89 0.427076 0.991085 0.596926
|
| 90 |
+
0.9 0.355622 0.993421 0.523753
|
| 91 |
+
0.91 0.278522 0.995622 0.435276
|
| 92 |
+
0.92 0.225169 0.996738 0.367351
|
| 93 |
+
0.93 0.145354 0.99803 0.253752
|
| 94 |
+
0.94 0.0959961 0.99866 0.175155
|
| 95 |
+
0.95 0.0390728 0.998928 0.0752041
|
| 96 |
+
0.96 0.0163508 0.99861 0.0321749
|
| 97 |
+
0.97 0.00220779 0.998104 0.00440584
|
| 98 |
+
0.98 0.000103649 1 0.000207277
|
| 99 |
+
0.99 0 0 0
|
res/BIPED/DexiNed-a/ios_res.txt
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name,oisT1,oisR1,oisP1,oisF1
|
| 2 |
+
RGB_008,0.6700,0.9180,0.9217,0.9198
|
| 3 |
+
RGB_010,0.6700,0.9242,0.8846,0.9040
|
| 4 |
+
RGB_017,0.6800,0.8293,0.8176,0.8234
|
| 5 |
+
RGB_025,0.7000,0.9364,0.9052,0.9205
|
| 6 |
+
RGB_029,0.7200,0.8935,0.8644,0.8787
|
| 7 |
+
RGB_033,0.7000,0.8795,0.8869,0.8831
|
| 8 |
+
RGB_035,0.6700,0.9291,0.8566,0.8914
|
| 9 |
+
RGB_039,0.6700,0.9139,0.8782,0.8957
|
| 10 |
+
RGB_042,0.7100,0.8739,0.8951,0.8844
|
| 11 |
+
RGB_052,0.7000,0.9167,0.9152,0.9159
|
| 12 |
+
RGB_056,0.6700,0.9203,0.8884,0.9040
|
| 13 |
+
RGB_057,0.6500,0.8760,0.9056,0.8905
|
| 14 |
+
RGB_059,0.6561,0.9411,0.8907,0.9152
|
| 15 |
+
RGB_066,0.7037,0.8876,0.8837,0.8856
|
| 16 |
+
RGB_067,0.6200,0.9452,0.9127,0.9287
|
| 17 |
+
RGB_070,0.7200,0.9044,0.8926,0.8985
|
| 18 |
+
RGB_071,0.7300,0.9323,0.8982,0.9150
|
| 19 |
+
RGB_075,0.6474,0.9116,0.8919,0.9016
|
| 20 |
+
RGB_081,0.6900,0.9439,0.9470,0.9454
|
| 21 |
+
RGB_083,0.6639,0.9418,0.9215,0.9315
|
| 22 |
+
RGB_090,0.7300,0.9739,0.8539,0.9100
|
| 23 |
+
RGB_092,0.6800,0.9215,0.9272,0.9244
|
| 24 |
+
RGB_094,0.6200,0.9246,0.9371,0.9308
|
| 25 |
+
RGB_098,0.6900,0.9370,0.8434,0.8877
|
| 26 |
+
RGB_102,0.7000,0.9120,0.9206,0.9163
|
| 27 |
+
RGB_107,0.6800,0.9055,0.8885,0.8969
|
| 28 |
+
RGB_111,0.6600,0.8656,0.9157,0.8899
|
| 29 |
+
RGB_120,0.7500,0.8926,0.9081,0.9003
|
| 30 |
+
RGB_124,0.6800,0.9358,0.9157,0.9257
|
| 31 |
+
RGB_132,0.7100,0.9136,0.8903,0.9018
|
| 32 |
+
RGB_138,0.7400,0.9048,0.8635,0.8837
|
| 33 |
+
RGB_139,0.5900,0.6831,0.9216,0.7847
|
| 34 |
+
RGB_141,0.7100,0.8385,0.8736,0.8557
|
| 35 |
+
RGB_145,0.6500,0.9029,0.9144,0.9086
|
| 36 |
+
RGB_160,0.6800,0.9132,0.9104,0.9118
|
| 37 |
+
RGB_170,0.6300,0.9057,0.8931,0.8993
|
| 38 |
+
RGB_181,0.6900,0.8878,0.8929,0.8904
|
| 39 |
+
RGB_182,0.5900,0.8456,0.9145,0.8787
|
| 40 |
+
RGB_190,0.7100,0.9085,0.9067,0.9076
|
| 41 |
+
RGB_192,0.6700,0.9497,0.8858,0.9167
|
| 42 |
+
RGB_206,0.7100,0.8899,0.9495,0.9187
|
| 43 |
+
RGB_212,0.4100,0.8491,0.8745,0.8616
|
| 44 |
+
RGB_214,0.6000,0.8057,0.8622,0.8330
|
| 45 |
+
RGB_226,0.7000,0.9001,0.9085,0.9043
|
| 46 |
+
RGB_228,0.7800,0.8446,0.9152,0.8785
|
| 47 |
+
RGB_234,0.7600,0.8911,0.8893,0.8902
|
| 48 |
+
RGB_237,0.5900,0.9403,0.9402,0.9402
|
| 49 |
+
RGB_247,0.5500,0.9169,0.9059,0.9113
|
| 50 |
+
RGB_248,0.5600,0.9303,0.8754,0.9020
|
| 51 |
+
RGB_254,0.5000,0.8830,0.9141,0.8983
|
res/BIPED/DexiNed-f/eval_bdry.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
0.72 0.893459 0.896543 0.894998 0.902943 0.89788 0.900405 0.926588
|
res/BIPED/DexiNed-f/eval_bdry_img.txt
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
1 0.69 0.926056 0.915888 0.920944
|
| 2 |
+
2 0.71 0.919448 0.908713 0.914049
|
| 3 |
+
3 0.75 0.843854 0.831785 0.837776
|
| 4 |
+
4 0.8 0.936259 0.909764 0.922821
|
| 5 |
+
5 0.77 0.88401 0.856038 0.869799
|
| 6 |
+
6 0.79 0.87562 0.902286 0.888753
|
| 7 |
+
7 0.65 0.949605 0.829958 0.885759
|
| 8 |
+
8 0.71 0.894801 0.891634 0.893214
|
| 9 |
+
9 0.744141 0.89899 0.914359 0.906609
|
| 10 |
+
10 0.68 0.934196 0.898731 0.916121
|
| 11 |
+
11 0.66 0.927261 0.887812 0.907107
|
| 12 |
+
12 0.69 0.860233 0.925554 0.891699
|
| 13 |
+
13 0.66 0.961541 0.904682 0.932245
|
| 14 |
+
14 0.71 0.90251 0.87612 0.889119
|
| 15 |
+
15 0.68 0.927315 0.940563 0.933892
|
| 16 |
+
16 0.77 0.910788 0.893992 0.902311
|
| 17 |
+
17 0.75 0.934857 0.896983 0.915529
|
| 18 |
+
18 0.65 0.918032 0.903552 0.910735
|
| 19 |
+
19 0.74 0.945621 0.952114 0.948856
|
| 20 |
+
20 0.61 0.958399 0.923796 0.940779
|
| 21 |
+
21 0.81 0.968809 0.865592 0.914296
|
| 22 |
+
22 0.74 0.932564 0.916397 0.92441
|
| 23 |
+
23 0.64 0.912742 0.94139 0.926845
|
| 24 |
+
24 0.71 0.934661 0.861214 0.896436
|
| 25 |
+
25 0.71 0.916226 0.924688 0.920438
|
| 26 |
+
26 0.72 0.915938 0.881975 0.898636
|
| 27 |
+
27 0.62 0.888638 0.897102 0.89285
|
| 28 |
+
28 0.78 0.926264 0.905505 0.915767
|
| 29 |
+
29 0.69 0.929126 0.914336 0.921672
|
| 30 |
+
30 0.73 0.921188 0.8909 0.905791
|
| 31 |
+
31 0.79 0.917942 0.851855 0.883664
|
| 32 |
+
32 0.55 0.686601 0.934876 0.791731
|
| 33 |
+
33 0.71 0.863806 0.866542 0.865172
|
| 34 |
+
34 0.61 0.913651 0.904125 0.908863
|
| 35 |
+
35 0.71 0.905047 0.90312 0.904082
|
| 36 |
+
36 0.59 0.92391 0.89769 0.910611
|
| 37 |
+
37 0.67 0.906366 0.879008 0.892477
|
| 38 |
+
38 0.55 0.848673 0.905456 0.876145
|
| 39 |
+
39 0.76 0.886487 0.902989 0.894662
|
| 40 |
+
40 0.68 0.945881 0.895856 0.920189
|
| 41 |
+
41 0.72 0.903101 0.937613 0.920033
|
| 42 |
+
42 0.16 0.844707 0.880088 0.862035
|
| 43 |
+
43 0.55 0.848311 0.854467 0.851378
|
| 44 |
+
44 0.73 0.890069 0.907548 0.898724
|
| 45 |
+
45 0.84 0.836801 0.91615 0.874679
|
| 46 |
+
46 0.78 0.909175 0.874802 0.891657
|
| 47 |
+
47 0.5 0.921918 0.944137 0.932895
|
| 48 |
+
48 0.32 0.921204 0.90472 0.912888
|
| 49 |
+
49 0.44 0.94737 0.889883 0.917727
|
| 50 |
+
50 0.25 0.89233 0.915361 0.903699
|
res/BIPED/DexiNed-f/eval_bdry_thr.txt
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
0.01 0.962888 0.692543 0.80564
|
| 2 |
+
0.02 0.960933 0.71092 0.817232
|
| 3 |
+
0.03 0.96017 0.717425 0.821235
|
| 4 |
+
0.04 0.959307 0.724555 0.825567
|
| 5 |
+
0.05 0.958872 0.728389 0.827889
|
| 6 |
+
0.06 0.958251 0.733298 0.830817
|
| 7 |
+
0.07 0.957905 0.736193 0.832541
|
| 8 |
+
0.08 0.95731 0.740079 0.834794
|
| 9 |
+
0.09 0.956905 0.742451 0.836147
|
| 10 |
+
0.1 0.956386 0.745858 0.838103
|
| 11 |
+
0.11 0.955846 0.7491 0.839938
|
| 12 |
+
0.12 0.955531 0.75113 0.84109
|
| 13 |
+
0.13 0.955084 0.754159 0.842812
|
| 14 |
+
0.14 0.954775 0.756175 0.843949
|
| 15 |
+
0.15 0.954276 0.759107 0.845576
|
| 16 |
+
0.16 0.95394 0.761087 0.84667
|
| 17 |
+
0.17 0.95336 0.764057 0.848275
|
| 18 |
+
0.18 0.952929 0.766236 0.849446
|
| 19 |
+
0.19 0.951941 0.769254 0.850902
|
| 20 |
+
0.2 0.951526 0.770822 0.851695
|
| 21 |
+
0.21 0.95103 0.773054 0.852856
|
| 22 |
+
0.22 0.950612 0.775275 0.854037
|
| 23 |
+
0.23 0.950318 0.776742 0.854808
|
| 24 |
+
0.24 0.949884 0.778958 0.855971
|
| 25 |
+
0.25 0.949554 0.78036 0.856683
|
| 26 |
+
0.26 0.949115 0.782458 0.857767
|
| 27 |
+
0.27 0.948809 0.783828 0.858464
|
| 28 |
+
0.28 0.948326 0.785945 0.859534
|
| 29 |
+
0.29 0.948024 0.787363 0.860256
|
| 30 |
+
0.3 0.947534 0.789401 0.861269
|
| 31 |
+
0.31 0.947056 0.791569 0.86236
|
| 32 |
+
0.32 0.946731 0.793041 0.863098
|
| 33 |
+
0.33 0.946165 0.795214 0.864147
|
| 34 |
+
0.34 0.945812 0.796697 0.864874
|
| 35 |
+
0.35 0.945213 0.798981 0.865967
|
| 36 |
+
0.36 0.944761 0.800546 0.866696
|
| 37 |
+
0.37 0.943906 0.802928 0.867728
|
| 38 |
+
0.38 0.943315 0.804466 0.868376
|
| 39 |
+
0.39 0.942604 0.806703 0.869374
|
| 40 |
+
0.4 0.942171 0.808189 0.870052
|
| 41 |
+
0.41 0.941488 0.810427 0.871055
|
| 42 |
+
0.42 0.940734 0.812654 0.872016
|
| 43 |
+
0.43 0.940212 0.814186 0.872673
|
| 44 |
+
0.44 0.939358 0.816525 0.873645
|
| 45 |
+
0.45 0.938869 0.818122 0.874347
|
| 46 |
+
0.46 0.938006 0.820602 0.875385
|
| 47 |
+
0.47 0.937369 0.822269 0.876055
|
| 48 |
+
0.48 0.936494 0.82485 0.877134
|
| 49 |
+
0.49 0.935873 0.826621 0.877861
|
| 50 |
+
0.5 0.934833 0.829298 0.878909
|
| 51 |
+
0.51 0.933855 0.832137 0.880067
|
| 52 |
+
0.52 0.933124 0.833972 0.880766
|
| 53 |
+
0.53 0.931935 0.836982 0.88191
|
| 54 |
+
0.54 0.931025 0.83903 0.882637
|
| 55 |
+
0.55 0.929619 0.842154 0.883728
|
| 56 |
+
0.56 0.928601 0.844236 0.884411
|
| 57 |
+
0.57 0.926943 0.847476 0.88543
|
| 58 |
+
0.58 0.92591 0.849679 0.886158
|
| 59 |
+
0.59 0.924312 0.852897 0.88717
|
| 60 |
+
0.6 0.923159 0.855004 0.887776
|
| 61 |
+
0.61 0.921425 0.858361 0.888776
|
| 62 |
+
0.62 0.919475 0.861817 0.889713
|
| 63 |
+
0.63 0.918119 0.864269 0.890381
|
| 64 |
+
0.64 0.915871 0.867947 0.891265
|
| 65 |
+
0.65 0.914291 0.870452 0.891833
|
| 66 |
+
0.66 0.911733 0.874354 0.892652
|
| 67 |
+
0.67 0.909824 0.877017 0.89312
|
| 68 |
+
0.68 0.906768 0.881267 0.893836
|
| 69 |
+
0.69 0.904447 0.884212 0.894215
|
| 70 |
+
0.7 0.900691 0.888645 0.894628
|
| 71 |
+
0.71 0.896555 0.893313 0.894931
|
| 72 |
+
0.72 0.893459 0.896543 0.894998
|
| 73 |
+
0.73 0.888287 0.901458 0.894824
|
| 74 |
+
0.74 0.884496 0.904712 0.89449
|
| 75 |
+
0.75 0.877767 0.909729 0.893462
|
| 76 |
+
0.76 0.872756 0.913224 0.892531
|
| 77 |
+
0.77 0.864504 0.918394 0.890635
|
| 78 |
+
0.78 0.858398 0.922011 0.889068
|
| 79 |
+
0.79 0.848066 0.927246 0.88589
|
| 80 |
+
0.8 0.840315 0.930758 0.883227
|
| 81 |
+
0.81 0.826772 0.935883 0.87795
|
| 82 |
+
0.82 0.81089 0.941024 0.871123
|
| 83 |
+
0.83 0.798715 0.944474 0.865501
|
| 84 |
+
0.84 0.777873 0.949745 0.85526
|
| 85 |
+
0.85 0.761862 0.95316 0.846842
|
| 86 |
+
0.86 0.734225 0.957972 0.831306
|
| 87 |
+
0.87 0.712997 0.961176 0.818691
|
| 88 |
+
0.88 0.675414 0.965892 0.794949
|
| 89 |
+
0.89 0.646561 0.969267 0.77569
|
| 90 |
+
0.9 0.595381 0.974561 0.73918
|
| 91 |
+
0.91 0.532278 0.979687 0.689785
|
| 92 |
+
0.92 0.482637 0.983132 0.647436
|
| 93 |
+
0.93 0.396158 0.987503 0.565467
|
| 94 |
+
0.94 0.331673 0.989725 0.496846
|
| 95 |
+
0.95 0.229612 0.992629 0.372953
|
| 96 |
+
0.96 0.161409 0.994562 0.277742
|
| 97 |
+
0.97 0.0714786 0.996692 0.133391
|
| 98 |
+
0.98 0.0295587 0.996888 0.0574149
|
| 99 |
+
0.99 0.00279374 0.997647 0.00557188
|
res/BIPED/DexiNed-f/ios_res.txt
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name,oisT1,oisR1,oisP1,oisF1
|
| 2 |
+
RGB_008,0.6900,0.9261,0.9159,0.9209
|
| 3 |
+
RGB_010,0.7100,0.9194,0.9087,0.9140
|
| 4 |
+
RGB_017,0.7500,0.8439,0.8318,0.8378
|
| 5 |
+
RGB_025,0.8000,0.9363,0.9098,0.9228
|
| 6 |
+
RGB_029,0.7700,0.8840,0.8560,0.8698
|
| 7 |
+
RGB_033,0.7900,0.8756,0.9023,0.8888
|
| 8 |
+
RGB_035,0.6500,0.9496,0.8300,0.8858
|
| 9 |
+
RGB_039,0.7100,0.8948,0.8916,0.8932
|
| 10 |
+
RGB_042,0.7441,0.8990,0.9144,0.9066
|
| 11 |
+
RGB_052,0.6800,0.9342,0.8987,0.9161
|
| 12 |
+
RGB_056,0.6600,0.9273,0.8878,0.9071
|
| 13 |
+
RGB_057,0.6900,0.8602,0.9256,0.8917
|
| 14 |
+
RGB_059,0.6600,0.9615,0.9047,0.9322
|
| 15 |
+
RGB_066,0.7100,0.9025,0.8761,0.8891
|
| 16 |
+
RGB_067,0.6800,0.9273,0.9406,0.9339
|
| 17 |
+
RGB_070,0.7700,0.9108,0.8940,0.9023
|
| 18 |
+
RGB_071,0.7500,0.9349,0.8970,0.9155
|
| 19 |
+
RGB_075,0.6500,0.9180,0.9036,0.9107
|
| 20 |
+
RGB_081,0.7400,0.9456,0.9521,0.9489
|
| 21 |
+
RGB_083,0.6100,0.9584,0.9238,0.9408
|
| 22 |
+
RGB_090,0.8100,0.9688,0.8656,0.9143
|
| 23 |
+
RGB_092,0.7400,0.9326,0.9164,0.9244
|
| 24 |
+
RGB_094,0.6400,0.9127,0.9414,0.9268
|
| 25 |
+
RGB_098,0.7100,0.9347,0.8612,0.8964
|
| 26 |
+
RGB_102,0.7100,0.9162,0.9247,0.9204
|
| 27 |
+
RGB_107,0.7200,0.9159,0.8820,0.8986
|
| 28 |
+
RGB_111,0.6200,0.8886,0.8971,0.8928
|
| 29 |
+
RGB_120,0.7800,0.9263,0.9055,0.9158
|
| 30 |
+
RGB_124,0.6900,0.9291,0.9143,0.9217
|
| 31 |
+
RGB_132,0.7300,0.9212,0.8909,0.9058
|
| 32 |
+
RGB_138,0.7900,0.9179,0.8519,0.8837
|
| 33 |
+
RGB_139,0.5500,0.6866,0.9349,0.7917
|
| 34 |
+
RGB_141,0.7100,0.8638,0.8665,0.8652
|
| 35 |
+
RGB_145,0.6100,0.9137,0.9041,0.9089
|
| 36 |
+
RGB_160,0.7100,0.9050,0.9031,0.9041
|
| 37 |
+
RGB_170,0.5900,0.9239,0.8977,0.9106
|
| 38 |
+
RGB_181,0.6700,0.9064,0.8790,0.8925
|
| 39 |
+
RGB_182,0.5500,0.8487,0.9055,0.8761
|
| 40 |
+
RGB_190,0.7600,0.8865,0.9030,0.8947
|
| 41 |
+
RGB_192,0.6800,0.9459,0.8959,0.9202
|
| 42 |
+
RGB_206,0.7200,0.9031,0.9376,0.9200
|
| 43 |
+
RGB_212,0.1600,0.8447,0.8801,0.8620
|
| 44 |
+
RGB_214,0.5500,0.8483,0.8545,0.8514
|
| 45 |
+
RGB_226,0.7300,0.8901,0.9075,0.8987
|
| 46 |
+
RGB_228,0.8400,0.8368,0.9162,0.8747
|
| 47 |
+
RGB_234,0.7800,0.9092,0.8748,0.8917
|
| 48 |
+
RGB_237,0.5000,0.9219,0.9441,0.9329
|
| 49 |
+
RGB_247,0.3200,0.9212,0.9047,0.9129
|
| 50 |
+
RGB_248,0.4400,0.9474,0.8899,0.9177
|
| 51 |
+
RGB_254,0.2500,0.8923,0.9154,0.9037
|
res/MDBD/DexiNed-a/eval_bdry.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
0.597374 0.885572 0.901677 0.893552 0.892316 0.912223 0.90216 0.950624
|
res/MDBD/DexiNed-a/eval_bdry_img.txt
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
1 0.56 0.901122 0.887133 0.894073
|
| 2 |
+
2 0.6 0.81555 0.891492 0.851832
|
| 3 |
+
3 0.67 0.896541 0.889383 0.892947
|
| 4 |
+
4 0.56 0.868946 0.917992 0.892796
|
| 5 |
+
5 0.69 0.913616 0.856855 0.884325
|
| 6 |
+
6 0.49 0.934683 0.921958 0.928277
|
| 7 |
+
7 0.74 0.883474 0.900804 0.892055
|
| 8 |
+
8 0.65 0.868302 0.823076 0.845084
|
| 9 |
+
9 0.67 0.924908 0.897714 0.911108
|
| 10 |
+
10 0.64 0.86446 0.916706 0.889817
|
| 11 |
+
11 0.53 0.86169 0.886498 0.873918
|
| 12 |
+
12 0.56 0.878293 0.915788 0.896649
|
| 13 |
+
13 0.46 0.856196 0.964041 0.906924
|
| 14 |
+
14 0.56 0.921281 0.928259 0.924757
|
| 15 |
+
15 0.54 0.86711 0.929321 0.897138
|
| 16 |
+
16 0.59 0.918537 0.93561 0.926995
|
| 17 |
+
17 0.63 0.885477 0.904377 0.894827
|
| 18 |
+
18 0.563434 0.908339 0.953304 0.930279
|
| 19 |
+
19 0.54 0.914219 0.94903 0.931299
|
| 20 |
+
20 0.53 0.9212 0.958346 0.939406
|
res/MDBD/DexiNed-a/eval_bdry_thr.txt
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
0.01 0.997164 0.45554 0.625383
|
| 2 |
+
0.02 0.995287 0.48181 0.6493
|
| 3 |
+
0.03 0.994349 0.49603 0.661881
|
| 4 |
+
0.04 0.993129 0.518086 0.680944
|
| 5 |
+
0.05 0.992364 0.531244 0.692025
|
| 6 |
+
0.06 0.991129 0.549036 0.706633
|
| 7 |
+
0.07 0.990422 0.559727 0.715242
|
| 8 |
+
0.08 0.989247 0.573851 0.726353
|
| 9 |
+
0.09 0.98832 0.58224 0.732783
|
| 10 |
+
0.1 0.986828 0.593985 0.741595
|
| 11 |
+
0.11 0.985176 0.60546 0.749995
|
| 12 |
+
0.12 0.984029 0.612892 0.755333
|
| 13 |
+
0.13 0.982403 0.623862 0.763117
|
| 14 |
+
0.14 0.981364 0.631107 0.768195
|
| 15 |
+
0.15 0.979793 0.641587 0.775416
|
| 16 |
+
0.16 0.978788 0.648459 0.780095
|
| 17 |
+
0.17 0.977308 0.658501 0.786838
|
| 18 |
+
0.18 0.976252 0.664958 0.791083
|
| 19 |
+
0.19 0.974762 0.674437 0.797254
|
| 20 |
+
0.2 0.973823 0.680309 0.801025
|
| 21 |
+
0.21 0.972416 0.688868 0.806444
|
| 22 |
+
0.22 0.971057 0.697024 0.811531
|
| 23 |
+
0.23 0.970157 0.702369 0.814825
|
| 24 |
+
0.24 0.968823 0.710171 0.819575
|
| 25 |
+
0.25 0.967954 0.715159 0.822572
|
| 26 |
+
0.26 0.966538 0.722379 0.82681
|
| 27 |
+
0.27 0.965605 0.727031 0.829505
|
| 28 |
+
0.28 0.964087 0.733703 0.833264
|
| 29 |
+
0.29 0.963088 0.738071 0.835698
|
| 30 |
+
0.3 0.961581 0.744561 0.839269
|
| 31 |
+
0.31 0.960053 0.750888 0.842685
|
| 32 |
+
0.32 0.958957 0.755057 0.844879
|
| 33 |
+
0.33 0.957326 0.761197 0.848069
|
| 34 |
+
0.34 0.956148 0.765238 0.850107
|
| 35 |
+
0.35 0.95449 0.771431 0.853252
|
| 36 |
+
0.36 0.953254 0.77559 0.855293
|
| 37 |
+
0.37 0.951372 0.781732 0.858249
|
| 38 |
+
0.38 0.950158 0.785862 0.860236
|
| 39 |
+
0.39 0.948265 0.792071 0.863159
|
| 40 |
+
0.4 0.946922 0.796288 0.865097
|
| 41 |
+
0.41 0.944817 0.802722 0.867992
|
| 42 |
+
0.42 0.942567 0.809143 0.870773
|
| 43 |
+
0.43 0.941031 0.813415 0.872582
|
| 44 |
+
0.44 0.938613 0.820013 0.875314
|
| 45 |
+
0.45 0.93692 0.82439 0.87706
|
| 46 |
+
0.46 0.934208 0.830853 0.879505
|
| 47 |
+
0.47 0.932229 0.835128 0.881011
|
| 48 |
+
0.48 0.929103 0.841585 0.883181
|
| 49 |
+
0.49 0.926979 0.845712 0.884483
|
| 50 |
+
0.5 0.923675 0.852045 0.886415
|
| 51 |
+
0.51 0.919927 0.858232 0.888009
|
| 52 |
+
0.52 0.91733 0.862296 0.888962
|
| 53 |
+
0.53 0.913235 0.868625 0.890372
|
| 54 |
+
0.54 0.910276 0.872732 0.891109
|
| 55 |
+
0.55 0.905607 0.87876 0.891982
|
| 56 |
+
0.56 0.902487 0.882871 0.892571
|
| 57 |
+
0.57 0.897167 0.888791 0.892959
|
| 58 |
+
0.58 0.893677 0.892722 0.893199
|
| 59 |
+
0.59 0.888421 0.898724 0.893543
|
| 60 |
+
0.6 0.884558 0.902729 0.893551
|
| 61 |
+
0.61 0.878321 0.908664 0.893235
|
| 62 |
+
0.62 0.871641 0.914455 0.892535
|
| 63 |
+
0.63 0.866907 0.918307 0.891867
|
| 64 |
+
0.64 0.859239 0.923631 0.890272
|
| 65 |
+
0.65 0.85383 0.927064 0.888941
|
| 66 |
+
0.66 0.845158 0.932109 0.886507
|
| 67 |
+
0.67 0.838919 0.935359 0.884518
|
| 68 |
+
0.68 0.828825 0.940001 0.880919
|
| 69 |
+
0.69 0.821503 0.942855 0.878006
|
| 70 |
+
0.7 0.810015 0.947101 0.87321
|
| 71 |
+
0.71 0.797573 0.951176 0.867628
|
| 72 |
+
0.72 0.788436 0.953801 0.863271
|
| 73 |
+
0.73 0.774273 0.957826 0.856324
|
| 74 |
+
0.74 0.764061 0.960408 0.851056
|
| 75 |
+
0.75 0.747309 0.964059 0.841958
|
| 76 |
+
0.76 0.735229 0.966431 0.835124
|
| 77 |
+
0.77 0.715608 0.969658 0.823484
|
| 78 |
+
0.78 0.701222 0.971753 0.814614
|
| 79 |
+
0.79 0.677738 0.975121 0.799677
|
| 80 |
+
0.8 0.66031 0.977105 0.788062
|
| 81 |
+
0.81 0.63136 0.980026 0.767971
|
| 82 |
+
0.82 0.598865 0.98275 0.744219
|
| 83 |
+
0.83 0.575167 0.98455 0.726132
|
| 84 |
+
0.84 0.535904 0.987078 0.694663
|
| 85 |
+
0.85 0.507979 0.988498 0.671091
|
| 86 |
+
0.86 0.461462 0.990022 0.629504
|
| 87 |
+
0.87 0.428033 0.991012 0.597846
|
| 88 |
+
0.88 0.375164 0.9928 0.544551
|
| 89 |
+
0.89 0.338149 0.993739 0.504595
|
| 90 |
+
0.9 0.28077 0.994884 0.437946
|
| 91 |
+
0.91 0.221726 0.996313 0.362728
|
| 92 |
+
0.92 0.183093 0.996871 0.309366
|
| 93 |
+
0.93 0.127928 0.998276 0.226792
|
| 94 |
+
0.94 0.093393 0.99886 0.170815
|
| 95 |
+
0.95 0.0508334 0.999626 0.096747
|
| 96 |
+
0.96 0.0296794 1 0.0576479
|
| 97 |
+
0.97 0.00867657 1 0.0172039
|
| 98 |
+
0.98 0.0021924 1 0.0043752
|
| 99 |
+
0.99 1.45917e-05 1 2.91829e-05
|
res/MDBD/DexiNed-a/ios_res.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name,oisT1,oisR1,oisP1,oisF1
|
| 2 |
+
4100_left_2268,0.5600,0.9011,0.8871,0.8941
|
| 3 |
+
4101_left_0382,0.6000,0.8156,0.8915,0.8518
|
| 4 |
+
4108_left_0082,0.6700,0.8965,0.8894,0.8929
|
| 5 |
+
4113_left_0082,0.5600,0.8689,0.9180,0.8928
|
| 6 |
+
4114_left_0611,0.6900,0.9136,0.8569,0.8843
|
| 7 |
+
4176_left_0273,0.4900,0.9347,0.9220,0.9283
|
| 8 |
+
4178_left_0052,0.7400,0.8835,0.9008,0.8921
|
| 9 |
+
4179_left_0315,0.6500,0.8683,0.8231,0.8451
|
| 10 |
+
4187_left_0071,0.6700,0.9249,0.8977,0.9111
|
| 11 |
+
4209_left_0034,0.6400,0.8645,0.9167,0.8898
|
| 12 |
+
4377_left_0016,0.5300,0.8617,0.8865,0.8739
|
| 13 |
+
4386_left_0020,0.5600,0.8783,0.9158,0.8966
|
| 14 |
+
4406_left_0030,0.4600,0.8562,0.9640,0.9069
|
| 15 |
+
4523_left_0070,0.5600,0.9213,0.9283,0.9248
|
| 16 |
+
4558_left_0260,0.5400,0.8671,0.9293,0.8971
|
| 17 |
+
4580_left_0165,0.5900,0.9185,0.9356,0.9270
|
| 18 |
+
4603_left_0050,0.6300,0.8855,0.9044,0.8948
|
| 19 |
+
4663_left_0010,0.5634,0.9083,0.9533,0.9303
|
| 20 |
+
4684_left_0010,0.5400,0.9142,0.9490,0.9313
|
| 21 |
+
4685_left_0045,0.5300,0.9212,0.9583,0.9394
|
res/MDBD/DexiNed-f/eval_bdry.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
0.53 0.886613 0.895778 0.891172 0.886553 0.905303 0.89583 0.930116
|
res/MDBD/DexiNed-f/eval_bdry_img.txt
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
1 0.51 0.878821 0.890935 0.884836
|
| 2 |
+
2 0.51 0.838008 0.84884 0.843389
|
| 3 |
+
3 0.63 0.892969 0.897147 0.895053
|
| 4 |
+
4 0.499798 0.875027 0.920392 0.897136
|
| 5 |
+
5 0.68 0.904454 0.863271 0.883383
|
| 6 |
+
6 0.45 0.932002 0.921072 0.926505
|
| 7 |
+
7 0.67 0.912025 0.891484 0.901637
|
| 8 |
+
8 0.62 0.874182 0.831176 0.852137
|
| 9 |
+
9 0.62 0.919341 0.900196 0.909668
|
| 10 |
+
10 0.62 0.864278 0.918305 0.890473
|
| 11 |
+
11 0.49 0.84351 0.871435 0.857245
|
| 12 |
+
12 0.5 0.877031 0.891973 0.884439
|
| 13 |
+
13 0.37 0.837118 0.942025 0.886478
|
| 14 |
+
14 0.46 0.91483 0.912852 0.91384
|
| 15 |
+
15 0.5 0.845711 0.924797 0.883487
|
| 16 |
+
16 0.51 0.910663 0.912789 0.911725
|
| 17 |
+
17 0.6 0.871541 0.896135 0.883667
|
| 18 |
+
18 0.5 0.902447 0.94623 0.92382
|
| 19 |
+
19 0.44 0.902223 0.95517 0.927942
|
| 20 |
+
20 0.42 0.91606 0.957079 0.93612
|
res/MDBD/DexiNed-f/eval_bdry_thr.txt
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
0.01 0.965678 0.692439 0.806545
|
| 2 |
+
0.02 0.958628 0.722879 0.824228
|
| 3 |
+
0.03 0.956763 0.730901 0.828719
|
| 4 |
+
0.04 0.955035 0.738735 0.833074
|
| 5 |
+
0.05 0.954159 0.742615 0.8352
|
| 6 |
+
0.06 0.953006 0.747683 0.837951
|
| 7 |
+
0.07 0.952371 0.75073 0.839614
|
| 8 |
+
0.08 0.951402 0.754995 0.841895
|
| 9 |
+
0.09 0.95076 0.7577 0.843322
|
| 10 |
+
0.1 0.949851 0.761252 0.845158
|
| 11 |
+
0.11 0.948941 0.764879 0.847026
|
| 12 |
+
0.12 0.948363 0.767223 0.84823
|
| 13 |
+
0.13 0.947501 0.770643 0.849969
|
| 14 |
+
0.14 0.946908 0.77311 0.851228
|
| 15 |
+
0.15 0.945982 0.776707 0.853028
|
| 16 |
+
0.16 0.945326 0.779021 0.854153
|
| 17 |
+
0.17 0.944324 0.782726 0.855965
|
| 18 |
+
0.18 0.943622 0.785122 0.857106
|
| 19 |
+
0.19 0.942603 0.788671 0.858794
|
| 20 |
+
0.2 0.941899 0.790932 0.859839
|
| 21 |
+
0.21 0.94086 0.794267 0.861371
|
| 22 |
+
0.22 0.939882 0.797898 0.86309
|
| 23 |
+
0.23 0.939216 0.800267 0.864192
|
| 24 |
+
0.24 0.938202 0.803735 0.865778
|
| 25 |
+
0.25 0.937494 0.806175 0.866889
|
| 26 |
+
0.26 0.936339 0.809779 0.868472
|
| 27 |
+
0.27 0.935561 0.812184 0.869518
|
| 28 |
+
0.28 0.934376 0.815838 0.871093
|
| 29 |
+
0.29 0.933536 0.818237 0.872092
|
| 30 |
+
0.3 0.932218 0.821922 0.873602
|
| 31 |
+
0.31 0.930724 0.82549 0.874954
|
| 32 |
+
0.32 0.929701 0.82789 0.875847
|
| 33 |
+
0.33 0.928087 0.831446 0.877113
|
| 34 |
+
0.34 0.926953 0.833929 0.877984
|
| 35 |
+
0.35 0.925207 0.837501 0.879172
|
| 36 |
+
0.36 0.92399 0.83988 0.879929
|
| 37 |
+
0.37 0.922091 0.843496 0.881044
|
| 38 |
+
0.38 0.920841 0.845898 0.88178
|
| 39 |
+
0.39 0.918976 0.849412 0.882826
|
| 40 |
+
0.4 0.917685 0.851842 0.883539
|
| 41 |
+
0.41 0.915677 0.855602 0.884621
|
| 42 |
+
0.42 0.913514 0.859323 0.88559
|
| 43 |
+
0.43 0.911999 0.861899 0.886242
|
| 44 |
+
0.44 0.909645 0.865832 0.887198
|
| 45 |
+
0.45 0.907982 0.868393 0.887746
|
| 46 |
+
0.46 0.905435 0.872228 0.888521
|
| 47 |
+
0.47 0.903599 0.874846 0.88899
|
| 48 |
+
0.48 0.900794 0.878956 0.889741
|
| 49 |
+
0.49 0.898862 0.881509 0.890101
|
| 50 |
+
0.5 0.895733 0.885508 0.890591
|
| 51 |
+
0.51 0.892475 0.889491 0.89098
|
| 52 |
+
0.52 0.890182 0.891997 0.891088
|
| 53 |
+
0.53 0.886613 0.895778 0.891172
|
| 54 |
+
0.54 0.884083 0.898142 0.891057
|
| 55 |
+
0.55 0.880063 0.90178 0.890789
|
| 56 |
+
0.56 0.877293 0.90423 0.890558
|
| 57 |
+
0.57 0.872936 0.907771 0.890013
|
| 58 |
+
0.58 0.869865 0.910329 0.889637
|
| 59 |
+
0.59 0.865244 0.913996 0.888952
|
| 60 |
+
0.6 0.862111 0.916521 0.888484
|
| 61 |
+
0.61 0.856915 0.920525 0.887582
|
| 62 |
+
0.62 0.851391 0.924404 0.886396
|
| 63 |
+
0.63 0.847464 0.926962 0.885432
|
| 64 |
+
0.64 0.841336 0.930631 0.883734
|
| 65 |
+
0.65 0.837 0.933276 0.88252
|
| 66 |
+
0.66 0.829985 0.937115 0.880302
|
| 67 |
+
0.67 0.824815 0.939536 0.878446
|
| 68 |
+
0.68 0.816661 0.943224 0.875391
|
| 69 |
+
0.69 0.810776 0.945443 0.872946
|
| 70 |
+
0.7 0.801784 0.948789 0.869114
|
| 71 |
+
0.71 0.79181 0.951996 0.864546
|
| 72 |
+
0.72 0.784888 0.95394 0.861196
|
| 73 |
+
0.73 0.773639 0.957107 0.855648
|
| 74 |
+
0.74 0.765556 0.95905 0.851448
|
| 75 |
+
0.75 0.75246 0.962235 0.844516
|
| 76 |
+
0.76 0.743163 0.964212 0.839378
|
| 77 |
+
0.77 0.727774 0.96712 0.830547
|
| 78 |
+
0.78 0.716703 0.968852 0.823918
|
| 79 |
+
0.79 0.698734 0.97168 0.812907
|
| 80 |
+
0.8 0.685435 0.97361 0.804494
|
| 81 |
+
0.81 0.663805 0.976447 0.79033
|
| 82 |
+
0.82 0.639137 0.979333 0.773481
|
| 83 |
+
0.83 0.62099 0.981101 0.760573
|
| 84 |
+
0.84 0.591026 0.983656 0.738392
|
| 85 |
+
0.85 0.568244 0.985456 0.720834
|
| 86 |
+
0.86 0.529949 0.987811 0.689818
|
| 87 |
+
0.87 0.501772 0.989322 0.665839
|
| 88 |
+
0.88 0.455247 0.991302 0.62395
|
| 89 |
+
0.89 0.422051 0.99255 0.592261
|
| 90 |
+
0.9 0.36763 0.994005 0.536746
|
| 91 |
+
0.91 0.310516 0.994874 0.473306
|
| 92 |
+
0.92 0.270527 0.995394 0.425431
|
| 93 |
+
0.93 0.210046 0.996397 0.346953
|
| 94 |
+
0.94 0.170149 0.996698 0.290676
|
| 95 |
+
0.95 0.112359 0.997894 0.201976
|
| 96 |
+
0.96 0.0767081 0.998212 0.142468
|
| 97 |
+
0.97 0.0334125 0.999904 0.0646642
|
| 98 |
+
0.98 0.0136791 1 0.026989
|
| 99 |
+
0.99 0.00108374 1 0.00216512
|