def forward(self,fast_feature, proposal_bboxes: Tensor, gt_classes_batch: Optional[Tensor] = None, gt_bboxes_batch: Optional[Tensor] = None) \ -> Union[Tuple[Tensor], Tuple[Tensor, Tensor, Tensor, Tensor]]: ## slow_feature, , Tensor batch_size = fast_feature.shape[0] ## fast_feature:{1,256,16,16] feature = nn.AvgPool3d( kernel_size=(fast_feature.shape[2], 1, 1))(fast_feature).squeeze( 2) ## feature: [1,2304,16,16] # slow_feature = nn.AvgPool3d(kernel_size=(slow_feature.shape[2], 1, 1))(slow_feature).squeeze(2) # feature=torch.cat([fast_feature, slow_feature],dim=1) if not self.training: assert batch_size == 1 proposal_batch_indices = torch.arange( end=batch_size, dtype=torch.long, device=proposal_bboxes.device).view(-1, 1).repeat( 1, proposal_bboxes.shape[0])[0] pool = Pooler.apply(feature, proposal_bboxes, proposal_batch_indices, mode=Pooler.Mode.POOLING) hidden = self.hidden(pool) proposal_classes = self._proposal_class(hidden) return proposal_classes else: #过滤掉补充的0 # find labels for each `proposal_bboxes` ious = BBox.iou(proposal_bboxes, gt_bboxes_batch) proposal_max_ious, proposal_assignments = ious.max(dim=2) fg_masks = proposal_max_ious >= 0.85 if len(fg_masks.nonzero()) > 0: #fg_masks.nonzero()[:, 0]是在获取batch proposal_bboxes = proposal_bboxes[fg_masks.nonzero()[:, 0], fg_masks.nonzero()[:, 1]] batch_indices = fg_masks.nonzero()[:, 0] labels = gt_classes_batch[fg_masks.nonzero()[:, 0], proposal_assignments[fg_masks]] else: print('bbox warning') fg_masks = proposal_max_ious >= 0.5 proposal_bboxes = proposal_bboxes[fg_masks.nonzero()[:, 0], fg_masks.nonzero()[:, 1]] batch_indices = fg_masks.nonzero()[:, 0] labels = gt_classes_batch[fg_masks.nonzero()[:, 0], proposal_assignments[fg_masks]] # # #空间池化,拼接 pool = Pooler.apply(feature, proposal_bboxes, batch_indices, mode=Pooler.Mode.POOLING) # print("******** pool shape *******", pool.shape) [6, 2048, 3, 3] hidden = self.hidden(pool) proposal_classes = self._proposal_class(hidden) proposal_class_losses = self.loss(proposal_classes, labels, batch_size, batch_indices) return proposal_classes, proposal_class_losses
def forward(self, features: Tensor, proposal_bboxes: Tensor, gt_classes_batch: Optional[Tensor] = None, gt_bboxes_batch: Optional[Tensor] = None) -> Union[Tuple[Tensor, Tensor], Tuple[Tensor, Tensor, Tensor, Tensor]]: batch_size = features.shape[0] if not self.training: proposal_batch_indices = torch.arange(end=batch_size, dtype=torch.long, device=proposal_bboxes.device).view(-1, 1).repeat(1, proposal_bboxes.shape[1]) pool = Pooler.apply(features, proposal_bboxes.view(-1, 4), proposal_batch_indices.view(-1), mode=self._pooler_mode) hidden = self.hidden(pool) hidden = F.adaptive_max_pool2d(input=hidden, output_size=1) hidden = hidden.view(hidden.shape[0], -1) proposal_classes = self._proposal_class(hidden) proposal_transformers = self._proposal_transformer(hidden) proposal_classes = proposal_classes.view(batch_size, -1, proposal_classes.shape[-1]) proposal_transformers = proposal_transformers.view(batch_size, -1, proposal_transformers.shape[-1]) return proposal_classes, proposal_transformers else: # find labels for each `proposal_bboxes` labels = torch.full((batch_size, proposal_bboxes.shape[1]), -1, dtype=torch.long, device=proposal_bboxes.device) ious = BBox.iou(proposal_bboxes, gt_bboxes_batch) proposal_max_ious, proposal_assignments = ious.max(dim=2) labels[proposal_max_ious < 0.5] = 0 fg_masks = proposal_max_ious >= 0.5 if len(fg_masks.nonzero()) > 0: labels[fg_masks] = gt_classes_batch[fg_masks.nonzero()[:, 0], proposal_assignments[fg_masks]] # select 128 x `batch_size` samples fg_indices = (labels > 0).nonzero() bg_indices = (labels == 0).nonzero() fg_indices = fg_indices[torch.randperm(len(fg_indices))[:min(len(fg_indices), 32 * batch_size)]] bg_indices = bg_indices[torch.randperm(len(bg_indices))[:128 * batch_size - len(fg_indices)]] selected_indices = torch.cat([fg_indices, bg_indices], dim=0) selected_indices = selected_indices[torch.randperm(len(selected_indices))].unbind(dim=1) proposal_bboxes = proposal_bboxes[selected_indices] gt_bboxes = gt_bboxes_batch[selected_indices[0], proposal_assignments[selected_indices]] gt_proposal_classes = labels[selected_indices] gt_proposal_transformers = BBox.calc_transformer(proposal_bboxes, gt_bboxes) batch_indices = selected_indices[0] pool = Pooler.apply(features, proposal_bboxes, proposal_batch_indices=batch_indices, mode=self._pooler_mode) hidden = self.hidden(pool) hidden = F.adaptive_max_pool2d(input=hidden, output_size=1) hidden = hidden.view(hidden.shape[0], -1) proposal_classes = self._proposal_class(hidden) proposal_transformers = self._proposal_transformer(hidden) proposal_class_losses, proposal_transformer_losses = self.loss(proposal_classes, proposal_transformers, gt_proposal_classes, gt_proposal_transformers, batch_size, batch_indices) return proposal_classes, proposal_transformers, proposal_class_losses, proposal_transformer_losses
def forward(self, p2: Tensor, p3: Tensor, p4: Tensor, p5: Tensor, proposal_bboxes: Tensor, image_width: int, image_height: int) -> Tuple[Tensor, Tensor]: w = proposal_bboxes[:, 2] - proposal_bboxes[:, 0] h = proposal_bboxes[:, 3] - proposal_bboxes[:, 1] k0 = 4 k = torch.floor(k0 + torch.log2(torch.sqrt(w * h) / 224)).long() k = torch.clamp(k, min=2, max=5) k_to_p_dict = {2: p2, 3: p3, 4: p4, 5: p5} unique_k = torch.unique(k) # NOTE: `picked_indices` is for recording the order of selection from `proposal_bboxes` # so that `pools` can be then restored to make it have a consistent correspondence # with `proposal_bboxes`. For example: # # proposal_bboxes => B0 B1 B2 # picked_indices => 1 2 0 # pools => BP1 BP2 BP0 # sorted_indices => 2 0 1 # pools => BP0 BP1 BP2 pools = [] picked_indices = [] for uk in unique_k: uk = uk.item() p = k_to_p_dict[uk] uk_indices = (k == uk).nonzero().view(-1) uk_proposal_bboxes = proposal_bboxes[uk_indices] pool = Pooler.apply(p, uk_proposal_bboxes, mode=self._pooler_mode) pools.append(pool) picked_indices.append(uk_indices) pools = torch.cat(pools, dim=0) picked_indices = torch.cat(picked_indices, dim=0) _, sorted_indices = torch.sort(picked_indices) pools = pools[sorted_indices] pools = pools.view(pools.shape[0], -1) hidden = self._hidden(pools) classes = self._class(hidden) transformers = self._transformer(hidden) return classes, transformers
def forward( self, fast_feature, slow_feature, proposal_bboxes: Tensor, gt_classes_batch: Optional[Tensor] = None, gt_bboxes_batch: Optional[Tensor] = None ) -> Union[Tuple[Tensor, Tensor], Tuple[Tensor, Tensor, Tensor, Tensor]]: batch_size = fast_feature.shape[0] fast_feature = nn.AvgPool3d( kernel_size=(fast_feature.shape[2], 1, 1))(fast_feature).squeeze(2) #print("fast_feature:",fast_feature.shape) slow_feature = nn.AvgPool3d( kernel_size=(slow_feature.shape[2], 1, 1))(slow_feature).squeeze(2) feature = torch.cat([fast_feature, slow_feature], dim=1) if not self.training: assert batch_size == 1 # a=torch.arange(end=batch_size, dtype=torch.long, device=proposal_bboxes.device).view(-1, 1) # b=a.repeat(1, proposal_bboxes.shape[1]) ###################################### ######## @ FATAL ERROR @ ############### ###################################### proposal_batch_indices = torch.arange( end=batch_size, dtype=torch.long, device=proposal_bboxes.device).view(-1, 1).repeat( 1, proposal_bboxes.shape[0])[0] # pool_f = Pooler.apply(fast_feature, proposal_bboxes.view(-1, 4), proposal_batch_indices.view(-1), mode=self._pooler_mode) # pool_s = Pooler.apply(slow_feature, proposal_bboxes.view(-1, 4), proposal_batch_indices.view(-1), mode=self._pooler_mode) # # 空间池化,拼接 # pool_f = nn.AdaptiveAvgPool3d((1, pool_f.shape[3], pool_f.shape[4]))(pool_f) # pool_s = nn.AdaptiveAvgPool3d((1, pool_s.shape[3], pool_s.shape[4]))(pool_s) # pool_f = pool_f.squeeze(2) # pool_s = pool_s.squeeze(2) # pool = torch.cat([pool_f, pool_s], dim=1) pool = Pooler.apply(feature, proposal_bboxes, proposal_batch_indices, mode=Pooler.Mode.POOLING) hidden = self.hidden(pool) proposal_classes = self._proposal_class(hidden) #proposal_classes = proposal_classes.view(batch_size, -1, proposal_classes.shape[-1]) return proposal_classes else: #过滤掉补充的0 # find labels for each `proposal_bboxes` ious = BBox.iou(proposal_bboxes, gt_bboxes_batch) proposal_max_ious, proposal_assignments = ious.max(dim=2) #_, proposal_which = ious.max(dim=1) fg_masks = proposal_max_ious >= 0.85 if len(fg_masks.nonzero()) > 0: #fg_masks.nonzero()[:, 0]是在获取batch proposal_bboxes = proposal_bboxes[fg_masks.nonzero()[:, 0], fg_masks.nonzero()[:, 1]] batch_indices = fg_masks.nonzero()[:, 0] labels = gt_classes_batch[fg_masks.nonzero()[:, 0], proposal_assignments[fg_masks]] else: print('bbox warning') fg_masks = proposal_max_ious >= 0.5 proposal_bboxes = proposal_bboxes[fg_masks.nonzero()[:, 0], fg_masks.nonzero()[:, 1]] batch_indices = fg_masks.nonzero()[:, 0] labels = gt_classes_batch[fg_masks.nonzero()[:, 0], proposal_assignments[fg_masks]] # pool_f_pre= Pooler.apply(fast_feature, proposal_bboxes, batch_indices,mode=self._pooler_mode) # pool_s_pre= Pooler.apply(slow_feature, proposal_bboxes,batch_indices, mode=self._pooler_mode) # #空间池化,拼接 # pool_f_a = nn.AdaptiveAvgPool3d((1, pool_f_pre.shape[3], pool_f_pre.shape[4]))(pool_f_pre) # pool_s_a = nn.AdaptiveAvgPool3d((1, pool_s_pre.shape[3], pool_s_pre.shape[4]))(pool_s_pre) # pool_f_s = pool_f_a.squeeze(2) # pool_s_s = pool_s_a.squeeze(2) # pool=torch.cat([pool_f_s, pool_s_s], dim=1) pool = Pooler.apply(feature, proposal_bboxes, batch_indices, mode=Pooler.Mode.POOLING) #sure 5 #print("cls_labels:",labels) hidden = self.hidden(pool) proposal_classes = self._proposal_class(hidden) proposal_class_losses = self.loss(proposal_classes, labels, batch_size, batch_indices) return proposal_classes, proposal_class_losses
def forward( self, features: Tensor, proposal_bboxes: Tensor, gt_classes_batch: Optional[Tensor] = None, gt_bboxes_batch: Optional[Tensor] = None ) -> Union[Tuple[Tensor, Tensor], Tuple[Tensor, Tensor, Tensor, Tensor]]: #features@(bn,1024,h/16,w/16) #pb@(bn,gp_n,4) batch_size = features.shape[0] if not self.training: #(bn,gp_n) proposal_batch_indices = torch.arange( end=batch_size, dtype=torch.long, device=proposal_bboxes.device).view(-1, 1).repeat( 1, proposal_bboxes.shape[1]) #ROI pooling:(bn,gp_n,1024,7,7). 这里的ROI pooling相当于把features与pb进行合并 pool = Pooler.apply(features, proposal_bboxes.view(-1, 4), proposal_batch_indices.view(-1), mode=self._pooler_mode) hidden = self.hidden( pool ) #(bn,gp_n,2048,4,4). 这里(7,7)变为(4,4)的原因是hidden中还有个stride=2的卷积层. hidden = F.adaptive_max_pool2d( input=hidden, output_size=1) #(bn,gp_n,2048,1,1) hidden = hidden.view(hidden.shape[0], -1) #(bn,gp_n,2048) #self._proposal_class@Linear(2048,num_cls) self._proposal_transformer@Linear(2048,4*num_cls) proposal_classes = self._proposal_class( hidden) #作分类的线性变换:(bn,gp_n,num_cls) proposal_transformers = self._proposal_transformer( hidden) #框回归:(bn,gp_n,num_cls*4) proposal_classes = proposal_classes.view( batch_size, -1, proposal_classes.shape[-1]) #(bn,gp_n,num_cls) proposal_transformers = proposal_transformers.view( batch_size, -1, proposal_transformers.shape[-1]) #(bn,gp_n,num_cls*4) return proposal_classes, proposal_transformers else: #NOTE 总的处理流程类似rpn的训练forward: ious->labels->fg/bg->selected_indices. # find labels for each `proposal_bboxes` # 1.为每个pb找到类label@(bn,gp_n),默认值为-1 labels = torch.full((batch_size, proposal_bboxes.shape[1]), -1, dtype=torch.long, device=proposal_bboxes.device) # ious@(bn,gp_n,gb_n) ious是确定labels的关键 ious = BBox.iou( proposal_bboxes, gt_bboxes_batch ) #NOTE iou在detection.forward中只用到一次,在rpn.forward中也只用到一次 proposal_max_ious, proposal_assignments = ious.max( dim=2) #(bn,gp_n) labels[proposal_max_ious < 0.5] = 0 #背景类 fg_masks = proposal_max_ious >= 0.5 #(bn,gp_n) 前景类的条件 if len(fg_masks.nonzero()) > 0: labels[fg_masks] = gt_classes_batch[ fg_masks.nonzero()[:, 0], proposal_assignments[fg_masks]] # gt_classes_batch@(b,gt_n). 为前景类设置 类label #现在labels共分为3种: #a. 为0 ,对应背景proposal #b. 为cls_label(>0),对应前景proposal #c. 为-1的默认值,忽略 # select 128 x `batch_size` samples #2.确定selected_indices, 选出 batch_size x 128 个训练样本 fg_indices = (labels > 0).nonzero() #(fg_n,2) bg_indices = (labels == 0).nonzero() #(bg_n,2) fg_indices = fg_indices[torch.randperm( len(fg_indices))[:min(len(fg_indices), 32 * batch_size)]] #最少len_fg,最多32个 bg_indices = bg_indices[torch.randperm( len(bg_indices))[:128 * batch_size - len(fg_indices)]] selected_indices = torch.cat([fg_indices, bg_indices], dim=0) #(bn*128,2) #分裂为元素为2的tuple,每个元素是上面的一列:([批内索引],[pb内索引]) selected_indices = selected_indices[torch.randperm( len(selected_indices))].unbind(dim=1) proposal_bboxes = proposal_bboxes[ selected_indices] #(bn*128,4) #以下是对gt_bboxes_batch的多维索引:selected_indices[0]是128个批内图像的索引,表示选择128个图像, #proposal_assignments[selected_indices]表示128个图像对应的gt_box序号,也是128个 #最终选择了128个gt_bboxes. gt_bboxes = gt_bboxes_batch[ selected_indices[0], proposal_assignments[selected_indices]] #(bn*128,4) gt_proposal_classes = labels[selected_indices] #(bn*128,) gt_proposal_transformers = BBox.calc_transformer( proposal_bboxes, gt_bboxes) #(bn*128,4) batch_indices = selected_indices[0] #(bn*128) #features@(bn,1024,w/16,h/16) proposal_bboxes@(bn*128,4) #pool@(bn*128,1024,7,7) pool = Pooler.apply(features, proposal_bboxes, proposal_batch_indices=batch_indices, mode=self._pooler_mode) hidden = self.hidden(pool) #(bn*128,2048,4,4) hidden = F.adaptive_max_pool2d( input=hidden, output_size=1) #(bn*128,2048,1,1) hidden = hidden.view(hidden.shape[0], -1) #(bn*128,2048) #self._proposal_class@Linear(2048,num_cls) self._proposal_transformer@Linear(2048,4*num_cls) proposal_classes = self._proposal_class( hidden) #(bn*128,num_cls) proposal_transformers = self._proposal_transformer( hidden) #(bn*128,num_cls*4) proposal_class_losses, proposal_transformer_losses = self.loss( proposal_classes, proposal_transformers, gt_proposal_classes, gt_proposal_transformers, batch_size, batch_indices) return proposal_classes, proposal_transformers, proposal_class_losses, proposal_transformer_losses
def forward( self, features: Tensor, proposal_bboxes: Tensor, gt_classes_batch: Optional[Tensor] = None, gt_bboxes_batch: Optional[Tensor] = None, gt_vertices_batch: Optional[Tensor] = None, image_width=None, image_height=None ) -> Union[Tuple[Tensor, Tensor, Tensor], Tuple[Tensor, Tensor, Tensor, Tensor, Tensor]]: batch_size = features.shape[0] if not self.training: proposal_batch_indices = torch.arange( end=batch_size, dtype=torch.long, device=proposal_bboxes.device).view(-1, 1).repeat( 1, proposal_bboxes.shape[1]) pool = Pooler.apply(features, proposal_bboxes.view(-1, 4), proposal_batch_indices.view(-1), mode=self._pooler_mode) pool = pool.view(pool.shape[0], -1) hidden = self.hidden[0](pool) hidden = self.hidden[1](hidden) hidden = self.hidden[3](hidden) hidden = self.hidden[4](hidden) #hidden = F.adaptive_max_pool2d(input=hidden, output_size=1) #hidden = hidden.view(hidden.shape[0], -1) proposal_transformers = self._proposal_transformer(hidden) if self.iteration: detection_bboxes = self.create_bboxes( proposal_bboxes, proposal_transformers.unsqueeze(0), image_width, image_height, 1) detection_bboxes = detection_bboxes.view(-1, 4) pool = Pooler.apply(features, detection_bboxes.view(-1, 4), proposal_batch_indices.view(-1), mode=self._pooler_mode) pool = pool.view(pool.shape[0], -1) hidden = self.hidden[0](pool) hidden = self.hidden[1](hidden) hidden = self.hidden[3](hidden) hidden = self.hidden[4](hidden) proposal_transformers2 = self._proposal_transformer(hidden) proposal_transformers2 = proposal_transformers2.view( batch_size, -1, proposal_transformers.shape[-1]) else: proposal_transformers2 = None proposal_classes = self._proposal_class(hidden) proposal_vertices = self._proposal_vertices(hidden) proposal_classes = proposal_classes.view( batch_size, -1, proposal_classes.shape[-1]) proposal_transformers = proposal_transformers.view( batch_size, -1, proposal_transformers.shape[-1]) proposal_vertices = proposal_vertices.view( batch_size, -1, proposal_vertices.shape[-1]) return proposal_vertices, proposal_classes, proposal_transformers, proposal_transformers2 else: labels = torch.full((batch_size, proposal_bboxes.shape[1]), -1, dtype=torch.long, device=proposal_bboxes.device) # print(proposal_bboxes.size(), gt_bboxes_batch.size()) ious = BBox.iou(proposal_bboxes, gt_bboxes_batch) #print(proposal_bboxes.size(), gt_bboxes_batch.size(), ious.size()) proposal_max_ious, proposal_assignments = ious.max(dim=2) labels[proposal_max_ious < 0.5] = 0 fg_masks = proposal_max_ious >= 0.5 if len(fg_masks.nonzero()) > 0: labels[fg_masks] = gt_classes_batch[ fg_masks.nonzero()[:, 0], proposal_assignments[fg_masks]] # select 128 x `batch_size` samples fg_indices = (labels > 0).nonzero() bg_indices = (labels == 0).nonzero() fg_indices = fg_indices[torch.randperm( len(fg_indices))[:min(len(fg_indices), 32 * batch_size)]] bg_indices = bg_indices[torch.randperm( len(bg_indices))[:128 * batch_size - len(fg_indices)]] selected_indices = torch.cat([fg_indices, bg_indices], dim=0) selected_indices = selected_indices[torch.randperm( len(selected_indices))].unbind(dim=1) proposal_bboxes = proposal_bboxes[selected_indices] gt_bboxes = gt_bboxes_batch[ selected_indices[0], proposal_assignments[selected_indices]] gt_vertices = gt_vertices_batch[ selected_indices[0], proposal_assignments[selected_indices]] gt_proposal_classes = labels[selected_indices] gt_proposal_transformers = BBox.calc_transformer( proposal_bboxes, gt_bboxes) batch_indices = selected_indices[0] #print('before', gt_proposal_classes) #print(gt_proposal_classes.size()) pool = Pooler.apply(features, proposal_bboxes, proposal_batch_indices=batch_indices, mode=self._pooler_mode) #vgg16 hidden = self.hidden(pool.view(pool.shape[0], -1)) #resnet101 # hidden = self.hidden(pool) # hidden = F.adaptive_max_pool2d(input=hidden, output_size=1) # hidden = hidden.view(hidden.shape[0], -1) if self.iteration: proposal_transformers_first_iter = self._proposal_transformer( hidden) detection_bboxes = self.create_bboxes( proposal_bboxes.unsqueeze(0), proposal_transformers_first_iter.unsqueeze(0), image_width, image_height, 1) detection_bboxes = detection_bboxes.view(-1, 4) pool = Pooler.apply(features, detection_bboxes, proposal_batch_indices=batch_indices, mode=self._pooler_mode) hidden = self.hidden(pool.view(pool.shape[0], -1)) bboxes_centers = torch.stack( ((detection_bboxes[:, 0] + detection_bboxes[:, 2]) / 2, (detection_bboxes[:, 1] + detection_bboxes[:, 3]) / 2), dim=1) width = detection_bboxes[:, 2] - detection_bboxes[:, 0] height = detection_bboxes[:, 3] - detection_bboxes[:, 1] gt_proposal_transformers = BBox.calc_transformer( detection_bboxes, gt_bboxes).detach() for batch_index in range(batch_size): selected_batch_indices = ( batch_indices == batch_index).nonzero().view(-1) ious = BBox.iou( detection_bboxes[selected_batch_indices].unsqueeze( 0), gt_bboxes_batch[batch_index].unsqueeze( 0)).detach() #print('iter', detection_bboxes.size(), gt_bboxes.size(), ious.size()) max_ious, _ = ious.max(dim=2) # print(gt_proposal_classes.size(), max_ious.size()) gt_proposal_classes[selected_batch_indices][ max_ious[0] < 0.5] = 0 gt_proposal_classes[selected_batch_indices][ max_ious[0] >= 0.5] = 1 #print('after', gt_proposal_classes) #print(gt_proposal_classes.size()) # #if fg_indices.nelement() > 0: # infinites = torch.isinf(gt_proposal_transformers) # if gt_bboxes[gt_bboxes > 0].nelement() > 0 and infinites[infinites == 1].nelement() > 0: # #print(infinites) # #print(gt_proposal_transformers) # # print(infinites.size()) # indices = torch.max(infinites,1)[0] # #print(indices) # indices = indices.nonzero().view(-1) #print(indices) #print('gt_proposal_transformers', gt_proposal_transformers[indices]) #print('detection_bboxes', detection_bboxes[indices]) #print('gt_bboxes', gt_bboxes[indices]) #print('ious', ious[0,index], ious.size()) #print(ious.size()) #print('max_ious', max_ious[0,indices], max_ious.size()) #print('gt_proposal_classes', gt_proposal_classes[indices], gt_proposal_classes.size()) # #yo = BBox.calc_transformer(detection_bboxes[index].unsqueeze(0), gt_bboxes[index].unsqueeze(0), print_it=True).detach() else: bboxes_centers = torch.stack( ((proposal_bboxes[:, 0] + proposal_bboxes[:, 2]) / 2, (proposal_bboxes[:, 1] + proposal_bboxes[:, 3]) / 2), dim=1) width = proposal_bboxes[:, 2] - proposal_bboxes[:, 0] height = proposal_bboxes[:, 3] - proposal_bboxes[:, 1] gt_vertices_norm = torch.empty(gt_vertices.size(), dtype=torch.float, device=gt_vertices.device) for i in range(gt_vertices_norm.size()[-1]): gt_vertices_norm[:, :, i] = torch.stack( ((gt_vertices[:, 0, i] - bboxes_centers[:, 0]) / width, (gt_vertices[:, 1, i] - bboxes_centers[:, 1]) / height), dim=1) gt_vertices_norm = gt_vertices_norm.detach() proposal_classes = self._proposal_class(hidden) proposal_vertices = self._proposal_vertices(hidden) proposal_transformers = self._proposal_transformer(hidden) proposal_class_losses, proposal_transformer_losses, vertex_losses = self.loss( proposal_vertices, proposal_classes, proposal_transformers, gt_proposal_classes, gt_proposal_transformers, gt_vertices_norm, batch_size, batch_indices) return proposal_vertices, proposal_classes, proposal_transformers, proposal_class_losses, proposal_transformer_losses, vertex_losses