Dinars34 commited on
Commit
89c5d90
·
verified ·
1 Parent(s): c13371c

Upload 60 files

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +8 -0
  2. =1.4 +52 -0
  3. DexiNed-TF2/README.md +47 -0
  4. DexiNed-TF2/dataset_manager.py +280 -0
  5. DexiNed-TF2/mainTF.py +99 -0
  6. DexiNed-TF2/model.py +346 -0
  7. DexiNed-TF2/run_model.py +234 -0
  8. DexiNed-TF2/utls.py +257 -0
  9. LICENSE +21 -0
  10. README.md +204 -19
  11. __pycache__/datasets.cpython-312.pyc +0 -0
  12. __pycache__/dexi_utils.cpython-312.pyc +0 -0
  13. __pycache__/losses.cpython-312.pyc +0 -0
  14. __pycache__/model.cpython-312.pyc +0 -0
  15. app.py +84 -0
  16. checkpoints/BIPED/10/10_model.pth +3 -0
  17. data/1739757991209.png +3 -0
  18. dataset-lists/MDBD/test_pair.lst +20 -0
  19. datasets.py +490 -0
  20. dexi_utils.py +87 -0
  21. figs/DexiNed_banner.png +3 -0
  22. legacy/README.md +132 -0
  23. legacy/figs/DexiNed_banner.png +3 -0
  24. legacy/models/dexined.py +503 -0
  25. legacy/requirements.txt +33 -0
  26. legacy/run_model.py +134 -0
  27. legacy/test.py +129 -0
  28. legacy/train.py +150 -0
  29. legacy/utls/dataset_manager.py +1336 -0
  30. legacy/utls/losses.py +47 -0
  31. legacy/utls/utls.py +385 -0
  32. losses.py +148 -0
  33. main.py +481 -0
  34. model.py +286 -0
  35. requirements.txt +8 -3
  36. res/BIPED/DexiNed-a/eval_bdry.txt +1 -0
  37. res/BIPED/DexiNed-a/eval_bdry_img.txt +50 -0
  38. res/BIPED/DexiNed-a/eval_bdry_thr.txt +99 -0
  39. res/BIPED/DexiNed-a/ios_res.txt +51 -0
  40. res/BIPED/DexiNed-f/eval_bdry.txt +1 -0
  41. res/BIPED/DexiNed-f/eval_bdry_img.txt +50 -0
  42. res/BIPED/DexiNed-f/eval_bdry_thr.txt +99 -0
  43. res/BIPED/DexiNed-f/ios_res.txt +51 -0
  44. res/MDBD/DexiNed-a/eval_bdry.txt +1 -0
  45. res/MDBD/DexiNed-a/eval_bdry_img.txt +20 -0
  46. res/MDBD/DexiNed-a/eval_bdry_thr.txt +99 -0
  47. res/MDBD/DexiNed-a/ios_res.txt +21 -0
  48. res/MDBD/DexiNed-f/eval_bdry.txt +1 -0
  49. res/MDBD/DexiNed-f/eval_bdry_img.txt +20 -0
  50. 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
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
- title: DexinedApp
3
- emoji: 🚀
4
- colorFrom: red
5
- colorTo: red
6
- sdk: docker
7
- app_port: 8501
8
- tags:
9
- - streamlit
10
- pinned: false
11
- short_description: App that implemented dexined
12
- ---
13
-
14
- # Welcome to Streamlit!
15
-
16
- Edit `/src/streamlit_app.py` to customize this app to your heart's desire. :heart:
17
-
18
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
19
- forums](https://discuss.streamlit.io).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [![PWC](https://img.shields.io/endpoint.svg?url=https://paperswithcode.com/badge/dense-extreme-inception-network-for-edge/edge-detection-on-biped-1)](https://paperswithcode.com/sota/edge-detection-on-biped-1?p=dense-extreme-inception-network-for-edge)
2
+ [![PWC](https://img.shields.io/endpoint.svg?url=https://paperswithcode.com/badge/dense-extreme-inception-network-for-edge/edge-detection-on-mdbd)](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
+ [![GitHub stars](https://img.shields.io/github/stars/xavysp/DexiNed.svg?style=social&label=Star&maxAge=3600)](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

  • SHA256: 817f6924804a34382f9a454aa63c3c4a69985b3805801c9e752a36cc667df150
  • Pointer size: 131 Bytes
  • Size of remote file: 749 kB
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

  • SHA256: 58d47ef9c4b0528adf24c665649e3f6144e41861716384c0da5faae60e6bd230
  • Pointer size: 132 Bytes
  • Size of remote file: 1.32 MB
legacy/README.md ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [![PWC](https://img.shields.io/endpoint.svg?url=https://paperswithcode.com/badge/dense-extreme-inception-network-towards-a/edge-detection-on-biped)](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
+ [![GitHub stars](https://img.shields.io/github/stars/xavysp/DexiNed.svg?style=social&label=Star&maxAge=3600)](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

  • SHA256: 912b68de4a967882db58c308a3a70cebd0238646b7268b500ddb4cde0716af37
  • Pointer size: 131 Bytes
  • Size of remote file: 655 kB
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
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
- altair
2
- pandas
3
- streamlit
 
 
 
 
 
 
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