33#
44# This source code is licensed under the license found in the
55# LICENSE file in the root directory of this source tree.
6- #
6+ ##############################################################################
7+
8+ """Various network "heads" for dense human pose estimation in DensePose.
9+
10+ The design is as follows:
11+
12+ ... -> RoI ----\ /-> mask output -> cls loss
13+ -> RoIFeatureXform -> body UV head -> patch output -> cls loss
14+ ... -> Feature / \-> UV output -> reg loss
15+ Map
16+
17+ The body UV head produces a feature representation of the RoI for the purpose
18+ of dense semantic mask prediction, body surface patch prediction and body UV
19+ coordinates regression. The body UV output module converts the feature
20+ representation into heatmaps for dense mask, patch index and UV coordinates.
21+ """
722
823from __future__ import absolute_import
924from __future__ import division
1025from __future__ import print_function
1126from __future__ import unicode_literals
1227
1328from caffe2 .python import core
14-
1529from detectron .core .config import cfg
16-
30+ from detectron . utils . c2 import const_fill
1731import detectron .modeling .ResNet as ResNet
1832import detectron .utils .blob as blob_utils
1933
2034# ---------------------------------------------------------------------------- #
21- # Body UV heads
35+ # Body UV outputs and losses
2236# ---------------------------------------------------------------------------- #
2337
24- def add_body_uv_outputs (model , blob_in , dim , pref = '' ):
25- ####
26- model . ConvTranspose ( blob_in , 'AnnIndex_lowres' + pref , dim , 15 , cfg . BODY_UV_RCNN . DECONV_KERNEL , pad = int ( cfg . BODY_UV_RCNN . DECONV_KERNEL / 2 - 1 ), stride = 2 , weight_init = ( cfg . BODY_UV_RCNN . CONV_INIT , { 'std' : 0.001 }), bias_init = ( 'ConstantFill' , { 'value' : 0. }))
27- ####
28- model . ConvTranspose ( blob_in , 'Index_UV_lowres' + pref , dim , cfg . BODY_UV_RCNN . NUM_PATCHES + 1 , cfg . BODY_UV_RCNN . DECONV_KERNEL , pad = int ( cfg . BODY_UV_RCNN . DECONV_KERNEL / 2 - 1 ), stride = 2 , weight_init = ( cfg . BODY_UV_RCNN . CONV_INIT , { 'std' : 0.001 }), bias_init = ( 'ConstantFill' , { 'value' : 0. }))
29- ####
30- model . ConvTranspose (
31- blob_in , 'U_lowres' + pref , dim , ( cfg . BODY_UV_RCNN . NUM_PATCHES + 1 ),
32- cfg .BODY_UV_RCNN .DECONV_KERNEL ,
33- pad = int ( cfg . BODY_UV_RCNN . DECONV_KERNEL / 2 - 1 ),
34- stride = 2 ,
35- weight_init = ( cfg . BODY_UV_RCNN . CONV_INIT , { 'std' : 0.001 }),
36- bias_init = ( 'ConstantFill' , { 'value' : 0. }))
37- #####
38- model . ConvTranspose (
39- blob_in , 'V_lowres' + pref , dim , cfg . BODY_UV_RCNN . NUM_PATCHES + 1 ,
38+ def add_body_uv_outputs (model , blob_in , dim ):
39+ """Add DensePose body UV specific outputs: heatmaps of dense mask, patch index
40+ and patch-specific UV coordinates. All dense masks are mapped to labels in
41+ [0, ... S] for S semantically meaningful body parts.
42+ """
43+ # Apply ConvTranspose to the feature representation; results in 2x upsampling
44+ for name in [ 'AnnIndex' , 'Index_UV' , 'U' , 'V' ]:
45+ if name == 'AnnIndex' :
46+ dim_out = cfg .BODY_UV_RCNN .NUM_SEMANTIC_PARTS + 1
47+ else :
48+ dim_out = cfg . BODY_UV_RCNN . NUM_PATCHES + 1
49+ model . ConvTranspose (
50+ blob_in ,
51+ name + '_lowres' ,
52+ dim ,
53+ dim_out ,
4054 cfg .BODY_UV_RCNN .DECONV_KERNEL ,
4155 pad = int (cfg .BODY_UV_RCNN .DECONV_KERNEL / 2 - 1 ),
4256 stride = 2 ,
4357 weight_init = (cfg .BODY_UV_RCNN .CONV_INIT , {'std' : 0.001 }),
44- bias_init = ('ConstantFill' , {'value' : 0. }))
45- ####
46- blob_Ann_Index = model .BilinearInterpolation ('AnnIndex_lowres' + pref , 'AnnIndex' + pref , cfg .BODY_UV_RCNN .NUM_PATCHES + 1 , cfg .BODY_UV_RCNN .NUM_PATCHES + 1 , cfg .BODY_UV_RCNN .UP_SCALE )
47- blob_Index = model .BilinearInterpolation ('Index_UV_lowres' + pref , 'Index_UV' + pref , cfg .BODY_UV_RCNN .NUM_PATCHES + 1 , cfg .BODY_UV_RCNN .NUM_PATCHES + 1 , cfg .BODY_UV_RCNN .UP_SCALE )
48- blob_U = model .BilinearInterpolation ('U_lowres' + pref , 'U_estimated' + pref , cfg .BODY_UV_RCNN .NUM_PATCHES + 1 , cfg .BODY_UV_RCNN .NUM_PATCHES + 1 , cfg .BODY_UV_RCNN .UP_SCALE )
49- blob_V = model .BilinearInterpolation ('V_lowres' + pref , 'V_estimated' + pref , cfg .BODY_UV_RCNN .NUM_PATCHES + 1 , cfg .BODY_UV_RCNN .NUM_PATCHES + 1 , cfg .BODY_UV_RCNN .UP_SCALE )
50- ###
51- return blob_U ,blob_V ,blob_Index ,blob_Ann_Index
52-
53-
54- def add_body_uv_losses (model , pref = '' ):
55-
56- ## Reshape for GT blobs.
57- model .net .Reshape ( ['body_uv_X_points' ], ['X_points_reshaped' + pref , 'X_points_shape' + pref ], shape = ( - 1 ,1 ) )
58- model .net .Reshape ( ['body_uv_Y_points' ], ['Y_points_reshaped' + pref , 'Y_points_shape' + pref ], shape = ( - 1 ,1 ) )
59- model .net .Reshape ( ['body_uv_I_points' ], ['I_points_reshaped' + pref , 'I_points_shape' + pref ], shape = ( - 1 ,1 ) )
60- model .net .Reshape ( ['body_uv_Ind_points' ], ['Ind_points_reshaped' + pref , 'Ind_points_shape' + pref ], shape = ( - 1 ,1 ) )
61- ## Concat Ind,x,y to get Coordinates blob.
62- model .net .Concat ( ['Ind_points_reshaped' + pref ,'X_points_reshaped' + pref , \
63- 'Y_points_reshaped' + pref ],['Coordinates' + pref ,'Coordinate_Shapes' + pref ], axis = 1 )
64- ##
65- ### Now reshape UV blobs, such that they are 1x1x(196*NumSamples)xNUM_PATCHES
66- ## U blob to
67- ##
68- model .net .Reshape (['body_uv_U_points' ], \
69- ['U_points_reshaped' + pref , 'U_points_old_shape' + pref ],\
70- shape = (- 1 ,cfg .BODY_UV_RCNN .NUM_PATCHES + 1 ,196 ))
71- model .net .Transpose (['U_points_reshaped' + pref ] ,['U_points_reshaped_transpose' + pref ],axes = (0 ,2 ,1 ) )
72- model .net .Reshape (['U_points_reshaped_transpose' + pref ], \
73- ['U_points' + pref , 'U_points_old_shape2' + pref ], \
74- shape = (1 ,1 ,- 1 ,cfg .BODY_UV_RCNN .NUM_PATCHES + 1 ))
75- ## V blob
76- ##
77- model .net .Reshape (['body_uv_V_points' ], \
78- ['V_points_reshaped' + pref , 'V_points_old_shape' + pref ],\
79- shape = (- 1 ,cfg .BODY_UV_RCNN .NUM_PATCHES + 1 ,196 ))
80- model .net .Transpose (['V_points_reshaped' + pref ] ,['V_points_reshaped_transpose' + pref ],axes = (0 ,2 ,1 ) )
81- model .net .Reshape (['V_points_reshaped_transpose' + pref ], \
82- ['V_points' + pref , 'V_points_old_shape2' + pref ], \
83- shape = (1 ,1 ,- 1 ,cfg .BODY_UV_RCNN .NUM_PATCHES + 1 ))
84- ###
85- ## UV weights blob
86- ##
87- model .net .Reshape (['body_uv_point_weights' ], \
88- ['Uv_point_weights_reshaped' + pref , 'Uv_point_weights_old_shape' + pref ],\
89- shape = (- 1 ,cfg .BODY_UV_RCNN .NUM_PATCHES + 1 ,196 ))
90- model .net .Transpose (['Uv_point_weights_reshaped' + pref ] ,['Uv_point_weights_reshaped_transpose' + pref ],axes = (0 ,2 ,1 ) )
91- model .net .Reshape (['Uv_point_weights_reshaped_transpose' + pref ], \
92- ['Uv_point_weights' + pref , 'Uv_point_weights_old_shape2' + pref ], \
93- shape = (1 ,1 ,- 1 ,cfg .BODY_UV_RCNN .NUM_PATCHES + 1 ))
94-
95- #####################
96- ### Pool IUV for points via bilinear interpolation.
97- model .PoolPointsInterp (['U_estimated' ,'Coordinates' + pref ], ['interp_U' + pref ])
98- model .PoolPointsInterp (['V_estimated' ,'Coordinates' + pref ], ['interp_V' + pref ])
99- model .PoolPointsInterp (['Index_UV' + pref ,'Coordinates' + pref ], ['interp_Index_UV' + pref ])
100-
101- ## Reshape interpolated UV coordinates to apply the loss.
102-
103- model .net .Reshape (['interp_U' + pref ], \
104- ['interp_U_reshaped' + pref , 'interp_U_shape' + pref ],\
105- shape = (1 , 1 , - 1 , cfg .BODY_UV_RCNN .NUM_PATCHES + 1 ))
106-
107- model .net .Reshape (['interp_V' + pref ], \
108- ['interp_V_reshaped' + pref , 'interp_V_shape' + pref ],\
109- shape = (1 , 1 , - 1 , cfg .BODY_UV_RCNN .NUM_PATCHES + 1 ))
110- ###
111-
112- ### Do the actual labels here !!!!
113- model .net .Reshape ( ['body_uv_ann_labels' ], \
114- ['body_uv_ann_labels_reshaped' + pref , 'body_uv_ann_labels_old_shape' + pref ], \
115- shape = (- 1 , cfg .BODY_UV_RCNN .HEATMAP_SIZE , cfg .BODY_UV_RCNN .HEATMAP_SIZE ))
116-
117- model .net .Reshape ( ['body_uv_ann_weights' ], \
118- ['body_uv_ann_weights_reshaped' + pref , 'body_uv_ann_weights_old_shape' + pref ], \
119- shape = ( - 1 , cfg .BODY_UV_RCNN .HEATMAP_SIZE , cfg .BODY_UV_RCNN .HEATMAP_SIZE ))
120- ###
121- model .net .Cast ( ['I_points_reshaped' + pref ], ['I_points_reshaped_int' + pref ], to = core .DataType .INT32 )
122- ### Now add the actual losses
123- ## The mask segmentation loss (dense)
124- probs_seg_AnnIndex , loss_seg_AnnIndex = model .net .SpatialSoftmaxWithLoss ( \
125- ['AnnIndex' + pref , 'body_uv_ann_labels_reshaped' + pref ,'body_uv_ann_weights_reshaped' + pref ],\
126- ['probs_seg_AnnIndex' + pref ,'loss_seg_AnnIndex' + pref ], \
127- scale = cfg .BODY_UV_RCNN .INDEX_WEIGHTS / cfg .NUM_GPUS )
128- ## Point Patch Index Loss.
129- probs_IndexUVPoints , loss_IndexUVPoints = model .net .SoftmaxWithLoss (\
130- ['interp_Index_UV' + pref ,'I_points_reshaped_int' + pref ],\
131- ['probs_IndexUVPoints' + pref ,'loss_IndexUVPoints' + pref ], \
132- scale = cfg .BODY_UV_RCNN .PART_WEIGHTS / cfg .NUM_GPUS , spatial = 0 )
133- ## U and V point losses.
134- loss_Upoints = model .net .SmoothL1Loss ( \
135- ['interp_U_reshaped' + pref , 'U_points' + pref , \
136- 'Uv_point_weights' + pref , 'Uv_point_weights' + pref ], \
137- 'loss_Upoints' + pref , \
138- scale = cfg .BODY_UV_RCNN .POINT_REGRESSION_WEIGHTS / cfg .NUM_GPUS )
58+ bias_init = const_fill (0.0 )
59+ )
60+ # Increase heatmap output size via bilinear upsampling
61+ blob_outputs = []
62+ for name in ['AnnIndex' , 'Index_UV' , 'U' , 'V' ]:
63+ blob_outputs .append (
64+ model .BilinearInterpolation (
65+ name + '_lowres' ,
66+ name + '_estimated' if name in ['U' , 'V' ] else name ,
67+ cfg .BODY_UV_RCNN .NUM_PATCHES + 1 ,
68+ cfg .BODY_UV_RCNN .NUM_PATCHES + 1 ,
69+ cfg .BODY_UV_RCNN .UP_SCALE
70+ )
71+ )
72+
73+ return blob_outputs
74+
75+
76+ def add_body_uv_losses (model ):
77+ """Add DensePose body UV specific losses."""
78+ # Pool estimated IUV points via bilinear interpolation.
79+ for name in ['U' , 'V' , 'Index_UV' ]:
80+ model .PoolPointsInterp (
81+ [
82+ name + '_estimated' if name in ['U' , 'V' ] else name ,
83+ 'body_uv_coords_xy'
84+ ],
85+ ['interp_' + name ]
86+ )
13987
140- loss_Vpoints = model .net .SmoothL1Loss ( \
141- ['interp_V_reshaped' + pref , 'V_points' + pref , \
142- 'Uv_point_weights' + pref , 'Uv_point_weights' + pref ], \
143- 'loss_Vpoints' + pref , scale = cfg .BODY_UV_RCNN .POINT_REGRESSION_WEIGHTS / cfg .NUM_GPUS )
144- ## Add the losses.
145- loss_gradients = blob_utils .get_loss_gradients (model , \
146- [ loss_Upoints , loss_Vpoints , loss_seg_AnnIndex , loss_IndexUVPoints ])
147- model .losses = list (set (model .losses + \
148- ['loss_Upoints' + pref , 'loss_Vpoints' + pref , \
149- 'loss_seg_AnnIndex' + pref ,'loss_IndexUVPoints' + pref ]))
88+ # Compute spatial softmax normalized probabilities, after which
89+ # cross-entropy loss is computed for semantic parts classification.
90+ probs_AnnIndex , loss_AnnIndex = model .net .SpatialSoftmaxWithLoss (
91+ [
92+ 'AnnIndex' ,
93+ 'body_uv_parts' , 'body_uv_parts_weights'
94+ ],
95+ ['probs_AnnIndex' , 'loss_AnnIndex' ],
96+ scale = cfg .BODY_UV_RCNN .INDEX_WEIGHTS / cfg .NUM_GPUS
97+ )
98+ # Softmax loss for surface patch classification.
99+ probs_I_points , loss_I_points = model .net .SoftmaxWithLoss (
100+ ['interp_Index_UV' , 'body_uv_I_points' ],
101+ ['probs_I_points' , 'loss_I_points' ],
102+ scale = cfg .BODY_UV_RCNN .PART_WEIGHTS / cfg .NUM_GPUS ,
103+ spatial = 0
104+ )
105+ ## Smooth L1 loss for each patch-specific UV coordinates regression.
106+ # Reshape U,V blobs of both interpolated and ground-truth to compute
107+ # summarized (instead of averaged) SmoothL1Loss.
108+ loss_UV = list ()
109+ model .net .Reshape (
110+ ['body_uv_point_weights' ],
111+ ['UV_point_weights' , 'body_uv_point_weights_shape' ],
112+ shape = (1 , - 1 , cfg .BODY_UV_RCNN .NUM_PATCHES + 1 )
113+ )
114+ for name in ['U' , 'V' ]:
115+ # Reshape U/V coordinates of both interpolated points and ground-truth
116+ # points from (#points, #patches) to (1, #points, #patches).
117+ model .net .Reshape (
118+ ['body_uv_' + name + '_points' ],
119+ [name + '_points' , 'body_uv_' + name + '_points_shape' ],
120+ shape = (1 , - 1 , cfg .BODY_UV_RCNN .NUM_PATCHES + 1 )
121+ )
122+ model .net .Reshape (
123+ ['interp_' + name ],
124+ ['interp_' + name + '_reshaped' , 'interp_' + name + 'shape' ],
125+ shape = (1 , - 1 , cfg .BODY_UV_RCNN .NUM_PATCHES + 1 )
126+ )
127+ # Compute summarized SmoothL1Loss of all points.
128+ loss_UV .append (
129+ model .net .SmoothL1Loss (
130+ [
131+ 'interp_' + name + '_reshaped' , name + '_points' ,
132+ 'UV_point_weights' , 'UV_point_weights'
133+ ],
134+ 'loss_' + name + '_points' ,
135+ scale = cfg .BODY_UV_RCNN .POINT_REGRESSION_WEIGHTS / cfg .NUM_GPUS
136+ )
137+ )
138+ # Add all losses to compute gradients
139+ loss_gradients = blob_utils .get_loss_gradients (
140+ model , [loss_AnnIndex , loss_I_points ] + loss_UV
141+ )
142+ # Update model training losses
143+ model .AddLosses (
144+ ['loss_' + name for name in ['AnnIndex' , 'I_points' , 'U_points' , 'V_points' ]]
145+ )
150146
151147 return loss_gradients
152148
@@ -155,17 +151,17 @@ def add_body_uv_losses(model, pref=''):
155151# Body UV heads
156152# ---------------------------------------------------------------------------- #
157153
158- def add_ResNet_roi_conv5_head_for_bodyUV (
159- model , blob_in , dim_in , spatial_scale
160- ):
154+ def add_ResNet_roi_conv5_head_for_bodyUV (model , blob_in , dim_in , spatial_scale ):
161155 """Add a ResNet "conv5" / "stage5" head for body UV prediction."""
162156 model .RoIFeatureTransform (
163- blob_in , '_[body_uv]_pool5' ,
157+ blob_in ,
158+ '_[body_uv]_pool5' ,
164159 blob_rois = 'body_uv_rois' ,
165160 method = cfg .BODY_UV_RCNN .ROI_XFORM_METHOD ,
166161 resolution = cfg .BODY_UV_RCNN .ROI_XFORM_RESOLUTION ,
167162 sampling_ratio = cfg .BODY_UV_RCNN .ROI_XFORM_SAMPLING_RATIO ,
168- spatial_scale = spatial_scale )
163+ spatial_scale = spatial_scale
164+ )
169165 # Using the prefix '_[body_uv]_' to 'res5' enables initializing the head's
170166 # parameters using pretrained 'res5' parameters if given (see
171167 # utils.net.initialize_from_weights_file)
@@ -184,7 +180,7 @@ def add_ResNet_roi_conv5_head_for_bodyUV(
184180
185181
186182def add_roi_body_uv_head_v1convX (model , blob_in , dim_in , spatial_scale ):
187- """v1convX design: X * (conv)."""
183+ """Add a DensePose body UV head. v1convX design: X * (conv)."""
188184 hidden_dim = cfg .BODY_UV_RCNN .CONV_HEAD_DIM
189185 kernel_size = cfg .BODY_UV_RCNN .CONV_HEAD_KERNEL
190186 pad_size = kernel_size // 2
@@ -208,7 +204,7 @@ def add_roi_body_uv_head_v1convX(model, blob_in, dim_in, spatial_scale):
208204 stride = 1 ,
209205 pad = pad_size ,
210206 weight_init = (cfg .BODY_UV_RCNN .CONV_INIT , {'std' : 0.01 }),
211- bias_init = ( 'ConstantFill' , { 'value' : 0. } )
207+ bias_init = const_fill ( 0.0 )
212208 )
213209 current = model .Relu (current , current )
214210 dim_in = hidden_dim
0 commit comments