00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 import numpy as np
00018 import matplotlib.pylab as plt
00019 import matplotlib
00020 matplotlib.rcParams['ps.useafm'] = True
00021 matplotlib.rcParams['pdf.use14corefonts'] = True
00022 matplotlib.rcParams['text.usetex'] = True
00023
00024 import sys
00025 import os
00026 import os.path
00027
00028 import re
00029 import shutil
00030
00031
00032
00033 fscore_beta = 0.5
00034
00035 full_pattern = '(segment_ext_d_and_c_rb)(([0-9]+))'
00036 wo_st_pattern= '(segment_no_st_ext_d_and_c_rb)(([0-9]+))'
00037
00038
00039 wo_st_template = 'segment_no_st_ext_d_and_c_rb%d.txt'
00040
00041 variant2labelAndStyle = {
00042
00043 full_pattern: ({'label': "Full", 'lw': 3.0, 'ls': "-", 'color': 'k'}, 0),
00044 wo_st_pattern: ({'label': "Full w/o Shape Tracking", 'lw': 3.0, 'ls': "--", 'color': 'k', 'alpha': 0.5}, 1),
00045 '(segment_naive_depth_rb)([0-9]+)': ({'label': 'Shape-based (depth only)', 'lw': 1.0, 'ls': "--", 'color': 'b'}, 4),
00046 '(segment_naive_color_rb)([0-9]+)': ({'label': 'Shape-based (color only)', 'lw': 1.0, 'ls': "--", 'color': 'r'}, 5),
00047 '(segment_depth_rb)([0-9]+)': ({'label': 'Motion (depth only)', 'lw': 1.5, 'ls': "-", 'color': 'b'}, 2),
00048 '(segment_color_rb)([0-9]+)': ({'label': 'Motion (color only)', 'lw': 1.5, 'ls': "-", 'color': 'r'}, 3),
00049 '(ochs)': ({'label': 'Ochs et al.', 'lw': 3.0, 'ls': ":", 'color': 'g'}, 6),
00050
00051
00052 }
00053
00054 folderElems2Title = {
00055 ('box'): 'Box',
00056 ('globe'): 'Globe',
00057 ('metalcase'): '2 Bodies: Metal case',
00058 ('statue'): '2 Bodies: Statue',
00059 ('head1'): 'Head',
00060 ('robotDrawer'): 'Drawer',
00061 ('redthing'): 'Red shape',
00062 ('ks_drawer_full_gt_drawer'): 'Cabinet: Drawer',
00063 ('ks_drawer_full_gt_base'): 'Cabinet: Frame',
00064 ('ks_laptop_full_gt_lid'): 'Laptop: Lid',
00065 ('ks_laptop_full_gt_base'): 'Laptop: Base',
00066 }
00067
00068 folderElems2Order = [
00069 ('robotDrawer'),
00070 ('box'),
00071 ('globe'),
00072 ('head1'),
00073 ('metalcase'),
00074 ('statue'),
00075 ('redthing'),
00076 ('ks_drawer_full_gt_base'),
00077 ('ks_drawer_full_gt_drawer'),
00078 ('ks_laptop_full_gt_base'),
00079 ('ks_laptop_full_gt_lid'),
00080 ]
00081
00082
00083 def compare_statistics(folder, show_fscore=True, multiple_figures=True):
00084 stats_map = collect_stats(folder)
00085
00086 no_exp = len(stats_map)
00087
00088 figures = []
00089 if multiple_figures:
00090 for i in range(3*no_exp):
00091 figures.append(plt.figure(figsize=(2,2)))
00092 else:
00093
00094 fig = plt.figure(figsize=(10,3*no_exp))
00095 figures.append(fig)
00096
00097
00098
00099 stats_map_sorted = []
00100 for i, name in enumerate(folderElems2Order):
00101 for k,v in stats_map.items():
00102 if name in k:
00103 stats_map_sorted.append ( (k,v) )
00104 break
00105 print [ k for k,v in stats_map_sorted ]
00106
00107
00108
00109 cols = 2
00110 if show_fscore:
00111 cols = 3
00112
00113
00114 figure_names = []
00115 figure_rel_idx = []
00116 for i, (exp_name, variant_stats) in enumerate( stats_map_sorted ):
00117 if multiple_figures:
00118 fig = figures[cols*i]
00119 ax_prec = figures[cols*i].add_subplot(1,1,1)
00120 ax_rec = figures[cols*i+1].add_subplot(1,1,1)
00121 ax_fscore = None
00122 if show_fscore:
00123 ax_fscore = figures[cols*i+2].add_subplot(1,1,1)
00124 else:
00125 ax_prec = plt.subplot(no_exp, cols, cols*i+1)
00126 ax_rec = plt.subplot(no_exp, cols, cols*i+2)
00127 ax_fscore = None
00128 if show_fscore:
00129 ax_fscore = plt.subplot(no_exp, cols, cols*i+3)
00130
00131 plot_legend = i==0 and not multiple_figures
00132 plot_exp_name = not multiple_figures
00133 plot_stats_for_exp(exp_name, variant_stats, fig, ax_prec, ax_rec, ax_fscore, plot_legend, plot_exp_name)
00134
00135 for c in range(cols):
00136 figure_names.append(exp_name)
00137 figure_rel_idx.append(c)
00138
00139 if i == 0:
00140 ax_prec.set_title("\\textrm{Precision}")
00141 ax_rec.set_title("\\textrm{Recall}")
00142 if show_fscore:
00143 ax_fscore.set_title("\\textrm{F$_{%.1f}$ score}" % fscore_beta)
00144
00145 if i == len(stats_map_sorted)-1:
00146 time_label = "\\textrm{time (sec)}"
00147 ax_prec.set_xlabel(time_label)
00148 ax_rec.set_xlabel(time_label)
00149 if show_fscore:
00150 ax_fscore.set_xlabel(time_label)
00151
00152 for i, (fig, fig_idx) in enumerate(zip(figures, figure_rel_idx)):
00153 if multiple_figures:
00154 img_path = os.path.join(folder, "compare_results_%s_%d.pdf" % (figure_names[i], fig_idx))
00155 else:
00156 img_path = os.path.join(folder, "compare_results.pdf")
00157 print ("Saving image at %s" % img_path)
00158 fig.savefig(img_path, bbox_inches="tight")
00159
00160 def collect_stats(folder):
00161 stats_map = {}
00162
00163 for f in os.listdir(folder):
00164 fld = os.path.join(folder, f)
00165 real_fld = os.path.realpath(fld)
00166 print real_fld
00167 if not os.path.isdir(real_fld):
00168
00169 continue
00170
00171 stats_map[f] = collect_stats_for_exp(real_fld)
00172 return stats_map
00173
00174 def collect_stats_for_exp(folder):
00175
00176 variant_map = {}
00177
00178 for f in os.listdir(folder):
00179 if f[-3:] != "txt":
00180 continue
00181 filename = os.path.join(folder, f)
00182
00183 data = np.genfromtxt(filename, dtype=float, delimiter=' ', names=True)
00184
00185 precision = data['tp'] / (data['tp']+data['fp'])
00186 recall = data['tp'] / (data['tp']+data['fn'])
00187 seg_acc = data['tp'] / (data['tp']+data['fp']+data['fn'])
00188
00189 beta = fscore_beta
00190 fscore = (1+beta**2)* (precision*recall) / (beta**2 * precision + recall)
00191 time = data['time'] - data['time'][0]
00192
00193 freq = np.mean(data['time'][1:] - data['time'][:-1])
00194
00195
00196
00197
00198 precision = np.hstack( [ [0.], precision ] )
00199 recall = np.hstack( [ [0.], recall ] )
00200 fscore = np.hstack( [ [0.], fscore ] )
00201 time = np.hstack( [ time, [time[-1] + freq] ] )
00202
00203
00204
00205 precision[np.where(np.isnan(precision))] = 0.
00206 recall[np.where(np.isnan(recall))] = 0.
00207 seg_acc[np.where(np.isnan(seg_acc))] = 0.
00208 fscore[np.where(np.isnan(fscore))] = 0.
00209
00210 filetitle = f.split(".")[-2]
00211
00212 variant_map[filetitle] = {}
00213 variant_map[filetitle]['precision'] = precision
00214 variant_map[filetitle]['recall'] = recall
00215 variant_map[filetitle]['seg_acc'] = seg_acc
00216 variant_map[filetitle]['fscore'] = fscore
00217 variant_map[filetitle]['time'] = time
00218
00219
00220 return variant_map
00221
00222 def plot_stats_for_exp(exp_name, variant_stats, fig, ax_prec, ax_rec, ax_fscore=None, plot_legend=True, plot_exp_name=True):
00223
00224 print exp_name
00225
00226 processed_variants = []
00227
00228 lines = []
00229 labels = []
00230 order = []
00231
00232 for variant, stats in variant_stats.items():
00233 dct = None
00234 print " "+variant
00235
00236 try:
00237 for var_re, (dct_, order_) in variant2labelAndStyle.items():
00238 res = re.match(var_re, variant)
00239 if res is not None:
00240 print res.group(1)
00241 if res.group(1) in processed_variants:
00242 print "ERROR: More than one rigid body ground truth found - currently not supported. Delete the _rb* files that do not correspond to the ground truth and re-run"
00243 print " experiment: %s" % exp_name
00244 print " variant: %s" % variant
00245 raise Exception()
00246 dct = dct_
00247 processed_variants.append (res.group(1) )
00248 order.append(order_)
00249 except Exception, e:
00250
00251 pass
00252
00253 if dct is None:
00254 print " WARN: Variant unsupported %s " % variant
00255 continue
00256
00257 for y in np.arange(0.0, 1.1, 0.2):
00258 for ax in [ax_prec, ax_rec, ax_fscore]:
00259 if ax_fscore is None:
00260 continue
00261 ax.plot(stats['time'], [y] * len(stats['time']), "-.", lw=0.3, color="black", alpha=0.1)
00262
00263
00264 l1 = ax_prec.plot(stats['time'], stats['precision'], **dct)
00265 ax_rec.plot(stats['time'], stats['recall'], **dct)
00266
00267 if ax_fscore is not None:
00268 ax_fscore.plot(stats['time'], stats['fscore'], **dct)
00269
00270
00271 lines.extend(l1)
00272 labels.append( "\\textrm{%s}" % dct['label'])
00273
00274 if plot_exp_name:
00275 ax_prec.set_ylabel(exp_name[:15])
00276 for elem, title in folderElems2Title.items():
00277 if elem in exp_name:
00278 ax_prec.set_ylabel(title)
00279
00280 for ax in [ax_prec, ax_rec, ax_fscore]:
00281 if ax is None:
00282 continue
00283 ax.set_xlim(0, stats['time'][-1])
00284 ax.set_ylim(-0.1, 1.1)
00285
00286
00287
00288 if plot_legend:
00289 lines_sorted, labels_sorted, ordered = zip (* sorted( zip(lines, labels, order), key=lambda x: x[2]) )
00290
00291
00292
00293 fig.legend(lines_sorted, labels_sorted, 'lower center', ncol=4,prop={'size':12})
00294
00295
00296 def cherry_pick_full_wo_shape_tracker(wo_src, with_dst):
00297 print "Cherry-picking FULL result from %s" % wo_src
00298
00299 exp2res = {}
00300
00301
00302 for d in os.listdir(wo_src):
00303 exp_dir = os.path.join(wo_src, d)
00304 if not os.path.isdir(exp_dir):
00305 continue
00306 for f in os.listdir(exp_dir):
00307 res = re.match(full_pattern, f)
00308 if res is not None:
00309 exp_name = None
00310 for elem, _ in folderElems2Title.items():
00311 if elem in d:
00312 exp_name = elem
00313 if exp_name is None:
00314 print "WARNING: source experiment unknown: %s" % d
00315 else:
00316 exp2res[exp_name] = (os.path.join(exp_dir, f), res.group(2))
00317
00318
00319
00320
00321 for d in os.listdir(with_dst):
00322 exp_dir = os.path.join(with_dst, d)
00323 if not os.path.isdir(exp_dir):
00324 continue
00325
00326 for elem, _ in folderElems2Title.items():
00327 if elem in d:
00328 exp_name = elem
00329 if exp_name is None:
00330 print "WARNING: destination experiment unknown: %s" % d
00331 continue
00332
00333 if exp_name not in exp2res:
00334 print "ERROR: source %s does not contain experiment %s" % (with_dst, d)
00335 continue
00336
00337 fres, fres_rb = exp2res[exp_name]
00338 fdes = os.path.join(exp_dir, wo_st_template % int(fres_rb))
00339 print " Copying %s to %s" % (fres, fdes)
00340
00341 if os.path.exists(fdes):
00342 try:
00343 os.remove(fdes)
00344 except:
00345 print "Cannot move %s because file exists and cannot be deleted" % fdes
00346 continue
00347
00348 try:
00349 shutil.copyfile(fres, fdes)
00350 except Exception, e:
00351 print e
00352 print "Unknown error copying file %s" % fres
00353 continue
00354
00355
00356
00357 if __name__ == "__main__":
00358 if len(sys.argv) < 2:
00359 print "Usage: compare_statistics.py <experiment meta folder [contains ONLY folders that include statistics text files (and result bags)]> [<experiment meta folder w/o shape tracking]"
00360 sys.exit()
00361
00362 if len(sys.argv) > 2:
00363 wst_folder = sys.argv[2]
00364 cherry_pick_full_wo_shape_tracker(sys.argv[2], sys.argv[1])
00365
00366 print ("Starting compare statistics")
00367 multiple_figures=True
00368 compare_statistics(sys.argv[1],multiple_figures=multiple_figures)
00369
00370 if not multiple_figures:
00371 plt.show()
00372