Commit 3b6137be authored by Andrey Filippov's avatar Andrey Filippov

Implemented 2-stage inference network to be used with TP in Java

parent bcf427de
#!/usr/bin/env python3 #!/usr/bin/env python3
from numpy import float64 #from numpy import float64
__copyright__ = "Copyright 2018, Elphel, Inc." __copyright__ = "Copyright 2018, Elphel, Inc."
__license__ = "GPL-3.0+" __license__ = "GPL-3.0+"
...@@ -11,7 +11,7 @@ import glob ...@@ -11,7 +11,7 @@ import glob
import imagej_tiff as ijt import imagej_tiff as ijt
import numpy as np import numpy as np
import resource import resource
import timeit #import timeit
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
from scipy.ndimage.filters import gaussian_filter from scipy.ndimage.filters import gaussian_filter
import time import time
...@@ -123,19 +123,25 @@ def writeTFRewcordsImageTiles(img_path, tfr_filename): # test_set=False): ...@@ -123,19 +123,25 @@ def writeTFRewcordsImageTiles(img_path, tfr_filename): # test_set=False):
class ExploreData: class ExploreData:
"""
TODO: add to constructor parameters
"""
PATTERN = "*-DSI_COMBO.tiff" PATTERN = "*-DSI_COMBO.tiff"
# ML_DIR = "ml" # ML_DIR = "ml"
# ML_PATTERN = "*-ML_DATA*OFFS*.tiff" # ML_PATTERN = "*-ML_DATA*OFFS*.tiff"
# ML_PATTERN = "*-ML_DATA*MAIN*.tiff" # ML_PATTERN = "*-ML_DATA*MAIN*.tiff"
# ML_PATTERN = "*-ML_DATA*MAIN.tiff" # ML_PATTERN = "*-ML_DATA*MAIN.tiff"
# ML_PATTERN = "*-ML_DATA*MAIN_RND*.tiff" # ML_PATTERN = "*-ML_DATA*MAIN_RND*.tiff"
ML_PATTERN = "*-ML_DATA*RIG_RND*.tiff" ## ML_PATTERN = "*-ML_DATA*RIG_RND*.tiff"
# ML_PATTERN = "*-ML_DATA*OFFS-0.20000_0.20000.tiff" # ML_PATTERN = "*-ML_DATA*OFFS-0.20000_0.20000.tiff"
""" """
1527182801_296892-ML_DATARND-32B-O-FZ0.05-OFFS-0.20000_0.20000.tiff 1527182801_296892-ML_DATARND-32B-O-FZ0.05-OFFS-0.20000_0.20000.tiff
1527182805_696892-ML_DATA-32B-O-FZ0.05-RIG_RND2.00000.tiff 1527182805_696892-ML_DATA-32B-O-FZ0.05-RIG_RND2.00000.tiff
""" """
def getComboList(self, top_dir, latest_version_only): def getComboList(self, top_dir, latest_version_only):
if not top_dir:
return []
# patt = "*-DSI_COMBO.tiff" # patt = "*-DSI_COMBO.tiff"
tlist = [] tlist = []
for i in range(5): for i in range(5):
...@@ -234,7 +240,7 @@ class ExploreData: ...@@ -234,7 +240,7 @@ class ExploreData:
def __init__(self, def __init__(self,
topdir_train, topdir_train,
topdir_test, topdir_test,
ml_subdir, ml_pattern,
latest_version_only, latest_version_only,
max_main_offset = 2.0, # > 0.0 - do not use main camera tiles with offset more than this max_main_offset = 2.0, # > 0.0 - do not use main camera tiles with offset more than this
debug_level = 0, debug_level = 0,
...@@ -254,6 +260,7 @@ class ExploreData: ...@@ -254,6 +260,7 @@ class ExploreData:
): ):
# file name # file name
self.debug_level = debug_level self.debug_level = debug_level
self.ml_pattern = ml_pattern
#self.testImageTiles() #self.testImageTiles()
self.max_main_offset = max_main_offset self.max_main_offset = max_main_offset
self.disparity_bins = disparity_bins self.disparity_bins = disparity_bins
...@@ -277,7 +284,19 @@ class ExploreData: ...@@ -277,7 +284,19 @@ class ExploreData:
self.test_ds = self.loadComboFiles(self.files_test) self.test_ds = self.loadComboFiles(self.files_test)
self.num_tiles = self.train_ds.shape[1]*self.train_ds.shape[2] self.num_tiles = self.train_ds.shape[1]*self.train_ds.shape[2]
self.hist, xedges, yedges = self.getHistogramDSI( """
Traceback (most recent call last):
File "explore_data5.py", line 1036, in <module>
hist_cutoff= 0.001) # of maximal
File "explore_data5.py", line 286, in __init__
self.num_tiles = self.train_ds.shape[1]*self.train_ds.shape[2]
AttributeError: 'list' object has no attribute 'shape'
"""
## self.hist, xedges, yedges = self.getHistogramDSI(
self.hist, _, _ = self.getHistogramDSI(
list_rds = [self.train_ds,self.test_ds], # combo_rds, list_rds = [self.train_ds,self.test_ds], # combo_rds,
disparity_bins = self.disparity_bins, disparity_bins = self.disparity_bins,
strength_bins = self.strength_bins, strength_bins = self.strength_bins,
...@@ -365,10 +384,10 @@ class ExploreData: ...@@ -365,10 +384,10 @@ class ExploreData:
self.max_batch_files = max_batch_files self.max_batch_files = max_batch_files
hist_to_batch = np.zeros((self.blurred_hist.shape[0],self.blurred_hist.shape[1]),dtype=int) #zeros_like? hist_to_batch = np.zeros((self.blurred_hist.shape[0],self.blurred_hist.shape[1]),dtype=int) #zeros_like?
hist_to_batch_multi = np.ones((self.blurred_hist.shape[0],self.blurred_hist.shape[1]),dtype=int) #zeros_like? ## hist_to_batch_multi = np.ones((self.blurred_hist.shape[0],self.blurred_hist.shape[1]),dtype=int) #zeros_like?
scale_hist= (disp_bins * str_bins)/self.blurred_hist.sum() scale_hist= (disp_bins * str_bins)/self.blurred_hist.sum()
norm_b_hist = self.blurred_hist * scale_hist norm_b_hist = self.blurred_hist * scale_hist
disp_list = [] # last disparity hist ## disp_list = [] # last disparity hist
# disp_multi = [] # number of disp rows to fit # disp_multi = [] # number of disp rows to fit
disp_run_tot = 0.0 disp_run_tot = 0.0
disp_batch = 0 disp_batch = 0
...@@ -426,8 +445,8 @@ class ExploreData: ...@@ -426,8 +445,8 @@ class ExploreData:
""" """
for each file, each tile get histogram index (or -1 for bad tiles) for each file, each tile get histogram index (or -1 for bad tiles)
""" """
hist_to_batch = self.hist_to_batch ## hist_to_batch = self.hist_to_batch
files_batch_list = [] ## files_batch_list = []
disp_step = ( self.disparity_max_clip - self.disparity_min_clip )/ self.disparity_bins disp_step = ( self.disparity_max_clip - self.disparity_min_clip )/ self.disparity_bins
str_step = ( self.strength_max_clip - self.strength_min_clip )/ self.strength_bins str_step = ( self.strength_max_clip - self.strength_min_clip )/ self.strength_bins
bb = np.empty_like(data_ds[...,0],dtype=int) bb = np.empty_like(data_ds[...,0],dtype=int)
...@@ -448,11 +467,11 @@ class ExploreData: ...@@ -448,11 +467,11 @@ class ExploreData:
disp_neibs = None, # number of valid tiles around each center tile (for 3x3 (radius = 1) - maximal is 9 disp_neibs = None, # number of valid tiles around each center tile (for 3x3 (radius = 1) - maximal is 9
min_var = None, # Minimal tile variance to include min_var = None, # Minimal tile variance to include
max_var = None, # Maximal tile variance to include max_var = None, # Maximal tile variance to include
scale_disp = 5.0, ## scale_disp = 5.0,
min_neibs = None):# Minimal number of valid tiles to include min_neibs = None):# Minimal number of valid tiles to include
if data_ds is None: if data_ds is None:
data_ds = self.train_ds data_ds = self.train_ds
hist_to_batch = self.hist_to_batch ## hist_to_batch = self.hist_to_batch
num_batch_tiles = np.empty((data_ds.shape[0],self.hist_to_batch.max()+1),dtype = int) num_batch_tiles = np.empty((data_ds.shape[0],self.hist_to_batch.max()+1),dtype = int)
bb = self.getBB(data_ds) bb = self.getBB(data_ds)
use_neibs = not ((disp_var is None) or (disp_neibs is None) or (min_var is None) or (max_var is None) or (min_neibs is None)) use_neibs = not ((disp_var is None) or (disp_neibs is None) or (min_var is None) or (max_var is None) or (min_neibs is None))
...@@ -563,7 +582,9 @@ ValueError: need at least one array to concatenate ...@@ -563,7 +582,9 @@ ValueError: need at least one array to concatenate
def getMLList(self, ml_subdir, flist): def getMLList(self, ml_subdir, flist):
ml_list = [] ml_list = []
for fn in flist: for fn in flist:
ml_patt = os.path.join(os.path.dirname(fn), ml_subdir, ExploreData.ML_PATTERN) # ml_patt = os.path.join(os.path.dirname(fn), ml_subdir, ExploreData.ML_PATTERN)
## if isinstance(ml_subdir,list)
ml_patt = os.path.join(os.path.dirname(fn), ml_subdir, self.ml_pattern)
ml_list.append(glob.glob(ml_patt)) ml_list.append(glob.glob(ml_patt))
## self.ml_list = ml_list ## self.ml_list = ml_list
return ml_list return ml_list
...@@ -571,7 +592,7 @@ ValueError: need at least one array to concatenate ...@@ -571,7 +592,7 @@ ValueError: need at least one array to concatenate
def getBatchData( def getBatchData(
self, self,
flist, flist,
tiles, ## tiles,
ml_list, ml_list,
ml_num = None ): # 0 - use all ml files for the scene, >0 select random number ml_num = None ): # 0 - use all ml files for the scene, >0 select random number
if ml_num is None: if ml_num is None:
...@@ -624,10 +645,14 @@ ValueError: need at least one array to concatenate ...@@ -624,10 +645,14 @@ ValueError: need at least one array to concatenate
flist,tiles = self.augmentBatchFileIndices(seed_index, min_choices, max_files, set_ds) flist,tiles = self.augmentBatchFileIndices(seed_index, min_choices, max_files, set_ds)
# ml_all_files = self.getBatchData(flist, tiles, ml_list, ml_num) # 0 - use all ml files for the scene, >0 select random number # ml_all_files = self.getBatchData(flist, tiles, ml_list, ml_num) # 0 - use all ml files for the scene, >0 select random number
ml_all_files = self.getBatchData(flist, tiles, ml_list, 0) # ml_num) # 0 - use all ml files for the scene, >0 select random number ml_all_files = self.getBatchData(
flist,
## tiles,
ml_list,
0) # ml_num) # 0 - use all ml files for the scene, >0 select random number
if self.debug_level > 1: if self.debug_level > 1:
print ("==============",seed_index, flist) print ("==============",seed_index, flist)
for i, findx in enumerate(flist): for i, _ in enumerate(flist):
print(i,"\n".join(ml_all_files[i])) print(i,"\n".join(ml_all_files[i]))
print(tiles[i]) print(tiles[i])
total_tiles = 0 total_tiles = 0
...@@ -664,7 +689,7 @@ ValueError: need at least one array to concatenate ...@@ -664,7 +689,7 @@ ValueError: need at least one array to concatenate
file_tiles.append([]) file_tiles.append([])
num_scene_files = len(scene_files) num_scene_files = len(scene_files)
for t in full_tiles: for t in full_tiles:
fi = np.random.randint(0, num_scene_files) #error here - probably wron ml file pattern (no files matched) fi = np.random.randint(0, num_scene_files) #error here - probably wrong ml file pattern (no files matched)
file_tiles[fi].append(t) file_tiles[fi].append(t)
file_indices.append(fi) file_indices.append(fi)
corr2d_list = [] corr2d_list = []
...@@ -736,7 +761,13 @@ ValueError: need at least one array to concatenate ...@@ -736,7 +761,13 @@ ValueError: need at least one array to concatenate
#$ files_list = [self.files_train, self.files_test][test_set] #$ files_list = [self.files_train, self.files_test][test_set]
if num_scenes is None: if num_scenes is None:
num_scenes = len(files_list) num_scenes = len(files_list)
if len(files_list) <= num_scenes:
seed_list = np.arange(num_scenes) % len(files_list) seed_list = np.arange(num_scenes) % len(files_list)
np.random.shuffle(seed_list)
else:
seed_list = np.arange(len(files_list))
np.random.shuffle(seed_list)
seed_list = seed_list[:num_scenes]
# seed_list = np.arange(len(files_list)) # seed_list = np.arange(len(files_list))
np.random.shuffle(seed_list) np.random.shuffle(seed_list)
cluster_size = (2 * radius + 1) * (2 * radius + 1) cluster_size = (2 * radius + 1) * (2 * radius + 1)
...@@ -832,7 +863,8 @@ ValueError: need at least one array to concatenate ...@@ -832,7 +863,8 @@ ValueError: need at least one array to concatenate
# np.clip(strength, self.strength_min_clip, self.strength_max_clip, out = strength) # np.clip(strength, self.strength_min_clip, self.strength_max_clip, out = strength)
good_tiles_list.append(good_tiles) good_tiles_list.append(good_tiles)
combo_rds = np.concatenate(rds_list) combo_rds = np.concatenate(rds_list)
hist, xedges, yedges = np.histogram2d( # xedges, yedges - just for debugging # hist, xedges, yedges = np.histogram2d( # xedges, yedges - just for debugging
hist, _, _ = np.histogram2d( # xedges, yedges - just for debugging
x = combo_rds[...,1].flatten(), x = combo_rds[...,1].flatten(),
y = combo_rds[...,0].flatten(), y = combo_rds[...,0].flatten(),
bins= (self.strength_bins, self.disparity_bins), bins= (self.strength_bins, self.disparity_bins),
...@@ -860,28 +892,45 @@ if __name__ == "__main__": ...@@ -860,28 +892,45 @@ if __name__ == "__main__":
topdir_train = sys.argv[1] topdir_train = sys.argv[1]
except IndexError: except IndexError:
# topdir_train = "/mnt/dde6f983-d149-435e-b4a2-88749245cc6c/home/eyesis/x3d_data/data_sets/train"#test" #all/" # topdir_train = "/mnt/dde6f983-d149-435e-b4a2-88749245cc6c/home/eyesis/x3d_data/data_sets/train"#test" #all/"
topdir_train = "/data_ssd/data_sets/train_mlr32_18d" ## topdir_train = "/data_ssd/data_sets/train_mlr32_18d"
## topdir_train = '/data_ssd/data_sets/test_only'# ''
topdir_train = '/data_ssd/data_sets/train_set2'# ''
# tf_data_5x5_main_10_heur
try: try:
topdir_test = sys.argv[2] topdir_test = sys.argv[2]
except IndexError: except IndexError:
# topdir_test = "/mnt/dde6f983-d149-435e-b4a2-88749245cc6c/home/eyesis/x3d_data/data_sets/test"#test" #all/" # topdir_test = "/mnt/dde6f983-d149-435e-b4a2-88749245cc6c/home/eyesis/x3d_data/data_sets/test"#test" #all/"
topdir_test = "/data_ssd/data_sets/test_mlr32_18d" # topdir_test = "/data_ssd/data_sets/test_mlr32_18d"
## topdir_test = '/data_ssd/data_sets/test_only'
topdir_test = '/data_ssd/data_sets/test_set2'
try: try:
pathTFR = sys.argv[3] pathTFR = sys.argv[3]
except IndexError: except IndexError:
# pathTFR = "/mnt/dde6f983-d149-435e-b4a2-88749245cc6c/home/eyesis/x3d_data/data_sets/tf_data_3x3b" #no trailing "/" # pathTFR = "/mnt/dde6f983-d149-435e-b4a2-88749245cc6c/home/eyesis/x3d_data/data_sets/tf_data_3x3b" #no trailing "/"
# pathTFR = "/home/eyesis/x3d_data/data_sets/tf_data_5x5" #no trailing "/" # pathTFR = "/home/eyesis/x3d_data/data_sets/tf_data_5x5" #no trailing "/"
pathTFR = "/data_ssd/data_sets/tf_data_5x5_main_12_rigrnd" #no trailing "/" pathTFR = "/data_ssd/data_sets/tf_data_5x5_main_13_heur"
## pathTFR = "/data_ssd/data_sets/tf_data_5x5_main_11_rnd"
## pathTFR = "/data_ssd/data_sets/tf_data_5x5_main_12_rigrnd"
try: try:
ml_subdir = sys.argv[4] ml_subdir = sys.argv[4]
except IndexError: except IndexError:
# ml_subdir = "ml" # ml_subdir = "ml"
# ml_subdir = "mlr32_18a" # ml_subdir = "mlr32_18a"
ml_subdir = "mlr32_18d" # ml_subdir = "mlr32_18d"
# ml_subdir = "{ml32,mlr32_18d}"
ml_subdir = "ml*"
try:
ml_pattern = sys.argv[5]
except IndexError:
ml_pattern = "*-ML_DATA*MAIN.tiff" ## pathTFR = "/data_ssd/data_sets/tf_data_5x5_main_10_heur"
## ml_pattern = "*-ML_DATA*MAIN_RND*.tiff" ## pathTFR = "/data_ssd/data_sets/tf_data_5x5_main_11_rnd"
## ml_pattern = "*-ML_DATA*RIG_RND*.tiff" ## pathTFR = "/data_ssd/data_sets/tf_data_5x5_main_12_rigrnd"
## ML_PATTERN = "*-ML_DATA*RIG_RND*.tiff"
#1527182801_296892-ML_DATA-32B-O-FZ0.05-MAIN_RND2.00000.tiff
# pathTFR = "/mnt/dde6f983-d149-435e-b4a2-88749245cc6c/home/eyesis/x3d_data/data_sets/tf_data_3x3b" #no trailing "/" # pathTFR = "/mnt/dde6f983-d149-435e-b4a2-88749245cc6c/home/eyesis/x3d_data/data_sets/tf_data_3x3b" #no trailing "/"
# test_corr = '/home/eyesis/x3d_data/models/var_main/www/html/x3domlet/models/all-clean/overlook/1527257933_150165/v04/mlr32_18a/1527257933_150165-ML_DATA-32B-O-FZ0.05-MAIN.tiff' # overlook # test_corr = '/home/eyesis/x3d_data/models/var_main/www/html/x3domlet/models/all-clean/overlook/1527257933_150165/v04/mlr32_18a/1527257933_150165-ML_DATA-32B-O-FZ0.05-MAIN.tiff' # overlook
...@@ -924,8 +973,6 @@ if __name__ == "__main__": ...@@ -924,8 +973,6 @@ if __name__ == "__main__":
'/data_ssd/data_sets/test_mlr32_18d/1527182805_096892/v02/mlr32_18d/1527182805_096892-ML_DATA-32B-O-FZ0.05-MAIN_RND2.00000.tiff', # medium plane" '/data_ssd/data_sets/test_mlr32_18d/1527182805_096892/v02/mlr32_18d/1527182805_096892-ML_DATA-32B-O-FZ0.05-MAIN_RND2.00000.tiff', # medium plane"
'/data_ssd/data_sets/test_mlr32_18d/1527182810_096892/v02/mlr32_18d/1527182810_096892-ML_DATA-32B-O-FZ0.05-MAIN_RND2.00000.tiff', # far plane '/data_ssd/data_sets/test_mlr32_18d/1527182810_096892/v02/mlr32_18d/1527182810_096892-ML_DATA-32B-O-FZ0.05-MAIN_RND2.00000.tiff', # far plane
] ]
"""
# These images are made with large random offset
test_corrs = [ test_corrs = [
'/data_ssd/data_sets/test_mlr32_18d/1527257933_150165/v04/mlr32_18d/1527257933_150165-ML_DATA-32B-O-FZ0.05-RIG_RND2.00000.tiff', # overlook '/data_ssd/data_sets/test_mlr32_18d/1527257933_150165/v04/mlr32_18d/1527257933_150165-ML_DATA-32B-O-FZ0.05-RIG_RND2.00000.tiff', # overlook
'/data_ssd/data_sets/test_mlr32_18d/1527256816_150165/v02/mlr32_18d/1527256816_150165-ML_DATA-32B-O-FZ0.05-RIG_RND2.00000.tiff', # State Street '/data_ssd/data_sets/test_mlr32_18d/1527256816_150165/v02/mlr32_18d/1527256816_150165-ML_DATA-32B-O-FZ0.05-RIG_RND2.00000.tiff', # State Street
...@@ -934,18 +981,38 @@ if __name__ == "__main__": ...@@ -934,18 +981,38 @@ if __name__ == "__main__":
'/data_ssd/data_sets/test_mlr32_18d/1527182805_096892/v02/mlr32_18d/1527182805_096892-ML_DATA-32B-O-FZ0.05-RIG_RND2.00000.tiff', # medium plane" '/data_ssd/data_sets/test_mlr32_18d/1527182805_096892/v02/mlr32_18d/1527182805_096892-ML_DATA-32B-O-FZ0.05-RIG_RND2.00000.tiff', # medium plane"
'/data_ssd/data_sets/test_mlr32_18d/1527182810_096892/v02/mlr32_18d/1527182810_096892-ML_DATA-32B-O-FZ0.05-RIG_RND2.00000.tiff', # far plane '/data_ssd/data_sets/test_mlr32_18d/1527182810_096892/v02/mlr32_18d/1527182810_096892-ML_DATA-32B-O-FZ0.05-RIG_RND2.00000.tiff', # far plane
] ]
"""
# These images are made with large random offset
test_corrs = [
'/data_ssd/data_sets/test_only/1527258897_071435/v02/ml32/1527258897_071435-ML_DATA-32B-O-FZ0.05-MAIN.tiff',
'/data_ssd/data_sets/test_only/1527257894_750165/v02/ml32/1527257894_750165-ML_DATA-32B-O-FZ0.05-MAIN.tiff',
'/data_ssd/data_sets/test_only/1527257406_950165/v02/ml32/1527257406_950165-ML_DATA-32B-O-FZ0.05-MAIN.tiff',
'/data_ssd/data_sets/test_only/1527257757_950165/v02/ml32/1527257757_950165-ML_DATA-32B-O-FZ0.05-MAIN.tiff',
'/data_ssd/data_sets/test_only/1527257370_950165/v02/ml32/1527257370_950165-ML_DATA-32B-O-FZ0.05-MAIN.tiff',
'/data_ssd/data_sets/test_only/1527257235_950165/v02/ml32/1527257235_950165-ML_DATA-32B-O-FZ0.05-MAIN.tiff',
'/data_ssd/data_sets/test_only/1527257235_350165/v02/ml32/1527257235_350165-ML_DATA-32B-O-FZ0.05-MAIN.tiff',
'/data_ssd/data_sets/test_only/1527259003_271435/v02/ml32/1527259003_271435-ML_DATA-32B-O-FZ0.05-MAIN.tiff',
'/data_ssd/data_sets/test_only/1527257787_950165/v02/ml32/1527257787_950165-ML_DATA-32B-O-FZ0.05-MAIN.tiff',
'/data_ssd/data_sets/test_only/1527257235_150165/v02/ml32/1527257235_150165-ML_DATA-32B-O-FZ0.05-MAIN.tiff',
'/data_ssd/data_sets/test_only/1527257235_750165/v02/ml32/1527257235_750165-ML_DATA-32B-O-FZ0.05-MAIN.tiff',
'/data_ssd/data_sets/test_only/1527258936_671435/v02/ml32/1527258936_671435-ML_DATA-32B-O-FZ0.05-MAIN.tiff',
'/data_ssd/data_sets/test_only/1527257244_350165/v02/ml32/1527257244_350165-ML_DATA-32B-O-FZ0.05-MAIN.tiff',
'/data_ssd/data_sets/test_only/1527257235_550165/v02/ml32/1527257235_550165-ML_DATA-32B-O-FZ0.05-MAIN.tiff',
]
#1527257933_150165-ML_DATA-32B-O-FZ0.05-MAIN-RND2.00000.tiff #1527257933_150165-ML_DATA-32B-O-FZ0.05-MAIN-RND2.00000.tiff
#/home/eyesis/x3d_data/data_sets/test_mlr32_18a/1527257933_150165/v04/mlr32_18c/1527257933_150165-ML_DATA-32B-O-FZ0.05-MAIN.tiff #/home/eyesis/x3d_data/data_sets/test_mlr32_18a/1527257933_150165/v04/mlr32_18c/1527257933_150165-ML_DATA-32B-O-FZ0.05-MAIN.tiff
#Parameters to generate neighbors data. Set radius to 0 to generate single-tile #Parameters to generate neighbors data. Set radius to 0 to generate single-tile
TEST_SAME_LENGTH_AS_TRAIN = True # make test to have same number of entries as train ones TEST_SAME_LENGTH_AS_TRAIN = False # True # make test to have same number of entries as train ones
FIXED_TEST_LENGTH = None # put number of test scenes to output (used when making test only from few or single test file
RADIUS = 2 # 5x5 RADIUS = 2 # 5x5
MIN_NEIBS = (2 * RADIUS + 1) * (2 * RADIUS + 1) # All tiles valid == 9 MIN_NEIBS = (2 * RADIUS + 1) * (2 * RADIUS + 1) # All tiles valid == 9
VARIANCE_THRESHOLD = 0.4 # 1.5 VARIANCE_THRESHOLD = 0.4 # 1.5
VARIANCE_SCALE_DISPARITY = 5.0 #Scale variance if average is above this VARIANCE_SCALE_DISPARITY = 5.0 #Scale variance if average is above this
NUM_TRAIN_SETS = 32 # 8 NUM_TRAIN_SETS = 32 # 8
if not topdir_train:
NUM_TRAIN_SETS = 0
if RADIUS == 0: if RADIUS == 0:
BATCH_DISP_BINS = 50 # 1000 * 1 BATCH_DISP_BINS = 50 # 1000 * 1
BATCH_STR_BINS = 20 # 10 BATCH_STR_BINS = 20 # 10
...@@ -967,7 +1034,7 @@ if __name__ == "__main__": ...@@ -967,7 +1034,7 @@ if __name__ == "__main__":
ex_data = ExploreData( ex_data = ExploreData(
topdir_train = topdir_train, topdir_train = topdir_train,
topdir_test = topdir_test, topdir_test = topdir_test,
ml_subdir = ml_subdir, ml_pattern = ml_pattern,
latest_version_only = LATEST_VERSION_ONLY, latest_version_only = LATEST_VERSION_ONLY,
debug_level = 1, #3, ##0, #3, debug_level = 1, #3, ##0, #3,
disparity_bins = 200, #1000, disparity_bins = 200, #1000,
...@@ -1042,7 +1109,12 @@ if __name__ == "__main__": ...@@ -1042,7 +1109,12 @@ if __name__ == "__main__":
ml_list_train=ex_data.getMLList(ml_subdir, ex_data.files_train) ml_list_train=ex_data.getMLList(ml_subdir, ex_data.files_train)
ml_list_test= ex_data.getMLList(ml_subdir, ex_data.files_test) ml_list_test= ex_data.getMLList(ml_subdir, ex_data.files_test)
if FIXED_TEST_LENGTH is None:
num_test_scenes = len([ex_data.files_test, ex_data.files_train][TEST_SAME_LENGTH_AS_TRAIN]) num_test_scenes = len([ex_data.files_test, ex_data.files_train][TEST_SAME_LENGTH_AS_TRAIN])
else:
num_test_scenes = FIXED_TEST_LENGTH
if RADIUS == 0 : if RADIUS == 0 :
...@@ -1066,12 +1138,71 @@ if __name__ == "__main__": ...@@ -1066,12 +1138,71 @@ if __name__ == "__main__":
disp_neibs = num_neibs_test, # number of valid tiles around each center tile (for 3x3 (radius = 1) - macximal is 9 disp_neibs = num_neibs_test, # number of valid tiles around each center tile (for 3x3 (radius = 1) - macximal is 9
min_var = 0.0, # Minimal tile variance to include min_var = 0.0, # Minimal tile variance to include
max_var = VARIANCE_THRESHOLD, # Maximal tile variance to include max_var = VARIANCE_THRESHOLD, # Maximal tile variance to include
scale_disp = VARIANCE_SCALE_DISPARITY, ## scale_disp = VARIANCE_SCALE_DISPARITY,
min_neibs = MIN_NEIBS) # Minimal number of valid tiles to include min_neibs = MIN_NEIBS) # Minimal number of valid tiles to include
fpath = test_filenameTFR # +("-%03d"%(train_var,)) fpath = test_filenameTFR # +("-%03d"%(train_var,))
ex_data.writeTFRewcordsEpoch(fpath, ml_list = ml_list_train, files_list = ex_data.files_test, set_ds= ex_data.test_ds, num_scenes = num_test_scenes) ex_data.writeTFRewcordsEpoch(fpath, ml_list = ml_list_test, files_list = ex_data.files_test, set_ds= ex_data.test_ds, num_scenes = num_test_scenes)
pass pass
else: # RADIUS > 0 else: # RADIUS > 0
# test
list_of_file_lists_test, num_batch_tiles_test = ex_data.makeBatchLists( # results are also saved to self.*
data_ds = ex_data.test_ds,
disp_var = disp_var_test, # difference between maximal and minimal disparity for each scene, each tile
disp_neibs = num_neibs_test, # number of valid tiles around each center tile (for 3x3 (radius = 1) - macximal is 9
min_var = 0.0, # Minimal tile variance to include
max_var = VARIANCE_THRESHOLD, # Maximal tile variance to include
## scale_disp = VARIANCE_SCALE_DISPARITY,
min_neibs = MIN_NEIBS) # Minimal number of valid tiles to include
num_le_test = num_batch_tiles_test.sum()
print("Number of <= %f disparity variance tiles: %d (est)"%(VARIANCE_THRESHOLD, num_le_test))
fpath = test_filenameTFR +("TEST_R%d_LE%4.1f"%(RADIUS,VARIANCE_THRESHOLD))
ex_data.writeTFRewcordsEpoch(fpath, ml_list = ml_list_test, files_list = ex_data.files_test, set_ds= ex_data.test_ds, radius = RADIUS, num_scenes = num_test_scenes)
list_of_file_lists_test, num_batch_tiles_test = ex_data.makeBatchLists( # results are also saved to self.*
data_ds = ex_data.test_ds,
disp_var = disp_var_test, # difference between maximal and minimal disparity for each scene, each tile
disp_neibs = num_neibs_test, # number of valid tiles around each center tile (for 3x3 (radius = 1) - macximal is 9
min_var = VARIANCE_THRESHOLD, # Minimal tile variance to include
max_var = 1000.0, # Maximal tile variance to include
## scale_disp = VARIANCE_SCALE_DISPARITY,
min_neibs = MIN_NEIBS) # Minimal number of valid tiles to include
num_gt_test = num_batch_tiles_test.sum()
high_fract_test = 1.0 * num_gt_test / (num_le_test + num_gt_test)
print("Number of > %f disparity variance tiles: %d, fraction = %f (test)"%(VARIANCE_THRESHOLD, num_gt_test, high_fract_test))
fpath = test_filenameTFR +("TEST_R%d_GT%4.1f"%(RADIUS,VARIANCE_THRESHOLD))
ex_data.writeTFRewcordsEpoch(fpath, ml_list = ml_list_test, files_list = ex_data.files_test, set_ds= ex_data.test_ds, radius = RADIUS, num_scenes = num_test_scenes)
#fake
if NUM_TRAIN_SETS > 0:
list_of_file_lists_fake, num_batch_tiles_fake = ex_data.makeBatchLists( # results are also saved to self.*
data_ds = ex_data.train_ds,
disp_var = disp_var_train, # difference between maximal and minimal disparity for each scene, each tile
disp_neibs = num_neibs_train, # number of valid tiles around each center tile (for 3x3 (radius = 1) - macximal is 9
min_var = 0.0, # Minimal tile variance to include
max_var = VARIANCE_THRESHOLD, # Maximal tile variance to include
## scale_disp = VARIANCE_SCALE_DISPARITY,
min_neibs = MIN_NEIBS) # Minimal number of valid tiles to include
num_le_fake = num_batch_tiles_fake.sum()
print("Number of <= %f disparity variance tiles: %d (test)"%(VARIANCE_THRESHOLD, num_le_fake))
fpath = test_filenameTFR +("FAKE_R%d_LE%4.1f"%(RADIUS,VARIANCE_THRESHOLD))
ex_data.writeTFRewcordsEpoch(fpath, ml_list = ml_list_train, files_list = ex_data.files_train, set_ds= ex_data.train_ds, radius = RADIUS, num_scenes = num_test_scenes)
list_of_file_lists_fake, num_batch_tiles_fake = ex_data.makeBatchLists( # results are also saved to self.*
data_ds = ex_data.train_ds,
disp_var = disp_var_train, # difference between maximal and minimal disparity for each scene, each tile
disp_neibs = num_neibs_train, # number of valid tiles around each center tile (for 3x3 (radius = 1) - macximal is 9
min_var = VARIANCE_THRESHOLD, # Minimal tile variance to include
max_var = 1000.0, # Maximal tile variance to include
## scale_disp = VARIANCE_SCALE_DISPARITY,
min_neibs = MIN_NEIBS) # Minimal number of valid tiles to include
num_gt_fake = num_batch_tiles_fake.sum()
high_fract_fake = 1.0 * num_gt_fake / (num_le_fake + num_gt_fake)
print("Number of > %f disparity variance tiles: %d, fraction = %f (test)"%(VARIANCE_THRESHOLD, num_gt_fake, high_fract_fake))
fpath = test_filenameTFR +("FAKE_R%d_GT%4.1f"%(RADIUS,VARIANCE_THRESHOLD))
ex_data.writeTFRewcordsEpoch(fpath, ml_list = ml_list_train, files_list = ex_data.files_train, set_ds= ex_data.train_ds, radius = RADIUS, num_scenes = num_test_scenes)
# train # train
for train_var in range (NUM_TRAIN_SETS): # Recalculate list for each file - slower, but will alternate lvar/hvar for train_var in range (NUM_TRAIN_SETS): # Recalculate list for each file - slower, but will alternate lvar/hvar
list_of_file_lists_train, num_batch_tiles_train = ex_data.makeBatchLists( # results are also saved to self.* list_of_file_lists_train, num_batch_tiles_train = ex_data.makeBatchLists( # results are also saved to self.*
...@@ -1080,7 +1211,7 @@ if __name__ == "__main__": ...@@ -1080,7 +1211,7 @@ if __name__ == "__main__":
disp_neibs = num_neibs_train, # number of valid tiles around each center tile (for 3x3 (radius = 1) - macximal is 9 disp_neibs = num_neibs_train, # number of valid tiles around each center tile (for 3x3 (radius = 1) - macximal is 9
min_var = 0.0, # Minimal tile variance to include min_var = 0.0, # Minimal tile variance to include
max_var = VARIANCE_THRESHOLD, # Maximal tile variance to include max_var = VARIANCE_THRESHOLD, # Maximal tile variance to include
scale_disp = VARIANCE_SCALE_DISPARITY, ## scale_disp = VARIANCE_SCALE_DISPARITY,
min_neibs = MIN_NEIBS) # Minimal number of valid tiles to include min_neibs = MIN_NEIBS) # Minimal number of valid tiles to include
num_le_train = num_batch_tiles_train.sum() num_le_train = num_batch_tiles_train.sum()
print("Number of <= %f disparity variance tiles: %d (train)"%(VARIANCE_THRESHOLD, num_le_train)) print("Number of <= %f disparity variance tiles: %d (train)"%(VARIANCE_THRESHOLD, num_le_train))
...@@ -1094,7 +1225,7 @@ if __name__ == "__main__": ...@@ -1094,7 +1225,7 @@ if __name__ == "__main__":
disp_neibs = num_neibs_train, # number of valid tiles around each center tile (for 3x3 (radius = 1) - macximal is 9 disp_neibs = num_neibs_train, # number of valid tiles around each center tile (for 3x3 (radius = 1) - macximal is 9
min_var = VARIANCE_THRESHOLD, # Minimal tile variance to include min_var = VARIANCE_THRESHOLD, # Minimal tile variance to include
max_var = 1000.0, # Maximal tile variance to include max_var = 1000.0, # Maximal tile variance to include
scale_disp = VARIANCE_SCALE_DISPARITY, ## scale_disp = VARIANCE_SCALE_DISPARITY,
min_neibs = MIN_NEIBS) # Minimal number of valid tiles to include min_neibs = MIN_NEIBS) # Minimal number of valid tiles to include
num_gt_train = num_batch_tiles_train.sum() num_gt_train = num_batch_tiles_train.sum()
high_fract_train = 1.0 * num_gt_train / (num_le_train + num_gt_train) high_fract_train = 1.0 * num_gt_train / (num_le_train + num_gt_train)
...@@ -1103,35 +1234,7 @@ if __name__ == "__main__": ...@@ -1103,35 +1234,7 @@ if __name__ == "__main__":
fpath = (train_filenameTFR+("%03d_R%d_GT%4.1f"%(train_var,RADIUS,VARIANCE_THRESHOLD))) fpath = (train_filenameTFR+("%03d_R%d_GT%4.1f"%(train_var,RADIUS,VARIANCE_THRESHOLD)))
ex_data.writeTFRewcordsEpoch(fpath, ml_list = ml_list_train, files_list = ex_data.files_train, set_ds= ex_data.train_ds, radius = RADIUS) ex_data.writeTFRewcordsEpoch(fpath, ml_list = ml_list_train, files_list = ex_data.files_train, set_ds= ex_data.train_ds, radius = RADIUS)
if train_var < 1: # make test files immediately after the train ones ## if train_var < 1: # make test files immediately after the train ones
# test
list_of_file_lists_test, num_batch_tiles_test = ex_data.makeBatchLists( # results are also saved to self.*
data_ds = ex_data.test_ds,
disp_var = disp_var_test, # difference between maximal and minimal disparity for each scene, each tile
disp_neibs = num_neibs_test, # number of valid tiles around each center tile (for 3x3 (radius = 1) - macximal is 9
min_var = 0.0, # Minimal tile variance to include
max_var = VARIANCE_THRESHOLD, # Maximal tile variance to include
scale_disp = VARIANCE_SCALE_DISPARITY,
min_neibs = MIN_NEIBS) # Minimal number of valid tiles to include
num_le_test = num_batch_tiles_test.sum()
print("Number of <= %f disparity variance tiles: %d (est)"%(VARIANCE_THRESHOLD, num_le_test))
fpath = test_filenameTFR +("TEST_R%d_LE%4.1f"%(RADIUS,VARIANCE_THRESHOLD))
ex_data.writeTFRewcordsEpoch(fpath, ml_list = ml_list_test, files_list = ex_data.files_test, set_ds= ex_data.test_ds, radius = RADIUS, num_scenes = num_test_scenes)
list_of_file_lists_test, num_batch_tiles_test = ex_data.makeBatchLists( # results are also saved to self.*
data_ds = ex_data.test_ds,
disp_var = disp_var_test, # difference between maximal and minimal disparity for each scene, each tile
disp_neibs = num_neibs_test, # number of valid tiles around each center tile (for 3x3 (radius = 1) - macximal is 9
min_var = VARIANCE_THRESHOLD, # Minimal tile variance to include
max_var = 1000.0, # Maximal tile variance to include
scale_disp = VARIANCE_SCALE_DISPARITY,
min_neibs = MIN_NEIBS) # Minimal number of valid tiles to include
num_gt_test = num_batch_tiles_test.sum()
high_fract_test = 1.0 * num_gt_test / (num_le_test + num_gt_test)
print("Number of > %f disparity variance tiles: %d, fraction = %f (test)"%(VARIANCE_THRESHOLD, num_gt_test, high_fract_test))
fpath = test_filenameTFR +("TEST_R%d_GT%4.1f"%(RADIUS,VARIANCE_THRESHOLD))
ex_data.writeTFRewcordsEpoch(fpath, ml_list = ml_list_test, files_list = ex_data.files_test, set_ds= ex_data.test_ds, radius = RADIUS, num_scenes = num_test_scenes)
plt.show() plt.show()
""" """
scene = os.path.basename(test_corr)[:17] scene = os.path.basename(test_corr)[:17]
......
#!/usr/bin/env python3
from tensorflow.python.framework.ops import GraphKeys
__copyright__ = "Copyright 2018, Elphel, Inc."
__license__ = "GPL-3.0+"
__email__ = "andrey@elphel.com"
#python3 nn_ds_neibs17.py /home/eyesis/x3d_data/data_sets/conf/qcstereo_conf13.xml /home/eyesis/x3d_data/data_sets
import os
import sys
import numpy as np
import time
import shutil
from threading import Thread
import qcstereo_network
import qcstereo_losses
import qcstereo_functions as qsf
import tensorflow as tf
from tensorflow.python.ops import resource_variable_ops
tf.ResourceVariable = resource_variable_ops.ResourceVariable
qsf.TIME_START = time.time()
qsf.TIME_LAST = qsf.TIME_START
IMG_WIDTH = 324 # tiles per image row
DEBUG_LEVEL= 1
try:
conf_file = sys.argv[1]
except IndexError:
print("Configuration path is required as a first argument. Optional second argument specifies root directory for data files")
exit(1)
try:
root_dir = sys.argv[2]
except IndexError:
root_dir = os.path.dirname(conf_file)
print ("Configuration file: " + conf_file)
parameters, dirs, files, _ = qsf.parseXmlConfig(conf_file, root_dir)
"""
Temporarily for backward compatibility
"""
if not "SLOSS_CLIP" in parameters:
parameters['SLOSS_CLIP'] = 0.5
print ("Old config, setting SLOSS_CLIP=", parameters['SLOSS_CLIP'])
"""
Defined in config file
"""
TILE_SIDE, TILE_LAYERS, TWO_TRAINS, NET_ARCH1, NET_ARCH2 = [None]*5
ABSOLUTE_DISPARITY,SYM8_SUB, WLOSS_LAMBDA, SLOSS_LAMBDA, SLOSS_CLIP = [None]*5
SPREAD_CONVERGENCE, INTER_CONVERGENCE, HOR_FLIP, DISP_DIFF_CAP, DISP_DIFF_SLOPE = [None]*5
CLUSTER_RADIUS = None
PARTIALS_WEIGHTS, MAX_IMGS_IN_MEM, MAX_FILES_PER_GROUP, BATCH_WEIGHTS, ONLY_TILE = [None] * 5
USE_CONFIDENCE, WBORDERS_ZERO, EPOCHS_TO_RUN, FILE_UPDATE_EPOCHS = [None] * 4
LR600,LR400,LR200,LR100,LR = [None]*5
SHUFFLE_FILES, EPOCHS_FULL_TEST, SAVE_TIFFS = [None] * 3
CHECKPOINT_PERIOD = None
TRAIN_BUFFER_GPU, TRAIN_BUFFER_CPU = [None]*2
TEST_TITLES = None
USE_SPARSE_ONLY = True
LOGFILE="results-infer.txt"
"""
Next gets globals from the config file
"""
globals().update(parameters)
WIDTH = 324
HEIGHT = 242
TILE_SIZE = TILE_SIDE* TILE_SIDE # == 81
FEATURES_PER_TILE = TILE_LAYERS * TILE_SIZE# == 324
BATCH_SIZE = ([1,2][TWO_TRAINS])*2*1000//25 # == 80 Each batch of tiles has balanced D/S tiles, shuffled batches but not inside batches
SUFFIX=(str(NET_ARCH1)+'-'+str(NET_ARCH2)+
(["R","A"][ABSOLUTE_DISPARITY]) +
(["NS","S8"][SYM8_SUB])+
"WLAM"+str(WLOSS_LAMBDA)+
"SLAM"+str(SLOSS_LAMBDA)+
"SCLP"+str(SLOSS_CLIP)+
(['_nG','_G'][SPREAD_CONVERGENCE])+
(['_nI','_I'][INTER_CONVERGENCE]) +
(['_nHF',"_HF"][HOR_FLIP]) +
('_CP'+str(DISP_DIFF_CAP)) +
('_S'+str(DISP_DIFF_SLOPE))
)
NN_LAYOUT1 = qcstereo_network.NN_LAYOUTS[NET_ARCH1]
NN_LAYOUT2 = qcstereo_network.NN_LAYOUTS[NET_ARCH2]
# Tiff export slice labels
SLICE_LABELS = ["nn_out_ext","hier_out_ext","gt_disparity","gt_strength"]#,
# "cutcorn_cost_nw","cutcorn_cost",
# "gt-avg_dist","avg8_disp","gt_disp","out-avg"]
##############################################################################
cluster_size = (2 * CLUSTER_RADIUS + 1) * (2 * CLUSTER_RADIUS + 1)
center_tile_index = 2 * CLUSTER_RADIUS * (CLUSTER_RADIUS + 1)
qsf.prepareFiles(dirs,
files,
suffix = SUFFIX)
print ("Copying config files to results directory:\n ('%s' -> '%s')"%(conf_file,dirs['result']))
try:
os.makedirs(dirs['result'])
except:
pass
shutil.copy2(conf_file,dirs['result'])
LOGPATH = os.path.join(dirs['result'],LOGFILE)
image_data = qsf.initImageData( # just use image_data[0]
files = files,
max_imgs = MAX_IMGS_IN_MEM,
cluster_radius = 0, # CLUSTER_RADIUS,
tile_layers = TILE_LAYERS,
tile_side = TILE_SIDE,
width = IMG_WIDTH,
replace_nans = True,
infer = True,
keep_gt = True) # to generate same output files
ph_corr2d = tf.placeholder(np.float32, (None,FEATURES_PER_TILE))
ph_target_disparity = tf.placeholder(np.float32, (None,1))
#ph_tile_yx = tf.placeholder(np.int32, (None,2)) #tile_y, tile_x
ph_ntile = tf.placeholder(np.int32, (None,)) #nTile
ph_ntile_out = tf.placeholder(np.int32, (None,)) #which tiles should be calculated in stage2
"""
dataset_img = tf.data.Dataset.from_tensor_slices({
"corr2d": corr2d_placeholder,
"target_disparity": target_disparity_placeholder,
"xy": tile_xy_placeholder})
dataset_img = dataset_img.prefetch(image_data[0]['corr2d'].shape[0])
iterator_img = dataset_img.make_initializable_iterator()
next_element_tt = iterator_img.get_next()
"""
#No need to use datasets here = whole input even for the full frame( ~100MB) should fit
#corr2d9x325 = tf.concat([tf.reshape(next_element_tt['corr2d'],[-1,cluster_size,FEATURES_PER_TILE]) , tf.reshape(next_element_tt['target_disparity'], [-1,cluster_size, 1])],2)
tf_intile325 = tf.concat([ph_corr2d, ph_target_disparity],axis=1,name="tf_intile325") # [?,325]
pass
"""
target_disparity_cluster = tf.reshape(next_element_tt['target_disparity'], [-1,cluster_size, 1], name="targdisp_cluster")
corr2d_Nx325 = tf.concat([tf.reshape(next_element_tt['corr2d'],[-1,cluster_size,FEATURES_PER_TILE], name="coor2d_cluster"),
target_disparity_cluster], axis=2, name = "corr2d_Nx325")
"""
cluster_radius = CLUSTER_RADIUS
"""
Probably ResourceVariable is not needed here because of the tf.scatter_update()
If collection is not provided, it defaults to [GraphKeys.GLOBAL_VARIABLES], and that in turn fails saver.restore() as this variable was not available in the trained model
"""
rv_stage1_out = resource_variable_ops.ResourceVariable(
np.zeros([HEIGHT * WIDTH, NN_LAYOUT1[-1]]),
## collections = [],
collections = [GraphKeys.LOCAL_VARIABLES],# Works, available with tf.local_variables()
dtype=np.float32,
name = 'rv_stage1_out')
##stage1_tiled = tf.reshape(rv_stage1_out.read_value(),[HEIGHT, WIDTH, -1], name = 'stage1_tiled')
stage1_tiled = tf.reshape(rv_stage1_out, [HEIGHT, WIDTH, -1], name = 'stage1_tiled') # no need to synchronize here?
tf_stage1_exth = tf.concat([stage1_tiled[:,:1,:]]*cluster_radius +
[stage1_tiled] +
[stage1_tiled[:,-1:,:]]*cluster_radius, axis = 1,name = 'stage1_exth')
tf_stage1_ext = tf.concat([tf_stage1_exth[ :1,:,:]]*cluster_radius +
[tf_stage1_exth] +
[tf_stage1_exth[-1:,:,:]]*cluster_radius, axis = 0, name = 'stage1_exth')
tf_stage1_ext4 = tf.expand_dims(tf_stage1_ext, axis = 2, name = 'stage1_ext4')
concat_list = []
cluster_side = 2 * cluster_radius+1
for dy in range(cluster_side):
for dx in range(cluster_side):
# concat_list.append(tf_stage1_ext4[dy: cluster_side-dy, dx: cluster_side-dx,:,:])
concat_list.append(tf.slice(tf_stage1_ext4,[dy,dx,0,0],[HEIGHT, WIDTH,-1,-1]))
pass
tf_stage2_inm = tf.concat(concat_list, axis = 2, name ='stage2_inm') #242, 324, 25, 64
tf_stage2_in = tf.reshape(tf_stage2_inm,[-1,rv_stage1_out.shape[1]*cluster_side*cluster_side], name = 'stage2_in')
tf_stage2_in_sparse = tf.gather(tf_stage2_in, indices= ph_ntile_out, axis=0, name = 'stage2_in_sparse')
#aextv=np.concatenate([a[:,:1,:]]*2 + [a] + [a[:,-1:,:]]*2,axis = 1)
#ext=np.concatenate([aextv[:1,:,:]]*1 + [aextv] + [aextv[-1:,:,:]]*3,axis = 0)
with tf.name_scope("Siam_net"): # to have the same scope for weight/biases?
ns, _ = qcstereo_network.network_sub(tf_intile325,
input_global = [None,ph_target_disparity][SPREAD_CONVERGENCE], # input_global[:,i,:],
layout= NN_LAYOUT1,
reuse= False,
sym8 = SYM8_SUB,
cluster_radius = 0)
update=tf.scatter_update(ref=rv_stage1_out,
indices = ph_ntile,
updates = ns,
use_locking = False,
name = 'update')
with tf.control_dependencies([update]):
stage1done = tf.constant(1, dtype=tf.int32, name="stage1done")
pass
stage2_out_sparse = qcstereo_network.network_inter (
input_tensor = tf_stage2_in_sparse,
input_global = None, # [None, ig][inter_convergence], # optionally feed all convergence values (from each tile of a cluster)
layout = NN_LAYOUT2,
reuse = False,
use_confidence = False)
if not USE_SPARSE_ONLY: #Does it reduce the graph size?
stage2_out_full = qcstereo_network.network_inter (
input_tensor = tf_stage2_in,
input_global = None, # [None, ig][inter_convergence], # optionally feed all convergence values (from each tile of a cluster)
layout = NN_LAYOUT2,
reuse = True,
use_confidence = False)
pass
ROOT_PATH = './attic/infer_qcds_graph'+SUFFIX+"/" # for tensorboard
saver=tf.train.Saver()
"""
saver_def = saver.as_saver_def()
# The name of the tensor you must feed with a filename when saving/restoring.
print ('saver_def.filename_tensor_name=',saver_def.filename_tensor_name)
# The name of the target operation you must run when restoring.
print ('saver_def.restore_op_name=',saver_def.restore_op_name)
# The name of the target operation you must run when saving.
print ('saver_def.save_tensor_name=',saver_def.save_tensor_name)
saver_def.filename_tensor_name= save/Const:0
saver_def.restore_op_name= save/restore_all
saver_def.save_tensor_name= save/control_dependency:0
print(saver.save(sess, files["checkpoints"]))
"""
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
sess.run(tf.local_variables_initializer())
saver.restore(sess, files["checkpoints"])
merged = tf.summary.merge_all()
writer = tf.summary.FileWriter(ROOT_PATH, sess.graph)
lf = None
if LOGPATH:
lf=open(LOGPATH,"w") #overwrite previous (or make it "a"?
for nimg,_ in enumerate(image_data):
dataset_img = qsf.readImageData(
image_data = image_data,
files = files,
indx = nimg,
cluster_radius = 0, # CLUSTER_RADIUS,
tile_layers = TILE_LAYERS,
tile_side = TILE_SIDE,
width = IMG_WIDTH,
replace_nans = True,
infer = True,
keep_gt = True) # to generate same output files
img_corr2d = dataset_img['corr2d'] # [?,324)
img_target = dataset_img['target_disparity'] # [?,324)
img_ntile = dataset_img['ntile'].reshape([-1])
#run first stage network
qsf.print_time("Running inferred model, stage1", end=" ")
_ = sess.run([stage1done],
feed_dict={ph_corr2d: img_corr2d,
ph_target_disparity: img_target,
ph_ntile: img_ntile })
qsf.print_time("Done.")
qsf.print_time("Running inferred model, stage2", end=" ")
disp_out, = sess.run([stage2_out_sparse],
feed_dict={ph_ntile_out: img_ntile })
qsf.print_time("Done.")
result_file = files['result'][nimg].replace('.npy','-infer.npy') #not to overwrite training result files that are more complete
try:
os.makedirs(os.path.dirname(result_file))
except:
pass
rslt = np.concatenate(
[disp_out.reshape(-1,1),
dataset_img['t_disps'], #t_disps[ntest],
dataset_img['gtruths'], # gtruths[ntest],
# dbg_cost_nw.reshape(-1,1),
# dbg_cost_w.reshape(-1,1),
# dbg_d.reshape(-1,1),
# dbg_avg_disparity.reshape(-1,1),
# dbg_gt_disparity.reshape(-1,1),
# dbg_offs.reshape(-1,1)
],1)
np.save(result_file, rslt.reshape(HEIGHT,WIDTH,-1))
rslt = qsf.eval_results(result_file, ABSOLUTE_DISPARITY, radius=CLUSTER_RADIUS, logfile=lf) # (re-loads results). Only uses first 4 layers
if SAVE_TIFFS:
qsf.result_npy_to_tiff(result_file, ABSOLUTE_DISPARITY, fix_nan = True,labels=SLICE_LABELS, logfile=lf)
"""
Remove dataset_img (if it is not [0] to reduce memory footprint
"""
image_data[nimg] = None
if lf:
lf.close()
writer.close()
#!/usr/bin/env python3
##from numpy import float64
##from tensorflow.contrib.losses.python.metric_learning.metric_loss_ops import npairs_loss
##from debian.deb822 import PdiffIndex
__copyright__ = "Copyright 2018, Elphel, Inc."
__license__ = "GPL-3.0+"
__email__ = "andrey@elphel.com"
#python3 nn_ds_neibs17.py /home/eyesis/x3d_data/data_sets/conf/qcstereo_conf13.xml /home/eyesis/x3d_data/data_sets
import os
import sys
import numpy as np
import time
import shutil
from threading import Thread
import qcstereo_network
import qcstereo_losses
import qcstereo_functions as qsf
qsf.TIME_START = time.time()
qsf.TIME_LAST = qsf.TIME_START
IMG_WIDTH = 324 # tiles per image row
DEBUG_LEVEL= 1
try:
conf_file = sys.argv[1]
except IndexError:
print("Configuration path is required as a first argument. Optional second argument specifies root directory for data files")
exit(1)
try:
root_dir = sys.argv[2]
except IndexError:
root_dir = os.path.dirname(conf_file)
print ("Configuration file: " + conf_file)
parameters, dirs, files, _ = qsf.parseXmlConfig(conf_file, root_dir)
"""
Temporarily for backward compatibility
"""
if not "SLOSS_CLIP" in parameters:
parameters['SLOSS_CLIP'] = 0.5
print ("Old config, setting SLOSS_CLIP=", parameters['SLOSS_CLIP'])
"""
Defined in config file
"""
TILE_SIDE, TILE_LAYERS, TWO_TRAINS, NET_ARCH1, NET_ARCH2 = [None]*5
ABSOLUTE_DISPARITY,SYM8_SUB, WLOSS_LAMBDA, SLOSS_LAMBDA, SLOSS_CLIP = [None]*5
SPREAD_CONVERGENCE, INTER_CONVERGENCE, HOR_FLIP, DISP_DIFF_CAP, DISP_DIFF_SLOPE = [None]*5
CLUSTER_RADIUS = None
PARTIALS_WEIGHTS, MAX_IMGS_IN_MEM, MAX_FILES_PER_GROUP, BATCH_WEIGHTS, ONLY_TILE = [None] * 5
USE_CONFIDENCE, WBORDERS_ZERO, EPOCHS_TO_RUN, FILE_UPDATE_EPOCHS = [None] * 4
LR600,LR400,LR200,LR100,LR = [None]*5
SHUFFLE_FILES, EPOCHS_FULL_TEST, SAVE_TIFFS = [None] * 3
TRAIN_BUFFER_GPU, TRAIN_BUFFER_CPU = [None]*2
"""
Next gets globals from the config file
"""
globals().update(parameters)
TRAIN_BUFFER_SIZE = TRAIN_BUFFER_GPU * TRAIN_BUFFER_CPU # in merged (quad) batches
#exit(0)
WIDTH = 324
HEIGHT = 242
TILE_SIZE = TILE_SIDE* TILE_SIDE # == 81
FEATURES_PER_TILE = TILE_LAYERS * TILE_SIZE# == 324
BATCH_SIZE = ([1,2][TWO_TRAINS])*2*1000//25 # == 80 Each batch of tiles has balanced D/S tiles, shuffled batches but not inside batches
SUFFIX=(str(NET_ARCH1)+'-'+str(NET_ARCH2)+
(["R","A"][ABSOLUTE_DISPARITY]) +
(["NS","S8"][SYM8_SUB])+
"WLAM"+str(WLOSS_LAMBDA)+
"SLAM"+str(SLOSS_LAMBDA)+
"SCLP"+str(SLOSS_CLIP)+
(['_nG','_G'][SPREAD_CONVERGENCE])+
(['_nI','_I'][INTER_CONVERGENCE]) +
(['_nHF',"_HF"][HOR_FLIP]) +
('_CP'+str(DISP_DIFF_CAP)) +
('_S'+str(DISP_DIFF_SLOPE))
)
NN_LAYOUTS = {0:[0, 0, 0, 32, 20, 16],
1:[0, 0, 0, 256, 128, 64],
2:[0, 128, 32, 32, 32, 16],
3:[0, 0, 40, 32, 20, 16],
4:[0, 0, 0, 0, 16, 16],
5:[0, 0, 64, 32, 32, 16],
6:[0, 0, 32, 16, 16, 16],
7:[0, 0, 64, 16, 16, 16],
8:[0, 0, 0, 64, 20, 16],
9:[0, 0, 256, 64, 32, 16],
10:[0, 256, 128, 64, 32, 16],
11:[0, 0, 0, 0, 64, 32],
}
NN_LAYOUT1 = NN_LAYOUTS[NET_ARCH1]
NN_LAYOUT2 = NN_LAYOUTS[NET_ARCH2]
USE_PARTIALS = not PARTIALS_WEIGHTS is None # False - just a single Siamese net, True - partial outputs that use concentric squares of the first level subnets
# Tiff export slice labels
SLICE_LABELS = ["nn_out_ext","hier_out_ext","gt_disparity","gt_strength",
"cutcorn_cost_nw","cutcorn_cost",
"gt-avg_dist","avg8_disp","gt_disp","out-avg"]
##############################################################################
cluster_size = (2 * CLUSTER_RADIUS + 1) * (2 * CLUSTER_RADIUS + 1)
center_tile_index = 2 * CLUSTER_RADIUS * (CLUSTER_RADIUS + 1)
qsf.prepareFiles(dirs, files, suffix = SUFFIX)
partials = None
partials = qsf.concentricSquares(CLUSTER_RADIUS)
PARTIALS_WEIGHTS = [1.0*pw/sum(PARTIALS_WEIGHTS) for pw in PARTIALS_WEIGHTS]
if not USE_PARTIALS:
partials = partials[0:1]
PARTIALS_WEIGHTS = [1.0]
import tensorflow as tf
qsf.evaluateAllResults(result_files = files['result'],
absolute_disparity = ABSOLUTE_DISPARITY,
cluster_radius = CLUSTER_RADIUS,
labels = SLICE_LABELS)
image_data = qsf.initImageData(
files = files,
max_imgs = MAX_IMGS_IN_MEM,
cluster_radius = CLUSTER_RADIUS,
tile_layers = TILE_LAYERS,
tile_side = TILE_SIDE,
width = IMG_WIDTH,
replace_nans = True)
corr2d_len, target_disparity_len, _ = qsf.get_lengths(CLUSTER_RADIUS, TILE_LAYERS, TILE_SIDE)
train_next, dataset_train, datasets_test= qsf.initTrainTestData(
files = files,
cluster_radius = CLUSTER_RADIUS,
buffer_size = TRAIN_BUFFER_SIZE * BATCH_SIZE) # number of clusters per train
corr2d_train_placeholder = tf.placeholder(dataset_train.dtype, (None,FEATURES_PER_TILE * cluster_size)) # corr2d_train.shape)
target_disparity_train_placeholder = tf.placeholder(dataset_train.dtype, (None,1 * cluster_size)) #target_disparity_train.shape)
gt_ds_train_placeholder = tf.placeholder(dataset_train.dtype, (None,2 * cluster_size)) #gt_ds_train.shape)
dataset_tt = tf.data.Dataset.from_tensor_slices({
"corr2d": corr2d_train_placeholder,
"target_disparity": target_disparity_train_placeholder,
"gt_ds": gt_ds_train_placeholder})
tf_batch_weights = tf.placeholder(shape=(None,), dtype=tf.float32, name = "batch_weights") # way to increase importance of the high variance clusters
feed_batch_weights = np.array(BATCH_WEIGHTS*(BATCH_SIZE//len(BATCH_WEIGHTS)), dtype=np.float32)
feed_batch_weight_1 = np.array([1.0], dtype=np.float32)
dataset_test_size = len(datasets_test[0])
dataset_test_size //= BATCH_SIZE
dataset_img_size = len(image_data[0]['corr2d'])
dataset_img_size //= BATCH_SIZE
dataset_tt = dataset_tt.batch(BATCH_SIZE)
dataset_tt = dataset_tt.prefetch(BATCH_SIZE)
iterator_tt = dataset_tt.make_initializable_iterator()
next_element_tt = iterator_tt.get_next()
result_dir = './attic/result_neibs_'+ SUFFIX+'/'
checkpoint_dir = './attic/result_neibs_'+ SUFFIX+'/'
save_freq = 500
def debug_gt_variance(
indx, # This tile index (0..8)
center_indx, # center tile index
gt_ds_batch # [?:9:2]
):
with tf.name_scope("Debug_GT_Variance"):
d_gt_this = tf.reshape(gt_ds_batch[:,2 * indx],[-1], name = "d_this")
d_gt_center = tf.reshape(gt_ds_batch[:,2 * center_indx],[-1], name = "d_center")
d_gt_diff = tf.subtract(d_gt_this, d_gt_center, name = "d_diff")
d_gt_diff2 = tf.multiply(d_gt_diff, d_gt_diff, name = "d_diff2")
d_gt_var = tf.reduce_mean(d_gt_diff2, name = "d_gt_var")
return d_gt_var
target_disparity_cluster = tf.reshape(next_element_tt['target_disparity'], [-1,cluster_size, 1], name="targdisp_cluster")
corr2d_Nx325 = tf.concat([tf.reshape(next_element_tt['corr2d'],[-1,cluster_size,FEATURES_PER_TILE], name="coor2d_cluster"),
target_disparity_cluster], axis=2, name = "corr2d_Nx325")
if SPREAD_CONVERGENCE:
outs, inp_weights = qcstereo_network.networks_siam(
input = corr2d_Nx325,
input_global = target_disparity_cluster,
layout1 = NN_LAYOUT1,
layout2 = NN_LAYOUT2,
inter_convergence = INTER_CONVERGENCE,
sym8 = SYM8_SUB,
only_tile = ONLY_TILE, #Remove/put None for normal operation
partials = partials,
use_confidence= USE_CONFIDENCE)
else:
outs, inp_weights = qcstereo_network.networks_siam(
input_tensor= corr2d_Nx325,
input_global = None,
layout1 = NN_LAYOUT1,
layout2 = NN_LAYOUT2,
inter_convergence = False,
sym8 = SYM8_SUB,
only_tile = ONLY_TILE, #Remove/put None for normal operation
partials = partials,
use_confidence= USE_CONFIDENCE)
tf_partial_weights = tf.constant(PARTIALS_WEIGHTS,dtype=tf.float32,name="partial_weights")
G_losses = [0.0]*len(partials)
target_disparity_batch= next_element_tt['target_disparity'][:,center_tile_index:center_tile_index+1]
gt_ds_batch_clust = next_element_tt['gt_ds']
gt_ds_batch = gt_ds_batch_clust[:,2 * center_tile_index: 2 * (center_tile_index +1)]
G_losses[0], _disp_slice, _d_gt_slice, _out_diff, _out_diff2, _w_norm, _out_wdiff2, _cost1 = qcstereo_losses.batchLoss(
out_batch = outs[0], # [batch_size,(1..2)] tf_result
target_disparity_batch= target_disparity_batch, # next_element_tt['target_disparity'][:,center_tile_index:center_tile_index+1], # target_disparity_batch_center, # next_element_tt['target_disparity'], # target_disparity, ### target_d, # [batch_size] tf placeholder
gt_ds_batch = gt_ds_batch, # next_element_tt['gt_ds'][:,2 * center_tile_index: 2 * (center_tile_index +1)], # gt_ds_batch_center, ## next_element_tt['gt_ds'], # gt_ds, ### gt, # [batch_size,2] tf placeholder
batch_weights = tf_batch_weights,
disp_diff_cap = DISP_DIFF_CAP,
disp_diff_slope= DISP_DIFF_SLOPE,
absolute_disparity = ABSOLUTE_DISPARITY,
use_confidence = USE_CONFIDENCE, # True,
lambda_conf_avg = 0.01,
## lambda_conf_pwr = 0.1,
conf_pwr = 2.0,
gt_conf_offset = 0.08,
gt_conf_pwr = 2.0,
error2_offset = 0, # 0.0025, # (0.05^2)
disp_wmin = 1.0, # minimal disparity to apply weight boosting for small disparities
disp_wmax = 8.0, # maximal disparity to apply weight boosting for small disparities
use_out = False) # use calculated disparity for disparity weight boosting (False - use target disparity)
G_loss = G_losses[0]
for n in range (1,len(partials)):
G_losses[n], _, _, _, _, _, _, _ = qcstereo_losses.batchLoss(
out_batch = outs[n], # [batch_size,(1..2)] tf_result
target_disparity_batch= target_disparity_batch, #next_element_tt['target_disparity'][:,center_tile_index:center_tile_index+1], # target_disparity_batch_center, # next_element_tt['target_disparity'], # target_disparity, ### target_d, # [batch_size] tf placeholder
gt_ds_batch = gt_ds_batch, # next_element_tt['gt_ds'][:,2 * center_tile_index: 2 * (center_tile_index +1)], # gt_ds_batch_center, ## next_element_tt['gt_ds'], # gt_ds, ### gt, # [batch_size,2] tf placeholder
batch_weights = tf_batch_weights,
disp_diff_cap = DISP_DIFF_CAP,
disp_diff_slope= DISP_DIFF_SLOPE,
absolute_disparity = ABSOLUTE_DISPARITY,
use_confidence = USE_CONFIDENCE, # True,
lambda_conf_avg = 0.01,
# lambda_conf_pwr = 0.1,
conf_pwr = 2.0,
gt_conf_offset = 0.08,
gt_conf_pwr = 2.0,
error2_offset = 0, # 0.0025, # (0.05^2)
disp_wmin = 1.0, # minimal disparity to apply weight boosting for small disparities
disp_wmax = 8.0, # maximal disparity to apply weight boosting for small disparities
use_out = False) # use calculated disparity for disparity weight boosting (False - use target disparity)
tf_wlosses = tf.multiply(G_losses, tf_partial_weights, name = "tf_wlosses")
G_losses_sum = tf.reduce_sum(tf_wlosses, name = "G_losses_sum")
if SLOSS_LAMBDA > 0:
S_loss, rslt_cost_nw, rslt_cost_w, rslt_d , rslt_avg_disparity, rslt_gt_disparity, rslt_offs = qcstereo_losses.smoothLoss(
out_batch = outs[0], # [batch_size,(1..2)] tf_result
target_disparity_batch = target_disparity_batch, # [batch_size] tf placeholder
gt_ds_batch_clust = gt_ds_batch_clust, # [batch_size,25,2] tf placeholder
clip = SLOSS_CLIP,
absolute_disparity = ABSOLUTE_DISPARITY, #when false there should be no activation on disparity output !
cluster_radius = CLUSTER_RADIUS)
GS_loss = tf.add(G_losses_sum, SLOSS_LAMBDA * S_loss, name = "GS_loss")
else:
S_loss = tf.constant(0.0, dtype=tf.float32,name = "S_loss")
GS_loss = G_losses_sum # G_loss
if WLOSS_LAMBDA > 0.0:
W_loss = qcstereo_losses.weightsLoss(
inp_weights = inp_weights[0], # inp_weights - list of tensors, currently - just [0]
tile_layers= TILE_LAYERS, # 4
tile_side = TILE_SIDE, # 9
wborders_zero = WBORDERS_ZERO)
GW_loss = tf.add(GS_loss, WLOSS_LAMBDA * W_loss, name = "GW_loss")
else:
GW_loss = GS_loss # G_loss
W_loss = tf.constant(0.0, dtype=tf.float32,name = "W_loss")
GT_variance = debug_gt_variance(indx = 0, # This tile index (0..8)
center_indx = 4, # center tile index
gt_ds_batch = next_element_tt['gt_ds'])# [?:18]
tf_ph_G_loss = tf.placeholder(tf.float32,shape=None,name='G_loss_avg')
tf_ph_G_losses = tf.placeholder(tf.float32,shape=[len(partials)],name='G_losses_avg')
tf_ph_S_loss = tf.placeholder(tf.float32,shape=None,name='S_loss_avg')
tf_ph_W_loss = tf.placeholder(tf.float32,shape=None,name='W_loss_avg')
tf_ph_GW_loss = tf.placeholder(tf.float32,shape=None,name='GW_loss_avg')
tf_ph_sq_diff = tf.placeholder(tf.float32,shape=None,name='sq_diff_avg')
tf_gtvar_diff = tf.placeholder(tf.float32,shape=None,name='gtvar_diff')
tf_img_test0 = tf.placeholder(tf.float32,shape=None,name='img_test0')
tf_img_test9 = tf.placeholder(tf.float32,shape=None,name='img_test9')
with tf.name_scope('sample'):
tf.summary.scalar("GW_loss", GW_loss)
tf.summary.scalar("G_loss", G_loss)
tf.summary.scalar("S_loss", S_loss)
tf.summary.scalar("W_loss", W_loss)
tf.summary.scalar("sq_diff", _cost1)
tf.summary.scalar("gtvar_diff", GT_variance)
with tf.name_scope('epoch_average'):
for i in range(tf_ph_G_losses.shape[0]):
tf.summary.scalar("G_loss_epoch_"+str(i), tf_ph_G_losses[i])
tf.summary.scalar("GW_loss_epoch", tf_ph_GW_loss)
tf.summary.scalar("G_loss_epoch", tf_ph_G_loss)
tf.summary.scalar("S_loss_epoch", tf_ph_S_loss)
tf.summary.scalar("W_loss_epoch", tf_ph_W_loss)
tf.summary.scalar("sq_diff_epoch", tf_ph_sq_diff)
tf.summary.scalar("gtvar_diff", tf_gtvar_diff)
tf.summary.scalar("img_test0", tf_img_test0)
tf.summary.scalar("img_test9", tf_img_test9)
t_vars= tf.trainable_variables()
lr= tf.placeholder(tf.float32)
G_opt= tf.train.AdamOptimizer(learning_rate=lr).minimize(GW_loss)
ROOT_PATH = './attic/nn_ds_neibs18_graph'+SUFFIX+"/"
TT_SUBDIRS = ['train'] #,'test0','test1','test2','test3']
for i,_ in enumerate(datasets_test):
TT_SUBDIRS.append('test%d'%(i))
TT_PATHS = [ROOT_PATH + p for p in TT_SUBDIRS]
# CLEAN OLD STAFF
for p in TT_PATHS:
shutil.rmtree(p, ignore_errors=True)
num_train_subs = len(train_next) # number of (different type) merged training sets
dataset_train_size = TRAIN_BUFFER_GPU * num_train_subs # TRAIN_BUFFER_SIZE
tt_summaries = [0.0 for e in TT_SUBDIRS]
tt_avg = [0.0 for e in TT_SUBDIRS]
tt2_avg = [0.0 for e in TT_SUBDIRS]
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
sess.run(tf.local_variables_initializer())
merged = tf.summary.merge_all()
tt_writers = []
for p in TT_PATHS:
tt_writers.append(tf.summary.FileWriter(p, sess.graph))
loss_gw_train_hist= np.empty(dataset_train_size, dtype=np.float32)
loss_g_train_hist= np.empty(dataset_train_size, dtype=np.float32)
loss_g_train_hists= [np.empty(dataset_train_size, dtype=np.float32) for p in partials]
loss_s_train_hist= np.empty(dataset_train_size, dtype=np.float32)
loss_w_train_hist= np.empty(dataset_train_size, dtype=np.float32)
loss_gw_test_hist= np.empty(dataset_test_size, dtype=np.float32)
loss_g_test_hists= [np.empty(dataset_test_size, dtype=np.float32) for p in partials]
loss_s_test_hist= np.empty(dataset_test_size, dtype=np.float32)
loss_w_test_hist= np.empty(dataset_test_size, dtype=np.float32)
loss2_train_hist= np.empty(dataset_train_size, dtype=np.float32)
loss2_test_hist= np.empty(dataset_test_size, dtype=np.float32)
train_gw_avg = 0.0
train_g_avg = 0.0
train_g_avgs = [0.0]*len(partials)
train_w_avg = 0.0
train_s_avg = 0.0
test_gw_avg = 0.0
test_g_avg = 0.0
test_g_avgs = [0.0]*len(partials)
test_w_avg = 0.0
test_s_avg = 0.0
gtvar_train_hist= np.empty(dataset_train_size, dtype=np.float32)
gtvar_test_hist= np.empty(dataset_test_size, dtype=np.float32)
gtvar_train = 0.0
gtvar_test = 0.0
gtvar_train_avg = 0.0
gtvar_test_avg = 0.0
img_gain_test0 = 1.0
img_gain_test9 = 1.0
thr=None
thr_result = None
trains_to_update = [train_next[n_train]['more_files'] for n_train in range(len(train_next))]
for epoch in range (EPOCHS_TO_RUN):
"""
update files after each epoch, all 4.
Convert to threads after testing
"""
if (FILE_UPDATE_EPOCHS > 0) and (epoch % FILE_UPDATE_EPOCHS == 0):
if not thr is None:
if thr.is_alive():
qsf.print_time("***WAITING*** until tfrecord gets loaded", end=" ")
else:
qsf.print_time("tfrecord is ***ALREADY LOADED*** ", end=" ")
thr.join()
qsf.print_time("Done")
qsf.print_time("Inserting new data", end=" ")
for n_train in range(len(trains_to_update)):
if trains_to_update[n_train]:
qsf.add_file_to_dataset(dataset = dataset_train,
new_dataset = thr_result[n_train],
train_next = train_next[n_train])
qsf.print_time("Done")
thr_result = []
fpaths = []
for n_train in range(len(trains_to_update)):
if trains_to_update[n_train]:
fpaths.append(files['train'][n_train][train_next[n_train]['file']])
qsf.print_time("Will read in background: "+fpaths[-1])
thr = Thread(target=qsf.getMoreFiles, args=(fpaths,thr_result, CLUSTER_RADIUS, HOR_FLIP, TILE_LAYERS, TILE_SIDE))
thr.start()
train_buf_index = epoch % TRAIN_BUFFER_CPU # GPU memory from CPU memory (now 4)
if epoch >=600:
learning_rate = LR600
elif epoch >=400:
learning_rate = LR400
elif epoch >=200:
learning_rate = LR200
elif epoch >=100:
learning_rate = LR100
else:
learning_rate = LR
if (train_buf_index == 0) and SHUFFLE_FILES:
qsf.print_time("Shuffling how datasets datasets_train_lvar and datasets_train_hvar are zipped together", end="")
qsf.shuffle_in_place(
dataset_data = dataset_train, #alternating clusters from 4 sources.each cluster has all needed data (concatenated)
period = num_train_subs)
qsf.print_time(" Done")
sti = train_buf_index * dataset_train_size * BATCH_SIZE # TRAIN_BUFFER_GPU * num_train_subs
eti = sti+ dataset_train_size * BATCH_SIZE# (train_buf_index +1) * TRAIN_BUFFER_GPU * num_train_subs
sess.run(iterator_tt.initializer, feed_dict={corr2d_train_placeholder: dataset_train[sti:eti,:corr2d_len],
target_disparity_train_placeholder: dataset_train[sti:eti,corr2d_len:corr2d_len+target_disparity_len],
gt_ds_train_placeholder: dataset_train[sti:eti,corr2d_len+target_disparity_len:] })
for i in range(dataset_train_size):
try:
tt_summaries[0],_, GW_loss_trained, G_losses_trained, S_loss_trained, W_loss_trained, output, disp_slice, d_gt_slice, out_diff, out_diff2, w_norm, out_wdiff2, out_cost1, gt_variance = sess.run(
[ merged,
G_opt,
GW_loss,
G_losses,
S_loss,
W_loss,
outs[0],
_disp_slice,
_d_gt_slice,
_out_diff,
_out_diff2,
_w_norm,
_out_wdiff2,
_cost1,
GT_variance
],
feed_dict={tf_batch_weights: feed_batch_weights,
lr: learning_rate,
tf_ph_GW_loss: train_gw_avg,
tf_ph_G_loss: train_g_avgs[0], #train_g_avg,
tf_ph_G_losses: train_g_avgs,
tf_ph_S_loss: train_s_avg,
tf_ph_W_loss: train_w_avg,
tf_ph_sq_diff: tt2_avg[0], # train2_avg,
tf_gtvar_diff: gtvar_train_avg,
tf_img_test0: img_gain_test0,
tf_img_test9: img_gain_test9}) # previous value of *_avg #Fetch argument 0.0 has invalid type <class 'float'>, must be a string or Tensor. (Can not convert a float into a Tensor or Operation.)
loss_gw_train_hist[i] = GW_loss_trained
for nn, gl in enumerate(G_losses_trained):
loss_g_train_hists[nn][i] = gl
loss_s_train_hist[i] = S_loss_trained
loss_w_train_hist[i] = W_loss_trained
loss2_train_hist[i] = out_cost1
gtvar_train_hist[i] = gt_variance
except tf.errors.OutOfRangeError:
print("****** NO MORE DATA! train done at step %d"%(i))
break
train_gw_avg = np.average(loss_gw_train_hist).astype(np.float32)
train_g_avg = np.average(loss_g_train_hist).astype(np.float32)
for nn, lgth in enumerate(loss_g_train_hists):
train_g_avgs[nn] = np.average(lgth).astype(np.float32)
train_s_avg = np.average(loss_s_train_hist).astype(np.float32)
train_w_avg = np.average(loss_w_train_hist).astype(np.float32)
tt2_avg[0] = np.average(loss2_train_hist).astype(np.float32)
gtvar_train_avg = np.average(gtvar_train_hist).astype(np.float32)
for ntest,dataset_test in enumerate(datasets_test):
sess.run(iterator_tt.initializer, feed_dict={corr2d_train_placeholder: dataset_test[:, :corr2d_len], #['corr2d'],
target_disparity_train_placeholder: dataset_test[:, corr2d_len:corr2d_len+target_disparity_len], # ['target_disparity'],
gt_ds_train_placeholder: dataset_test[:, corr2d_len+target_disparity_len:] }) # ['gt_ds']})
for i in range(dataset_test_size):
try:
tt_summaries[ntest+1], GW_loss_tested, G_losses_tested, S_loss_tested, W_loss_tested, output, disp_slice, d_gt_slice, out_diff, out_diff2, w_norm, out_wdiff2, out_cost1, gt_variance = sess.run(
[merged,
GW_loss,
G_losses,
S_loss,
W_loss,
outs[0],
_disp_slice,
_d_gt_slice,
_out_diff,
_out_diff2,
_w_norm,
_out_wdiff2,
_cost1,
GT_variance
],
feed_dict={tf_batch_weights: feed_batch_weight_1 , # feed_batch_weights,
lr: learning_rate,
tf_ph_GW_loss: test_gw_avg,
tf_ph_G_loss: test_g_avg,
tf_ph_G_losses: test_g_avgs, # train_g_avgs, # temporary, there is o data fro test
tf_ph_S_loss: test_s_avg,
tf_ph_W_loss: test_w_avg,
tf_ph_sq_diff: tt2_avg[ntest+1], #test2_avg,
tf_gtvar_diff: gtvar_test_avg,
tf_img_test0: img_gain_test0,
tf_img_test9: img_gain_test9}) # previous value of *_avg
loss_gw_test_hist[i] = GW_loss_tested
for nn, gl in enumerate(G_losses_tested):
loss_g_test_hists[nn][i] = gl
loss_s_test_hist[i] = S_loss_tested
loss_w_test_hist[i] = W_loss_tested
loss2_test_hist[i] = out_cost1
gtvar_test_hist[i] = gt_variance
except tf.errors.OutOfRangeError:
print("test done at step %d"%(i))
break
for nn, lgth in enumerate(loss_g_test_hists):
test_g_avgs[nn] = np.average(lgth).astype(np.float32)
test_s_avg = np.average(loss_s_test_hist).astype(np.float32)
test_w_avg = np.average(loss_w_test_hist).astype(np.float32)
tt_avg[ntest+1] = np.average(loss_gw_test_hist).astype(np.float32)
tt2_avg[ntest+1] = np.average(loss2_test_hist).astype(np.float32)
gtvar_test_avg = np.average(gtvar_test_hist).astype(np.float32)
for n,tt_writer in enumerate(tt_writers):
tt_writer.add_summary(tt_summaries[n],epoch)
qsf.print_time("==== %d:%d -> %f %f %f (%f %f %f) dbg:%f %f ===="%(epoch,i,train_gw_avg, tt_avg[1], tt_avg[2], tt2_avg[0], tt2_avg[1], tt2_avg[2], gtvar_train_avg, gtvar_test_avg))
if (((epoch + 1) == EPOCHS_TO_RUN) or (((epoch + 1) % EPOCHS_FULL_TEST) == 0)) and (len(image_data) > 0) :
if (epoch + 1) == EPOCHS_TO_RUN: # last
print("Last epoch, removing train/test datasets to reduce memory footprint")
del(dataset_train)
del(dataset_test)
last_epoch = (epoch + 1) == EPOCHS_TO_RUN
ind_img = [0]
if last_epoch:
ind_img = [i for i in range(len(image_data))]
###################################################
# Read the full image
###################################################
test_summaries_img = [0.0]*len(ind_img) # datasets_img)
disp_out= np.empty((WIDTH*HEIGHT), dtype=np.float32)
dbg_cost_nw= np.empty((WIDTH*HEIGHT), dtype=np.float32)
dbg_cost_w= np.empty((WIDTH*HEIGHT), dtype=np.float32)
dbg_d= np.empty((WIDTH*HEIGHT), dtype=np.float32)
dbg_avg_disparity = np.empty((WIDTH*HEIGHT), dtype=np.float32)
dbg_gt_disparity = np.empty((WIDTH*HEIGHT), dtype=np.float32)
dbg_offs = np.empty((WIDTH*HEIGHT), dtype=np.float32)
for ntest in ind_img: # datasets_img):
dataset_img = qsf.readImageData(
image_data = image_data,
files = files,
indx = ntest,
cluster_radius = CLUSTER_RADIUS,
tile_layers = TILE_LAYERS,
tile_side = TILE_SIDE,
width = IMG_WIDTH,
replace_nans = True)
sess.run(iterator_tt.initializer, feed_dict={corr2d_train_placeholder: dataset_img['corr2d'],
target_disparity_train_placeholder: dataset_img['target_disparity'],
gt_ds_train_placeholder: dataset_img['gt_ds']})
for start_offs in range(0,disp_out.shape[0],BATCH_SIZE):
end_offs = min(start_offs+BATCH_SIZE,disp_out.shape[0])
try:
test_summaries_img[ntest],output, cost_nw, cost_w, dd, avg_disparity, gt_disparity, offs = sess.run(
[merged,
outs[0], # {?,1]
rslt_cost_nw, #[?,]
rslt_cost_w, #[?,]
rslt_d, #[?,]
rslt_avg_disparity,
rslt_gt_disparity,
rslt_offs
],
feed_dict={
tf_batch_weights: feed_batch_weight_1, # feed_batch_weights,
tf_ph_GW_loss: test_gw_avg,
tf_ph_G_loss: test_g_avg,
tf_ph_G_losses: train_g_avgs, # temporary, there is o data for test
tf_ph_S_loss: test_s_avg,
tf_ph_W_loss: test_w_avg,
tf_ph_sq_diff: 0, # test2_avg,
tf_gtvar_diff: gtvar_test_avg,
tf_img_test0: img_gain_test0,
tf_img_test9: img_gain_test9}) # previous value of *_avg
except tf.errors.OutOfRangeError:
print("test done at step %d"%(i))
break
try:
disp_out[start_offs:end_offs] = output.flatten()
dbg_cost_nw[start_offs:end_offs] = cost_nw.flatten()
dbg_cost_w [start_offs:end_offs] = cost_w.flatten()
dbg_d[start_offs:end_offs] = dd.flatten()
dbg_avg_disparity[start_offs:end_offs] = avg_disparity.flatten()
dbg_gt_disparity[start_offs:end_offs] = gt_disparity.flatten()
dbg_offs[start_offs:end_offs] = offs.flatten()
except ValueError:
print("dataset_img_size= %d, i=%d, output.shape[0]=%d "%(dataset_img_size, i, output.shape[0]))
break;
pass
result_file = files['result'][ntest] # result_files[ntest]
try:
os.makedirs(os.path.dirname(result_file))
except:
pass
rslt = np.concatenate(
[disp_out.reshape(-1,1),
dataset_img['t_disps'], #t_disps[ntest],
dataset_img['gtruths'], # gtruths[ntest],
dbg_cost_nw.reshape(-1,1),
dbg_cost_w.reshape(-1,1),
dbg_d.reshape(-1,1),
dbg_avg_disparity.reshape(-1,1),
dbg_gt_disparity.reshape(-1,1),
dbg_offs.reshape(-1,1)],1)
np.save(result_file, rslt.reshape(HEIGHT,WIDTH,-1))
rslt = qsf.eval_results(result_file, ABSOLUTE_DISPARITY,radius=CLUSTER_RADIUS)
img_gain_test0 = rslt[0][0]/rslt[0][1]
img_gain_test9 = rslt[9][0]/rslt[9][1]
if SAVE_TIFFS:
qsf.result_npy_to_tiff(result_file, ABSOLUTE_DISPARITY, fix_nan = True,labels=SLICE_LABELS)
"""
Remove dataset_img (if it is not [0] to reduce memory footprint
"""
if ntest > 0:
image_data[ntest] = None
# Close writers
for tt_writer in tt_writers:
try:
tt_writer.close()
except:
print ("Could not close tt_writer: ",tt_writer)
print("All done")
exit (0)
#!/usr/bin/env python3
##from numpy import float64
##from tensorflow.contrib.losses.python.metric_learning.metric_loss_ops import npairs_loss
##from debian.deb822 import PdiffIndex
__copyright__ = "Copyright 2018, Elphel, Inc."
__license__ = "GPL-3.0+"
__email__ = "andrey@elphel.com"
#python3 nn_ds_neibs17.py /home/eyesis/x3d_data/data_sets/conf/qcstereo_conf13.xml /home/eyesis/x3d_data/data_sets
import os
import sys
import numpy as np
import time
import shutil
from threading import Thread
import qcstereo_network
import qcstereo_losses
import qcstereo_functions as qsf
import tensorflow as tf
qsf.TIME_START = time.time()
qsf.TIME_LAST = qsf.TIME_START
IMG_WIDTH = 324 # tiles per image row
DEBUG_LEVEL= 1
try:
conf_file = sys.argv[1]
except IndexError:
print("Configuration path is required as a first argument. Optional second argument specifies root directory for data files")
exit(1)
try:
root_dir = sys.argv[2]
except IndexError:
root_dir = os.path.dirname(conf_file)
print ("Configuration file: " + conf_file)
parameters, dirs, files, _ = qsf.parseXmlConfig(conf_file, root_dir)
"""
Temporarily for backward compatibility
"""
if not "SLOSS_CLIP" in parameters:
parameters['SLOSS_CLIP'] = 0.5
print ("Old config, setting SLOSS_CLIP=", parameters['SLOSS_CLIP'])
"""
Defined in config file
"""
TILE_SIDE, TILE_LAYERS, TWO_TRAINS, NET_ARCH1, NET_ARCH2 = [None]*5
ABSOLUTE_DISPARITY,SYM8_SUB, WLOSS_LAMBDA, SLOSS_LAMBDA, SLOSS_CLIP = [None]*5
SPREAD_CONVERGENCE, INTER_CONVERGENCE, HOR_FLIP, DISP_DIFF_CAP, DISP_DIFF_SLOPE = [None]*5
CLUSTER_RADIUS = None
PARTIALS_WEIGHTS, MAX_IMGS_IN_MEM, MAX_FILES_PER_GROUP, BATCH_WEIGHTS, ONLY_TILE = [None] * 5
USE_CONFIDENCE, WBORDERS_ZERO, EPOCHS_TO_RUN, FILE_UPDATE_EPOCHS = [None] * 4
LR600,LR400,LR200,LR100,LR = [None]*5
SHUFFLE_FILES, EPOCHS_FULL_TEST, SAVE_TIFFS = [None] * 3
TRAIN_BUFFER_GPU, TRAIN_BUFFER_CPU = [None]*2
TEST_TITLES = None
"""
Next gets globals from the config file
"""
globals().update(parameters)
TRAIN_BUFFER_SIZE = TRAIN_BUFFER_GPU * TRAIN_BUFFER_CPU # in merged (quad) batches
#exit(0)
WIDTH = 324
HEIGHT = 242
TILE_SIZE = TILE_SIDE* TILE_SIDE # == 81
FEATURES_PER_TILE = TILE_LAYERS * TILE_SIZE# == 324
BATCH_SIZE = ([1,2][TWO_TRAINS])*2*1000//25 # == 80 Each batch of tiles has balanced D/S tiles, shuffled batches but not inside batches
SUFFIX=(str(NET_ARCH1)+'-'+str(NET_ARCH2)+
(["R","A"][ABSOLUTE_DISPARITY]) +
(["NS","S8"][SYM8_SUB])+
"WLAM"+str(WLOSS_LAMBDA)+
"SLAM"+str(SLOSS_LAMBDA)+
"SCLP"+str(SLOSS_CLIP)+
(['_nG','_G'][SPREAD_CONVERGENCE])+
(['_nI','_I'][INTER_CONVERGENCE]) +
(['_nHF',"_HF"][HOR_FLIP]) +
('_CP'+str(DISP_DIFF_CAP)) +
('_S'+str(DISP_DIFF_SLOPE))
)
NN_LAYOUTS = {0:[0, 0, 0, 32, 20, 16],
1:[0, 0, 0, 256, 128, 64],
2:[0, 128, 32, 32, 32, 16],
3:[0, 0, 40, 32, 20, 16],
4:[0, 0, 0, 0, 16, 16],
5:[0, 0, 64, 32, 32, 16],
6:[0, 0, 32, 16, 16, 16],
7:[0, 0, 64, 16, 16, 16],
8:[0, 0, 0, 64, 20, 16],
9:[0, 0, 256, 64, 32, 16],
10:[0, 256, 128, 64, 32, 16],
11:[0, 0, 0, 0, 64, 32],
}
NN_LAYOUT1 = NN_LAYOUTS[NET_ARCH1]
NN_LAYOUT2 = NN_LAYOUTS[NET_ARCH2]
USE_PARTIALS = not PARTIALS_WEIGHTS is None # False - just a single Siamese net, True - partial outputs that use concentric squares of the first level subnets
# Tiff export slice labels
SLICE_LABELS = ["nn_out_ext","hier_out_ext","gt_disparity","gt_strength",
"cutcorn_cost_nw","cutcorn_cost",
"gt-avg_dist","avg8_disp","gt_disp","out-avg"]
##############################################################################
cluster_size = (2 * CLUSTER_RADIUS + 1) * (2 * CLUSTER_RADIUS + 1)
center_tile_index = 2 * CLUSTER_RADIUS * (CLUSTER_RADIUS + 1)
qsf.prepareFiles(dirs, files, suffix = SUFFIX)
if TEST_TITLES is None:
TEST_TITLES = qsf.defaultTestTitles(files)
partials = None
partials = qsf.concentricSquares(CLUSTER_RADIUS)
PARTIALS_WEIGHTS = [1.0*pw/sum(PARTIALS_WEIGHTS) for pw in PARTIALS_WEIGHTS]
if not USE_PARTIALS:
partials = partials[0:1]
PARTIALS_WEIGHTS = [1.0]
qsf.evaluateAllResults(result_files = files['result'],
absolute_disparity = ABSOLUTE_DISPARITY,
cluster_radius = CLUSTER_RADIUS,
labels = SLICE_LABELS)
image_data = qsf.initImageData(
files = files,
max_imgs = MAX_IMGS_IN_MEM,
cluster_radius = CLUSTER_RADIUS,
tile_layers = TILE_LAYERS,
tile_side = TILE_SIDE,
width = IMG_WIDTH,
replace_nans = True)
corr2d_len, target_disparity_len, _ = qsf.get_lengths(CLUSTER_RADIUS, TILE_LAYERS, TILE_SIDE)
train_next, dataset_train, datasets_test= qsf.initTrainTestData(
files = files,
cluster_radius = CLUSTER_RADIUS,
buffer_size = TRAIN_BUFFER_SIZE * BATCH_SIZE, # number of clusters per train
test_titles = TEST_TITLES)
corr2d_train_placeholder = tf.placeholder(dataset_train.dtype, (None,FEATURES_PER_TILE * cluster_size)) # corr2d_train.shape)
target_disparity_train_placeholder = tf.placeholder(dataset_train.dtype, (None,1 * cluster_size)) #target_disparity_train.shape)
gt_ds_train_placeholder = tf.placeholder(dataset_train.dtype, (None,2 * cluster_size)) #gt_ds_train.shape)
dataset_tt = tf.data.Dataset.from_tensor_slices({
"corr2d": corr2d_train_placeholder,
"target_disparity": target_disparity_train_placeholder,
"gt_ds": gt_ds_train_placeholder})
tf_batch_weights = tf.placeholder(shape=(None,), dtype=tf.float32, name = "batch_weights") # way to increase importance of the high variance clusters
feed_batch_weights = np.array(BATCH_WEIGHTS*(BATCH_SIZE//len(BATCH_WEIGHTS)), dtype=np.float32)
feed_batch_weight_1 = np.array([1.0], dtype=np.float32)
dataset_test_size = len(datasets_test[0])
dataset_test_size //= BATCH_SIZE
dataset_img_size = len(image_data[0]['corr2d'])
dataset_img_size //= BATCH_SIZE
dataset_tt = dataset_tt.batch(BATCH_SIZE)
dataset_tt = dataset_tt.prefetch(BATCH_SIZE)
iterator_tt = dataset_tt.make_initializable_iterator()
next_element_tt = iterator_tt.get_next()
result_dir = './attic/result_neibs_'+ SUFFIX+'/'
checkpoint_dir = './attic/result_neibs_'+ SUFFIX+'/'
save_freq = 500
def debug_gt_variance(
indx, # This tile index (0..8)
center_indx, # center tile index
gt_ds_batch # [?:9:2]
):
with tf.name_scope("Debug_GT_Variance"):
d_gt_this = tf.reshape(gt_ds_batch[:,2 * indx],[-1], name = "d_this")
d_gt_center = tf.reshape(gt_ds_batch[:,2 * center_indx],[-1], name = "d_center")
d_gt_diff = tf.subtract(d_gt_this, d_gt_center, name = "d_diff")
d_gt_diff2 = tf.multiply(d_gt_diff, d_gt_diff, name = "d_diff2")
d_gt_var = tf.reduce_mean(d_gt_diff2, name = "d_gt_var")
return d_gt_var
target_disparity_cluster = tf.reshape(next_element_tt['target_disparity'], [-1,cluster_size, 1], name="targdisp_cluster")
corr2d_Nx325 = tf.concat([tf.reshape(next_element_tt['corr2d'],[-1,cluster_size,FEATURES_PER_TILE], name="coor2d_cluster"),
target_disparity_cluster], axis=2, name = "corr2d_Nx325")
if SPREAD_CONVERGENCE:
outs, inp_weights = qcstereo_network.networks_siam(
input = corr2d_Nx325,
input_global = target_disparity_cluster,
layout1 = NN_LAYOUT1,
layout2 = NN_LAYOUT2,
inter_convergence = INTER_CONVERGENCE,
sym8 = SYM8_SUB,
only_tile = ONLY_TILE, #Remove/put None for normal operation
partials = partials,
use_confidence= USE_CONFIDENCE)
else:
outs, inp_weights = qcstereo_network.networks_siam(
input_tensor= corr2d_Nx325,
input_global = None,
layout1 = NN_LAYOUT1,
layout2 = NN_LAYOUT2,
inter_convergence = False,
sym8 = SYM8_SUB,
only_tile = ONLY_TILE, #Remove/put None for normal operation
partials = partials,
use_confidence= USE_CONFIDENCE)
tf_partial_weights = tf.constant(PARTIALS_WEIGHTS,dtype=tf.float32,name="partial_weights")
G_losses = [0.0]*len(partials)
target_disparity_batch= next_element_tt['target_disparity'][:,center_tile_index:center_tile_index+1]
gt_ds_batch_clust = next_element_tt['gt_ds']
gt_ds_batch = gt_ds_batch_clust[:,2 * center_tile_index: 2 * (center_tile_index +1)]
G_losses[0], _disp_slice, _d_gt_slice, _out_diff, _out_diff2, _w_norm, _out_wdiff2, _cost1 = qcstereo_losses.batchLoss(
out_batch = outs[0], # [batch_size,(1..2)] tf_result
target_disparity_batch= target_disparity_batch, # next_element_tt['target_disparity'][:,center_tile_index:center_tile_index+1], # target_disparity_batch_center, # next_element_tt['target_disparity'], # target_disparity, ### target_d, # [batch_size] tf placeholder
gt_ds_batch = gt_ds_batch, # next_element_tt['gt_ds'][:,2 * center_tile_index: 2 * (center_tile_index +1)], # gt_ds_batch_center, ## next_element_tt['gt_ds'], # gt_ds, ### gt, # [batch_size,2] tf placeholder
batch_weights = tf_batch_weights,
disp_diff_cap = DISP_DIFF_CAP,
disp_diff_slope= DISP_DIFF_SLOPE,
absolute_disparity = ABSOLUTE_DISPARITY,
use_confidence = USE_CONFIDENCE, # True,
lambda_conf_avg = 0.01,
## lambda_conf_pwr = 0.1,
conf_pwr = 2.0,
gt_conf_offset = 0.08,
gt_conf_pwr = 2.0,
error2_offset = 0, # 0.0025, # (0.05^2)
disp_wmin = 1.0, # minimal disparity to apply weight boosting for small disparities
disp_wmax = 8.0, # maximal disparity to apply weight boosting for small disparities
use_out = False) # use calculated disparity for disparity weight boosting (False - use target disparity)
G_loss = G_losses[0]
for n in range (1,len(partials)):
G_losses[n], _, _, _, _, _, _, _ = qcstereo_losses.batchLoss(
out_batch = outs[n], # [batch_size,(1..2)] tf_result
target_disparity_batch= target_disparity_batch, #next_element_tt['target_disparity'][:,center_tile_index:center_tile_index+1], # target_disparity_batch_center, # next_element_tt['target_disparity'], # target_disparity, ### target_d, # [batch_size] tf placeholder
gt_ds_batch = gt_ds_batch, # next_element_tt['gt_ds'][:,2 * center_tile_index: 2 * (center_tile_index +1)], # gt_ds_batch_center, ## next_element_tt['gt_ds'], # gt_ds, ### gt, # [batch_size,2] tf placeholder
batch_weights = tf_batch_weights,
disp_diff_cap = DISP_DIFF_CAP,
disp_diff_slope= DISP_DIFF_SLOPE,
absolute_disparity = ABSOLUTE_DISPARITY,
use_confidence = USE_CONFIDENCE, # True,
lambda_conf_avg = 0.01,
# lambda_conf_pwr = 0.1,
conf_pwr = 2.0,
gt_conf_offset = 0.08,
gt_conf_pwr = 2.0,
error2_offset = 0, # 0.0025, # (0.05^2)
disp_wmin = 1.0, # minimal disparity to apply weight boosting for small disparities
disp_wmax = 8.0, # maximal disparity to apply weight boosting for small disparities
use_out = False) # use calculated disparity for disparity weight boosting (False - use target disparity)
tf_wlosses = tf.multiply(G_losses, tf_partial_weights, name = "tf_wlosses")
G_losses_sum = tf.reduce_sum(tf_wlosses, name = "G_losses_sum")
if SLOSS_LAMBDA > 0:
S_loss, rslt_cost_nw, rslt_cost_w, rslt_d , rslt_avg_disparity, rslt_gt_disparity, rslt_offs = qcstereo_losses.smoothLoss(
out_batch = outs[0], # [batch_size,(1..2)] tf_result
target_disparity_batch = target_disparity_batch, # [batch_size] tf placeholder
gt_ds_batch_clust = gt_ds_batch_clust, # [batch_size,25,2] tf placeholder
clip = SLOSS_CLIP,
absolute_disparity = ABSOLUTE_DISPARITY, #when false there should be no activation on disparity output !
cluster_radius = CLUSTER_RADIUS)
GS_loss = tf.add(G_losses_sum, SLOSS_LAMBDA * S_loss, name = "GS_loss")
else:
S_loss = tf.constant(0.0, dtype=tf.float32,name = "S_loss")
GS_loss = G_losses_sum # G_loss
if WLOSS_LAMBDA > 0.0:
W_loss = qcstereo_losses.weightsLoss(
inp_weights = inp_weights[0], # inp_weights - list of tensors, currently - just [0]
tile_layers= TILE_LAYERS, # 4
tile_side = TILE_SIDE, # 9
wborders_zero = WBORDERS_ZERO)
GW_loss = tf.add(GS_loss, WLOSS_LAMBDA * W_loss, name = "GW_loss")
else:
GW_loss = GS_loss # G_loss
W_loss = tf.constant(0.0, dtype=tf.float32,name = "W_loss")
GT_variance = debug_gt_variance(indx = 0, # This tile index (0..8)
center_indx = 4, # center tile index
gt_ds_batch = next_element_tt['gt_ds'])# [?:18]
tf_ph_G_loss = tf.placeholder(tf.float32,shape=None,name='G_loss_avg')
tf_ph_G_losses = tf.placeholder(tf.float32,shape=[len(partials)],name='G_losses_avg')
tf_ph_S_loss = tf.placeholder(tf.float32,shape=None,name='S_loss_avg')
tf_ph_W_loss = tf.placeholder(tf.float32,shape=None,name='W_loss_avg')
tf_ph_GW_loss = tf.placeholder(tf.float32,shape=None,name='GW_loss_avg')
tf_ph_sq_diff = tf.placeholder(tf.float32,shape=None,name='sq_diff_avg')
tf_gtvar_diff = tf.placeholder(tf.float32,shape=None,name='gtvar_diff')
tf_img_test0 = tf.placeholder(tf.float32,shape=None,name='img_test0')
tf_img_test9 = tf.placeholder(tf.float32,shape=None,name='img_test9')
"""
with tf.name_scope('sample'):
tf.summary.scalar("GW_loss", GW_loss)
tf.summary.scalar("G_loss", G_loss)
tf.summary.scalar("S_loss", S_loss)
tf.summary.scalar("W_loss", W_loss)
tf.summary.scalar("sq_diff", _cost1)
tf.summary.scalar("gtvar_diff", GT_variance)
"""
with tf.name_scope('epoch_average'):
for i in range(tf_ph_G_losses.shape[0]):
tf.summary.scalar("G_loss_epoch_"+str(i), tf_ph_G_losses[i])
tf.summary.scalar("GW_loss_epoch", tf_ph_GW_loss)
tf.summary.scalar("G_loss_epoch", tf_ph_G_loss)
tf.summary.scalar("S_loss_epoch", tf_ph_S_loss)
tf.summary.scalar("W_loss_epoch", tf_ph_W_loss)
tf.summary.scalar("sq_diff_epoch", tf_ph_sq_diff)
tf.summary.scalar("gtvar_diff", tf_gtvar_diff)
tf.summary.scalar("img_test0", tf_img_test0)
tf.summary.scalar("img_test9", tf_img_test9)
t_vars= tf.trainable_variables()
lr= tf.placeholder(tf.float32)
G_opt= tf.train.AdamOptimizer(learning_rate=lr).minimize(GW_loss)
ROOT_PATH = './attic/nn_ds_neibs19_graph'+SUFFIX+"/"
TT_SUBDIRS = ['train'] #,'test0','test1','test2','test3']
for i,_ in enumerate(datasets_test):
# TT_SUBDIRS.append('test%d'%(i))
TT_SUBDIRS.append(TEST_TITLES[i].replace(' ','_'))
TT_PATHS = [ROOT_PATH + p for p in TT_SUBDIRS]
# CLEAN OLD STAFF
shutil.rmtree(ROOT_PATH, ignore_errors=True)
#for p in TT_PATHS:
# shutil.rmtree(p, ignore_errors=True)
#seems that runs use directory creation time to order graphs
#for p in TT_PATHS:
# os.makedirs(p)
# time.sleep(1.5) # reduce later
num_train_subs = len(train_next) # number of (different type) merged training sets
dataset_train_size = TRAIN_BUFFER_GPU * num_train_subs # TRAIN_BUFFER_SIZE
tt_summaries = [0.0 for e in TT_SUBDIRS]
tt2_avg = [0.0 for e in TT_SUBDIRS]
tt_gw_avg = [0.0 for e in TT_SUBDIRS]
tt_g_avgs = [[0.0]*len(partials) for e in TT_SUBDIRS]
tt_w_avg = [0.0 for e in TT_SUBDIRS]
tt_s_avg = [0.0 for e in TT_SUBDIRS]
tt_gtvar_avg = [0.0 for e in TT_SUBDIRS]
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
sess.run(tf.local_variables_initializer())
merged = tf.summary.merge_all()
tt_writers = []
for p in TT_PATHS:
tt_writers.append(tf.summary.FileWriter(p, sess.graph))
print ("Adding delay to make directory creation time different: "+p)
time.sleep(2.0) # reduce later
loss_gw_train_hist= np.empty(dataset_train_size, dtype=np.float32)
loss_g_train_hists= [np.empty(dataset_train_size, dtype=np.float32) for p in partials]
loss_s_train_hist= np.empty(dataset_train_size, dtype=np.float32)
loss_w_train_hist= np.empty(dataset_train_size, dtype=np.float32)
loss_gw_test_hist= np.empty(dataset_test_size, dtype=np.float32)
loss_g_test_hists= [np.empty(dataset_test_size, dtype=np.float32) for p in partials]
loss_s_test_hist= np.empty(dataset_test_size, dtype=np.float32)
loss_w_test_hist= np.empty(dataset_test_size, dtype=np.float32)
loss2_train_hist= np.empty(dataset_train_size, dtype=np.float32)
loss2_test_hist= np.empty(dataset_test_size, dtype=np.float32)
gtvar_train_hist= np.empty(dataset_train_size, dtype=np.float32)
gtvar_test_hist= np.empty(dataset_test_size, dtype=np.float32)
gtvar_train = 0.0
gtvar_test = 0.0
img_gain_test0 = 1.0
img_gain_test9 = 1.0
thr=None
thr_result = None
trains_to_update = [train_next[n_train]['more_files'] for n_train in range(len(train_next))]
for epoch in range (EPOCHS_TO_RUN):
"""
update files after each epoch, all 4.
Convert to threads after testing
"""
if (FILE_UPDATE_EPOCHS > 0) and (epoch % FILE_UPDATE_EPOCHS == 0):
if not thr is None:
if thr.is_alive():
qsf.print_time("***WAITING*** until tfrecord gets loaded", end=" ")
else:
qsf.print_time("tfrecord is ***ALREADY LOADED*** ", end=" ")
thr.join()
qsf.print_time("Done")
qsf.print_time("Inserting new data", end=" ")
for n_train in range(len(trains_to_update)):
if trains_to_update[n_train]:
qsf.add_file_to_dataset(dataset = dataset_train,
new_dataset = thr_result[n_train],
train_next = train_next[n_train])
qsf.print_time("Done")
thr_result = []
fpaths = []
for n_train in range(len(trains_to_update)):
if trains_to_update[n_train]:
fpaths.append(files['train'][n_train][train_next[n_train]['file']])
qsf.print_time("Will read in background: "+fpaths[-1])
thr = Thread(target=qsf.getMoreFiles, args=(fpaths,thr_result, CLUSTER_RADIUS, HOR_FLIP, TILE_LAYERS, TILE_SIDE))
thr.start()
train_buf_index = epoch % TRAIN_BUFFER_CPU # GPU memory from CPU memory (now 4)
if epoch >=600:
learning_rate = LR600
elif epoch >=400:
learning_rate = LR400
elif epoch >=200:
learning_rate = LR200
elif epoch >=100:
learning_rate = LR100
else:
learning_rate = LR
if (train_buf_index == 0) and SHUFFLE_FILES:
qsf.print_time("Shuffling how datasets datasets_train_lvar and datasets_train_hvar are zipped together", end="")
qsf.shuffle_in_place(
dataset_data = dataset_train, #alternating clusters from 4 sources.each cluster has all needed data (concatenated)
period = num_train_subs)
qsf.print_time(" Done")
sti = train_buf_index * dataset_train_size * BATCH_SIZE # TRAIN_BUFFER_GPU * num_train_subs
eti = sti+ dataset_train_size * BATCH_SIZE# (train_buf_index +1) * TRAIN_BUFFER_GPU * num_train_subs
sess.run(iterator_tt.initializer, feed_dict={corr2d_train_placeholder: dataset_train[sti:eti,:corr2d_len],
target_disparity_train_placeholder: dataset_train[sti:eti,corr2d_len:corr2d_len+target_disparity_len],
gt_ds_train_placeholder: dataset_train[sti:eti,corr2d_len+target_disparity_len:] })
for i in range(dataset_train_size):
# try:
_, GW_loss_trained, G_losses_trained, S_loss_trained, W_loss_trained, output, disp_slice, d_gt_slice, out_diff, out_diff2, w_norm, out_wdiff2, out_cost1, gt_variance = sess.run(
[ G_opt,
GW_loss,
G_losses,
S_loss,
W_loss,
outs[0],
_disp_slice,
_d_gt_slice,
_out_diff,
_out_diff2,
_w_norm,
_out_wdiff2,
_cost1,
GT_variance
],
feed_dict={tf_batch_weights: feed_batch_weights,
lr: learning_rate
}) # previous value of *_avg #Fetch argument 0.0 has invalid type <class 'float'>, must be a string or Tensor. (Can not convert a float into a Tensor or Operation.)
loss_gw_train_hist[i] = GW_loss_trained
for nn, gl in enumerate(G_losses_trained):
loss_g_train_hists[nn][i] = gl
loss_s_train_hist[i] = S_loss_trained
loss_w_train_hist[i] = W_loss_trained
loss2_train_hist[i] = out_cost1
gtvar_train_hist[i] = gt_variance
# except tf.errors.OutOfRangeError:
# print("****** NO MORE DATA! train done at step %d"%(i))
# break
tt_gw_avg[0] = np.average(loss_gw_train_hist).astype(np.float32)
for nn, lgth in enumerate(loss_g_train_hists):
tt_g_avgs[0][nn] = np.average(lgth).astype(np.float32)
tt_s_avg[0] = np.average(loss_s_train_hist).astype(np.float32)
tt_w_avg[0] = np.average(loss_w_train_hist).astype(np.float32)
tt2_avg[0] = np.average(loss2_train_hist).astype(np.float32)
tt_gtvar_avg[0] = np.average(gtvar_train_hist).astype(np.float32)
for ntest,dataset_test in enumerate(datasets_test):
sess.run(iterator_tt.initializer, feed_dict={corr2d_train_placeholder: dataset_test[:, :corr2d_len], #['corr2d'],
target_disparity_train_placeholder: dataset_test[:, corr2d_len:corr2d_len+target_disparity_len], # ['target_disparity'],
gt_ds_train_placeholder: dataset_test[:, corr2d_len+target_disparity_len:] }) # ['gt_ds']})
"""
TODO: Make it possible to have different length dataset_test arrays to mix different length test files
"""
for i in range(dataset_test_size):
# for i in range(dataset_test.shape[0]):
# try:
GW_loss_tested, G_losses_tested, S_loss_tested, W_loss_tested, output, disp_slice, d_gt_slice, out_diff, out_diff2, w_norm, out_wdiff2, out_cost1, gt_variance = sess.run(
[GW_loss,
G_losses,
S_loss,
W_loss,
outs[0],
_disp_slice,
_d_gt_slice,
_out_diff,
_out_diff2,
_w_norm,
_out_wdiff2,
_cost1,
GT_variance
],
feed_dict={tf_batch_weights: feed_batch_weight_1 , # feed_batch_weights,
lr: learning_rate
}) # previous value of *_avg
loss_gw_test_hist[i] = GW_loss_tested
for nn, gl in enumerate(G_losses_tested):
loss_g_test_hists[nn][i] = gl
loss_s_test_hist[i] = S_loss_tested
loss_w_test_hist[i] = W_loss_tested
loss2_test_hist[i] = out_cost1
gtvar_test_hist[i] = gt_variance
# except tf.errors.OutOfRangeError:
# print("test done at step %d"%(i))
# break
tt_gw_avg[ntest+1] = np.average(loss_gw_test_hist).astype(np.float32)
for nn, lgth in enumerate(loss_g_test_hists):
tt_g_avgs[ntest+1][nn] = np.average(lgth).astype(np.float32)
tt_s_avg[ntest+1] = np.average(loss_s_test_hist).astype(np.float32)
tt_w_avg[ntest+1] = np.average(loss_w_test_hist).astype(np.float32)
tt2_avg[ntest+1] = np.average(loss2_test_hist).astype(np.float32)
tt_gtvar_avg[ntest+1] = np.average(gtvar_test_hist).astype(np.float32)
if (((epoch + 1) == EPOCHS_TO_RUN) or (((epoch + 1) % EPOCHS_FULL_TEST) == 0)) and (len(image_data) > 0) :
if (epoch + 1) == EPOCHS_TO_RUN: # last
print("Last epoch, removing train/test datasets to reduce memory footprint")
del(dataset_train)
del(dataset_test)
last_epoch = (epoch + 1) == EPOCHS_TO_RUN
ind_img = [0]
if last_epoch:
ind_img = [i for i in range(len(image_data))]
###################################################
# Read the full image
###################################################
## test_summaries_img = [0.0]*len(ind_img) # datasets_img)
disp_out= np.empty((WIDTH*HEIGHT), dtype=np.float32)
dbg_cost_nw= np.empty((WIDTH*HEIGHT), dtype=np.float32)
dbg_cost_w= np.empty((WIDTH*HEIGHT), dtype=np.float32)
dbg_d= np.empty((WIDTH*HEIGHT), dtype=np.float32)
dbg_avg_disparity = np.empty((WIDTH*HEIGHT), dtype=np.float32)
dbg_gt_disparity = np.empty((WIDTH*HEIGHT), dtype=np.float32)
dbg_offs = np.empty((WIDTH*HEIGHT), dtype=np.float32)
for ntest in ind_img: # datasets_img):
dataset_img = qsf.readImageData(
image_data = image_data,
files = files,
indx = ntest,
cluster_radius = CLUSTER_RADIUS,
tile_layers = TILE_LAYERS,
tile_side = TILE_SIDE,
width = IMG_WIDTH,
replace_nans = True)
sess.run(iterator_tt.initializer, feed_dict={corr2d_train_placeholder: dataset_img['corr2d'],
target_disparity_train_placeholder: dataset_img['target_disparity'],
gt_ds_train_placeholder: dataset_img['gt_ds']})
for start_offs in range(0,disp_out.shape[0],BATCH_SIZE):
end_offs = min(start_offs+BATCH_SIZE,disp_out.shape[0])
# try:
output, cost_nw, cost_w, dd, avg_disparity, gt_disparity, offs = sess.run(
[outs[0], # {?,1]
rslt_cost_nw, #[?,]
rslt_cost_w, #[?,]
rslt_d, #[?,]
rslt_avg_disparity,
rslt_gt_disparity,
rslt_offs
],
feed_dict={
tf_batch_weights: feed_batch_weight_1 # feed_batch_weights,
}) # previous value of *_avg
# except tf.errors.OutOfRangeError:
# print("test done at step %d"%(i))
# break
# try:
disp_out[start_offs:end_offs] = output.flatten()
dbg_cost_nw[start_offs:end_offs] = cost_nw.flatten()
dbg_cost_w [start_offs:end_offs] = cost_w.flatten()
dbg_d[start_offs:end_offs] = dd.flatten()
dbg_avg_disparity[start_offs:end_offs] = avg_disparity.flatten()
dbg_gt_disparity[start_offs:end_offs] = gt_disparity.flatten()
dbg_offs[start_offs:end_offs] = offs.flatten()
# except ValueError:
# print("dataset_img_size= %d, i=%d, output.shape[0]=%d "%(dataset_img_size, i, output.shape[0]))
# break;
pass
result_file = files['result'][ntest] # result_files[ntest]
try:
os.makedirs(os.path.dirname(result_file))
except:
pass
rslt = np.concatenate(
[disp_out.reshape(-1,1),
dataset_img['t_disps'], #t_disps[ntest],
dataset_img['gtruths'], # gtruths[ntest],
dbg_cost_nw.reshape(-1,1),
dbg_cost_w.reshape(-1,1),
dbg_d.reshape(-1,1),
dbg_avg_disparity.reshape(-1,1),
dbg_gt_disparity.reshape(-1,1),
dbg_offs.reshape(-1,1)],1)
np.save(result_file, rslt.reshape(HEIGHT,WIDTH,-1))
rslt = qsf.eval_results(result_file, ABSOLUTE_DISPARITY,radius=CLUSTER_RADIUS)
img_gain_test0 = rslt[0][0]/rslt[0][1]
img_gain_test9 = rslt[9][0]/rslt[9][1]
if SAVE_TIFFS:
qsf.result_npy_to_tiff(result_file, ABSOLUTE_DISPARITY, fix_nan = True,labels=SLICE_LABELS)
"""
Remove dataset_img (if it is not [0] to reduce memory footprint
"""
if ntest > 0:
image_data[ntest] = None
# tensorboard scalars
tt_summaries[0] = sess.run([merged],
feed_dict={ tf_ph_GW_loss: tt_gw_avg[0],
tf_ph_G_loss: tt_g_avgs[0][0], #train_g_avg,
tf_ph_G_losses: tt_g_avgs[0],
tf_ph_S_loss: tt_s_avg[0],
tf_ph_W_loss: tt_w_avg[0],
tf_ph_sq_diff: tt2_avg[0], # train2_avg,
tf_gtvar_diff: tt_gtvar_avg[0],
tf_img_test0: img_gain_test0,
tf_img_test9: img_gain_test9}) # previous value of *_avg #Fetch argument 0.0 has invalid type <class 'float'>, must be a string or Tensor. (Can not convert a float into a Tensor or Operation.)
for ntest, _ in enumerate(datasets_test):
tt_summaries[ntest+1] = sess.run([merged],
feed_dict={
tf_ph_GW_loss: tt_gw_avg[ntest+1],
tf_ph_G_loss: tt_g_avgs[ntest+1][0],
tf_ph_G_losses: tt_g_avgs[ntest+1], # train_g_avgs, # temporary, there is o data fro test
tf_ph_S_loss: tt_s_avg[ntest+1],
tf_ph_W_loss: tt_w_avg[ntest+1],
tf_ph_sq_diff: tt2_avg[ntest+1], #test2_avg,
tf_gtvar_diff: tt_gtvar_avg[ntest+1],
tf_img_test0: img_gain_test0,
tf_img_test9: img_gain_test9})
for n,tt_writer in enumerate(tt_writers):
## tt_writer.add_summary(tt_summaries[n],epoch)
tt_writer.add_summary(tt_summaries[n][0],epoch)
# if epoch ==0 :
# print ("adding delay to make directory creation time different")
# time.sleep(2.0) # reduce later
qsf.print_time("==== %d:%d -> %f %f %f %f %f (%f %f %f %f %f) ===="%(epoch,i,tt_gw_avg[0], tt_gw_avg[1], tt_gw_avg[2], tt_gw_avg[3], tt_gw_avg[4], tt2_avg[0], tt2_avg[1], tt2_avg[2], tt2_avg[3], tt2_avg[4]))
# Close writers
for tt_writer in tt_writers:
try:
tt_writer.close()
except:
print ("Could not close tt_writer: ",tt_writer)
print("All done")
exit (0)
#!/usr/bin/env python3
##from numpy import float64
##from tensorflow.contrib.losses.python.metric_learning.metric_loss_ops import npairs_loss
##from debian.deb822 import PdiffIndex
__copyright__ = "Copyright 2018, Elphel, Inc."
__license__ = "GPL-3.0+"
__email__ = "andrey@elphel.com"
#python3 nn_ds_neibs17.py /home/eyesis/x3d_data/data_sets/conf/qcstereo_conf13.xml /home/eyesis/x3d_data/data_sets
import os
import sys
import numpy as np
import time
import shutil
from threading import Thread
import qcstereo_network
import qcstereo_losses
import qcstereo_functions as qsf
import tensorflow as tf
qsf.TIME_START = time.time()
qsf.TIME_LAST = qsf.TIME_START
IMG_WIDTH = 324 # tiles per image row
DEBUG_LEVEL= 1
try:
conf_file = sys.argv[1]
except IndexError:
print("Configuration path is required as a first argument. Optional second argument specifies root directory for data files")
exit(1)
try:
root_dir = sys.argv[2]
except IndexError:
root_dir = os.path.dirname(conf_file)
print ("Configuration file: " + conf_file)
parameters, dirs, files, _ = qsf.parseXmlConfig(conf_file, root_dir)
"""
Temporarily for backward compatibility
"""
if not "SLOSS_CLIP" in parameters:
parameters['SLOSS_CLIP'] = 0.5
print ("Old config, setting SLOSS_CLIP=", parameters['SLOSS_CLIP'])
"""
Defined in config file
"""
TILE_SIDE, TILE_LAYERS, TWO_TRAINS, NET_ARCH1, NET_ARCH2 = [None]*5
ABSOLUTE_DISPARITY,SYM8_SUB, WLOSS_LAMBDA, SLOSS_LAMBDA, SLOSS_CLIP = [None]*5
SPREAD_CONVERGENCE, INTER_CONVERGENCE, HOR_FLIP, DISP_DIFF_CAP, DISP_DIFF_SLOPE = [None]*5
CLUSTER_RADIUS = None
PARTIALS_WEIGHTS, MAX_IMGS_IN_MEM, MAX_FILES_PER_GROUP, BATCH_WEIGHTS, ONLY_TILE = [None] * 5
USE_CONFIDENCE, WBORDERS_ZERO, EPOCHS_TO_RUN, FILE_UPDATE_EPOCHS = [None] * 4
LR600,LR400,LR200,LR100,LR = [None]*5
SHUFFLE_FILES, EPOCHS_FULL_TEST, SAVE_TIFFS = [None] * 3
CHECKPOINT_PERIOD = None
TRAIN_BUFFER_GPU, TRAIN_BUFFER_CPU = [None]*2
TEST_TITLES = None
"""
Next gets globals from the config file
"""
globals().update(parameters)
TRAIN_BUFFER_SIZE = TRAIN_BUFFER_GPU * TRAIN_BUFFER_CPU # in merged (quad) batches
#exit(0)
WIDTH = 324
HEIGHT = 242
TILE_SIZE = TILE_SIDE* TILE_SIDE # == 81
FEATURES_PER_TILE = TILE_LAYERS * TILE_SIZE# == 324
BATCH_SIZE = ([1,2][TWO_TRAINS])*2*1000//25 # == 80 Each batch of tiles has balanced D/S tiles, shuffled batches but not inside batches
SUFFIX=(str(NET_ARCH1)+'-'+str(NET_ARCH2)+
(["R","A"][ABSOLUTE_DISPARITY]) +
(["NS","S8"][SYM8_SUB])+
"WLAM"+str(WLOSS_LAMBDA)+
"SLAM"+str(SLOSS_LAMBDA)+
"SCLP"+str(SLOSS_CLIP)+
(['_nG','_G'][SPREAD_CONVERGENCE])+
(['_nI','_I'][INTER_CONVERGENCE]) +
(['_nHF',"_HF"][HOR_FLIP]) +
('_CP'+str(DISP_DIFF_CAP)) +
('_S'+str(DISP_DIFF_SLOPE))
)
NN_LAYOUTS = {0:[0, 0, 0, 32, 20, 16],
1:[0, 0, 0, 256, 128, 64],
2:[0, 128, 32, 32, 32, 16],
3:[0, 0, 40, 32, 20, 16],
4:[0, 0, 0, 0, 16, 16],
5:[0, 0, 64, 32, 32, 16],
6:[0, 0, 32, 16, 16, 16],
7:[0, 0, 64, 16, 16, 16],
8:[0, 0, 0, 64, 20, 16],
9:[0, 0, 256, 64, 32, 16],
10:[0, 256, 128, 64, 32, 16],
11:[0, 0, 0, 0, 64, 32],
}
NN_LAYOUT1 = NN_LAYOUTS[NET_ARCH1]
NN_LAYOUT2 = NN_LAYOUTS[NET_ARCH2]
USE_PARTIALS = not PARTIALS_WEIGHTS is None # False - just a single Siamese net, True - partial outputs that use concentric squares of the first level subnets
# Tiff export slice labels
SLICE_LABELS = ["nn_out_ext","hier_out_ext","gt_disparity","gt_strength",
"cutcorn_cost_nw","cutcorn_cost",
"gt-avg_dist","avg8_disp","gt_disp","out-avg"]
##############################################################################
cluster_size = (2 * CLUSTER_RADIUS + 1) * (2 * CLUSTER_RADIUS + 1)
center_tile_index = 2 * CLUSTER_RADIUS * (CLUSTER_RADIUS + 1)
qsf.prepareFiles(dirs, files, suffix = SUFFIX)
if TEST_TITLES is None:
TEST_TITLES = qsf.defaultTestTitles(files)
partials = None
partials = qsf.concentricSquares(CLUSTER_RADIUS)
PARTIALS_WEIGHTS = [1.0*pw/sum(PARTIALS_WEIGHTS) for pw in PARTIALS_WEIGHTS]
if not USE_PARTIALS:
partials = partials[0:1]
PARTIALS_WEIGHTS = [1.0]
qsf.evaluateAllResults(result_files = files['result'],
absolute_disparity = ABSOLUTE_DISPARITY,
cluster_radius = CLUSTER_RADIUS,
labels = SLICE_LABELS)
image_data = qsf.initImageData(
files = files,
max_imgs = MAX_IMGS_IN_MEM,
cluster_radius = CLUSTER_RADIUS,
tile_layers = TILE_LAYERS,
tile_side = TILE_SIDE,
width = IMG_WIDTH,
replace_nans = True)
corr2d_len, target_disparity_len, _ = qsf.get_lengths(CLUSTER_RADIUS, TILE_LAYERS, TILE_SIDE)
train_next, dataset_train, datasets_test= qsf.initTrainTestData(
files = files,
cluster_radius = CLUSTER_RADIUS,
buffer_size = TRAIN_BUFFER_SIZE * BATCH_SIZE, # number of clusters per train
test_titles = TEST_TITLES)
corr2d_train_placeholder = tf.placeholder(dataset_train.dtype, (None,FEATURES_PER_TILE * cluster_size)) # corr2d_train.shape)
target_disparity_train_placeholder = tf.placeholder(dataset_train.dtype, (None,1 * cluster_size)) #target_disparity_train.shape)
gt_ds_train_placeholder = tf.placeholder(dataset_train.dtype, (None,2 * cluster_size)) #gt_ds_train.shape)
dataset_tt = tf.data.Dataset.from_tensor_slices({
"corr2d": corr2d_train_placeholder,
"target_disparity": target_disparity_train_placeholder,
"gt_ds": gt_ds_train_placeholder})
tf_batch_weights = tf.placeholder(shape=(None,), dtype=tf.float32, name = "batch_weights") # way to increase importance of the high variance clusters
feed_batch_weights = np.array(BATCH_WEIGHTS*(BATCH_SIZE//len(BATCH_WEIGHTS)), dtype=np.float32)
feed_batch_weight_1 = np.array([1.0], dtype=np.float32)
dataset_test_size = len(datasets_test[0])
dataset_test_size //= BATCH_SIZE
dataset_img_size = len(image_data[0]['corr2d'])
dataset_img_size //= BATCH_SIZE
dataset_tt = dataset_tt.batch(BATCH_SIZE)
dataset_tt = dataset_tt.prefetch(BATCH_SIZE)
iterator_tt = dataset_tt.make_initializable_iterator()
next_element_tt = iterator_tt.get_next()
result_dir = './attic/result_neibs_'+ SUFFIX+'/'
checkpoint_dir = './attic/result_neibs_'+ SUFFIX+'/'
save_freq = 500
def debug_gt_variance(
indx, # This tile index (0..8)
center_indx, # center tile index
gt_ds_batch # [?:9:2]
):
with tf.name_scope("Debug_GT_Variance"):
d_gt_this = tf.reshape(gt_ds_batch[:,2 * indx],[-1], name = "d_this")
d_gt_center = tf.reshape(gt_ds_batch[:,2 * center_indx],[-1], name = "d_center")
d_gt_diff = tf.subtract(d_gt_this, d_gt_center, name = "d_diff")
d_gt_diff2 = tf.multiply(d_gt_diff, d_gt_diff, name = "d_diff2")
d_gt_var = tf.reduce_mean(d_gt_diff2, name = "d_gt_var")
return d_gt_var
target_disparity_cluster = tf.reshape(next_element_tt['target_disparity'], [-1,cluster_size, 1], name="targdisp_cluster")
corr2d_Nx325 = tf.concat([tf.reshape(next_element_tt['corr2d'],[-1,cluster_size,FEATURES_PER_TILE], name="coor2d_cluster"),
target_disparity_cluster], axis=2, name = "corr2d_Nx325")
if SPREAD_CONVERGENCE:
outs, inp_weights = qcstereo_network.networks_siam(
input = corr2d_Nx325,
input_global = target_disparity_cluster,
layout1 = NN_LAYOUT1,
layout2 = NN_LAYOUT2,
inter_convergence = INTER_CONVERGENCE,
sym8 = SYM8_SUB,
only_tile = ONLY_TILE, #Remove/put None for normal operation
partials = partials,
use_confidence= USE_CONFIDENCE)
else:
outs, inp_weights = qcstereo_network.networks_siam(
input_tensor= corr2d_Nx325,
input_global = None,
layout1 = NN_LAYOUT1,
layout2 = NN_LAYOUT2,
inter_convergence = False,
sym8 = SYM8_SUB,
only_tile = ONLY_TILE, #Remove/put None for normal operation
partials = partials,
use_confidence= USE_CONFIDENCE)
tf_partial_weights = tf.constant(PARTIALS_WEIGHTS,dtype=tf.float32,name="partial_weights")
G_losses = [0.0]*len(partials)
target_disparity_batch= next_element_tt['target_disparity'][:,center_tile_index:center_tile_index+1]
gt_ds_batch_clust = next_element_tt['gt_ds']
gt_ds_batch = gt_ds_batch_clust[:,2 * center_tile_index: 2 * (center_tile_index +1)]
G_losses[0], _disp_slice, _d_gt_slice, _out_diff, _out_diff2, _w_norm, _out_wdiff2, _cost1 = qcstereo_losses.batchLoss(
out_batch = outs[0], # [batch_size,(1..2)] tf_result
target_disparity_batch= target_disparity_batch, # next_element_tt['target_disparity'][:,center_tile_index:center_tile_index+1], # target_disparity_batch_center, # next_element_tt['target_disparity'], # target_disparity, ### target_d, # [batch_size] tf placeholder
gt_ds_batch = gt_ds_batch, # next_element_tt['gt_ds'][:,2 * center_tile_index: 2 * (center_tile_index +1)], # gt_ds_batch_center, ## next_element_tt['gt_ds'], # gt_ds, ### gt, # [batch_size,2] tf placeholder
batch_weights = tf_batch_weights,
disp_diff_cap = DISP_DIFF_CAP,
disp_diff_slope= DISP_DIFF_SLOPE,
absolute_disparity = ABSOLUTE_DISPARITY,
use_confidence = USE_CONFIDENCE, # True,
lambda_conf_avg = 0.01,
## lambda_conf_pwr = 0.1,
conf_pwr = 2.0,
gt_conf_offset = 0.08,
gt_conf_pwr = 2.0,
error2_offset = 0, # 0.0025, # (0.05^2)
disp_wmin = 1.0, # minimal disparity to apply weight boosting for small disparities
disp_wmax = 8.0, # maximal disparity to apply weight boosting for small disparities
use_out = False) # use calculated disparity for disparity weight boosting (False - use target disparity)
G_loss = G_losses[0]
for n in range (1,len(partials)):
G_losses[n], _, _, _, _, _, _, _ = qcstereo_losses.batchLoss(
out_batch = outs[n], # [batch_size,(1..2)] tf_result
target_disparity_batch= target_disparity_batch, #next_element_tt['target_disparity'][:,center_tile_index:center_tile_index+1], # target_disparity_batch_center, # next_element_tt['target_disparity'], # target_disparity, ### target_d, # [batch_size] tf placeholder
gt_ds_batch = gt_ds_batch, # next_element_tt['gt_ds'][:,2 * center_tile_index: 2 * (center_tile_index +1)], # gt_ds_batch_center, ## next_element_tt['gt_ds'], # gt_ds, ### gt, # [batch_size,2] tf placeholder
batch_weights = tf_batch_weights,
disp_diff_cap = DISP_DIFF_CAP,
disp_diff_slope= DISP_DIFF_SLOPE,
absolute_disparity = ABSOLUTE_DISPARITY,
use_confidence = USE_CONFIDENCE, # True,
lambda_conf_avg = 0.01,
# lambda_conf_pwr = 0.1,
conf_pwr = 2.0,
gt_conf_offset = 0.08,
gt_conf_pwr = 2.0,
error2_offset = 0, # 0.0025, # (0.05^2)
disp_wmin = 1.0, # minimal disparity to apply weight boosting for small disparities
disp_wmax = 8.0, # maximal disparity to apply weight boosting for small disparities
use_out = False) # use calculated disparity for disparity weight boosting (False - use target disparity)
tf_wlosses = tf.multiply(G_losses, tf_partial_weights, name = "tf_wlosses")
G_losses_sum = tf.reduce_sum(tf_wlosses, name = "G_losses_sum")
if SLOSS_LAMBDA > 0:
S_loss, rslt_cost_nw, rslt_cost_w, rslt_d , rslt_avg_disparity, rslt_gt_disparity, rslt_offs = qcstereo_losses.smoothLoss(
out_batch = outs[0], # [batch_size,(1..2)] tf_result
target_disparity_batch = target_disparity_batch, # [batch_size] tf placeholder
gt_ds_batch_clust = gt_ds_batch_clust, # [batch_size,25,2] tf placeholder
clip = SLOSS_CLIP,
absolute_disparity = ABSOLUTE_DISPARITY, #when false there should be no activation on disparity output !
cluster_radius = CLUSTER_RADIUS)
GS_loss = tf.add(G_losses_sum, SLOSS_LAMBDA * S_loss, name = "GS_loss")
else:
S_loss = tf.constant(0.0, dtype=tf.float32,name = "S_loss")
GS_loss = G_losses_sum # G_loss
if WLOSS_LAMBDA > 0.0:
W_loss = qcstereo_losses.weightsLoss(
inp_weights = inp_weights[0], # inp_weights - list of tensors, currently - just [0]
tile_layers= TILE_LAYERS, # 4
tile_side = TILE_SIDE, # 9
wborders_zero = WBORDERS_ZERO)
GW_loss = tf.add(GS_loss, WLOSS_LAMBDA * W_loss, name = "GW_loss")
else:
GW_loss = GS_loss # G_loss
W_loss = tf.constant(0.0, dtype=tf.float32,name = "W_loss")
GT_variance = debug_gt_variance(indx = 0, # This tile index (0..8)
center_indx = 4, # center tile index
gt_ds_batch = next_element_tt['gt_ds'])# [?:18]
tf_ph_G_loss = tf.placeholder(tf.float32,shape=None,name='G_loss_avg')
tf_ph_G_losses = tf.placeholder(tf.float32,shape=[len(partials)],name='G_losses_avg')
tf_ph_S_loss = tf.placeholder(tf.float32,shape=None,name='S_loss_avg')
tf_ph_W_loss = tf.placeholder(tf.float32,shape=None,name='W_loss_avg')
tf_ph_GW_loss = tf.placeholder(tf.float32,shape=None,name='GW_loss_avg')
tf_ph_sq_diff = tf.placeholder(tf.float32,shape=None,name='sq_diff_avg')
tf_gtvar_diff = tf.placeholder(tf.float32,shape=None,name='gtvar_diff')
tf_img_test0 = tf.placeholder(tf.float32,shape=None,name='img_test0')
tf_img_test9 = tf.placeholder(tf.float32,shape=None,name='img_test9')
"""
with tf.name_scope('sample'):
tf.summary.scalar("GW_loss", GW_loss)
tf.summary.scalar("G_loss", G_loss)
tf.summary.scalar("S_loss", S_loss)
tf.summary.scalar("W_loss", W_loss)
tf.summary.scalar("sq_diff", _cost1)
tf.summary.scalar("gtvar_diff", GT_variance)
"""
with tf.name_scope('epoch_average'):
for i in range(tf_ph_G_losses.shape[0]):
tf.summary.scalar("G_loss_epoch_"+str(i), tf_ph_G_losses[i])
tf.summary.scalar("GW_loss_epoch", tf_ph_GW_loss)
tf.summary.scalar("G_loss_epoch", tf_ph_G_loss)
tf.summary.scalar("S_loss_epoch", tf_ph_S_loss)
tf.summary.scalar("W_loss_epoch", tf_ph_W_loss)
tf.summary.scalar("sq_diff_epoch", tf_ph_sq_diff)
tf.summary.scalar("gtvar_diff", tf_gtvar_diff)
tf.summary.scalar("img_test0", tf_img_test0)
tf.summary.scalar("img_test9", tf_img_test9)
trainable_vars= tf.trainable_variables()
lr= tf.placeholder(tf.float32)
G_opt= tf.train.AdamOptimizer(learning_rate=lr).minimize(GW_loss)
ROOT_PATH = './attic/nn_ds_neibs20_graph'+SUFFIX+"/" # for tensorboard
TT_SUBDIRS = ['train'] #,'test0','test1','test2','test3']
for i,_ in enumerate(datasets_test):
# TT_SUBDIRS.append('test%d'%(i))
TT_SUBDIRS.append(TEST_TITLES[i].replace(' ','_'))
TT_PATHS = [ROOT_PATH + p for p in TT_SUBDIRS]
# CLEAN OLD STAFF
shutil.rmtree(ROOT_PATH, ignore_errors=True)
#for p in TT_PATHS:
# shutil.rmtree(p, ignore_errors=True)
#seems that runs use directory creation time to order graphs
#for p in TT_PATHS:
# os.makedirs(p)
# time.sleep(1.5) # reduce later
num_train_subs = len(train_next) # number of (different type) merged training sets
dataset_train_size = TRAIN_BUFFER_GPU * num_train_subs # TRAIN_BUFFER_SIZE
tt_summaries = [0.0 for e in TT_SUBDIRS]
tt2_avg = [0.0 for e in TT_SUBDIRS]
tt_gw_avg = [0.0 for e in TT_SUBDIRS]
tt_g_avgs = [[0.0]*len(partials) for e in TT_SUBDIRS]
tt_w_avg = [0.0 for e in TT_SUBDIRS]
tt_s_avg = [0.0 for e in TT_SUBDIRS]
tt_gtvar_avg = [0.0 for e in TT_SUBDIRS]
saver=tf.train.Saver(trainable_vars)
saver_def = saver.as_saver_def()
# The name of the tensor you must feed with a filename when saving/restoring.
print ('saver_def.filename_tensor_name=',saver_def.filename_tensor_name)
# The name of the target operation you must run when restoring.
print ('saver_def.restore_op_name=',saver_def.restore_op_name)
# The name of the target operation you must run when saving.
print ('saver_def.save_tensor_name=',saver_def.save_tensor_name)
try:
os.makedirs(os.path.dirname(files['checkpoints']))
print ("Created directory ",os.path.dirname(files['checkpoints']))
# os.makedirs(files['checkpoints'])
except:
pass
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
sess.run(tf.local_variables_initializer())
merged = tf.summary.merge_all()
tt_writers = []
for p in TT_PATHS:
tt_writers.append(tf.summary.FileWriter(p, sess.graph))
print ("Adding delay to make directory creation time different: "+p)
time.sleep(2.0) # reduce later
loss_gw_train_hist= np.empty(dataset_train_size, dtype=np.float32)
loss_g_train_hists= [np.empty(dataset_train_size, dtype=np.float32) for p in partials]
loss_s_train_hist= np.empty(dataset_train_size, dtype=np.float32)
loss_w_train_hist= np.empty(dataset_train_size, dtype=np.float32)
loss_gw_test_hist= np.empty(dataset_test_size, dtype=np.float32)
loss_g_test_hists= [np.empty(dataset_test_size, dtype=np.float32) for p in partials]
loss_s_test_hist= np.empty(dataset_test_size, dtype=np.float32)
loss_w_test_hist= np.empty(dataset_test_size, dtype=np.float32)
loss2_train_hist= np.empty(dataset_train_size, dtype=np.float32)
loss2_test_hist= np.empty(dataset_test_size, dtype=np.float32)
gtvar_train_hist= np.empty(dataset_train_size, dtype=np.float32)
gtvar_test_hist= np.empty(dataset_test_size, dtype=np.float32)
gtvar_train = 0.0
gtvar_test = 0.0
img_gain_test0 = 1.0
img_gain_test9 = 1.0
thr=None
thr_result = None
trains_to_update = [train_next[n_train]['more_files'] for n_train in range(len(train_next))]
for epoch in range (EPOCHS_TO_RUN):
"""
update files after each epoch, all 4.
Convert to threads after testing
"""
if (FILE_UPDATE_EPOCHS > 0) and (epoch % FILE_UPDATE_EPOCHS == 0):
if not thr is None:
if thr.is_alive():
qsf.print_time("***WAITING*** until tfrecord gets loaded", end=" ")
else:
qsf.print_time("tfrecord is ***ALREADY LOADED*** ", end=" ")
thr.join()
qsf.print_time("Done")
qsf.print_time("Inserting new data", end=" ")
for n_train in range(len(trains_to_update)):
if trains_to_update[n_train]:
qsf.add_file_to_dataset(dataset = dataset_train,
new_dataset = thr_result[n_train],
train_next = train_next[n_train])
qsf.print_time("Done")
thr_result = []
fpaths = []
for n_train in range(len(trains_to_update)):
if trains_to_update[n_train]:
fpaths.append(files['train'][n_train][train_next[n_train]['file']])
qsf.print_time("Will read in background: "+fpaths[-1])
thr = Thread(target=qsf.getMoreFiles, args=(fpaths,thr_result, CLUSTER_RADIUS, HOR_FLIP, TILE_LAYERS, TILE_SIDE))
thr.start()
train_buf_index = epoch % TRAIN_BUFFER_CPU # GPU memory from CPU memory (now 4)
if epoch >=600:
learning_rate = LR600
elif epoch >=400:
learning_rate = LR400
elif epoch >=200:
learning_rate = LR200
elif epoch >=100:
learning_rate = LR100
else:
learning_rate = LR
if (train_buf_index == 0) and SHUFFLE_FILES:
qsf.print_time("Shuffling how datasets datasets_train_lvar and datasets_train_hvar are zipped together", end="")
qsf.shuffle_in_place(
dataset_data = dataset_train, #alternating clusters from 4 sources.each cluster has all needed data (concatenated)
period = num_train_subs)
qsf.print_time(" Done")
sti = train_buf_index * dataset_train_size * BATCH_SIZE # TRAIN_BUFFER_GPU * num_train_subs
eti = sti+ dataset_train_size * BATCH_SIZE# (train_buf_index +1) * TRAIN_BUFFER_GPU * num_train_subs
sess.run(iterator_tt.initializer, feed_dict={corr2d_train_placeholder: dataset_train[sti:eti,:corr2d_len],
target_disparity_train_placeholder: dataset_train[sti:eti,corr2d_len:corr2d_len+target_disparity_len],
gt_ds_train_placeholder: dataset_train[sti:eti,corr2d_len+target_disparity_len:] })
for i in range(dataset_train_size):
# try:
_, GW_loss_trained, G_losses_trained, S_loss_trained, W_loss_trained, output, disp_slice, d_gt_slice, out_diff, out_diff2, w_norm, out_wdiff2, out_cost1, gt_variance = sess.run(
[ G_opt,
GW_loss,
G_losses,
S_loss,
W_loss,
outs[0],
_disp_slice,
_d_gt_slice,
_out_diff,
_out_diff2,
_w_norm,
_out_wdiff2,
_cost1,
GT_variance
],
feed_dict={tf_batch_weights: feed_batch_weights,
lr: learning_rate
}) # previous value of *_avg #Fetch argument 0.0 has invalid type <class 'float'>, must be a string or Tensor. (Can not convert a float into a Tensor or Operation.)
loss_gw_train_hist[i] = GW_loss_trained
for nn, gl in enumerate(G_losses_trained):
loss_g_train_hists[nn][i] = gl
loss_s_train_hist[i] = S_loss_trained
loss_w_train_hist[i] = W_loss_trained
loss2_train_hist[i] = out_cost1
gtvar_train_hist[i] = gt_variance
# except tf.errors.OutOfRangeError:
# print("****** NO MORE DATA! train done at step %d"%(i))
# break
tt_gw_avg[0] = np.average(loss_gw_train_hist).astype(np.float32)
for nn, lgth in enumerate(loss_g_train_hists):
tt_g_avgs[0][nn] = np.average(lgth).astype(np.float32)
tt_s_avg[0] = np.average(loss_s_train_hist).astype(np.float32)
tt_w_avg[0] = np.average(loss_w_train_hist).astype(np.float32)
tt2_avg[0] = np.average(loss2_train_hist).astype(np.float32)
tt_gtvar_avg[0] = np.average(gtvar_train_hist).astype(np.float32)
for ntest,dataset_test in enumerate(datasets_test):
sess.run(iterator_tt.initializer, feed_dict={corr2d_train_placeholder: dataset_test[:, :corr2d_len], #['corr2d'],
target_disparity_train_placeholder: dataset_test[:, corr2d_len:corr2d_len+target_disparity_len], # ['target_disparity'],
gt_ds_train_placeholder: dataset_test[:, corr2d_len+target_disparity_len:] }) # ['gt_ds']})
"""
TODO: Make it possible to have different length dataset_test arrays to mix different length test files
"""
for i in range(dataset_test_size):
# for i in range(dataset_test.shape[0]):
# try:
GW_loss_tested, G_losses_tested, S_loss_tested, W_loss_tested, output, disp_slice, d_gt_slice, out_diff, out_diff2, w_norm, out_wdiff2, out_cost1, gt_variance = sess.run(
[GW_loss,
G_losses,
S_loss,
W_loss,
outs[0],
_disp_slice,
_d_gt_slice,
_out_diff,
_out_diff2,
_w_norm,
_out_wdiff2,
_cost1,
GT_variance
],
feed_dict={tf_batch_weights: feed_batch_weight_1 , # feed_batch_weights,
lr: learning_rate
}) # previous value of *_avg
loss_gw_test_hist[i] = GW_loss_tested
for nn, gl in enumerate(G_losses_tested):
loss_g_test_hists[nn][i] = gl
loss_s_test_hist[i] = S_loss_tested
loss_w_test_hist[i] = W_loss_tested
loss2_test_hist[i] = out_cost1
gtvar_test_hist[i] = gt_variance
# except tf.errors.OutOfRangeError:
# print("test done at step %d"%(i))
# break
tt_gw_avg[ntest+1] = np.average(loss_gw_test_hist).astype(np.float32)
for nn, lgth in enumerate(loss_g_test_hists):
tt_g_avgs[ntest+1][nn] = np.average(lgth).astype(np.float32)
tt_s_avg[ntest+1] = np.average(loss_s_test_hist).astype(np.float32)
tt_w_avg[ntest+1] = np.average(loss_w_test_hist).astype(np.float32)
tt2_avg[ntest+1] = np.average(loss2_test_hist).astype(np.float32)
tt_gtvar_avg[ntest+1] = np.average(gtvar_test_hist).astype(np.float32)
if (((epoch + 1) == EPOCHS_TO_RUN) or (((epoch + 1) % EPOCHS_FULL_TEST) == 0)) and (len(image_data) > 0) :
if (epoch + 1) == EPOCHS_TO_RUN: # last
print("Last epoch, removing train/test datasets to reduce memory footprint")
del(dataset_train)
del(dataset_test)
last_epoch = (epoch + 1) == EPOCHS_TO_RUN
ind_img = [0]
if last_epoch:
ind_img = [i for i in range(len(image_data))]
###################################################
# Read the full image
###################################################
## test_summaries_img = [0.0]*len(ind_img) # datasets_img)
disp_out= np.empty((WIDTH*HEIGHT), dtype=np.float32)
dbg_cost_nw= np.empty((WIDTH*HEIGHT), dtype=np.float32)
dbg_cost_w= np.empty((WIDTH*HEIGHT), dtype=np.float32)
dbg_d= np.empty((WIDTH*HEIGHT), dtype=np.float32)
dbg_avg_disparity = np.empty((WIDTH*HEIGHT), dtype=np.float32)
dbg_gt_disparity = np.empty((WIDTH*HEIGHT), dtype=np.float32)
dbg_offs = np.empty((WIDTH*HEIGHT), dtype=np.float32)
for ntest in ind_img: # datasets_img):
dataset_img = qsf.readImageData(
image_data = image_data,
files = files,
indx = ntest,
cluster_radius = CLUSTER_RADIUS,
tile_layers = TILE_LAYERS,
tile_side = TILE_SIDE,
width = IMG_WIDTH,
replace_nans = True)
sess.run(iterator_tt.initializer, feed_dict={corr2d_train_placeholder: dataset_img['corr2d'],
target_disparity_train_placeholder: dataset_img['target_disparity'],
gt_ds_train_placeholder: dataset_img['gt_ds']})
for start_offs in range(0,disp_out.shape[0],BATCH_SIZE):
end_offs = min(start_offs+BATCH_SIZE,disp_out.shape[0])
# try:
output, cost_nw, cost_w, dd, avg_disparity, gt_disparity, offs = sess.run(
[outs[0], # {?,1]
rslt_cost_nw, #[?,]
rslt_cost_w, #[?,]
rslt_d, #[?,]
rslt_avg_disparity,
rslt_gt_disparity,
rslt_offs
],
feed_dict={
tf_batch_weights: feed_batch_weight_1 # feed_batch_weights,
}) # previous value of *_avg
# except tf.errors.OutOfRangeError:
# print("test done at step %d"%(i))
# break
# try:
disp_out[start_offs:end_offs] = output.flatten()
dbg_cost_nw[start_offs:end_offs] = cost_nw.flatten()
dbg_cost_w [start_offs:end_offs] = cost_w.flatten()
dbg_d[start_offs:end_offs] = dd.flatten()
dbg_avg_disparity[start_offs:end_offs] = avg_disparity.flatten()
dbg_gt_disparity[start_offs:end_offs] = gt_disparity.flatten()
dbg_offs[start_offs:end_offs] = offs.flatten()
# except ValueError:
# print("dataset_img_size= %d, i=%d, output.shape[0]=%d "%(dataset_img_size, i, output.shape[0]))
# break;
pass
result_file = files['result'][ntest] # result_files[ntest]
try:
os.makedirs(os.path.dirname(result_file))
except:
pass
rslt = np.concatenate(
[disp_out.reshape(-1,1),
dataset_img['t_disps'], #t_disps[ntest],
dataset_img['gtruths'], # gtruths[ntest],
dbg_cost_nw.reshape(-1,1),
dbg_cost_w.reshape(-1,1),
dbg_d.reshape(-1,1),
dbg_avg_disparity.reshape(-1,1),
dbg_gt_disparity.reshape(-1,1),
dbg_offs.reshape(-1,1)],1)
np.save(result_file, rslt.reshape(HEIGHT,WIDTH,-1))
rslt = qsf.eval_results(result_file, ABSOLUTE_DISPARITY,radius=CLUSTER_RADIUS)
img_gain_test0 = rslt[0][0]/rslt[0][1]
img_gain_test9 = rslt[9][0]/rslt[9][1]
if SAVE_TIFFS:
qsf.result_npy_to_tiff(result_file, ABSOLUTE_DISPARITY, fix_nan = True,labels=SLICE_LABELS)
"""
Remove dataset_img (if it is not [0] to reduce memory footprint
"""
if ntest > 0:
image_data[ntest] = None
# tensorboard scalars
tt_summaries[0] = sess.run([merged],
feed_dict={ tf_ph_GW_loss: tt_gw_avg[0],
tf_ph_G_loss: tt_g_avgs[0][0], #train_g_avg,
tf_ph_G_losses: tt_g_avgs[0],
tf_ph_S_loss: tt_s_avg[0],
tf_ph_W_loss: tt_w_avg[0],
tf_ph_sq_diff: tt2_avg[0], # train2_avg,
tf_gtvar_diff: tt_gtvar_avg[0],
tf_img_test0: img_gain_test0,
tf_img_test9: img_gain_test9}) # previous value of *_avg #Fetch argument 0.0 has invalid type <class 'float'>, must be a string or Tensor. (Can not convert a float into a Tensor or Operation.)
for ntest, _ in enumerate(datasets_test):
tt_summaries[ntest+1] = sess.run([merged],
feed_dict={
tf_ph_GW_loss: tt_gw_avg[ntest+1],
tf_ph_G_loss: tt_g_avgs[ntest+1][0],
tf_ph_G_losses: tt_g_avgs[ntest+1], # train_g_avgs, # temporary, there is o data fro test
tf_ph_S_loss: tt_s_avg[ntest+1],
tf_ph_W_loss: tt_w_avg[ntest+1],
tf_ph_sq_diff: tt2_avg[ntest+1], #test2_avg,
tf_gtvar_diff: tt_gtvar_avg[ntest+1],
tf_img_test0: img_gain_test0,
tf_img_test9: img_gain_test9})
for n,tt_writer in enumerate(tt_writers):
## tt_writer.add_summary(tt_summaries[n],epoch)
tt_writer.add_summary(tt_summaries[n][0],epoch)
# if epoch ==0 :
# print ("adding delay to make directory creation time different")
# time.sleep(2.0) # reduce later
qsf.print_time("==== %d:%d -> %f %f %f %f %f (%f %f %f %f %f) ===="%(epoch,i,tt_gw_avg[0], tt_gw_avg[1], tt_gw_avg[2], tt_gw_avg[3], tt_gw_avg[4], tt2_avg[0], tt2_avg[1], tt2_avg[2], tt2_avg[3], tt2_avg[4]))
if (not CHECKPOINT_PERIOD is None) and (((epoch + 1) % CHECKPOINT_PERIOD) == 0):
print("Saving periodic checkpoint (trained variables only) to %s, global_step = %d"%(os.path.dirname(files['checkpoints']), epoch),end=" => ")
print(saver.save(sess, files['checkpoints'], global_step=epoch, write_meta_graph=False))
# Close writers
for tt_writer in tt_writers:
try:
tt_writer.close()
except:
print ("Could not close tt_writer: ",tt_writer)
print("Saving final checkpoint (trained variables only) to %s"%(files['checkpoints']),end=" => ")
print(saver.save(sess, files["checkpoints"]))
print("All done")
exit (0)
#!/usr/bin/env python3
__copyright__ = "Copyright 2018, Elphel, Inc."
__license__ = "GPL-3.0+"
__email__ = "andrey@elphel.com"
#python3 nn_ds_neibs17.py /home/eyesis/x3d_data/data_sets/conf/qcstereo_conf13.xml /home/eyesis/x3d_data/data_sets
import os
import sys
import numpy as np
import time
import shutil
from threading import Thread
import qcstereo_network
import qcstereo_losses
import qcstereo_functions as qsf
import tensorflow as tf
qsf.TIME_START = time.time()
qsf.TIME_LAST = qsf.TIME_START
IMG_WIDTH = 324 # tiles per image row
DEBUG_LEVEL= 1
try:
conf_file = sys.argv[1]
except IndexError:
print("Configuration path is required as a first argument. Optional second argument specifies root directory for data files")
exit(1)
try:
root_dir = sys.argv[2]
except IndexError:
root_dir = os.path.dirname(conf_file)
print ("Configuration file: " + conf_file)
parameters, dirs, files, _ = qsf.parseXmlConfig(conf_file, root_dir)
"""
Temporarily for backward compatibility
"""
if not "SLOSS_CLIP" in parameters:
parameters['SLOSS_CLIP'] = 0.5
print ("Old config, setting SLOSS_CLIP=", parameters['SLOSS_CLIP'])
"""
Defined in config file
"""
TILE_SIDE, TILE_LAYERS, TWO_TRAINS, NET_ARCH1, NET_ARCH2 = [None]*5
ABSOLUTE_DISPARITY,SYM8_SUB, WLOSS_LAMBDA, SLOSS_LAMBDA, SLOSS_CLIP = [None]*5
SPREAD_CONVERGENCE, INTER_CONVERGENCE, HOR_FLIP, DISP_DIFF_CAP, DISP_DIFF_SLOPE = [None]*5
CLUSTER_RADIUS = None
PARTIALS_WEIGHTS, MAX_IMGS_IN_MEM, MAX_FILES_PER_GROUP, BATCH_WEIGHTS, ONLY_TILE = [None] * 5
USE_CONFIDENCE, WBORDERS_ZERO, EPOCHS_TO_RUN, FILE_UPDATE_EPOCHS = [None] * 4
LR600,LR400,LR200,LR100,LR = [None]*5
SHUFFLE_FILES, EPOCHS_FULL_TEST, SAVE_TIFFS = [None] * 3
CHECKPOINT_PERIOD = None
TRAIN_BUFFER_GPU, TRAIN_BUFFER_CPU = [None]*2
TEST_TITLES = None
LOGFILE="results.txt"
"""
Next gets globals from the config file
"""
globals().update(parameters)
TRAIN_BUFFER_SIZE = TRAIN_BUFFER_GPU * TRAIN_BUFFER_CPU # in merged (quad) batches
#exit(0)
WIDTH = 324
HEIGHT = 242
TILE_SIZE = TILE_SIDE* TILE_SIDE # == 81
FEATURES_PER_TILE = TILE_LAYERS * TILE_SIZE# == 324
BATCH_SIZE = ([1,2][TWO_TRAINS])*2*1000//25 # == 80 Each batch of tiles has balanced D/S tiles, shuffled batches but not inside batches
SUFFIX=(str(NET_ARCH1)+'-'+str(NET_ARCH2)+
(["R","A"][ABSOLUTE_DISPARITY]) +
(["NS","S8"][SYM8_SUB])+
"WLAM"+str(WLOSS_LAMBDA)+
"SLAM"+str(SLOSS_LAMBDA)+
"SCLP"+str(SLOSS_CLIP)+
(['_nG','_G'][SPREAD_CONVERGENCE])+
(['_nI','_I'][INTER_CONVERGENCE]) +
(['_nHF',"_HF"][HOR_FLIP]) +
('_CP'+str(DISP_DIFF_CAP)) +
('_S'+str(DISP_DIFF_SLOPE))
)
NN_LAYOUT1 = qcstereo_network.NN_LAYOUTS[NET_ARCH1]
NN_LAYOUT2 = qcstereo_network.NN_LAYOUTS[NET_ARCH2]
USE_PARTIALS = not PARTIALS_WEIGHTS is None # False - just a single Siamese net, True - partial outputs that use concentric squares of the first level subnets
# Tiff export slice labels
SLICE_LABELS = ["nn_out_ext","hier_out_ext","gt_disparity","gt_strength",
"cutcorn_cost_nw","cutcorn_cost",
"gt-avg_dist","avg8_disp","gt_disp","out-avg"]
##############################################################################
cluster_size = (2 * CLUSTER_RADIUS + 1) * (2 * CLUSTER_RADIUS + 1)
center_tile_index = 2 * CLUSTER_RADIUS * (CLUSTER_RADIUS + 1)
qsf.prepareFiles(dirs, files, suffix = SUFFIX)
#copy config to results directory
print ("Copying config files to results directory:\n ('%s' -> '%s')"%(conf_file,dirs['result']))
try:
os.makedirs(dirs['result'])
except:
pass
shutil.copy2(conf_file,dirs['result'])
LOGPATH = os.path.join(dirs['result'],LOGFILE)
if TEST_TITLES is None:
TEST_TITLES = qsf.defaultTestTitles(files)
partials = None
partials = qsf.concentricSquares(CLUSTER_RADIUS)
PARTIALS_WEIGHTS = [1.0*pw/sum(PARTIALS_WEIGHTS) for pw in PARTIALS_WEIGHTS]
if not USE_PARTIALS:
partials = partials[0:1]
PARTIALS_WEIGHTS = [1.0]
qsf.evaluateAllResults(result_files = files['result'],
absolute_disparity = ABSOLUTE_DISPARITY,
cluster_radius = CLUSTER_RADIUS,
labels = SLICE_LABELS,
logpath= LOGPATH)
image_data = qsf.initImageData(
files = files,
max_imgs = MAX_IMGS_IN_MEM,
cluster_radius = CLUSTER_RADIUS,
tile_layers = TILE_LAYERS,
tile_side = TILE_SIDE,
width = IMG_WIDTH,
replace_nans = True)
corr2d_len, target_disparity_len, _ = qsf.get_lengths(CLUSTER_RADIUS, TILE_LAYERS, TILE_SIDE)
train_next, dataset_train, datasets_test= qsf.initTrainTestData(
files = files,
cluster_radius = CLUSTER_RADIUS,
buffer_size = TRAIN_BUFFER_SIZE * BATCH_SIZE, # number of clusters per train
test_titles = TEST_TITLES)
corr2d_train_placeholder = tf.placeholder(dataset_train.dtype, (None,FEATURES_PER_TILE * cluster_size)) # corr2d_train.shape)
target_disparity_train_placeholder = tf.placeholder(dataset_train.dtype, (None,1 * cluster_size)) #target_disparity_train.shape)
gt_ds_train_placeholder = tf.placeholder(dataset_train.dtype, (None,2 * cluster_size)) #gt_ds_train.shape)
dataset_tt = tf.data.Dataset.from_tensor_slices({
"corr2d": corr2d_train_placeholder,
"target_disparity": target_disparity_train_placeholder,
"gt_ds": gt_ds_train_placeholder})
tf_batch_weights = tf.placeholder(shape=(None,), dtype=tf.float32, name = "batch_weights") # way to increase importance of the high variance clusters
feed_batch_weights = np.array(BATCH_WEIGHTS*(BATCH_SIZE//len(BATCH_WEIGHTS)), dtype=np.float32)
feed_batch_weight_1 = np.array([1.0], dtype=np.float32)
dataset_test_size = len(datasets_test[0])
dataset_test_size //= BATCH_SIZE
dataset_img_size = len(image_data[0]['corr2d'])
dataset_img_size //= BATCH_SIZE
dataset_tt = dataset_tt.batch(BATCH_SIZE)
dataset_tt = dataset_tt.prefetch(BATCH_SIZE)
iterator_tt = dataset_tt.make_initializable_iterator()
next_element_tt = iterator_tt.get_next()
result_dir = './attic/result_neibs_'+ SUFFIX+'/'
checkpoint_dir = './attic/result_neibs_'+ SUFFIX+'/'
save_freq = 500
def debug_gt_variance(
indx, # This tile index (0..8)
center_indx, # center tile index
gt_ds_batch # [?:9:2]
):
with tf.name_scope("Debug_GT_Variance"):
d_gt_this = tf.reshape(gt_ds_batch[:,2 * indx],[-1], name = "d_this")
d_gt_center = tf.reshape(gt_ds_batch[:,2 * center_indx],[-1], name = "d_center")
d_gt_diff = tf.subtract(d_gt_this, d_gt_center, name = "d_diff")
d_gt_diff2 = tf.multiply(d_gt_diff, d_gt_diff, name = "d_diff2")
d_gt_var = tf.reduce_mean(d_gt_diff2, name = "d_gt_var")
return d_gt_var
target_disparity_cluster = tf.reshape(next_element_tt['target_disparity'], [-1,cluster_size, 1], name="targdisp_cluster")
corr2d_Nx325 = tf.concat([tf.reshape(next_element_tt['corr2d'],[-1,cluster_size,FEATURES_PER_TILE], name="coor2d_cluster"),
target_disparity_cluster], axis=2, name = "corr2d_Nx325")
if SPREAD_CONVERGENCE:
outs, inp_weights = qcstereo_network.networks_siam(
input = corr2d_Nx325,
input_global = target_disparity_cluster,
layout1 = NN_LAYOUT1,
layout2 = NN_LAYOUT2,
inter_convergence = INTER_CONVERGENCE,
sym8 = SYM8_SUB,
only_tile = ONLY_TILE, #Remove/put None for normal operation
partials = partials,
use_confidence= USE_CONFIDENCE,
cluster_radius = CLUSTER_RADIUS)
else:
outs, inp_weights = qcstereo_network.networks_siam(
input_tensor= corr2d_Nx325,
input_global = None,
layout1 = NN_LAYOUT1,
layout2 = NN_LAYOUT2,
inter_convergence = False,
sym8 = SYM8_SUB,
only_tile = ONLY_TILE, #Remove/put None for normal operation
partials = partials,
use_confidence= USE_CONFIDENCE,
cluster_radius = CLUSTER_RADIUS)
tf_partial_weights = tf.constant(PARTIALS_WEIGHTS,dtype=tf.float32,name="partial_weights")
G_losses = [0.0]*len(partials)
target_disparity_batch= next_element_tt['target_disparity'][:,center_tile_index:center_tile_index+1]
gt_ds_batch_clust = next_element_tt['gt_ds']
gt_ds_batch = gt_ds_batch_clust[:,2 * center_tile_index: 2 * (center_tile_index +1)]
G_losses[0], _disp_slice, _d_gt_slice, _out_diff, _out_diff2, _w_norm, _out_wdiff2, _cost1 = qcstereo_losses.batchLoss(
out_batch = outs[0], # [batch_size,(1..2)] tf_result
target_disparity_batch= target_disparity_batch, # next_element_tt['target_disparity'][:,center_tile_index:center_tile_index+1], # target_disparity_batch_center, # next_element_tt['target_disparity'], # target_disparity, ### target_d, # [batch_size] tf placeholder
gt_ds_batch = gt_ds_batch, # next_element_tt['gt_ds'][:,2 * center_tile_index: 2 * (center_tile_index +1)], # gt_ds_batch_center, ## next_element_tt['gt_ds'], # gt_ds, ### gt, # [batch_size,2] tf placeholder
batch_weights = tf_batch_weights,
disp_diff_cap = DISP_DIFF_CAP,
disp_diff_slope= DISP_DIFF_SLOPE,
absolute_disparity = ABSOLUTE_DISPARITY,
use_confidence = USE_CONFIDENCE, # True,
lambda_conf_avg = 0.01,
## lambda_conf_pwr = 0.1,
conf_pwr = 2.0,
gt_conf_offset = 0.08,
gt_conf_pwr = 2.0,
error2_offset = 0, # 0.0025, # (0.05^2)
disp_wmin = 1.0, # minimal disparity to apply weight boosting for small disparities
disp_wmax = 8.0, # maximal disparity to apply weight boosting for small disparities
use_out = False) # use calculated disparity for disparity weight boosting (False - use target disparity)
G_loss = G_losses[0]
for n in range (1,len(partials)):
G_losses[n], _, _, _, _, _, _, _ = qcstereo_losses.batchLoss(
out_batch = outs[n], # [batch_size,(1..2)] tf_result
target_disparity_batch= target_disparity_batch, #next_element_tt['target_disparity'][:,center_tile_index:center_tile_index+1], # target_disparity_batch_center, # next_element_tt['target_disparity'], # target_disparity, ### target_d, # [batch_size] tf placeholder
gt_ds_batch = gt_ds_batch, # next_element_tt['gt_ds'][:,2 * center_tile_index: 2 * (center_tile_index +1)], # gt_ds_batch_center, ## next_element_tt['gt_ds'], # gt_ds, ### gt, # [batch_size,2] tf placeholder
batch_weights = tf_batch_weights,
disp_diff_cap = DISP_DIFF_CAP,
disp_diff_slope= DISP_DIFF_SLOPE,
absolute_disparity = ABSOLUTE_DISPARITY,
use_confidence = USE_CONFIDENCE, # True,
lambda_conf_avg = 0.01,
# lambda_conf_pwr = 0.1,
conf_pwr = 2.0,
gt_conf_offset = 0.08,
gt_conf_pwr = 2.0,
error2_offset = 0, # 0.0025, # (0.05^2)
disp_wmin = 1.0, # minimal disparity to apply weight boosting for small disparities
disp_wmax = 8.0, # maximal disparity to apply weight boosting for small disparities
use_out = False) # use calculated disparity for disparity weight boosting (False - use target disparity)
tf_wlosses = tf.multiply(G_losses, tf_partial_weights, name = "tf_wlosses")
G_losses_sum = tf.reduce_sum(tf_wlosses, name = "G_losses_sum")
if SLOSS_LAMBDA > 0:
S_loss, rslt_cost_nw, rslt_cost_w, rslt_d , rslt_avg_disparity, rslt_gt_disparity, rslt_offs = qcstereo_losses.smoothLoss(
out_batch = outs[0], # [batch_size,(1..2)] tf_result
target_disparity_batch = target_disparity_batch, # [batch_size] tf placeholder
gt_ds_batch_clust = gt_ds_batch_clust, # [batch_size,25,2] tf placeholder
clip = SLOSS_CLIP,
absolute_disparity = ABSOLUTE_DISPARITY, #when false there should be no activation on disparity output !
cluster_radius = CLUSTER_RADIUS)
GS_loss = tf.add(G_losses_sum, SLOSS_LAMBDA * S_loss, name = "GS_loss")
else:
S_loss = tf.constant(0.0, dtype=tf.float32,name = "S_loss")
GS_loss = G_losses_sum # G_loss
if WLOSS_LAMBDA > 0.0:
W_loss = qcstereo_losses.weightsLoss(
inp_weights = inp_weights[0], # inp_weights - list of tensors, currently - just [0]
tile_layers= TILE_LAYERS, # 4
tile_side = TILE_SIDE, # 9
wborders_zero = WBORDERS_ZERO)
GW_loss = tf.add(GS_loss, WLOSS_LAMBDA * W_loss, name = "GW_loss")
else:
GW_loss = GS_loss # G_loss
W_loss = tf.constant(0.0, dtype=tf.float32,name = "W_loss")
GT_variance = debug_gt_variance(indx = 0, # This tile index (0..8)
center_indx = 4, # center tile index
gt_ds_batch = next_element_tt['gt_ds'])# [?:18]
tf_ph_G_loss = tf.placeholder(tf.float32,shape=None,name='G_loss_avg')
tf_ph_G_losses = tf.placeholder(tf.float32,shape=[len(partials)],name='G_losses_avg')
tf_ph_S_loss = tf.placeholder(tf.float32,shape=None,name='S_loss_avg')
tf_ph_W_loss = tf.placeholder(tf.float32,shape=None,name='W_loss_avg')
tf_ph_GW_loss = tf.placeholder(tf.float32,shape=None,name='GW_loss_avg')
tf_ph_sq_diff = tf.placeholder(tf.float32,shape=None,name='sq_diff_avg')
tf_gtvar_diff = tf.placeholder(tf.float32,shape=None,name='gtvar_diff')
tf_img_test0 = tf.placeholder(tf.float32,shape=None,name='img_test0')
tf_img_test9 = tf.placeholder(tf.float32,shape=None,name='img_test9')
"""
with tf.name_scope('sample'):
tf.summary.scalar("GW_loss", GW_loss)
tf.summary.scalar("G_loss", G_loss)
tf.summary.scalar("S_loss", S_loss)
tf.summary.scalar("W_loss", W_loss)
tf.summary.scalar("sq_diff", _cost1)
tf.summary.scalar("gtvar_diff", GT_variance)
"""
with tf.name_scope('epoch_average'):
for i in range(tf_ph_G_losses.shape[0]):
tf.summary.scalar("G_loss_epoch_"+str(i), tf_ph_G_losses[i])
tf.summary.scalar("GW_loss_epoch", tf_ph_GW_loss)
tf.summary.scalar("G_loss_epoch", tf_ph_G_loss)
tf.summary.scalar("S_loss_epoch", tf_ph_S_loss)
tf.summary.scalar("W_loss_epoch", tf_ph_W_loss)
tf.summary.scalar("sq_diff_epoch", tf_ph_sq_diff)
tf.summary.scalar("gtvar_diff", tf_gtvar_diff)
tf.summary.scalar("img_test0", tf_img_test0)
tf.summary.scalar("img_test9", tf_img_test9)
trainable_vars= tf.trainable_variables()
lr= tf.placeholder(tf.float32)
G_opt= tf.train.AdamOptimizer(learning_rate=lr).minimize(GW_loss)
ROOT_PATH = './attic/nn_ds_neibs21_graph'+SUFFIX+"/" # for tensorboard
TT_SUBDIRS = ['train'] #,'test0','test1','test2','test3']
for i,_ in enumerate(datasets_test):
# TT_SUBDIRS.append('test%d'%(i))
TT_SUBDIRS.append(TEST_TITLES[i].replace(' ','_'))
TT_PATHS = [ROOT_PATH + p for p in TT_SUBDIRS]
# CLEAN OLD STAFF
shutil.rmtree(ROOT_PATH, ignore_errors=True)
#for p in TT_PATHS:
# shutil.rmtree(p, ignore_errors=True)
#seems that runs use directory creation time to order graphs
#for p in TT_PATHS:
# os.makedirs(p)
# time.sleep(1.5) # reduce later
num_train_subs = len(train_next) # number of (different type) merged training sets
dataset_train_size = TRAIN_BUFFER_GPU * num_train_subs # TRAIN_BUFFER_SIZE
tt_summaries = [0.0 for e in TT_SUBDIRS]
tt2_avg = [0.0 for e in TT_SUBDIRS]
tt_gw_avg = [0.0 for e in TT_SUBDIRS]
tt_g_avgs = [[0.0]*len(partials) for e in TT_SUBDIRS]
tt_w_avg = [0.0 for e in TT_SUBDIRS]
tt_s_avg = [0.0 for e in TT_SUBDIRS]
tt_gtvar_avg = [0.0 for e in TT_SUBDIRS]
saver=tf.train.Saver(trainable_vars)
saver_def = saver.as_saver_def()
# The name of the tensor you must feed with a filename when saving/restoring.
print ('saver_def.filename_tensor_name=',saver_def.filename_tensor_name)
# The name of the target operation you must run when restoring.
print ('saver_def.restore_op_name=',saver_def.restore_op_name)
# The name of the target operation you must run when saving.
print ('saver_def.save_tensor_name=',saver_def.save_tensor_name)
try:
os.makedirs(os.path.dirname(files['checkpoints']))
print ("Created directory ",os.path.dirname(files['checkpoints']))
# os.makedirs(files['checkpoints'])
except:
pass
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
sess.run(tf.local_variables_initializer())
merged = tf.summary.merge_all()
tt_writers = []
for p in TT_PATHS:
tt_writers.append(tf.summary.FileWriter(p, sess.graph))
print ("Adding delay to make directory creation time different: "+p)
time.sleep(2.0) # reduce later
loss_gw_train_hist= np.empty(dataset_train_size, dtype=np.float32)
loss_g_train_hists= [np.empty(dataset_train_size, dtype=np.float32) for p in partials]
loss_s_train_hist= np.empty(dataset_train_size, dtype=np.float32)
loss_w_train_hist= np.empty(dataset_train_size, dtype=np.float32)
loss_gw_test_hist= np.empty(dataset_test_size, dtype=np.float32)
loss_g_test_hists= [np.empty(dataset_test_size, dtype=np.float32) for p in partials]
loss_s_test_hist= np.empty(dataset_test_size, dtype=np.float32)
loss_w_test_hist= np.empty(dataset_test_size, dtype=np.float32)
loss2_train_hist= np.empty(dataset_train_size, dtype=np.float32)
loss2_test_hist= np.empty(dataset_test_size, dtype=np.float32)
gtvar_train_hist= np.empty(dataset_train_size, dtype=np.float32)
gtvar_test_hist= np.empty(dataset_test_size, dtype=np.float32)
gtvar_train = 0.0
gtvar_test = 0.0
img_gain_test0 = 1.0
img_gain_test9 = 1.0
thr=None
thr_result = None
trains_to_update = [train_next[n_train]['more_files'] for n_train in range(len(train_next))]
for epoch in range (EPOCHS_TO_RUN):
"""
update files after each epoch, all 4.
Convert to threads after testing
"""
if (FILE_UPDATE_EPOCHS > 0) and (epoch % FILE_UPDATE_EPOCHS == 0):
if not thr is None:
if thr.is_alive():
qsf.print_time("***WAITING*** until tfrecord gets loaded", end=" ")
else:
qsf.print_time("tfrecord is ***ALREADY LOADED*** ", end=" ")
thr.join()
qsf.print_time("Done")
qsf.print_time("Inserting new data", end=" ")
for n_train in range(len(trains_to_update)):
if trains_to_update[n_train]:
qsf.add_file_to_dataset(dataset = dataset_train,
new_dataset = thr_result[n_train],
train_next = train_next[n_train])
qsf.print_time("Done")
thr_result = []
fpaths = []
for n_train in range(len(trains_to_update)):
if trains_to_update[n_train]:
fpaths.append(files['train'][n_train][train_next[n_train]['file']])
qsf.print_time("Will read in background: "+fpaths[-1])
thr = Thread(target=qsf.getMoreFiles, args=(fpaths,thr_result, CLUSTER_RADIUS, HOR_FLIP, TILE_LAYERS, TILE_SIDE))
thr.start()
train_buf_index = epoch % TRAIN_BUFFER_CPU # GPU memory from CPU memory (now 4)
if epoch >=600:
learning_rate = LR600
elif epoch >=400:
learning_rate = LR400
elif epoch >=200:
learning_rate = LR200
elif epoch >=100:
learning_rate = LR100
else:
learning_rate = LR
if (train_buf_index == 0) and SHUFFLE_FILES:
qsf.print_time("Shuffling how datasets datasets_train_lvar and datasets_train_hvar are zipped together", end="")
qsf.shuffle_in_place(
dataset_data = dataset_train, #alternating clusters from 4 sources.each cluster has all needed data (concatenated)
period = num_train_subs)
qsf.print_time(" Done")
sti = train_buf_index * dataset_train_size * BATCH_SIZE # TRAIN_BUFFER_GPU * num_train_subs
eti = sti+ dataset_train_size * BATCH_SIZE# (train_buf_index +1) * TRAIN_BUFFER_GPU * num_train_subs
sess.run(iterator_tt.initializer, feed_dict={corr2d_train_placeholder: dataset_train[sti:eti,:corr2d_len],
target_disparity_train_placeholder: dataset_train[sti:eti,corr2d_len:corr2d_len+target_disparity_len],
gt_ds_train_placeholder: dataset_train[sti:eti,corr2d_len+target_disparity_len:] })
for i in range(dataset_train_size):
# try:
_, GW_loss_trained, G_losses_trained, S_loss_trained, W_loss_trained, output, disp_slice, d_gt_slice, out_diff, out_diff2, w_norm, out_wdiff2, out_cost1, gt_variance = sess.run(
[ G_opt,
GW_loss,
G_losses,
S_loss,
W_loss,
outs[0],
_disp_slice,
_d_gt_slice,
_out_diff,
_out_diff2,
_w_norm,
_out_wdiff2,
_cost1,
GT_variance
],
feed_dict={tf_batch_weights: feed_batch_weights,
lr: learning_rate
}) # previous value of *_avg #Fetch argument 0.0 has invalid type <class 'float'>, must be a string or Tensor. (Can not convert a float into a Tensor or Operation.)
loss_gw_train_hist[i] = GW_loss_trained
for nn, gl in enumerate(G_losses_trained):
loss_g_train_hists[nn][i] = gl
loss_s_train_hist[i] = S_loss_trained
loss_w_train_hist[i] = W_loss_trained
loss2_train_hist[i] = out_cost1
gtvar_train_hist[i] = gt_variance
# except tf.errors.OutOfRangeError:
# print("****** NO MORE DATA! train done at step %d"%(i))
# break
tt_gw_avg[0] = np.average(loss_gw_train_hist).astype(np.float32)
for nn, lgth in enumerate(loss_g_train_hists):
tt_g_avgs[0][nn] = np.average(lgth).astype(np.float32)
tt_s_avg[0] = np.average(loss_s_train_hist).astype(np.float32)
tt_w_avg[0] = np.average(loss_w_train_hist).astype(np.float32)
tt2_avg[0] = np.average(loss2_train_hist).astype(np.float32)
tt_gtvar_avg[0] = np.average(gtvar_train_hist).astype(np.float32)
for ntest,dataset_test in enumerate(datasets_test):
sess.run(iterator_tt.initializer, feed_dict={corr2d_train_placeholder: dataset_test[:, :corr2d_len], #['corr2d'],
target_disparity_train_placeholder: dataset_test[:, corr2d_len:corr2d_len+target_disparity_len], # ['target_disparity'],
gt_ds_train_placeholder: dataset_test[:, corr2d_len+target_disparity_len:] }) # ['gt_ds']})
"""
TODO: Make it possible to have different length dataset_test arrays to mix different length test files
"""
for i in range(dataset_test_size):
# for i in range(dataset_test.shape[0]):
# try:
GW_loss_tested, G_losses_tested, S_loss_tested, W_loss_tested, output, disp_slice, d_gt_slice, out_diff, out_diff2, w_norm, out_wdiff2, out_cost1, gt_variance = sess.run(
[GW_loss,
G_losses,
S_loss,
W_loss,
outs[0],
_disp_slice,
_d_gt_slice,
_out_diff,
_out_diff2,
_w_norm,
_out_wdiff2,
_cost1,
GT_variance
],
feed_dict={tf_batch_weights: feed_batch_weight_1 , # feed_batch_weights,
lr: learning_rate
}) # previous value of *_avg
loss_gw_test_hist[i] = GW_loss_tested
for nn, gl in enumerate(G_losses_tested):
loss_g_test_hists[nn][i] = gl
loss_s_test_hist[i] = S_loss_tested
loss_w_test_hist[i] = W_loss_tested
loss2_test_hist[i] = out_cost1
gtvar_test_hist[i] = gt_variance
# except tf.errors.OutOfRangeError:
# print("test done at step %d"%(i))
# break
tt_gw_avg[ntest+1] = np.average(loss_gw_test_hist).astype(np.float32)
for nn, lgth in enumerate(loss_g_test_hists):
tt_g_avgs[ntest+1][nn] = np.average(lgth).astype(np.float32)
tt_s_avg[ntest+1] = np.average(loss_s_test_hist).astype(np.float32)
tt_w_avg[ntest+1] = np.average(loss_w_test_hist).astype(np.float32)
tt2_avg[ntest+1] = np.average(loss2_test_hist).astype(np.float32)
tt_gtvar_avg[ntest+1] = np.average(gtvar_test_hist).astype(np.float32)
if (((epoch + 1) == EPOCHS_TO_RUN) or (((epoch + 1) % EPOCHS_FULL_TEST) == 0)) and (len(image_data) > 0) :
lf = None
if (epoch + 1) == EPOCHS_TO_RUN: # last
print("Last epoch, removing train/test datasets to reduce memory footprint")
del(dataset_train)
del(dataset_test)
if LOGPATH:
lf=open(LOGPATH,"w") #overwrite previous (or make it "a"?
last_epoch = (epoch + 1) == EPOCHS_TO_RUN
ind_img = [0]
if last_epoch:
ind_img = [i for i in range(len(image_data))]
###################################################
# Read the full image
###################################################
## test_summaries_img = [0.0]*len(ind_img) # datasets_img)
disp_out= np.empty((WIDTH*HEIGHT), dtype=np.float32)
dbg_cost_nw= np.empty((WIDTH*HEIGHT), dtype=np.float32)
dbg_cost_w= np.empty((WIDTH*HEIGHT), dtype=np.float32)
dbg_d= np.empty((WIDTH*HEIGHT), dtype=np.float32)
dbg_avg_disparity = np.empty((WIDTH*HEIGHT), dtype=np.float32)
dbg_gt_disparity = np.empty((WIDTH*HEIGHT), dtype=np.float32)
dbg_offs = np.empty((WIDTH*HEIGHT), dtype=np.float32)
for ntest in ind_img: # datasets_img):
dataset_img = qsf.readImageData(
image_data = image_data,
files = files,
indx = ntest,
cluster_radius = CLUSTER_RADIUS,
tile_layers = TILE_LAYERS,
tile_side = TILE_SIDE,
width = IMG_WIDTH,
replace_nans = True)
sess.run(iterator_tt.initializer, feed_dict={corr2d_train_placeholder: dataset_img['corr2d'],
target_disparity_train_placeholder: dataset_img['target_disparity'],
gt_ds_train_placeholder: dataset_img['gt_ds']})
for start_offs in range(0,disp_out.shape[0],BATCH_SIZE):
end_offs = min(start_offs+BATCH_SIZE,disp_out.shape[0])
# try:
output, cost_nw, cost_w, dd, avg_disparity, gt_disparity, offs = sess.run(
[outs[0], # {?,1]
rslt_cost_nw, #[?,]
rslt_cost_w, #[?,]
rslt_d, #[?,]
rslt_avg_disparity,
rslt_gt_disparity,
rslt_offs
],
feed_dict={
tf_batch_weights: feed_batch_weight_1 # feed_batch_weights,
}) # previous value of *_avg
# except tf.errors.OutOfRangeError:
# print("test done at step %d"%(i))
# break
# try:
disp_out[start_offs:end_offs] = output.flatten()
dbg_cost_nw[start_offs:end_offs] = cost_nw.flatten()
dbg_cost_w [start_offs:end_offs] = cost_w.flatten()
dbg_d[start_offs:end_offs] = dd.flatten()
dbg_avg_disparity[start_offs:end_offs] = avg_disparity.flatten()
dbg_gt_disparity[start_offs:end_offs] = gt_disparity.flatten()
dbg_offs[start_offs:end_offs] = offs.flatten()
# except ValueError:
# print("dataset_img_size= %d, i=%d, output.shape[0]=%d "%(dataset_img_size, i, output.shape[0]))
# break;
pass
result_file = files['result'][ntest] # result_files[ntest]
try:
os.makedirs(os.path.dirname(result_file))
except:
pass
rslt = np.concatenate(
[disp_out.reshape(-1,1),
dataset_img['t_disps'], #t_disps[ntest],
dataset_img['gtruths'], # gtruths[ntest],
dbg_cost_nw.reshape(-1,1),
dbg_cost_w.reshape(-1,1),
dbg_d.reshape(-1,1),
dbg_avg_disparity.reshape(-1,1),
dbg_gt_disparity.reshape(-1,1),
dbg_offs.reshape(-1,1)],1)
np.save(result_file, rslt.reshape(HEIGHT,WIDTH,-1))
rslt = qsf.eval_results(result_file, ABSOLUTE_DISPARITY, radius=CLUSTER_RADIUS, logfile=lf)
img_gain_test0 = rslt[0][0]/rslt[0][1]
img_gain_test9 = rslt[9][0]/rslt[9][1]
if SAVE_TIFFS:
qsf.result_npy_to_tiff(result_file, ABSOLUTE_DISPARITY, fix_nan = True,labels=SLICE_LABELS, logfile=lf)
"""
Remove dataset_img (if it is not [0] to reduce memory footprint
"""
if ntest > 0:
image_data[ntest] = None
if lf:
lf.close()
# tensorboard scalars
tt_summaries[0] = sess.run([merged],
feed_dict={ tf_ph_GW_loss: tt_gw_avg[0],
tf_ph_G_loss: tt_g_avgs[0][0], #train_g_avg,
tf_ph_G_losses: tt_g_avgs[0],
tf_ph_S_loss: tt_s_avg[0],
tf_ph_W_loss: tt_w_avg[0],
tf_ph_sq_diff: tt2_avg[0], # train2_avg,
tf_gtvar_diff: tt_gtvar_avg[0],
tf_img_test0: img_gain_test0,
tf_img_test9: img_gain_test9}) # previous value of *_avg #Fetch argument 0.0 has invalid type <class 'float'>, must be a string or Tensor. (Can not convert a float into a Tensor or Operation.)
for ntest, _ in enumerate(datasets_test):
tt_summaries[ntest+1] = sess.run([merged],
feed_dict={
tf_ph_GW_loss: tt_gw_avg[ntest+1],
tf_ph_G_loss: tt_g_avgs[ntest+1][0],
tf_ph_G_losses: tt_g_avgs[ntest+1], # train_g_avgs, # temporary, there is o data fro test
tf_ph_S_loss: tt_s_avg[ntest+1],
tf_ph_W_loss: tt_w_avg[ntest+1],
tf_ph_sq_diff: tt2_avg[ntest+1], #test2_avg,
tf_gtvar_diff: tt_gtvar_avg[ntest+1],
tf_img_test0: img_gain_test0,
tf_img_test9: img_gain_test9})
for n,tt_writer in enumerate(tt_writers):
## tt_writer.add_summary(tt_summaries[n],epoch)
tt_writer.add_summary(tt_summaries[n][0],epoch)
# if epoch ==0 :
# print ("adding delay to make directory creation time different")
# time.sleep(2.0) # reduce later
qsf.print_time("==== %d:%d -> %f %f %f %f %f (%f %f %f %f %f) ===="%(epoch,i,tt_gw_avg[0], tt_gw_avg[1], tt_gw_avg[2], tt_gw_avg[3], tt_gw_avg[4], tt2_avg[0], tt2_avg[1], tt2_avg[2], tt2_avg[3], tt2_avg[4]))
if (not CHECKPOINT_PERIOD is None) and (((epoch + 1) % CHECKPOINT_PERIOD) == 0):
print("Saving periodic checkpoint (trained variables only) to %s, global_step = %d"%(os.path.dirname(files['checkpoints']), epoch),end=" => ")
print(saver.save(sess, files['checkpoints'], global_step=epoch, write_meta_graph=False))
# Close writers
for tt_writer in tt_writers:
try:
tt_writer.close()
except:
print ("Could not close tt_writer: ",tt_writer)
print("Saving final checkpoint (trained variables only) to %s"%(files['checkpoints']),end=" => ")
print(saver.save(sess, files["checkpoints"]))
print("All done")
exit (0)
...@@ -16,7 +16,7 @@ import sys ...@@ -16,7 +16,7 @@ import sys
import time import time
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages
import qcstereo_functions as qsf import qcstereo_functions as qsf
#import xml.etree.ElementTree as ET #import xml.etree.ElementTree as ET
...@@ -53,8 +53,17 @@ TILE_SIDE, TILE_LAYERS, TWO_TRAINS, NET_ARCH1, NET_ARCH2 = [None]*5 ...@@ -53,8 +53,17 @@ TILE_SIDE, TILE_LAYERS, TWO_TRAINS, NET_ARCH1, NET_ARCH2 = [None]*5
ABSOLUTE_DISPARITY,SYM8_SUB, WLOSS_LAMBDA, SLOSS_LAMBDA, SLOSS_CLIP = [None]*5 ABSOLUTE_DISPARITY,SYM8_SUB, WLOSS_LAMBDA, SLOSS_LAMBDA, SLOSS_CLIP = [None]*5
SPREAD_CONVERGENCE, INTER_CONVERGENCE, HOR_FLIP, DISP_DIFF_CAP, DISP_DIFF_SLOPE = [None]*5 SPREAD_CONVERGENCE, INTER_CONVERGENCE, HOR_FLIP, DISP_DIFF_CAP, DISP_DIFF_SLOPE = [None]*5
CLUSTER_RADIUS,ABSOLUTE_DISPARITY = [None]*2 CLUSTER_RADIUS,ABSOLUTE_DISPARITY = [None]*2
FIGS_EXTENSIONS = ['png','pdf','svg']
#FIGS_ESXTENSIONS = ['png','pdf','svg']
EVAL_MODES = ["train","infer"]
FIGS_SAVESHOW = ['save','show']
globals().update(parameters) globals().update(parameters)
try:
FIGS_EXTENSIONS = globals()['FIGS_ESXTENSIONS'] # fixing typo in configs
except:
pass
#exit(0) #exit(0)
...@@ -98,6 +107,7 @@ TIGHT_HPAD = 1.0 ...@@ -98,6 +107,7 @@ TIGHT_HPAD = 1.0
TIGHT_WPAD = 1.0 TIGHT_WPAD = 1.0
FIGSIZE = [8.5,11.0] FIGSIZE = [8.5,11.0]
WOI_COLOR = "red" WOI_COLOR = "red"
TRANSPARENT = True # for export
#dbg_parameters #dbg_parameters
def get_fig_params(disparity_ranges): def get_fig_params(disparity_ranges):
...@@ -121,17 +131,30 @@ def get_fig_params(disparity_ranges): ...@@ -121,17 +131,30 @@ def get_fig_params(disparity_ranges):
fig_params = get_fig_params(dbg_parameters['disparity_ranges']) fig_params = get_fig_params(dbg_parameters['disparity_ranges'])
pass pass
figs = []
def setlimsxy(lim_xy): if not 'show' in FIGS_SAVESHOW:
plt.ioff()
for mode in ['train','infer']:
figs = []
ffiles = [] # no ext
def setlimsxy(lim_xy):
if not lim_xy is None: if not lim_xy is None:
plt.xlim(min(lim_xy[:2]),max(lim_xy[:2])) plt.xlim(min(lim_xy[:2]),max(lim_xy[:2]))
plt.ylim(max(lim_xy[2:]),min(lim_xy[2:])) plt.ylim(max(lim_xy[2:]),min(lim_xy[2:]))
for nfile, fpars in enumerate(fig_params): for nfile, fpars in enumerate(fig_params):
if not fpars is None: if not fpars is None:
data = qsf.result_npy_prepare(files['result'][nfile], ABSOLUTE_DISPARITY, fix_nan=True, insert_deltas=True) img_file = files['result'][nfile]
if mode == 'infer':
img_file = img_file.replace('.npy','-infer.npy')
try:
data,_ = qsf.result_npy_prepare(img_file, ABSOLUTE_DISPARITY, fix_nan=True, insert_deltas=True)
except:
print ("Image file does not exist:", img_file)
continue
for rng in fpars['ranges']: for subindex, rng in enumerate(fpars['ranges']):
lim_val = rng['lim_val'] lim_val = rng['lim_val']
lim_xy = rng['lim_xy'] lim_xy = rng['lim_xy']
fig = plt.figure(figsize=FIGSIZE) fig = plt.figure(figsize=FIGSIZE)
...@@ -139,7 +162,7 @@ for nfile, fpars in enumerate(fig_params): ...@@ -139,7 +162,7 @@ for nfile, fpars in enumerate(fig_params):
fig.suptitle(fpars['name']) fig.suptitle(fpars['name'])
ax_conf=plt.subplot(322) ax_conf=plt.subplot(322)
ax_conf.set_title("Ground truth confidence") ax_conf.set_title("Ground truth confidence")
# fig.suptitle("Groud truth confidence") # fig.suptitle("Groud truth confidence")
plt.imshow(data[...,GT_CONF], vmin=0, vmax=CONF_MAX, cmap='gray') plt.imshow(data[...,GT_CONF], vmin=0, vmax=CONF_MAX, cmap='gray')
if not lim_xy is None: if not lim_xy is None:
pass # show frame pass # show frame
...@@ -147,7 +170,7 @@ for nfile, fpars in enumerate(fig_params): ...@@ -147,7 +170,7 @@ for nfile, fpars in enumerate(fig_params):
ydata=[min(lim_xy[2:]),min(lim_xy[2:]),max(lim_xy[2:]),max(lim_xy[2:]),min(lim_xy[2:])] ydata=[min(lim_xy[2:]),min(lim_xy[2:]),max(lim_xy[2:]),max(lim_xy[2:]),min(lim_xy[2:])]
plt.plot(xdata,ydata,color=WOI_COLOR) plt.plot(xdata,ydata,color=WOI_COLOR)
# setlimsxy(lim_xy) # setlimsxy(lim_xy)
plt.colorbar(orientation='vertical') # location='bottom') plt.colorbar(orientation='vertical') # location='bottom')
ax_gtd=plt.subplot(321) ax_gtd=plt.subplot(321)
...@@ -183,15 +206,58 @@ for nfile, fpars in enumerate(fig_params): ...@@ -183,15 +206,58 @@ for nfile, fpars in enumerate(fig_params):
plt.tight_layout(rect =[0,0,1,TIGHT_TOP], h_pad = TIGHT_HPAD, w_pad = TIGHT_WPAD) plt.tight_layout(rect =[0,0,1,TIGHT_TOP], h_pad = TIGHT_HPAD, w_pad = TIGHT_WPAD)
figs.append(fig) figs.append(fig)
fb_noext = os.path.splitext(os.path.basename(img_file))[0]#
if subindex > 0:
if subindex < 10:
fb_noext+="abcdefghi"[subindex-1]
else:
fb_noext+="-"+str(subindex)
ffiles.append(fb_noext)
pass pass
#whow to allow adjustment before applying tight_layout? #whow to allow adjustment before applying tight_layout?
pass pass
for fig in figs: for fig in figs:
fig.tight_layout(rect =[0,0,1,TIGHT_TOP], h_pad = TIGHT_HPAD, w_pad = TIGHT_WPAD) fig.tight_layout(rect =[0,0,1,TIGHT_TOP], h_pad = TIGHT_HPAD, w_pad = TIGHT_WPAD)
plt.show()
if FIGS_EXTENSIONS and figs and 'save' in FIGS_SAVESHOW:
try:
print ("Creating output directory for figures: ",dirs['figures'])
os.makedirs(dirs['figures'])
except:
pass
pp=None
if 'pdf' in FIGS_EXTENSIONS:
if mode == 'infer':
pdf_path = os.path.join(dirs['figures'],"figures-infer.pdf")
else:
pdf_path = os.path.join(dirs['figures'],"figures-train.pdf")
pp= PdfPages(pdf_path)
for fb_noext, fig in zip(ffiles,figs):
for ext in FIGS_EXTENSIONS:
if ext == 'pdf':
pass
fig.savefig(pp,format='pdf')
else:
if mode == 'infer':
noext = fb_noext+'-infer'
else:
noext = fb_noext+'-train'
fig.savefig(
fname = os.path.join(dirs['figures'],noext+"."+ext),
transparent = TRANSPARENT,
)
pass
if pp:
pp.close()
if 'show' in FIGS_SAVESHOW:
plt.show()
#FIGS_ESXTENSIONS
#qsf.evaluateAllResults(result_files = files['result'], #qsf.evaluateAllResults(result_files = files['result'],
# absolute_disparity = ABSOLUTE_DISPARITY, # absolute_disparity = ABSOLUTE_DISPARITY,
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<properties> <properties>
<parameters> <parameters>
<EPOCHS_TO_RUN> 650 </EPOCHS_TO_RUN> <!-- 752# 3000#0 #0 --> <EPOCHS_TO_RUN> 650 </EPOCHS_TO_RUN> <!-- 752# 3000#0 #0 -->
<NET_ARCH1> 1 </NET_ARCH1> <!--1-st stage network --> <NET_ARCH1> 13 </NET_ARCH1> <!--1-st stage network -->
<NET_ARCH2> 9 </NET_ARCH2> <!-- 2-nd stage network --> <NET_ARCH2> 9 </NET_ARCH2> <!-- 2-nd stage network -->
<SYM8_SUB> False </SYM8_SUB> <!-- enforce inputs from 2d correlation have symmetrical ones (groups of 8) --> <SYM8_SUB> False </SYM8_SUB> <!-- enforce inputs from 2d correlation have symmetrical ones (groups of 8) -->
<SPREAD_CONVERGENCE> False </SPREAD_CONVERGENCE><!-- Input target disparity to all nodes of the 1-st stage --> <SPREAD_CONVERGENCE> False </SPREAD_CONVERGENCE><!-- Input target disparity to all nodes of the 1-st stage -->
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
<ONLY_TILE> None </ONLY_TILE> <!-- (remove all but center tile data), put None here for normal operation) --> <ONLY_TILE> None </ONLY_TILE> <!-- (remove all but center tile data), put None here for normal operation) -->
<CLUSTER_RADIUS> 2 </CLUSTER_RADIUS> <!-- 1 # 1 - 3x3, 2 - 5x5 tiles --> <CLUSTER_RADIUS> 2 </CLUSTER_RADIUS> <!-- 1 # 1 - 3x3, 2 - 5x5 tiles -->
<SHUFFLE_FILES> True </SHUFFLE_FILES> <SHUFFLE_FILES> True </SHUFFLE_FILES>
<WLOSS_LAMBDA> 0.1 </WLOSS_LAMBDA> <!-- fraction of the W_loss (input layers weight non-uniformity) added to G_loss --> <WLOSS_LAMBDA> 0.5 </WLOSS_LAMBDA> <!-- fraction of the W_loss (input layers weight non-uniformity) added to G_loss -->
<SLOSS_LAMBDA> 0.1 </SLOSS_LAMBDA> <!-- weight of loss for smooth fg/bg transitions --> <SLOSS_LAMBDA> 0.1 </SLOSS_LAMBDA> <!-- weight of loss for smooth fg/bg transitions -->
<SLOSS_CLIP> 0.2 </SLOSS_CLIP> <!-- limit punishment for cutting corners (disparity pix) --> <SLOSS_CLIP> 0.2 </SLOSS_CLIP> <!-- limit punishment for cutting corners (disparity pix) -->
<WBORDERS_ZERO> True </WBORDERS_ZERO> <!-- Border conditions for first layer weights: False - free, True - tied to 0 --> <WBORDERS_ZERO> True </WBORDERS_ZERO> <!-- Border conditions for first layer weights: False - free, True - tied to 0 -->
...@@ -32,117 +32,176 @@ ...@@ -32,117 +32,176 @@
<PARTIALS_WEIGHTS> [2.0,0.5,0.2] </PARTIALS_WEIGHTS><!-- weight of full 5x5, center 3x3 and center 1x1. len(PARTIALS_WEIGHTS) == CLUSTER_RADIUS + 1. Set to None --> <PARTIALS_WEIGHTS> [2.0,0.5,0.2] </PARTIALS_WEIGHTS><!-- weight of full 5x5, center 3x3 and center 1x1. len(PARTIALS_WEIGHTS) == CLUSTER_RADIUS + 1. Set to None -->
<HOR_FLIP> True </HOR_FLIP><!-- randomly flip training data horizontally --> <HOR_FLIP> True </HOR_FLIP><!-- randomly flip training data horizontally -->
<SAVE_TIFFS> True </SAVE_TIFFS><!-- save Tiff files after each image evaluation --> <SAVE_TIFFS> True </SAVE_TIFFS><!-- save Tiff files after each image evaluation -->
<BATCH_WEIGHTS> [0.9, 1.0, 0.9, 1.0]</BATCH_WEIGHTS> <!-- lvar, hvar, lvar1, hvar1 (increase importance of non-flat clusters --> <BATCH_WEIGHTS> [0.9, 1.0, 0.1, 0.1]</BATCH_WEIGHTS> <!-- lvar, hvar, lvar1, hvar1 (increase importance of non-flat clusters -->
<DISP_DIFF_CAP> 0.3 </DISP_DIFF_CAP><!-- cap disparity difference (do not increase loss above)--> <DISP_DIFF_CAP> 0.3 </DISP_DIFF_CAP><!-- cap disparity difference (do not increase loss above)-->
<DISP_DIFF_SLOPE> 0.03 </DISP_DIFF_SLOPE><!-- allow squared error to grow above DISP_DIFF_CAP --> <DISP_DIFF_SLOPE> 0.03 </DISP_DIFF_SLOPE><!-- allow squared error to grow above DISP_DIFF_CAP -->
<TRAIN_BUFFER_GPU> 79 </TRAIN_BUFFER_GPU> <!-- in batches merged (now quad) batches--> <TRAIN_BUFFER_GPU> 79 </TRAIN_BUFFER_GPU> <!-- in batches merged (now quad) batches-->
<TRAIN_BUFFER_CPU> 4 </TRAIN_BUFFER_CPU> <!-- in TRAIN_BUFFER_GPU-s --> <TRAIN_BUFFER_CPU> 4 </TRAIN_BUFFER_CPU> <!-- in TRAIN_BUFFER_GPU-s -->
<!-- if TEST_TITLES is present, it should have 8 entries, use None to skip certain modes -->
<TEST_TITLES>["Test flat heuristic",
"Test edge heuristic",
"Test flat random",
"Test edge random",
"Fake flat heuristic",
"Fake edge heuristic",
"Fake flat random",
"Fake edge random"]</TEST_TITLES>
<CHECKPOINT_PERIOD>100</CHECKPOINT_PERIOD>
<!-- <FIGS_ESXTENSIONS>["png","pdf","svg"]</FIGS_ESXTENSIONS> -->
<FIGS_EXTENSIONS>["pdf"]</FIGS_EXTENSIONS>
<!-- <FIGS_SAVESHOW>['save','show']</FIGS_SAVESHOW> -->
<FIGS_SAVESHOW>['save']</FIGS_SAVESHOW>
<EVAL_MODES>["train","infer"]</EVAL_MODES>
</parameters> </parameters>
<dbg_parameters> <dbg_parameters>
<disparity_ranges> <disparity_ranges>
[[[0.0, 0.6,[140,230,135,60]], "Overlook"], [[[0.0, 5.0,[0, 323,0,241]], "City Creek 1"],
[[0.0, 4.0,[180,240, 90,140]], "City Creek 2"],
[[1.0, 2.0,[180,240, 90,140]], "City Creek 3"],
[[1.0, 1.5,[280,320, 70,120]], "City Creek 4"],
[[0.0, 0.5,[ 10,120, 60,120]], "City Creek 5"],
[[0.0, 2.0,[210,303, 70,130]], "City Creek 6"],
[[0.0, 3.0,[ 75,225, 50,140]], "State Capitol"],
[[0.0, 3.0,[170,225, 95,140]], "Stop Sign"],
[[0.0, 1.0,[ 75,135,100,135]], "SLC from Capitol Hill 1"],
[[0.0, 1.5,[ 90,190,125,170]], "SLC from Capitol Hill 2"],
[[0.0, 0.6,[ 95,210, 65,140]], "Overlook approach"],
[[0.0,10.0,[ 60,190, 95,145]], "North Salt Lake 1"],
[[0.0, 5.0,[120,230, 85,145]], "North Salt Lake 2"], <!-- bad pole -->
[[0.0, 2.0,[ 10,155, 90,150]], "North Salt Lake 3"], <!-- LPF? misaligned? -->
[[0.0, 0.6,[140,230,135,60]], "Overlook"],
[[0.0, 1.0,[120,180,125,80]],[2.0, 4.0, [50,130,125, 70]], "State Street1"], [[0.0, 1.0,[120,180,125,80]],[2.0, 4.0, [50,130,125, 70]], "State Street1"],
[[0.0, 1.0,[130,210,135,95]],[0.5, 2.5, [50,150,150, 75]], "State Street2"], [[0.0, 1.0,[130,210,135,95]],[0.5, 2.5, [50,150,150, 75]], "State Street2"],
[ [1.0, 2.5, [90,170, 50, 0]], "B737 near"], [ [1.0, 2.5, [90,170, 50, 0]], "B737 near"],
[ [0.75, 1.5, [125,150, 90, 70]], "B737 midrange"], [ [0.75, 1.5, [125,150, 90, 70]], "B737 midrange"],
[ [0.4, 0.8, [135,150,102,112]], "B737 far"]] [ [0.4, 0.8, [135,150,102,112]], "B737 far"]
]
</disparity_ranges> </disparity_ranges>
</dbg_parameters> </dbg_parameters>
<directories> <directories>
<train_lvar> <train_lvar>
"tf_data_5x5_main_1" "tf_data_5x5_main_13_heur"
</train_lvar> </train_lvar>
<train_hvar> <train_hvar>
"tf_data_5x5_main_1" "tf_data_5x5_main_13_heur"
</train_hvar> </train_hvar>
<train_lvar1> <train_lvar1>
"tf_data_5x5_main_6" "tf_data_5x5_main_11_rnd"
</train_lvar1> </train_lvar1>
<train_hvar1> <train_hvar1>
"tf_data_5x5_main_6" "tf_data_5x5_main_11_rnd"
</train_hvar1> </train_hvar1>
<test_lvar> <test_lvar>
"tf_data_5x5_main_1" "tf_data_5x5_main_10_heur" <!-- test file, no offset from hieuristic-->
</test_lvar> </test_lvar>
<test_hvar> <test_hvar>
"tf_data_5x5_main_5" "tf_data_5x5_main_10_heur" <!-- test file, no offset from hieuristic-->
</test_hvar> </test_hvar>
<test_lvar1>
"tf_data_5x5_main_11_rnd" <!-- test file, random +/1 2pix offset-->
</test_lvar1>
<test_hvar1>
"tf_data_5x5_main_11_rnd" <!-- test file, random +/1 2pix offset-->
</test_hvar1>
<fake_lvar>
"tf_data_5x5_main_10_heur" <!-- test file, no offset from hieuristic-->
</fake_lvar>
<fake_hvar>
"tf_data_5x5_main_10_heur" <!-- test file, no offset from hieuristic-->
</fake_hvar>
<fake_lvar1>
"tf_data_5x5_main_11_rnd" <!-- test file, random +/1 2pix offset-->
</fake_lvar1>
<fake_hvar1>
"tf_data_5x5_main_11_rnd" <!-- test file, random +/1 2pix offset-->
</fake_hvar1>
<images> <images>
"tf_data_5x5_main_6/img" "tf_data_5x5_main_13_heur/img"
</images> </images>
<result> <result>
"tf_data_5x5_main_6/result" "tf_data_5x5_main_13_heur/result"
</result> </result>
<figures>
"tf_data_5x5_main_13_heur/result/figs"
</figures>
<checkpoints>
"tf_data_5x5_main_13_heur/checkpoints"
</checkpoints>
</directories> </directories>
<files> <files>
<train_lvar> <train_lvar>
["train000_R2_LE_1.5.tfrecords", ["train000_R2_LE_0.4.tfrecords",
"train001_R2_LE_1.5.tfrecords", "train001_R2_LE_0.4.tfrecords",
"train002_R2_LE_1.5.tfrecords", "train002_R2_LE_0.4.tfrecords",
"train003_R2_LE_1.5.tfrecords", "train003_R2_LE_0.4.tfrecords",
"train004_R2_LE_1.5.tfrecords", "train004_R2_LE_0.4.tfrecords",
"train005_R2_LE_1.5.tfrecords", "train005_R2_LE_0.4.tfrecords",
"train006_R2_LE_1.5.tfrecords", "train006_R2_LE_0.4.tfrecords",
"train007_R2_LE_1.5.tfrecords", "train007_R2_LE_0.4.tfrecords",
"train008_R2_LE_1.5.tfrecords", "train008_R2_LE_0.4.tfrecords",
"train009_R2_LE_1.5.tfrecords", "train009_R2_LE_0.4.tfrecords",
"train010_R2_LE_1.5.tfrecords", "train010_R2_LE_0.4.tfrecords",
"train011_R2_LE_1.5.tfrecords", "train011_R2_LE_0.4.tfrecords",
"train012_R2_LE_1.5.tfrecords", "train012_R2_LE_0.4.tfrecords",
"train013_R2_LE_1.5.tfrecords", "train013_R2_LE_0.4.tfrecords",
"train014_R2_LE_1.5.tfrecords", "train014_R2_LE_0.4.tfrecords",
"train015_R2_LE_1.5.tfrecords", "train015_R2_LE_0.4.tfrecords",
"train016_R2_LE_1.5.tfrecords", <!--
"train017_R2_LE_1.5.tfrecords", "train016_R2_LE_0.4.tfrecords",
"train018_R2_LE_1.5.tfrecords", "train017_R2_LE_0.4.tfrecords",
"train019_R2_LE_1.5.tfrecords", "train018_R2_LE_0.4.tfrecords",
"train020_R2_LE_1.5.tfrecords", "train019_R2_LE_0.4.tfrecords",
"train021_R2_LE_1.5.tfrecords", "train020_R2_LE_0.4.tfrecords",
"train022_R2_LE_1.5.tfrecords", "train021_R2_LE_0.4.tfrecords",
"train023_R2_LE_1.5.tfrecords", "train022_R2_LE_0.4.tfrecords",
"train024_R2_LE_1.5.tfrecords", "train023_R2_LE_0.4.tfrecords",
"train025_R2_LE_1.5.tfrecords", "train024_R2_LE_0.4.tfrecords",
"train026_R2_LE_1.5.tfrecords", "train025_R2_LE_0.4.tfrecords",
"train027_R2_LE_1.5.tfrecords", "train026_R2_LE_0.4.tfrecords",
"train028_R2_LE_1.5.tfrecords", "train027_R2_LE_0.4.tfrecords",
"train029_R2_LE_1.5.tfrecords", "train028_R2_LE_0.4.tfrecords",
"train030_R2_LE_1.5.tfrecords", "train029_R2_LE_0.4.tfrecords",
"train031_R2_LE_1.5.tfrecords"] "train030_R2_LE_0.4.tfrecords",
"train031_R2_LE_0.4.tfrecords" -->]
</train_lvar> </train_lvar>
<train_hvar> <train_hvar>
["train000_R2_GT_1.5.tfrecords", ["train000_R2_GT_0.4.tfrecords",
"train001_R2_GT_1.5.tfrecords", "train001_R2_GT_0.4.tfrecords",
"train002_R2_GT_1.5.tfrecords", "train002_R2_GT_0.4.tfrecords",
"train003_R2_GT_1.5.tfrecords", "train003_R2_GT_0.4.tfrecords",
"train004_R2_GT_1.5.tfrecords", "train004_R2_GT_0.4.tfrecords",
"train005_R2_GT_1.5.tfrecords", "train005_R2_GT_0.4.tfrecords",
"train006_R2_GT_1.5.tfrecords", "train006_R2_GT_0.4.tfrecords",
"train007_R2_GT_1.5.tfrecords", "train007_R2_GT_0.4.tfrecords",
"train008_R2_GT_1.5.tfrecords", "train008_R2_GT_0.4.tfrecords",
"train009_R2_GT_1.5.tfrecords", "train009_R2_GT_0.4.tfrecords",
"train010_R2_GT_1.5.tfrecords", "train010_R2_GT_0.4.tfrecords",
"train011_R2_GT_1.5.tfrecords", "train011_R2_GT_0.4.tfrecords",
"train012_R2_GT_1.5.tfrecords", "train012_R2_GT_0.4.tfrecords",
"train013_R2_GT_1.5.tfrecords", "train013_R2_GT_0.4.tfrecords",
"train014_R2_GT_1.5.tfrecords", "train014_R2_GT_0.4.tfrecords",
"train015_R2_GT_1.5.tfrecords", "train015_R2_GT_0.4.tfrecords",
"train016_R2_GT_1.5.tfrecords", <!--
"train017_R2_GT_1.5.tfrecords", "train016_R2_GT_0.4.tfrecords",
"train018_R2_GT_1.5.tfrecords", "train017_R2_GT_0.4.tfrecords",
"train019_R2_GT_1.5.tfrecords", "train018_R2_GT_0.4.tfrecords",
"train020_R2_GT_1.5.tfrecords", "train019_R2_GT_0.4.tfrecords",
"train021_R2_GT_1.5.tfrecords", "train020_R2_GT_0.4.tfrecords",
"train022_R2_GT_1.5.tfrecords", "train021_R2_GT_0.4.tfrecords",
"train023_R2_GT_1.5.tfrecords", "train022_R2_GT_0.4.tfrecords",
"train024_R2_GT_1.5.tfrecords", "train023_R2_GT_0.4.tfrecords",
"train025_R2_GT_1.5.tfrecords", "train024_R2_GT_0.4.tfrecords",
"train026_R2_GT_1.5.tfrecords", "train025_R2_GT_0.4.tfrecords",
"train027_R2_GT_1.5.tfrecords", "train026_R2_GT_0.4.tfrecords",
"train028_R2_GT_1.5.tfrecords", "train027_R2_GT_0.4.tfrecords",
"train029_R2_GT_1.5.tfrecords", "train028_R2_GT_0.4.tfrecords",
"train030_R2_GT_1.5.tfrecords", "train029_R2_GT_0.4.tfrecords",
"train031_R2_GT_1.5.tfrecords"] "train030_R2_GT_0.4.tfrecords",
"train031_R2_GT_0.4.tfrecords"-->]
</train_hvar> </train_hvar>
<train_lvar1> <train_lvar1>
...@@ -214,23 +273,64 @@ ...@@ -214,23 +273,64 @@
"train031_R2_GT_0.4.tfrecords"] "train031_R2_GT_0.4.tfrecords"]
</train_hvar1> </train_hvar1>
<!-- Currently test* and fake* should have exactly one entry each.Should be defined for each non-None TEST_TITLES element-->
<test_lvar> <test_lvar>
["train004_R2_GT_1.5.tfrecords"] ["testTEST_R2_LE_0.4.tfrecords"] <!-- test file, low variance, no offset-->
</test_lvar> </test_lvar>
<test_hvar> <test_hvar>
["testTEST_R2_GT_1.5.tfrecords"] ["testTEST_R2_GT_0.4.tfrecords"] <!-- test file, high variance, no offset-->
</test_hvar> </test_hvar>
<test_lvar1>
["testTEST_R2_LE_0.4.tfrecords"] <!-- test file, low variance, +/-2 pix offset-->
</test_lvar1>
<test_hvar1>
["testTEST_R2_GT_0.4.tfrecords"] <!-- test file, high variance, +/-2 pix offset-->
</test_hvar1>
<fake_lvar>
["testFAKE_R2_LE_0.4.tfrecords"] <!-- fake test (made from train data) file, low variance, no offset-->
</fake_lvar>
<fake_hvar>
["testFAKE_R2_GT_0.4.tfrecords"] <!-- fake test (made from train data) file, high variance, no offset-->
</fake_hvar>
<fake_lvar1>
["testFAKE_R2_LE_0.4.tfrecords"] <!-- fake test (made from train data) file, low variance, +/-2 pix offset-->
</fake_lvar1>
<fake_hvar1>
["testFAKE_R2_GT_0.4.tfrecords"] <!-- fake test (made from train data) file, high variance, +/-2 pix offset-->
</fake_hvar1>
<images> <images>
["1527257933_150165-v04", <!-- overlook --> ["1527257235_150165-v02", <!-- City Creek 1 -->
"1527257235_350165-v02", <!-- City Creek 2 -->
"1527257235_550165-v02", <!-- City Creek 3 -->
"1527257235_750165-v02", <!-- City Creek 4 -->
"1527257235_950165-v02", <!-- City Creek 5 -->
"1527257244_350165-v02", <!-- City Creek 6 -->
"1527257370_950165-v02", <!-- State Capitol -->
"1527257406_950165-v02", <!-- Stop Sign -->
"1527257757_950165-v02", <!-- SLC from Capitol Hill 1 -->
"1527257787_950165-v02", <!-- SLC from Capitol Hill 2 -->
"1527257894_750165-v02", <!-- Overlook approach -->
"1527258897_071435-v02", <!-- North Salt Lake 1 -->
"1527258936_671435-v02", <!-- North Salt Lake 2 -->
"1527259003_271435-v02", <!-- North Salt Lake 3 -->
"1527257933_150165-v04", <!-- overlook -->
"1527256858_150165-v01", <!-- State Street --> "1527256858_150165-v01", <!-- State Street -->
"1527256816_150165-v02", <!-- State Street --> "1527256816_150165-v02", <!-- State Street -->
"1527182802_096892-v02", <!-- plane near plane --> "1527182802_096892-v02", <!-- plane near plane -->
"1527182805_096892-v02", <!-- plane midrange used up to -49 plane --> "1527182805_096892-v02", <!-- plane midrange used up to -49 plane -->
"1527182810_096892-v02"] <!-- plane far --> "1527182810_096892-v02" <!-- plane far -->
]
</images> </images>
<checkpoints>
"model_checkpoints"
</checkpoints>
</files> </files>
</properties> </properties>
...@@ -30,11 +30,22 @@ def print_time(txt="",end="\n"): ...@@ -30,11 +30,22 @@ def print_time(txt="",end="\n"):
print(("%s"+bcolors.BOLDWHITE+"at %.4fs (+%.4fs)"+bcolors.ENDC)%(txt,t-TIME_START,t-TIME_LAST), end = end, flush=True) print(("%s"+bcolors.BOLDWHITE+"at %.4fs (+%.4fs)"+bcolors.ENDC)%(txt,t-TIME_START,t-TIME_LAST), end = end, flush=True)
TIME_LAST = t TIME_LAST = t
DEFAULT_TITLES = [
['test_lvar','Test_flat_heuristic'],
['test_hvar','Test_edge_heuristic'],
['test_lvar1','Test_flat_random'],
['test_hvar1','Test_edge_random'],
['fake_lvar','Fake_flat_heuristic'],
['fake_hvar','Fake_edge_heuristic'],
['fake_lvar1','Fake_flat_random'],
['fake_hvar1','Fake_edge_random']]
def parseXmlConfig(conf_file, root_dir): def parseXmlConfig(conf_file, root_dir):
tree = ET.parse(conf_file) tree = ET.parse(conf_file)
root = tree.getroot() root = tree.getroot()
parameters = {} parameters = {}
for p in root.find('parameters'): for p in root.find('parameters'):
## print ("p.tag=%s, p.text.stri[p()=%s"%(p.tag,p.text.strip()))
parameters[p.tag]=eval(p.text.strip()) parameters[p.tag]=eval(p.text.strip())
# globals # globals
dirs={} dirs={}
...@@ -51,6 +62,14 @@ def parseXmlConfig(conf_file, root_dir): ...@@ -51,6 +62,14 @@ def parseXmlConfig(conf_file, root_dir):
return parameters, dirs, files, dbg_parameters return parameters, dirs, files, dbg_parameters
def defaultTestTitles(files):
test_titles = []
for f, n in DEFAULT_TITLES:
if f in files:
test_titles.append(n)
else:
test_titles.append(None)
return test_titles
def prepareFiles(dirs, files, suffix): def prepareFiles(dirs, files, suffix):
...@@ -72,11 +91,47 @@ def prepareFiles(dirs, files, suffix): ...@@ -72,11 +91,47 @@ def prepareFiles(dirs, files, suffix):
for i, path in enumerate(files['test_hvar']): for i, path in enumerate(files['test_hvar']):
files['test_hvar'][i]=os.path.join(dirs['test_hvar'], path) files['test_hvar'][i]=os.path.join(dirs['test_hvar'], path)
if ('test_lvar1' in files) and ('test_lvar1' in dirs):
for i, path in enumerate(files['test_lvar1']):
files['test_lvar1'][i]=os.path.join(dirs['test_lvar1'], path)
if ('test_hvar1' in files) and ('test_hvar1' in dirs):
for i, path in enumerate(files['test_hvar1']):
files['test_hvar1'][i]=os.path.join(dirs['test_hvar1'], path)
if ('fake_lvar' in files) and ('fake_lvar' in dirs):
for i, path in enumerate(files['fake_lvar']):
files['fake_lvar'][i]=os.path.join(dirs['fake_lvar'], path)
if ('fake_hvar' in files) and ('fake_hvar' in dirs):
for i, path in enumerate(files['fake_hvar']):
files['fake_hvar'][i]=os.path.join(dirs['fake_hvar'], path)
if ('fake_lvar1' in files) and ('fake_lvar1' in dirs):
for i, path in enumerate(files['fake_lvar1']):
files['fake_lvar1'][i]=os.path.join(dirs['fake_lvar1'], path)
if ('fake_hvar' in files) and ('fake_hvar' in dirs):
for i, path in enumerate(files['fake_hvar1']):
files['fake_hvar1'][i]=os.path.join(dirs['fake_hvar1'], path)
result_files=[] result_files=[]
for i, path in enumerate(files['images']): for i, path in enumerate(files['images']):
result_files.append(os.path.join(dirs['result'], path+"_"+suffix+'.npy')) result_files.append(os.path.join(dirs['result'], path+"_"+suffix+'.npy'))
files['result'] = result_files files['result'] = result_files
if not 'checkpoints' in files:
files['checkpoints'] = 'checkpoints'
if not 'checkpoints' in dirs:
dirs['checkpoints'] = dirs['result']
files['checkpoints'] = os.path.join(dirs['checkpoints'], files['checkpoints'])
if not 'figures' in dirs:
dirs['figures'] = os.path.join(dirs['result'],"figs")
files['train'] = [files['train_lvar'],files['train_hvar'], files['train_lvar1'], files['train_hvar1']] files['train'] = [files['train_lvar'],files['train_hvar'], files['train_lvar1'], files['train_hvar1']]
files['test'] = [files['test_lvar'], files['test_hvar']]
if 'test_lvar1' in files:
files['test'].append(files['test_lvar1'])
if 'test_hvar1' in files:
files['test'].append(files['test_hvar1'])
# should be after result files # should be after result files
for i, path in enumerate(files['images']): for i, path in enumerate(files['images']):
files['images'][i] = os.path.join(dirs['images'], path+'.tfrecords') files['images'][i] = os.path.join(dirs['images'], path+'.tfrecords')
...@@ -238,6 +293,7 @@ def replace_nan(datasets_data): # , cluster_radius): ...@@ -238,6 +293,7 @@ def replace_nan(datasets_data): # , cluster_radius):
if not rec is None: if not rec is None:
np.nan_to_num(rec['corr2d'], copy = False) np.nan_to_num(rec['corr2d'], copy = False)
np.nan_to_num(rec['target_disparity'], copy = False) np.nan_to_num(rec['target_disparity'], copy = False)
if 'gt_ds' in rec:
np.nan_to_num(rec['gt_ds'], copy = False) np.nan_to_num(rec['gt_ds'], copy = False)
def permute_to_swaps(perm): def permute_to_swaps(perm):
...@@ -257,26 +313,27 @@ def shuffle_in_place(dataset_data, #alternating clusters from 4 sources.each clu ...@@ -257,26 +313,27 @@ def shuffle_in_place(dataset_data, #alternating clusters from 4 sources.each clu
np.random.shuffle(dataset_data[i::period]) np.random.shuffle(dataset_data[i::period])
def add_file_to_dataset(dataset, new_dataset, train_next): def add_file_to_dataset(dataset, new_dataset, train_next):
train_next['file'] = (train_next['file']+1)%train_next['files']
l = new_dataset.shape[0] * train_next['step'] l = new_dataset.shape[0] * train_next['step']
rollover = False
if (train_next['entry'] + l) < (train_next['entries']+train_next['step']): if (train_next['entry'] + l) < (train_next['entries']+train_next['step']):
dataset[train_next['entry']:train_next['entry']+l:train_next['step']] = new_dataset dataset[train_next['entry']:train_next['entry']+l:train_next['step']] = new_dataset
train_next['entry'] += l
if (train_next['entry'] >= train_next['entries']):
train_next['entry'] -= train_next['entries']
return True
else:
return False
else: # split it two parts else: # split it two parts
rollover = True l = (train_next['entries'] - train_next['entry'] + (train_next['step']-1)) // train_next['step']
l = (train_next['entries'] - train_next['entry']) // train_next['step']
dataset[train_next['entry']::train_next['step']] = new_dataset[:l] dataset[train_next['entry']::train_next['step']] = new_dataset[:l]
train_next['entry'] = (train_next['entry'] + l * train_next['step']) % train_next['entries'] train_next['entry'] = (train_next['entry'] + l * train_next['step']) % train_next['entries'] #0,1,2,3
l1 = new_dataset.shape[0] - l # remainder l1 = new_dataset.shape[0] - l # remainder
ln = train_next['entry'] + l1 * train_next['step'] ln = train_next['entry'] + l1 * train_next['step']
dataset[train_next['entry']:ln:train_next['step']] = new_dataset[l:] dataset[train_next['entry']:ln:train_next['step']] = new_dataset[l:]
train_next['entry'] += new_dataset.shape[0] * train_next['step'] train_next['entry'] = ln
train_next['file'] = (train_next['file']+1)%train_next['files']
if (train_next['entry'] >= train_next['entries']):
train_next['entry'] -= train_next['entries']
return True return True
return rollover
""" """
train_next[n_train] train_next[n_train]
...@@ -287,6 +344,7 @@ def initTrainTestData( ...@@ -287,6 +344,7 @@ def initTrainTestData(
files, files,
cluster_radius, cluster_radius,
buffer_size, # number of clusters per train buffer_size, # number of clusters per train
test_titles = None
): ):
""" """
Generates a single np array for training with concatenated cluster of corr2d, Generates a single np array for training with concatenated cluster of corr2d,
...@@ -306,41 +364,47 @@ def initTrainTestData( ...@@ -306,41 +364,47 @@ def initTrainTestData(
new_dataset = readTFRewcordsEpoch(fpath, cluster_radius) new_dataset = readTFRewcordsEpoch(fpath, cluster_radius)
if dataset_train_merged is None: if dataset_train_merged is None:
dataset_train_merged = np.empty([num_entries,new_dataset.shape[1]], dtype =new_dataset.dtype) dataset_train_merged = np.empty([num_entries,new_dataset.shape[1]], dtype =new_dataset.dtype)
## print("\nbefore add_file_to_dataset: train_next["+str(n_train)+"]=",train_next[n_train])
rollover = add_file_to_dataset( rollover = add_file_to_dataset(
dataset = dataset_train_merged, dataset = dataset_train_merged,
new_dataset = new_dataset, new_dataset = new_dataset,
train_next = train_next[n_train]) train_next = train_next[n_train])
## print("after add_file_to_dataset: train_next["+str(n_train)+"]=",train_next[n_train])
print_time(" Done") print_time(" Done")
if rollover: if rollover:
buffer_full = True buffer_full = True
train_next[n_train][ 'more_files'] = train_next[n_train][ 'file'] < train_next[n_train][ 'files'] # Not all files used, need to load during training train_next[n_train][ 'more_files'] = train_next[n_train][ 'file'] < train_next[n_train][ 'files'] # Not all files used, need to load during training
break break
if test_titles is None:
datasets_test_lvar = [] test_titles = defaultTestTitles(files)
for fpath in files['test_lvar']: datasets_test = []
print_time("Importing test data (low variance) from "+fpath, end="") for t,v in zip(test_titles,DEFAULT_TITLES):
if not t is None:
grp = v[0]
for fpath in files[grp]:
print_time("Importing test data ("+grp+") from "+fpath, end="")
new_dataset = readTFRewcordsEpoch(fpath, cluster_radius) new_dataset = readTFRewcordsEpoch(fpath, cluster_radius)
datasets_test_lvar.append(new_dataset) datasets_test.append(new_dataset)
print_time(" Done") print_time(" Done")
datasets_test_hvar = [] """
for fpath in files['test_hvar']: for grp in ['test_lvar','test_hvar','test_lvar1','test_hvar1']:
print_time("Importing test data (high variance) from "+fpath, end="") if grp in files:
for fpath in files[grp]:
print_time("Importing test data ("+grp+") from "+fpath, end="")
new_dataset = readTFRewcordsEpoch(fpath, cluster_radius) new_dataset = readTFRewcordsEpoch(fpath, cluster_radius)
datasets_test_hvar.append(new_dataset) datasets_test.append(new_dataset)
print_time(" Done") print_time(" Done")
"""
datasets_train_lvar & datasets_train_hvar ( that will increase batch size and placeholders twice
test has to have even original, batches will not zip - just use two batches for one big one
""" """
datasets_test = []
for dataset_test_lvar in datasets_test_lvar:
datasets_test.append(dataset_test_lvar)
for dataset_test_hvar in datasets_test_hvar:
datasets_test.append(dataset_test_hvar)
return train_next, dataset_train_merged, datasets_test return train_next, dataset_train_merged, datasets_test
def get_full_tile_indices2d(height,width):
a = np.empty([height,width,2], dtype=np.int32)
a[...,0] = np.arange(height).reshape([height,1])
a[...,1] = np.arange(width)
return a.reshape(-1,2)
def get_full_tile_indices(height,width):
return np.arange(height*width).reshape(-1,1)
def readImageData(image_data, def readImageData(image_data,
files, files,
indx, indx,
...@@ -348,12 +412,26 @@ def readImageData(image_data, ...@@ -348,12 +412,26 @@ def readImageData(image_data,
tile_layers, tile_layers,
tile_side, tile_side,
width, width,
replace_nans): replace_nans,
infer = False,
keep_gt = False):
cl,tl,_ = get_lengths(0, tile_layers, tile_side) cl,tl,_ = get_lengths(0, tile_layers, tile_side)
if image_data[indx] is None: if image_data[indx] is None:
dataset = readTFRewcordsEpoch(files['images'][indx], cluster_radius = 0) dataset = readTFRewcordsEpoch(files['images'][indx], cluster_radius = 0)
corr2d = dataset[:,:cl] corr2d = dataset[:,:cl]
target_disparity = dataset[:,cl:cl+tl] target_disparity = dataset[:,cl:cl+tl]
if infer:
image_data[indx] = {
'corr2d': corr2d,
'target_disparity': target_disparity,
'xy':get_full_tile_indices2d(corr2d.shape[0]//width, width),
'ntile':get_full_tile_indices(corr2d.shape[0]//width, width)}
if keep_gt:
gt_ds = dataset[:,cl+tl:]
image_data[indx]["gt_ds"] = gt_ds
image_data[indx]["gtruths"]= gt_ds.copy()
image_data[indx]["t_disps"]= target_disparity.reshape([-1,1]).copy()
else:
gt_ds = dataset[:,cl+tl:] gt_ds = dataset[:,cl+tl:]
image_data[indx] = { image_data[indx] = {
'corr2d': corr2d, 'corr2d': corr2d,
...@@ -361,6 +439,7 @@ def readImageData(image_data, ...@@ -361,6 +439,7 @@ def readImageData(image_data,
"gt_ds": gt_ds, "gt_ds": gt_ds,
"gtruths": gt_ds.copy(), "gtruths": gt_ds.copy(),
"t_disps": target_disparity.reshape([-1,1]).copy()} "t_disps": target_disparity.reshape([-1,1]).copy()}
if cluster_radius > 0:
extend_img_to_clusters( extend_img_to_clusters(
[image_data[indx]], [image_data[indx]],
cluster_radius, cluster_radius,
...@@ -376,7 +455,10 @@ def initImageData(files, ...@@ -376,7 +455,10 @@ def initImageData(files,
tile_layers, tile_layers,
tile_side, tile_side,
width, width,
replace_nans): replace_nans,
infer = False,
keep_gt = False):
# no_train = False):
num_imgs = len(files['images']) num_imgs = len(files['images'])
img_data = [None] * num_imgs img_data = [None] * num_imgs
for nfile in range(min(num_imgs, max_imgs)): for nfile in range(min(num_imgs, max_imgs)):
...@@ -388,15 +470,21 @@ def initImageData(files, ...@@ -388,15 +470,21 @@ def initImageData(files,
tile_layers, tile_layers,
tile_side, tile_side,
width, width,
replace_nans) replace_nans,
infer = infer,
keep_gt = keep_gt)
print_time(" Done") print_time(" Done")
return img_data return img_data
def evaluateAllResults(result_files, absolute_disparity, cluster_radius, labels=None): def evaluateAllResults(result_files, absolute_disparity, cluster_radius, labels=None, logpath=None):
if logpath:
lf=open(logpath,"w")
else:
lf = None
for result_file in result_files: for result_file in result_files:
try: try:
print_time("Reading resuts from "+result_file, end=" ") print_time("Reading resuts from "+result_file, end=" ")
eval_results(result_file, absolute_disparity, radius=cluster_radius) eval_results(result_file, absolute_disparity, radius=cluster_radius, logfile=lf)
except: except:
print_time(" - does not exist") print_time(" - does not exist")
continue continue
...@@ -404,7 +492,8 @@ def evaluateAllResults(result_files, absolute_disparity, cluster_radius, labels= ...@@ -404,7 +492,8 @@ def evaluateAllResults(result_files, absolute_disparity, cluster_radius, labels=
print_time("Saving resuts to tiff", end=" ") print_time("Saving resuts to tiff", end=" ")
result_npy_to_tiff(result_file, absolute_disparity, fix_nan = True, labels=labels) result_npy_to_tiff(result_file, absolute_disparity, fix_nan = True, labels=labels)
print_time("Done") print_time("Done")
if lf:
lf.close()
def result_npy_prepare(npy_path, absolute, fix_nan, insert_deltas=True,labels=None): def result_npy_prepare(npy_path, absolute, fix_nan, insert_deltas=True,labels=None):
...@@ -417,7 +506,7 @@ def result_npy_prepare(npy_path, absolute, fix_nan, insert_deltas=True,labels=No ...@@ -417,7 +506,7 @@ def result_npy_prepare(npy_path, absolute, fix_nan, insert_deltas=True,labels=No
""" """
data = np.load(npy_path) #(324,242,4) [nn_disp, target_disp,gt_disp, gt_conf] data = np.load(npy_path) #(324,242,4) [nn_disp, target_disp,gt_disp, gt_conf]
if labels is None: if labels is None:
labels = ["chn%d"%(i) for i in range(data.shape[0])] labels = ["chn%d"%(i) for i in range(data.shape[2])]
# labels = ["nn_out","hier_out","gt_disparity","gt_strength"] # labels = ["nn_out","hier_out","gt_disparity","gt_strength"]
nn_out = 0 nn_out = 0
# target_disparity = 1 # target_disparity = 1
...@@ -430,11 +519,12 @@ def result_npy_prepare(npy_path, absolute, fix_nan, insert_deltas=True,labels=No ...@@ -430,11 +519,12 @@ def result_npy_prepare(npy_path, absolute, fix_nan, insert_deltas=True,labels=No
data[...,nn_out] += data[...,1] data[...,nn_out] += data[...,1]
if insert_deltas: if insert_deltas:
np.nan_to_num(data[...,gt_strength], copy=False) np.nan_to_num(data[...,gt_strength], copy=False)
data = np.concatenate([data[...,0:4],data[...,0:2],data[...,0:2],data[...,4:]], axis = 2) data = np.concatenate([data[...,0:4],data[...,0:2],data[...,0:2],data[...,4:]], axis = 2) # data[...,4:] may be empty
labels = labels[:4]+["nn_out","hier_out","nn_err","hier_err"]+labels[4:] labels = labels[:4]+["nn_out","hier_out","nn_err","hier_err"]+labels[4:]
data[...,6] -= data[...,gt_disparity] data[...,6] -= data[...,gt_disparity]
data[...,7] -= data[...,gt_disparity] data[...,7] -= data[...,gt_disparity]
for l in [2, 4, 5, 6, 7]: for l in [2, 4, 5, 6, 7]:
if l < data.shape[2]:
data[...,l] = np.select([data[...,gt_strength]==0.0, data[...,gt_strength]>0.0], [np.nan,data[...,l]]) data[...,l] = np.select([data[...,gt_strength]==0.0, data[...,gt_strength]>0.0], [np.nan,data[...,l]])
# All other layers - mast too # All other layers - mast too
for l in range(8,data.shape[2]): for l in range(8,data.shape[2]):
...@@ -445,7 +535,8 @@ def result_npy_to_tiff(npy_path, ...@@ -445,7 +535,8 @@ def result_npy_to_tiff(npy_path,
absolute, absolute,
fix_nan, fix_nan,
insert_deltas=True, insert_deltas=True,
labels = None): labels = None,
logfile = None):
""" """
@param npy_path full path to the npy file with 4-layer data (242,324,4) - nn_disparity(offset), target_disparity, gt disparity, gt strength @param npy_path full path to the npy file with 4-layer data (242,324,4) - nn_disparity(offset), target_disparity, gt disparity, gt strength
...@@ -458,6 +549,9 @@ def result_npy_to_tiff(npy_path, ...@@ -458,6 +549,9 @@ def result_npy_to_tiff(npy_path,
data = data.transpose(2,0,1) data = data.transpose(2,0,1)
print("Saving results to TIFF: "+tiff_path) print("Saving results to TIFF: "+tiff_path)
if (logfile):
print("Saving results to TIFF: "+tiff_path,file=logfile)
imagej_tiffwriter.save(tiff_path,data,labels=labels) imagej_tiffwriter.save(tiff_path,data,labels=labels)
def eval_results(rslt_path, absolute, def eval_results(rslt_path, absolute,
...@@ -466,7 +560,8 @@ def eval_results(rslt_path, absolute, ...@@ -466,7 +560,8 @@ def eval_results(rslt_path, absolute,
max_ofst_target = 1.0, max_ofst_target = 1.0,
max_ofst_result = 1.0, max_ofst_result = 1.0,
str_pow = 2.0, str_pow = 2.0,
radius = 0): radius = 0,
logfile = None):
variants = [[ -0.1, 5.0, 0.5, 0.5, 1.0], variants = [[ -0.1, 5.0, 0.5, 0.5, 1.0],
[ -0.1, 5.0, 0.5, 0.5, 2.0], [ -0.1, 5.0, 0.5, 0.5, 2.0],
[ -0.1, 5.0, 0.2, 0.2, 1.0], [ -0.1, 5.0, 0.2, 0.2, 1.0],
...@@ -498,6 +593,10 @@ def eval_results(rslt_path, absolute, ...@@ -498,6 +593,10 @@ def eval_results(rslt_path, absolute,
gt_disparity = np.nan_to_num(rslt[...,2], copy = False) gt_disparity = np.nan_to_num(rslt[...,2], copy = False)
gt_strength = np.nan_to_num(rslt[...,3], copy = False) gt_strength = np.nan_to_num(rslt[...,3], copy = False)
rslt = [] rslt = []
print ("--------------- %s ---------------"%(rslt_path))
if logfile:
print ("--------------- %s ---------------"%(rslt_path), file=logfile)
for min_disparity, max_disparity, max_offset_target, max_offset_result, strength_pow in variants: for min_disparity, max_disparity, max_offset_target, max_offset_result, strength_pow in variants:
good_tiles = not_nan.copy(); good_tiles = not_nan.copy();
good_tiles &= (gt_disparity >= min_disparity) good_tiles &= (gt_disparity >= min_disparity)
...@@ -516,6 +615,10 @@ def eval_results(rslt_path, absolute, ...@@ -516,6 +615,10 @@ def eval_results(rslt_path, absolute,
rms1 = np.sqrt(diff1_2w.sum()/sw) rms1 = np.sqrt(diff1_2w.sum()/sw)
print ("%7.3f<disp<%7.3f, offs_tgt<%5.2f, offs_rslt<%5.2f pwr=%05.3f, rms0=%7.4f, rms1=%7.4f (gain=%7.4f) num good tiles = %5d"%( print ("%7.3f<disp<%7.3f, offs_tgt<%5.2f, offs_rslt<%5.2f pwr=%05.3f, rms0=%7.4f, rms1=%7.4f (gain=%7.4f) num good tiles = %5d"%(
min_disparity, max_disparity, max_offset_target, max_offset_result, strength_pow, rms0, rms1, rms0/rms1, good_tiles.sum() )) min_disparity, max_disparity, max_offset_target, max_offset_result, strength_pow, rms0, rms1, rms0/rms1, good_tiles.sum() ))
if logfile:
print ("%7.3f<disp<%7.3f, offs_tgt<%5.2f, offs_rslt<%5.2f pwr=%05.3f, rms0=%7.4f, rms1=%7.4f (gain=%7.4f) num good tiles = %5d"%(
min_disparity, max_disparity, max_offset_target, max_offset_result, strength_pow, rms0, rms1, rms0/rms1, good_tiles.sum() ),file=logfile)
rslt.append([rms0,rms1]) rslt.append([rms0,rms1])
return rslt return rslt
......
...@@ -8,6 +8,21 @@ __email__ = "andrey@elphel.com" ...@@ -8,6 +8,21 @@ __email__ = "andrey@elphel.com"
import tensorflow as tf import tensorflow as tf
import tensorflow.contrib.slim as slim import tensorflow.contrib.slim as slim
NN_LAYOUTS = {0:[0, 0, 0, 32, 20, 16],
1:[0, 0, 0, 256, 128, 64],
2:[0, 128, 32, 32, 32, 16],
3:[0, 0, 40, 32, 20, 16],
4:[0, 0, 0, 0, 16, 16],
5:[0, 0, 64, 32, 32, 16],
6:[0, 0, 32, 16, 16, 16],
7:[0, 0, 64, 16, 16, 16],
8:[0, 0, 0, 64, 20, 16],
9:[0, 0, 256, 64, 32, 16],
10:[0, 256, 128, 64, 32, 16],
11:[0, 0, 0, 0, 64, 32],
12:[0, 0, 256, 128, 64, 32],
13:[0, 0, 0, 256, 128, 32],
}
def lrelu(x): def lrelu(x):
return tf.maximum(x*0.2,x) return tf.maximum(x*0.2,x)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment