10
10
from torch .autograd import Variable
11
11
from geotnf .point_tnf import PointTnf , PointsToUnitCoords , PointsToPixelCoords
12
12
from util .py_util import create_file_path
13
+ from model .loss import WeakInlierCount , TwoStageWeakInlierCount
13
14
14
- def theta_to_sampling_grid (out_h ,out_w ,theta_aff = None ,theta_tps = None ,theta_aff_tps = None ,use_cuda = True ,tps_reg_factor = 0 ):
15
- affTnf = GeometricTnf (out_h = out_h ,out_w = out_w ,geometric_model = 'affine' ,use_cuda = use_cuda )
16
- tpsTnf = GeometricTnf (out_h = out_h ,out_w = out_w ,geometric_model = 'tps' ,use_cuda = use_cuda ,tps_reg_factor = tps_reg_factor )
17
-
18
- if theta_aff is not None :
19
- sampling_grid_aff = affTnf (image_batch = None ,
20
- theta_batch = theta_aff .view (1 ,2 ,3 ),
21
- return_sampling_grid = True ,
22
- return_warped_image = False )
23
- else :
24
- sampling_grid_aff = None
25
-
26
- if theta_tps is not None :
27
- sampling_grid_tps = tpsTnf (image_batch = None ,
28
- theta_batch = theta_tps .view (1 ,- 1 ),
29
- return_sampling_grid = True ,
30
- return_warped_image = False )
31
- else :
32
- sampling_grid_tps = None
33
-
34
- if theta_aff is not None and theta_aff_tps is not None :
35
- sampling_grid_aff_tps = tpsTnf (image_batch = None ,
36
- theta_batch = theta_aff_tps .view (1 ,- 1 ),
37
- return_sampling_grid = True ,
38
- return_warped_image = False )
39
-
40
- # put 1e10 value in region out of bounds of sampling_grid_aff
41
- sampling_grid_aff = sampling_grid_aff .clone ()
42
- in_bound_mask_aff = Variable ((sampling_grid_aff .data [:,:,:,0 ]> - 1 ) & (sampling_grid_aff .data [:,:,:,0 ]< 1 ) & (sampling_grid_aff .data [:,:,:,1 ]> - 1 ) & (sampling_grid_aff .data [:,:,:,1 ]< 1 )).unsqueeze (3 )
43
- in_bound_mask_aff = in_bound_mask_aff .expand_as (sampling_grid_aff )
44
- sampling_grid_aff = torch .add ((in_bound_mask_aff .float ()- 1 )* (1e10 ),torch .mul (in_bound_mask_aff .float (),sampling_grid_aff ))
45
- # put 1e10 value in region out of bounds of sampling_grid_aff_tps_comp
46
- sampling_grid_aff_tps_comp = F .grid_sample (sampling_grid_aff .transpose (2 ,3 ).transpose (1 ,2 ), sampling_grid_aff_tps ).transpose (1 ,2 ).transpose (2 ,3 )
47
- in_bound_mask_aff_tps = Variable ((sampling_grid_aff_tps .data [:,:,:,0 ]> - 1 ) & (sampling_grid_aff_tps .data [:,:,:,0 ]< 1 ) & (sampling_grid_aff_tps .data [:,:,:,1 ]> - 1 ) & (sampling_grid_aff_tps .data [:,:,:,1 ]< 1 )).unsqueeze (3 )
48
- in_bound_mask_aff_tps = in_bound_mask_aff_tps .expand_as (sampling_grid_aff_tps_comp )
49
- sampling_grid_aff_tps_comp = torch .add ((in_bound_mask_aff_tps .float ()- 1 )* (1e10 ),torch .mul (in_bound_mask_aff_tps .float (),sampling_grid_aff_tps_comp ))
50
- else :
51
- sampling_grid_aff_tps_comp = None
52
-
53
- return (sampling_grid_aff ,sampling_grid_tps ,sampling_grid_aff_tps_comp )
54
15
55
16
def compute_metric (metric ,model ,dataset ,dataloader ,batch_tnf ,batch_size ,two_stage = True ,do_aff = False ,do_tps = False ,args = None ):
56
17
# Initialize stats
@@ -81,6 +42,10 @@ def compute_metric(metric,model,dataset,dataloader,batch_tnf,batch_size,two_stag
81
42
elif metric == 'flow' :
82
43
metrics = ['flow' ]
83
44
metric_fun = flow_metrics
45
+ elif metric == 'inlier_count' :
46
+ metrics = ['inlier_count' ]
47
+ metric_fun = inlier_count
48
+ model .return_correlation = True
84
49
# initialize vector for storing results for each metric
85
50
for key in stats .keys ():
86
51
for metric in metrics :
@@ -104,36 +69,43 @@ def compute_metric(metric,model,dataset,dataloader,batch_tnf,batch_size,two_stag
104
69
theta_aff ,theta_aff_tps ,corr_aff ,corr_aff_tps = model (batch )
105
70
elif do_aff :
106
71
theta_aff = model (batch )
72
+ if isinstance (theta_aff ,tuple ):
73
+ theta_aff = theta_aff [0 ]
107
74
elif do_tps :
108
75
theta_tps = model (batch )
109
-
110
- if metric_fun is not None :
76
+ if isinstance (theta_tps ,tuple ):
77
+ theta_tps = theta_tps [0 ]
78
+
79
+ if metric == 'inlier_count' :
80
+ stats = inlier_count (batch ,batch_start_idx ,theta_aff ,theta_tps ,theta_aff_tps ,corr_aff ,corr_aff_tps ,stats ,args )
81
+ elif metric_fun is not None :
111
82
stats = metric_fun (batch ,batch_start_idx ,theta_aff ,theta_tps ,theta_aff_tps ,stats ,args )
112
83
113
84
print ('Batch: [{}/{} ({:.0f}%)]' .format (i , len (dataloader ), 100. * i / len (dataloader )))
114
85
86
+ # Print results
87
+ if metric == 'flow' :
88
+ print ('Flow files have been saved to ' + args .flow_output_dir )
89
+ return stats
90
+
115
91
for key in stats .keys ():
116
92
print ('=== Results ' + key + ' ===' )
117
93
for metric in metrics :
94
+ # print per-class brakedown for PFPascal, or caltech
95
+ if isinstance (dataset ,PFPascalDataset ):
96
+ N_cat = int (np .max (dataset .category ))
97
+ for c in range (N_cat ):
98
+ cat_idx = np .nonzero (dataset .category == c + 1 )[0 ]
99
+ print (dataset .category_names [c ].ljust (15 )+ ': ' ,'{:.2%}' .format (np .mean (stats [key ][metric ][cat_idx ])))
100
+
101
+ # print mean value
118
102
results = stats [key ][metric ]
119
103
good_idx = np .flatnonzero ((results != - 1 ) * ~ np .isnan (results ))
120
104
print ('Total: ' + str (results .size ))
121
105
print ('Valid: ' + str (good_idx .size ))
122
- # import pdb; pdb.set_trace()
123
106
filtered_results = results [good_idx ]
124
107
print (metric + ':' ,'{:.2%}' .format (np .mean (filtered_results )))
125
- if isinstance (dataset ,CaltechDataset ) and key == 'aff_tps' and metric == 'intersection_over_union' :
126
- N_cat = int (np .max (dataset .category ))
127
- for c in range (N_cat ):
128
- cat_idx = np .nonzero (dataset .category == c + 1 )[0 ]
129
- print (dataset .category_names [c ].ljust (15 )+ ': ' ,'{:.2%}' .format (np .mean (stats [key ][metric ][cat_idx ])))
130
-
131
- if isinstance (dataset ,PFPascalDataset ):
132
- N_cat = int (np .max (dataset .category ))
133
- for c in range (N_cat ):
134
- cat_idx = np .nonzero (dataset .category == c + 1 )[0 ]
135
- print (dataset .category_names [c ].ljust (15 )+ ': ' ,'{:.2%}' .format (np .mean (stats [key ][metric ][cat_idx ])))
136
-
108
+
137
109
print ('\n ' )
138
110
139
111
return stats
@@ -224,6 +196,17 @@ def point_dist_metric(batch,batch_start_idx,theta_aff,theta_tps,theta_aff_tps,st
224
196
225
197
return stats
226
198
199
+ def inlier_count (batch ,batch_start_idx ,theta_aff ,theta_tps ,theta_aff_tps ,corr_aff ,corr_aff_tps ,stats ,args ,use_cuda = True ):
200
+ inliersComposed = TwoStageWeakInlierCount (use_cuda = torch .cuda .is_available (),dilation_filter = 0 ,normalize_inlier_count = True )
201
+ inliers_comp = inliersComposed (matches = corr_aff ,theta_aff = theta_aff ,theta_aff_tps = theta_aff_tps )
202
+ current_batch_size = batch ['source_im_size' ].size (0 )
203
+ indices = range (batch_start_idx ,batch_start_idx + current_batch_size )
204
+
205
+ stats ['aff_tps' ]['inlier_count' ][indices ] = inliers_comp .unsqueeze (1 ).cpu ().data .numpy ()
206
+
207
+ return stats
208
+
209
+
227
210
def pck_metric (batch ,batch_start_idx ,theta_aff ,theta_tps ,theta_aff_tps ,stats ,args ,use_cuda = True ):
228
211
alpha = args .pck_alpha
229
212
do_aff = theta_aff is not None
@@ -264,7 +247,7 @@ def pck_metric(batch,batch_start_idx,theta_aff,theta_tps,theta_aff_tps,stats,arg
264
247
current_batch_size = batch ['source_im_size' ].size (0 )
265
248
indices = range (batch_start_idx ,batch_start_idx + current_batch_size )
266
249
267
- # import pdb; pdb.set_trace()
250
+ # import pdb; pdb.set_trace()
268
251
269
252
if do_aff :
270
253
pck_aff = pck (source_points .data , warped_points_aff .data , L_pck , alpha )
@@ -352,8 +335,7 @@ def pascal_parts_metrics(batch,batch_start_idx,theta_aff,theta_tps,theta_aff_tps
352
335
if do_aff_tps :
353
336
warped_mask_aff_tps = F .grid_sample (source_mask , grid_aff_tps )
354
337
stats ['aff_tps' ]['intersection_over_union' ][idx ] = intersection_over_union (warped_mask_aff_tps ,target_mask )
355
- # if idx==300:
356
- # import pdb; pdb.set_trace()
338
+
357
339
return stats
358
340
359
341
def area_metrics (batch ,batch_start_idx ,theta_aff ,theta_tps ,theta_aff_tps ,stats ,args ,use_cuda = True ):
@@ -362,6 +344,9 @@ def area_metrics(batch,batch_start_idx,theta_aff,theta_tps,theta_aff_tps,stats,a
362
344
do_aff_tps = theta_aff_tps is not None
363
345
364
346
batch_size = batch ['source_im_size' ].size (0 )
347
+
348
+ pt = PointTnf (use_cuda = use_cuda )
349
+
365
350
for b in range (batch_size ):
366
351
h_src = int (batch ['source_im_size' ][b ,0 ].data .cpu ().numpy ())
367
352
w_src = int (batch ['source_im_size' ][b ,1 ].data .cpu ().numpy ())
@@ -376,30 +361,43 @@ def area_metrics(batch,batch_start_idx,theta_aff,theta_tps,theta_aff_tps,stats,a
376
361
batch ['source_polygon' ][1 ][b ],
377
362
h_src ,w_src ,use_cuda = use_cuda )
378
363
379
- grid_aff ,grid_tps ,grid_aff_tps = theta_to_sampling_grid (h_tgt ,w_tgt ,
380
- theta_aff [b ,:] if do_aff else None ,
381
- theta_tps [b ,:] if do_tps else None ,
382
- theta_aff_tps [b ,:] if do_aff_tps else None ,
383
- use_cuda = use_cuda ,
384
- tps_reg_factor = args .tps_reg_factor )
385
-
364
+ grid_X ,grid_Y = np .meshgrid (np .linspace (- 1 ,1 ,w_tgt ),np .linspace (- 1 ,1 ,h_tgt ))
365
+ grid_X = torch .FloatTensor (grid_X ).unsqueeze (0 ).unsqueeze (3 )
366
+ grid_Y = torch .FloatTensor (grid_Y ).unsqueeze (0 ).unsqueeze (3 )
367
+ grid_X = Variable (grid_X ,requires_grad = False )
368
+ grid_Y = Variable (grid_Y ,requires_grad = False )
369
+
370
+ if use_cuda :
371
+ grid_X = grid_X .cuda ()
372
+ grid_Y = grid_Y .cuda ()
373
+
374
+ grid_X_vec = grid_X .view (1 ,1 ,- 1 )
375
+ grid_Y_vec = grid_Y .view (1 ,1 ,- 1 )
376
+
377
+ grid_XY_vec = torch .cat ((grid_X_vec ,grid_Y_vec ),1 )
378
+
379
+ def pointsToGrid (x ,h_tgt = h_tgt ,w_tgt = w_tgt ): return x .contiguous ().view (1 ,2 ,h_tgt ,w_tgt ).transpose (1 ,2 ).transpose (2 ,3 )
380
+
386
381
idx = batch_start_idx + b
387
382
388
383
if do_aff :
384
+ grid_aff = pointsToGrid (pt .affPointTnf (theta_aff [b ,:].unsqueeze (0 ),grid_XY_vec ))
389
385
warped_mask_aff = F .grid_sample (source_mask , grid_aff )
390
386
flow_aff = th_sampling_grid_to_np_flow (source_grid = grid_aff ,h_src = h_src ,w_src = w_src )
391
387
392
388
stats ['aff' ]['intersection_over_union' ][idx ] = intersection_over_union (warped_mask_aff ,target_mask )
393
389
stats ['aff' ]['label_transfer_accuracy' ][idx ] = label_transfer_accuracy (warped_mask_aff ,target_mask )
394
390
stats ['aff' ]['localization_error' ][idx ] = localization_error (source_mask_np , target_mask_np , flow_aff )
395
391
if do_tps :
392
+ grid_tps = pointsToGrid (pt .tpsPointTnf (theta_tps [b ,:].unsqueeze (0 ),grid_XY_vec ))
396
393
warped_mask_tps = F .grid_sample (source_mask , grid_tps )
397
394
flow_tps = th_sampling_grid_to_np_flow (source_grid = grid_tps ,h_src = h_src ,w_src = w_src )
398
395
399
396
stats ['tps' ]['intersection_over_union' ][idx ] = intersection_over_union (warped_mask_tps ,target_mask )
400
397
stats ['tps' ]['label_transfer_accuracy' ][idx ] = label_transfer_accuracy (warped_mask_tps ,target_mask )
401
398
stats ['tps' ]['localization_error' ][idx ] = localization_error (source_mask_np , target_mask_np , flow_tps )
402
399
if do_aff_tps :
400
+ grid_aff_tps = pointsToGrid (pt .affPointTnf (theta_aff [b ,:].unsqueeze (0 ),pt .tpsPointTnf (theta_aff_tps [b ,:].unsqueeze (0 ),grid_XY_vec )))
403
401
warped_mask_aff_tps = F .grid_sample (source_mask , grid_aff_tps )
404
402
flow_aff_tps = th_sampling_grid_to_np_flow (source_grid = grid_aff_tps ,h_src = h_src ,w_src = w_src )
405
403
@@ -416,6 +414,8 @@ def flow_metrics(batch,batch_start_idx,theta_aff,theta_tps,theta_aff_tps,stats,a
416
414
do_aff = theta_aff is not None
417
415
do_tps = theta_tps is not None
418
416
do_aff_tps = theta_aff_tps is not None
417
+
418
+ pt = PointTnf (use_cuda = use_cuda )
419
419
420
420
batch_size = batch ['source_im_size' ].size (0 )
421
421
for b in range (batch_size ):
@@ -424,28 +424,42 @@ def flow_metrics(batch,batch_start_idx,theta_aff,theta_tps,theta_aff_tps,stats,a
424
424
h_tgt = int (batch ['target_im_size' ][b ,0 ].data .cpu ().numpy ())
425
425
w_tgt = int (batch ['target_im_size' ][b ,1 ].data .cpu ().numpy ())
426
426
427
- grid_aff ,grid_tps ,grid_aff_tps = theta_to_sampling_grid (h_tgt ,w_tgt ,
428
- theta_aff [b ,:] if do_aff else None ,
429
- theta_tps [b ,:] if do_tps else None ,
430
- theta_aff_tps [b ,:] if do_aff_tps else None ,
431
- use_cuda = use_cuda ,
432
- tps_reg_factor = args .tps_reg_factor )
433
-
434
- if do_aff_tps :
435
- flow_aff_tps = th_sampling_grid_to_np_flow (source_grid = grid_aff_tps ,h_src = h_src ,w_src = w_src )
436
- flow_aff_tps_path = os .path .join (result_path ,'aff_tps' ,batch ['flow_path' ][b ])
437
- create_file_path (flow_aff_tps_path )
438
- write_flo_file (flow_aff_tps ,flow_aff_tps_path )
439
- elif do_aff :
427
+ grid_X ,grid_Y = np .meshgrid (np .linspace (- 1 ,1 ,w_tgt ),np .linspace (- 1 ,1 ,h_tgt ))
428
+ grid_X = torch .FloatTensor (grid_X ).unsqueeze (0 ).unsqueeze (3 )
429
+ grid_Y = torch .FloatTensor (grid_Y ).unsqueeze (0 ).unsqueeze (3 )
430
+ grid_X = Variable (grid_X ,requires_grad = False )
431
+ grid_Y = Variable (grid_Y ,requires_grad = False )
432
+ if use_cuda :
433
+ grid_X = grid_X .cuda ()
434
+ grid_Y = grid_Y .cuda ()
435
+
436
+ grid_X_vec = grid_X .view (1 ,1 ,- 1 )
437
+ grid_Y_vec = grid_Y .view (1 ,1 ,- 1 )
438
+
439
+ grid_XY_vec = torch .cat ((grid_X_vec ,grid_Y_vec ),1 )
440
+
441
+ def pointsToGrid (x ,h_tgt = h_tgt ,w_tgt = w_tgt ): return x .contiguous ().view (1 ,2 ,h_tgt ,w_tgt ).transpose (1 ,2 ).transpose (2 ,3 )
442
+
443
+ idx = batch_start_idx + b
444
+
445
+ if do_aff :
446
+ grid_aff = pointsToGrid (pt .affPointTnf (theta_aff [b ,:].unsqueeze (0 ),grid_XY_vec ))
440
447
flow_aff = th_sampling_grid_to_np_flow (source_grid = grid_aff ,h_src = h_src ,w_src = w_src )
441
448
flow_aff_path = os .path .join (result_path ,'aff' ,batch ['flow_path' ][b ])
442
449
create_file_path (flow_aff_path )
443
450
write_flo_file (flow_aff ,flow_aff_path )
444
- elif do_tps :
451
+ if do_tps :
452
+ grid_tps = pointsToGrid (pt .tpsPointTnf (theta_tps [b ,:].unsqueeze (0 ),grid_XY_vec ))
445
453
flow_tps = th_sampling_grid_to_np_flow (source_grid = grid_tps ,h_src = h_src ,w_src = w_src )
446
454
flow_tps_path = os .path .join (result_path ,'tps' ,batch ['flow_path' ][b ])
447
455
create_file_path (flow_tps_path )
448
456
write_flo_file (flow_tps ,flow_tps_path )
457
+ if do_aff_tps :
458
+ grid_aff_tps = pointsToGrid (pt .affPointTnf (theta_aff [b ,:].unsqueeze (0 ),pt .tpsPointTnf (theta_aff_tps [b ,:].unsqueeze (0 ),grid_XY_vec )))
459
+ flow_aff_tps = th_sampling_grid_to_np_flow (source_grid = grid_aff_tps ,h_src = h_src ,w_src = w_src )
460
+ flow_aff_tps_path = os .path .join (result_path ,'aff_tps' ,batch ['flow_path' ][b ])
461
+ create_file_path (flow_aff_tps_path )
462
+ write_flo_file (flow_aff_tps ,flow_aff_tps_path )
449
463
450
464
idx = batch_start_idx + b
451
465
return stats
0 commit comments