Beispiel #1
0
 def get_stage_res(self, outs, mask_pos, pscores, plabels):
     ptxywh, pcls = outs
     ids_batch1, _ = torch.where(mask_pos)
     pxywh = boxes_decode4retina(self.cfg, self.anc_obj, ptxywh)
     pboxes_ltrb1 = xywh2ltrb(pxywh[mask_pos])
     pscores1 = pscores[mask_pos]
     plabels1 = plabels[mask_pos]
     plabels1 = plabels1 + 1
     return ids_batch1, pboxes_ltrb1, plabels1, pscores1
Beispiel #2
0
    def get_stage_res(self, outs, mask_pos, pscores, plabels):
        ptxywh, pcls = outs
        batch, hw, c = ptxywh.shape
        ids_batch1, _ = torch.where(mask_pos)
        ancs_xywh_3d = self.anc_obj.ancs_xywh.unsqueeze(0).repeat(batch, 1, 1)
        pxywh = boxes_decode4ssd(self.cfg, ptxywh, ancs_xywh_3d)

        # pxywh = boxes_decode4retina(self.cfg, self.anc_obj, ptxywh)
        pboxes_ltrb1 = xywh2ltrb(pxywh[mask_pos])
        pscores1 = pscores[mask_pos]
        plabels1 = plabels[mask_pos]
        plabels1 = plabels1 + 1
        return ids_batch1, pboxes_ltrb1, plabels1, pscores1
Beispiel #3
0
 def cre_anchors(self):
     '''
     形成的顺序是 每一个特图->每个格子(行优先) 建议从小到大 需与模型匹配 ->每一个尺寸
     :return:
         返回特图 h*w,4 anchors 是每个特图的长宽个 4维整框
         这里是 x,y,w,h 调整系数
     '''
     device = self.device
     ret_ancs = torch.empty((0, 4), device=device)
     for i, (row, col) in enumerate(self.feature_sizes):
         # 求xy 中心点坐标 行列与xy是反的
         rowcol_index = f_mershgrid(row, col, is_rowcol=True, num_repeat=1)
         rowcol_index = rowcol_index.to(device)
         # 这个特图的数量
         num_anc_one = rowcol_index.shape[0]  # 2704
         # 这个特图的尺寸 [[0.025, 0.025], [0.05, 0.05]]
         ancs_wh = self.ancs_scale[i]
         # 单体复制 每一个格子有
         num_anc = len(ancs_wh)
         self.nums_anc.append(num_anc)
         self.nums_level.append(num_anc_one *
                                num_anc)  # self.nums_feature 是全新
         rowcol_index = rowcol_index.repeat_interleave(num_anc,
                                                       dim=0)  # 单体复制
         rowcol = torch.tensor((row, col), device=device)
         # xy 与 rowcol相反
         ancs_yx = torch.true_divide(rowcol_index, rowcol)  # 特图归一化
         if self.is_xymid:  # 移动中心点到格子中间
             midyx = torch.true_divide(1, rowcol) / 2
             ancs_yx = ancs_yx + midyx
         ancs_wh = torch.tensor(ancs_wh,
                                device=device).repeat(num_anc_one, 1)
         ancs_xy = ancs_yx[:, [1, 0]]
         ans_xywh = torch.cat([ancs_xy, ancs_wh], dim=-1)
         ret_ancs = torch.cat([ret_ancs, ans_xywh], dim=0)
     if self.anchors_clip:  # 对于xywh 来说这个参数 是没有用的
         ret_ancs = xywh2ltrb(ret_ancs)
         ret_ancs.clamp_(min=0, max=1)  # 去除超边际的
         ret_ancs = ltrb2xywh(ret_ancs)
     if self.is_real_size:
         ret_ancs = ret_ancs * torch.tensor(self.img_in_size)[None].repeat(
             1, 2)
     # __d = 1
     if self.device is not None:
         ret_ancs = ret_ancs.to(self.device)
     return ret_ancs
Beispiel #4
0
    def get_stage_res(self, pssd, mask_pos, pscores, plabels):
        ids_batch1, _ = torch.where(mask_pos)

        preg, pcls = pssd
        batch, c, hw = preg.shape
        preg = preg.permute(0, 2, 1)  # 回归参数

        ptxywh_3d = preg
        ''' 预测 这里是修复是 xywh'''
        # 装入GPU
        ancs_xywh_3d = self.anc_obj.ancs_xywh.unsqueeze(0).repeat(batch, 1, 1)
        gxywh = boxes_decode4ssd(self.cfg, ptxywh_3d, ancs_xywh_3d)
        pboxes_ltrb1 = xywh2ltrb(gxywh[mask_pos])
        pboxes_ltrb1.clamp_(min=0., max=1.)  # 预测不返回

        pscores1 = pscores[mask_pos]
        plabels1 = plabels[mask_pos]
        plabels1 = plabels1  # 这里不是用的bce 不需要再加1

        return ids_batch1, pboxes_ltrb1, plabels1, pscores1
Beispiel #5
0
    def forward(self, pyolos, targets, imgs_ts=None):
        '''

        :param pyolos: torch.Size([3, 40, 13, 13]) [conf-1,class-3,box4] 5*8=40
            d19 torch.Size([2, 81, 13, 13])  9* conf +type4+ box4
        :param targets:
            target['boxes'] = target['boxes'].to(device)
            target['labels'] = target['labels'].to(device)
            target['size'] = target['size']
            target['image_id'] = int
        :param imgs_ts:
        :return:
        '''
        cfg = self.cfg
        device = pyolos.device
        batch, c, h, w = pyolos.shape
        s_ = 1 + cfg.NUM_CLASSES
        # [3, 40, 13, 13] -> [3, 8, 5, 13*13] -> [3, 169, 5, 8]
        pyolos = pyolos.view(batch, s_ + 4, cfg.NUM_ANC, - 1).permute(0, 3, 2, 1).contiguous()
        # [3, 169, 5, 8] -> [3, 169*5, 8]
        pyolos = pyolos.view(batch, -1, s_ + 4)
        preg_pos = pyolos[..., s_:s_ + 4]

        '''--------------gt匹配---------------'''
        # conf-1, cls-num_class, txywh-4, weight-1, gltrb-4
        if cfg.MODE_TRAIN == 4:
            gdim = 1 + cfg.NUM_CLASSES + 4 + 1 + 4 + 1  # torch.Size([3, 13, 13, 5, 13])
        else:
            gdim = 1 + cfg.NUM_CLASSES + 4 + 1 + 4  # torch.Size([3, 13, 13, 5, 13])

        gyolos = torch.empty((batch, h, w, cfg.NUM_ANC, gdim), device=device)

        # 匹配GT
        for i, target in enumerate(targets):  # batch遍历
            gboxes_ltrb_b = target['boxes']  # ltrb
            glabels_b = target['labels']

            # conf-1, cls-num_class, txywh-4, weight-1, gltrb-4
            if cfg.MODE_TRAIN == 4:
                gyolos[i] = fmatch4yolov2_99(
                    gboxes_ltrb_b=gboxes_ltrb_b,
                    glabels_b=glabels_b,
                    grid=h,  # 7 只有一层
                    gdim=gdim,
                    device=device,
                    cfg=cfg,
                    preg_b=preg_pos[i],
                    img_ts=imgs_ts[i],
                )
            else:
                gyolos[i] = fmatch4yolov2(
                    gboxes_ltrb_b=gboxes_ltrb_b,
                    glabels_b=glabels_b,
                    grid=h,  # 7 只有一层
                    gdim=gdim,
                    device=device,
                    cfg=cfg,
                    img_ts=imgs_ts[i],
                )

            '''可视化验证'''
            if cfg.IS_VISUAL:
                # conf-1, cls-num_class, txywh-4, weight-1, gltrb-4
                gyolo_test = gyolos[i].clone()  # torch.Size([32, 13, 13, 9])
                gyolo_test = gyolo_test.view(-1, gdim)
                gconf_one = gyolo_test[:, 0]
                # mask_pos = torch.logical_or(gconf_one == 1, gconf_one == -1)
                mask_pos_2d = gconf_one == 1

                gtxywh = gyolo_test[:, 1 + cfg.NUM_CLASSES:1 + cfg.NUM_CLASSES + 4]
                # 这里是修复是 xy
                _xy_grid = gtxywh[:, :2] + f_mershgrid(h, w, is_rowcol=False, num_repeat=cfg.NUM_ANC).to(device)
                hw_ts = torch.tensor((h, w), device=device)
                gtxywh[:, :2] = torch.true_divide(_xy_grid, hw_ts)
                gtxywh = gtxywh[mask_pos_2d]

                gtxywh[:, 2:4] = torch.exp(gtxywh[:, 2:]) / h  # 原图归一化

                from f_tools.pic.enhance.f_data_pretreatment4pil import f_recover_normalization4ts
                img_ts = f_recover_normalization4ts(imgs_ts[i])
                from torchvision.transforms import functional as transformsF
                img_pil = transformsF.to_pil_image(img_ts).convert('RGB')
                import numpy as np
                img_np = np.array(img_pil)
                f_show_od_np4plt(img_np, gboxes_ltrb=gboxes_ltrb_b.cpu()
                                 , pboxes_ltrb=xywh2ltrb(gtxywh.cpu()), is_recover_size=True,
                                 grids=(h, w))

        # torch.Size([32, 13, 13, 5, 13]) -> [32, 13*13*5, 13]
        gyolos = gyolos.view(batch, -1, gdim)
        gconf = gyolos[:, :, 0]  # 正例使用1  torch.Size([32, 910])
        mask_pos_2d = gconf > 0
        mask_neg_2d = gconf == 0  # 忽略-1 不管
        nums_pos = (mask_pos_2d.sum(-1).to(torch.float)).clamp(min=torch.finfo(torch.float16).eps)
        nums_neg = (mask_neg_2d.sum(-1).to(torch.float)).clamp(min=torch.finfo(torch.float16).eps)
        pyolos_pos = pyolos[mask_pos_2d]  # torch.Size([32, 845, 8]) -> torch.Size([40, 8])
        gyolos_pos = gyolos[mask_pos_2d]  # torch.Size([32, 845, 13]) -> torch.Size([40, 8])

        ''' ----------------cls损失---------------- '''
        pcls_sigmoid_pos = pyolos_pos[:, 1:s_].sigmoid()
        gcls_pos = gyolos_pos[:, 1:s_]
        _loss_val = x_bce(pcls_sigmoid_pos, gcls_pos, reduction="none")  # torch.Size([46, 3])
        # torch.Size([46, 3]) -> val
        l_cls = _loss_val.sum(-1).mean() * cfg.LOSS_WEIGHT[2]

        ''' ----------------conf损失 ---------------- '''
        pconf_sigmoid = pyolos[:, :, 0].sigmoid()  # 这个需要归一化 torch.Size([3, 845])

        # ------------conf-mse ------------
        # _loss_val = F.mse_loss(pconf_sigmoid, gconf, reduction="none")
        # l_conf_pos = ((_loss_val * mask_pos_2d).sum(-1) / nums_pos).mean() * 10
        # l_conf_neg = ((_loss_val * mask_neg_2d).sum(-1) / nums_neg).mean() * 30

        # ------------ focalloss   ------------
        mash_ignore_2d = torch.logical_not(torch.logical_or(mask_pos_2d, mask_neg_2d))
        l_pos, l_neg = focalloss(pconf_sigmoid, gconf, mask_pos=mask_pos_2d,
                                 mash_ignore=mash_ignore_2d, is_debug=True, alpha=0.5)
        l_conf_pos = (l_pos.sum(-1).sum(-1) / nums_pos).mean()
        l_conf_neg = (l_neg.sum(-1).sum(-1) / nums_neg).mean() * 3

        ''' ---------------- box损失 ----------------- '''
        log_dict = {}
        if cfg.MODE_TRAIN == 4:
            # ------------ iou损失   ------------
            # 解码pxywh 计算预测与 GT 的 iou 作为 gconf
            preg_pos = pyolos_pos[:, s_:s_ + 4]
            gltrb_pos_tx = gyolos_pos[:, s_ + 4 + 1:s_ + 4 + 1 + 4]
            match_anc_ids = gyolos_pos[:, s_ + 4 + 1 + 4]

            # 解码yolo2 特图尺寸
            pxy_pos_sigmoid = preg_pos[..., :2].sigmoid()

            # 这里与yolo1不一样
            match_ancs = torch.tensor(cfg.ANCS_SCALE, device=device)[match_anc_ids.long()]
            pwh_pos_scale = torch.exp(preg_pos[..., 2:4]) * match_ancs * h  # 恢复到特图
            pzxywh = torch.cat([pxy_pos_sigmoid, pwh_pos_scale], -1)

            iou_zg = bbox_iou4one_2d(xywh2ltrb(pzxywh), gltrb_pos_tx, is_giou=True)
            # iou_zg = bbox_iou4y(xywh2ltrb4ts(pzxywh), gltrb_pos_tx, GIoU=True)
            # print(iou_zg)
            l_reg = (1 - iou_zg).mean() * 2

            ''' ---------------- loss完成 ----------------- '''
            l_total = l_conf_pos + l_conf_neg + l_cls + l_reg
            log_dict['l_reg'] = l_reg.item()
        else:
            # ------------ mse+bce   ------------ 666666
            # conf-1, cls-num_class, txywh-4, weight-1, gltrb-4
            pxy_pos_sigmoid = pyolos_pos[:, s_:s_ + 2].sigmoid()  # 这个需要归一化
            pwh_pos_scale = pyolos_pos[:, s_ + 2:s_ + 4]
            weight_pos = gyolos_pos[:, s_ + 4 + 1]  # torch.Size([32, 845])
            gtxy_pos = gyolos_pos[:, s_:s_ + 2]  # [nn]
            gtwh_pos = gyolos_pos[:, s_ + 2:s_ + 4]

            _loss_val = x_bce(pxy_pos_sigmoid, gtxy_pos, reduction="none")
            l_txty = (_loss_val.sum(-1) * weight_pos).mean()
            _loss_val = F.mse_loss(pwh_pos_scale, gtwh_pos, reduction="none")
            l_twth = (_loss_val.sum(-1) * weight_pos).mean()

            ''' ---------------- loss完成 ----------------- '''
            l_total = l_conf_pos + l_conf_neg + l_cls + l_txty + l_twth
            log_dict['l_xy'] = l_txty.item()
            log_dict['l_wh'] = l_twth.item()

        log_dict['l_total'] = l_total.item()
        log_dict['l_conf_pos'] = l_conf_pos.item()
        log_dict['l_conf_neg'] = l_conf_neg.item()
        log_dict['l_cls'] = l_cls.item()

        log_dict['p_max'] = pconf_sigmoid.max().item()
        log_dict['p_min'] = pconf_sigmoid.min().item()
        log_dict['p_mean'] = pconf_sigmoid.mean().item()
        return l_total, log_dict
Beispiel #6
0
    def forward(self, pyolos, targets, imgs_ts=None):
        '''

        :param pyolos: torch.Size([2, 45, 13, 13])
        :param targets:
        :param imgs_ts:
        :return:
        '''
        cfg = self.cfg
        device = pyolos.device
        batch, c, h, w = pyolos.shape  # torch.Size([2, 45, 13, 13])

        # [3, 40, 13, 13] -> [3, 8, 5, 13*13] -> [3, 169, 5, 8]
        pyolos = pyolos.view(batch, 1 + cfg.NUM_CLASSES + 4, cfg.NUM_ANC, - 1).permute(0, 3, 2, 1).contiguous()

        # [3, 169, 5, 8] -> [3, 169*5, 8]
        pyolos = pyolos.view(batch, h * w * cfg.NUM_ANC, -1)
        # pyolos = pyolos.view(batch, -1, s_ + 4)

        preg = pyolos[..., 1 + cfg.NUM_CLASSES:1 + cfg.NUM_CLASSES + 4]  # torch.Size([2, 169, 5, 4])
        pltrb = boxes_decode4yolo2_v2(preg, h, w, cfg)  # 输出原图归一化 用于更新conf [2, 845, 4]

        '''--------------gt匹配---------------'''
        # conf-1, cls-1, txywh-4, weight-1, gltrb-4
        if cfg.MODE_TRAIN == 99 or cfg.MODE_TRAIN == 98:
            gdim = 1 + 1 + 4 + 1 + 4

        gyolos = torch.empty((batch, h, w, cfg.NUM_ANC, gdim), device=device)

        # 匹配GT
        for i, target in enumerate(targets):  # batch遍历
            gboxes_ltrb_b = target['boxes']  # ltrb
            glabels_b = target['labels']

            # conf-1, cls-num_class, txywh-4, weight-1, gltrb-4
            if cfg.MODE_TRAIN == 99 or cfg.MODE_TRAIN == 98:
                gyolos[i] = fmatch4yolov2_99(
                    gboxes_ltrb_b=gboxes_ltrb_b,
                    glabels_b=glabels_b,
                    grid=h,  # 7 只有一层
                    gdim=gdim,
                    device=device,
                    cfg=cfg,
                    preg_b=preg[i],
                    img_ts=imgs_ts[i],
                )

            '''可视化验证'''
            if cfg.IS_VISUAL:
                # conf-1, cls-num_class, txywh-4, weight-1, gltrb-4
                gyolo_test = gyolos[i].clone()  # torch.Size([32, 13, 13, 9])
                gyolo_test = gyolo_test.view(-1, gdim)
                gconf_one = gyolo_test[:, 0]
                # mask_pos = torch.logical_or(gconf_one == 1, gconf_one == -1)
                mask_pos_2d = gconf_one == 1

                gtxywh = gyolo_test[:, 1 + cfg.NUM_CLASSES:1 + cfg.NUM_CLASSES + 4]
                # 这里是修复是 xy
                _xy_grid = gtxywh[:, :2] + f_mershgrid(h, w, is_rowcol=False, num_repeat=cfg.NUM_ANC).to(device)
                hw_ts = torch.tensor((h, w), device=device)
                gtxywh[:, :2] = torch.true_divide(_xy_grid, hw_ts)
                gtxywh = gtxywh[mask_pos_2d]

                gtxywh[:, 2:4] = torch.exp(gtxywh[:, 2:]) / h  # 原图归一化

                from f_tools.pic.enhance.f_data_pretreatment4pil import f_recover_normalization4ts
                img_ts = f_recover_normalization4ts(imgs_ts[i])
                from torchvision.transforms import functional as transformsF
                img_pil = transformsF.to_pil_image(img_ts).convert('RGB')
                import numpy as np
                img_np = np.array(img_pil)
                f_show_od_np4plt(img_np, gboxes_ltrb=gboxes_ltrb_b.cpu()
                                 , pboxes_ltrb=xywh2ltrb(gtxywh.cpu()), is_recover_size=True,
                                 grids=(h, w))

        # conf-1, cls-num_class, txywh-4, weight-1, gltrb-4
        # torch.Size([32, 13, 13, 5, 11]) -> [32, 13*13*5, 11] ->[2, 845, 11]
        gyolos = gyolos.view(batch, -1, gdim)
        gconf = gyolos[:, :, 0]  # 正例使用1  torch.Size([32, 910])
        # mask_pos_3d = gyolos[:, :, :1] > 0
        # mask_neg_3d = gyolos[:, :, :1] == 0

        mask_pos_2d = gconf > 0
        mask_neg_2d = gconf == 0  # 忽略-1 不管
        nums_pos = (mask_pos_2d.sum(-1).to(torch.float)).clamp(min=torch.finfo(torch.float16).eps)
        nums_neg = (mask_neg_2d.sum(-1).to(torch.float)).clamp(min=torch.finfo(torch.float16).eps)
        pyolos_pos = pyolos[mask_pos_2d]  # torch.Size([32, 845, 8]) -> torch.Size([40, 8])
        gyolos_pos = gyolos[mask_pos_2d]  # torch.Size([32, 845, 13]) -> torch.Size([40, 8])

        # [2, 845, 4] ->
        # iou_zg = bbox_iou4one(pltrb, gyolos[..., 1 + 1 + 4 + 1:1 + 1 + 4 + 1 + 4], is_giou=True)
        iou_zg = bbox_iou4one(pltrb, gyolos[..., 1 + 1 + 4 + 1:1 + 1 + 4 + 1 + 4], is_ciou=True)

        ''' ----------------cls损失---------------- '''
        # pcls_sigmoid_pos = pyolos_pos[:, 1:1 + cfg.NUM_CLASSES].sigmoid()
        pcls_pos = pyolos_pos[:, 1:1 + cfg.NUM_CLASSES]
        gcls_pos = gyolos_pos[:, 1].long()
        # torch.Size([3, 4]) ^^ tensor([2., 2., 3.])
        _loss_val = F.cross_entropy(pcls_pos, gcls_pos, reduction="none")
        # _loss_val = x_bce(pcls_sigmoid_pos, gcls_pos, reduction="none")  # torch.Size([46, 3])
        # torch.Size([46, 3]) -> val
        l_cls = _loss_val.sum(-1).mean()

        ''' ----------------conf损失 ---------------- '''
        pconf_sigmoid = pyolos[:, :, 0].sigmoid()  # 这个需要归一化 torch.Size([3, 845])
        # ------------conf-mse ------------
        _loss_val = F.mse_loss(pconf_sigmoid, iou_zg, reduction="none")  # 这理用的IOU
        l_conf_pos = ((_loss_val * mask_pos_2d).sum(-1) / nums_pos).mean() * 5.
        l_conf_neg = ((_loss_val * mask_neg_2d).sum(-1) / nums_neg).mean() * 1.

        ''' ---------------- box损失 ----------------- '''
        pxy_pos_sigmoid = pyolos_pos[:, 1 + cfg.NUM_CLASSES:1 + cfg.NUM_CLASSES + 2].sigmoid()  # 这个需要归一化
        pwh_pos_scale = pyolos_pos[:, 1 + cfg.NUM_CLASSES + 2:1 + cfg.NUM_CLASSES + 4]
        weight_pos = gyolos_pos[:, 1 + 1 + 4 + 1]  # torch.Size([32, 845])
        gtxy_pos = gyolos_pos[:, 1 + 1:1 + 1 + 2]  # [nn]
        gtwh_pos = gyolos_pos[:, 1 + 1 + 2:1 + 1 + 4]

        _loss_val = x_bce(pxy_pos_sigmoid, gtxy_pos, reduction="none")
        l_txty = (_loss_val.sum(-1) * weight_pos).mean()
        _loss_val = F.mse_loss(pwh_pos_scale, gtwh_pos, reduction="none")
        l_twth = (_loss_val.sum(-1) * weight_pos).mean()

        ''' ---------------- loss完成 ----------------- '''
        log_dict = {}
        l_total = l_conf_pos + l_conf_neg + l_cls + l_txty + l_twth
        log_dict['l_total'] = l_total.item()
        log_dict['l_xy'] = l_txty.item()
        log_dict['l_wh'] = l_twth.item()
        log_dict['l_conf_pos'] = l_conf_pos.item()
        log_dict['l_conf_neg'] = l_conf_neg.item()
        log_dict['l_cls'] = l_cls.item()

        return l_total, log_dict
Beispiel #7
0
    def forward(self, outs, targets, imgs_ts=None):
        '''

        :param outs: tuple
            ptxywh, torch.Size([32, 10842, 4*8])
            pcls, torch.Size([32, 10842, 3])
        :param targets:
        :param imgs_ts:
        :return:
        '''
        cfg = self.cfg
        preg_32d, pcls = outs  # torch.Size([5, 3614, 4])
        device = preg_32d.device
        batch, pdim1, c = preg_32d.shape
        ''' conf-1, cls-3,  与预测对应gt_ltrb-4 ,ious_zg-1 ,'''
        gdim = 1 + cfg.NUM_CLASSES + 4 + 1
        if cfg.NUM_KEYPOINTS > 0:
            gdim += cfg.NUM_KEYPOINTS
        gretinas = torch.empty((batch, pdim1, gdim), device=device)

        for i in range(batch):
            # if cfg.IS_VISUAL:
            #     _img_ts = imgs_ts[i].clone()
            #     from f_tools.pic.enhance.f_data_pretreatment4pil import f_recover_normalization4ts
            #     _img_ts = f_recover_normalization4ts(_img_ts)
            #     f_show_od_ts4plt(_img_ts, gboxes_ltrb=boxes_ltrb_one.cpu(),
            #                      is_recover_size=True,
            #                      # grids=grids_ts.cpu().numpy(),
            #                      # plabels_text=pconf_b[index_match_dim].sigmoid(),
            #                      # glabels_text=colrow_index[None]
            #                      )

            gboxes_ltrb_b = targets[i]['boxes']
            glabels_b = targets[i]['labels']
            if cfg.NUM_KEYPOINTS > 0:
                gkeypoints_b = targets['keypoints']  # torch.Size([batch, 10])
            else:
                gkeypoints_b = None

            # gretinas[i] = matchs_gfl(cfg, dim=gdim,
            #                          gboxes_ltrb_b=gboxes_ltrb_b, glabels_b=glabels_b, anc_obj=self.anc_obj,
            #                          mode='atss', preg_32d_b=preg_32d[i], img_ts=imgs_ts[i])

            gretinas[i] = pos_match_retina4cls(cfg,
                                               dim=gdim,
                                               gkeypoints_b=None,
                                               gboxes_ltrb_b=gboxes_ltrb_b,
                                               glabels_b=glabels_b,
                                               anc_obj=self.anc_obj,
                                               ptxywh_b=preg_32d[i],
                                               img_ts=imgs_ts[i])

            # 匹配正例可视化
            if cfg.IS_VISUAL:
                _mask_pos = gretinas[i, :, 0] > 0  # 3d ->1d
                _img_ts = imgs_ts[i].clone()
                anc_ltrb = xywh2ltrb(self.anc_obj.ancs_xywh)[_mask_pos]
                from f_tools.pic.enhance.f_data_pretreatment4pil import f_recover_normalization4ts
                _img_ts = f_recover_normalization4ts(_img_ts)
                flog.debug('gt数 %s , 正例数量 %s' %
                           (gboxes_ltrb_b.shape[0], anc_ltrb.shape[0]))
                f_show_od_ts4plt(
                    _img_ts,
                    gboxes_ltrb=gboxes_ltrb_b.cpu(),
                    pboxes_ltrb=anc_ltrb.cpu(),
                    is_recover_size=True,
                    # grids=grids_ts.cpu().numpy(),
                    # plabels_text=pconf_b[index_match_dim].sigmoid(),
                    # glabels_text=colrow_index[None]
                )

        mask_pos_2d = gretinas[:, :, 0] > 0  # torch.Size([2, 32526])
        nums_pos = (mask_pos_2d.sum(-1).to(
            torch.float)).clamp(min=torch.finfo(torch.float16).eps)
        mask_neg_2d = gretinas[:, :, 0] == 0  # 不需要负例
        mash_ignore_2d = gretinas[:, :, 0] == -1  # 忽略没有
        ''' conf-1, cls-3,  与预测对应gt_ltrb-4 ,ious_zg-1 ,'''
        s_ = 1 + cfg.NUM_CLASSES
        ''' ---------------- 类别损失 ---------------- '''
        pcls_sigmoid = pcls.sigmoid()  # 统一归一化 torch.Size([5, 3614, 3])
        gcls = gretinas[:, :, 1:s_]  # torch.Size([5, 3614, 3])
        l_pos, l_neg = focalloss(pcls_sigmoid,
                                 gcls,
                                 mask_pos=mask_pos_2d,
                                 mash_ignore=mash_ignore_2d,
                                 is_debug=True,
                                 alpha=0.5)
        l_cls_pos = (l_pos.sum(-1).sum(-1) / nums_pos).mean() * 7
        l_cls_neg = (l_neg.sum(-1).sum(-1) / nums_pos).mean() * 7
        ''' ---------------- box损失 ----------------- '''
        # 正例筛选后计算
        gtxywh = gretinas[:, :, s_:s_ + 4]
        # _loss_val = F.mse_loss(ptxywh, gtxywh, reduction="none") * mask_pos.unsqueeze(-1)
        _loss_val = F.smooth_l1_loss(
            preg_32d, gtxywh, reduction="none") * mask_pos_2d.unsqueeze(-1)
        # _loss_val = torch.abs(ptxywh - gtxywh) * mask_pos.unsqueeze(-1)
        l_box = (_loss_val.sum(-1).sum(-1) / nums_pos).mean()

        # ''' ---------------- 正例box损失 giou与cls分数容合 ----------------- '''
        # # 这个损失加和
        # weight_cls = pcls_sigmoid.detach()
        # weight_cls = weight_cls.max(dim=-1)[0]
        # ious_zg = gretinas[:, :, 0]
        # _loss_val = (1 - ious_zg) * weight_cls * mask_pos_2d
        # loss_box = (_loss_val.sum(-1) / nums_pos).mean() * cfg.LOSS_WEIGHT[2]  # 2
        # # loss_box = (_loss_val.sum(-1)).mean() * cfg.LOSS_WEIGHT[2]  # 2
        #
        # ''' ---------------- 正例dfl损失 ---------------- '''
        # ''' ious_zg-1 , cls-3,  与预测对应 gt_ltrb-4 '''
        # gt_ltrb = gretinas[:, :, s_:s_ + 4]  # 匹配的回归值 在0~7之间
        # # preg_32d torch.Size([5, 3614, 32]) gt_ltrb
        # # torch.Size([5, 3614, 4])
        # _loss_val = distribution_focal_loss(cfg, preg_32d, gt_ltrb, mask_pos_2d)
        # loss_dfl = ((_loss_val.sum(-1) * mask_pos_2d).sum(-1) / nums_pos).mean() * cfg.LOSS_WEIGHT[3]
        #
        # ''' ---------------- gfl 损失 使用IOU分---------------- '''
        # # 这个需要每一个正例平均
        # gcls4iou = gretinas[:, :, 1:s_] * ious_zg.unsqueeze(-1)
        # l_pos, l_neg = quality_focal_loss2(pcls_sigmoid, gcls4iou, mask_pos=mask_pos_2d, is_debug=True)
        # # l_pos, l_neg = quality_focal_loss(pcls_sigmoid, gcls, ious_zg, mask_pos=mask_pos, is_debug=True)
        # loss_gfl_pos = (l_pos.sum(-1).sum(-1) / nums_pos).mean() * cfg.LOSS_WEIGHT[0]  # 0.25
        # loss_gfl_neg = (l_neg.sum(-1).sum(-1) / nums_pos).mean() * cfg.LOSS_WEIGHT[1]

        # l_pos, l_neg = focalloss(pcls_sigmoid, gcls, mask_pos=mask_pos, is_debug=True)
        # loss_gfl_pos = (l_pos.sum(-1).sum(-1) / nums_pos).mean() * cfg.LOSS_WEIGHT[0]
        # loss_gfl_neg = (l_neg.sum(-1).sum(-1) / nums_pos).mean() * cfg.LOSS_WEIGHT[1]
        # loss_total = loss_gfl_pos + loss_gfl_neg + loss_dfl + loss_box

        loss_total = l_cls_pos + l_cls_neg + l_box

        log_dict = OrderedDict()
        log_dict['l_total'] = loss_total.item()
        log_dict['l_cls_pos'] = l_cls_pos.item()
        log_dict['l_cls_neg'] = l_cls_neg.item()
        log_dict['l_box'] = l_box.item()

        log_dict['cls_max'] = pcls_sigmoid.max().item()
        log_dict['cls_mean'] = pcls_sigmoid.mean().item()
        log_dict['cls_min'] = pcls_sigmoid.min().item()

        return loss_total, log_dict
Beispiel #8
0
    def forward(self, outs, targets, imgs_ts=None):
        '''

        :param outs: tuple
            ptxywh, torch.Size([2, 32526, 4])
            pcls, torch.Size([2, 32526, 4]) 已归一化 cls+1
        :param targets:
        :param imgs_ts:
        :return:
        '''
        cfg = self.cfg
        ptxywh, pcategory_sigmoid = outs
        pcategory_sigmoid = pcategory_sigmoid.sigmoid()  # 统一归一化
        pconf_sigmoid = pcategory_sigmoid[:, :, 0]  # torch.Size([2, 32526])
        pcls_sigmoid = pcategory_sigmoid[:, :, 1:]  # 已sigmoid
        device = ptxywh.device
        batch, pdim1, c = ptxywh.shape

        # conf-1, cls-num_class, txywh-4, keypoint-nn  = 8 + nn
        gdim = 1 + cfg.NUM_CLASSES + 4
        if cfg.NUM_KEYPOINTS > 0:
            gdim += cfg.NUM_KEYPOINTS
        gretinas = torch.zeros((batch, pdim1, gdim), device=device)
        s_ = 1 + cfg.NUM_CLASSES  # 前面 两个是 conf-1, cls-3,

        for i in range(batch):
            # if cfg.IS_VISUAL:
            #     _img_ts = imgs_ts[i].clone()
            #     from f_tools.pic.enhance.f_data_pretreatment4pil import f_recover_normalization4ts
            #     _img_ts = f_recover_normalization4ts(_img_ts)
            #     f_show_od_ts4plt(_img_ts, gboxes_ltrb=boxes_ltrb_one.cpu(),
            #                      is_recover_size=True,
            #                      # grids=grids_ts.cpu().numpy(),
            #                      # plabels_text=pconf_b[index_match_dim].sigmoid(),
            #                      # glabels_text=colrow_index[None]
            #                      )

            gboxes_ltrb_b = targets[i]['boxes']
            glabels_b = targets[i]['labels']
            if cfg.NUM_KEYPOINTS > 0:
                gkeypoints_b = targets['keypoints']  # torch.Size([batch, 10])
            else:
                gkeypoints_b = None

            # 这里是一批的 mask_neg_b, mash_ignore_b 可能为None
            boxes_index, mask_pos_b, mask_neg_b, mash_ignore_b = matchs_gt_b(
                cfg,
                gboxes_ltrb_b=gboxes_ltrb_b,
                glabels_b=glabels_b,
                anc_obj=self.anc_obj,
                mode='iou',
                # mode='atss',
                ptxywh_b=ptxywh[i],
                img_ts=imgs_ts[i],
                num_atss_topk=9)
            '''正反例设置'''
            gretinas[i][mask_pos_b, 0] = torch.tensor(1., device=device)
            if mash_ignore_b is not None:
                gretinas[i][mash_ignore_b, 0] = torch.tensor(-1.,
                                                             device=device)

            labels_b = labels2onehot4ts(glabels_b - 1, cfg.NUM_CLASSES)
            gretinas[i][mask_pos_b,
                        1:s_] = labels_b[boxes_index][mask_pos_b].type(
                            torch.float)  # 正例才匹配
            # _gtxywh = boxes_encode4retina(cfg, self.anc_obj, gboxes_ltrb_b[boxes_index])
            # _gtxywh = boxes_encode4ssd(cfg, self.anc_obj, gboxes_ltrb_b[boxes_index])
            gretinas[i][mask_pos_b,
                        s_:s_ + 4] = gboxes_ltrb_b[boxes_index][mask_pos_b]

            # gretinas[i] = pos_match_retina(cfg, dim=gdim, gkeypoints_b=None,
            #                                gboxes_ltrb_b=gboxes_ltrb_b, glabels_b=glabels_b, anc_obj=self.anc_obj,
            #                                ptxywh_b=ptxywh[i], img_ts=imgs_ts[i])

            # 匹配正例可视化
            if cfg.IS_VISUAL:
                _mask_pos = gretinas[i, :, 0] > 0  # 3d ->1d
                _img_ts = imgs_ts[i].clone()
                anc_ltrb = xywh2ltrb(self.anc_obj.ancs_xywh)[_mask_pos]
                from f_tools.pic.enhance.f_data_pretreatment4pil import f_recover_normalization4ts
                _img_ts = f_recover_normalization4ts(_img_ts)
                flog.debug('gt数 %s , 正例数量 %s' %
                           (gboxes_ltrb_b.shape[0], anc_ltrb.shape[0]))
                f_show_od_ts4plt(
                    _img_ts,
                    gboxes_ltrb=gboxes_ltrb_b.cpu(),
                    pboxes_ltrb=anc_ltrb.cpu(),
                    is_recover_size=True,
                    # grids=grids_ts.cpu().numpy(),
                    # plabels_text=pconf_b[index_match_dim].sigmoid(),
                    # glabels_text=colrow_index[None]
                )

        mask_pos_2d = gretinas[:, :, 0] > 0  # torch.Size([2, 32526])
        nums_pos = (mask_pos_2d.sum(-1).to(
            torch.float)).clamp(min=torch.finfo(torch.float16).eps)
        # mask_neg_2d = gretinas[:, :, 0] == 0
        mask_ignore_2d = gretinas[:, :, 0] == -1
        # s_ = 1 + cfg.NUM_CLASSES
        ''' ----------------cls损失---------------- '''
        # pcls_sigmoid 已归一
        gcls = gretinas[:, :, 1:s_]
        _loss_val = x_bce(pcls_sigmoid, gcls, reduction="none")
        l_cls = ((_loss_val.sum(-1) * mask_pos_2d).sum(-1) /
                 nums_pos).mean() * cfg.LOSS_WEIGHT[2]
        ''' ----------------conf损失 ---------------- '''
        # pconf_sigmoid 已归一
        gconf = gretinas[:, :, 0]  # 已归一化
        _loss_val = x_bce(pconf_sigmoid, gconf, reduction="none")
        mask_neg_hard = f_ohem(_loss_val,
                               nums_pos * 3,
                               mask_pos=mask_pos_2d,
                               mash_ignore=mask_ignore_2d)
        l_conf_pos = ((_loss_val * mask_pos_2d).sum(-1) /
                      nums_pos).mean() * cfg.LOSS_WEIGHT[0]
        l_conf_neg = ((_loss_val * mask_neg_hard).sum(-1) /
                      nums_pos).mean() * cfg.LOSS_WEIGHT[1]

        # l_pos, l_neg = focalloss(pconf_sigmoid, gconf, mask_pos=mask_pos_2d, mash_ignore=mask_ignore_2d,
        #                          is_debug=True, alpha=0.5)
        # l_conf_pos = (l_pos.sum(-1).sum(-1) / nums_pos).mean() * 7
        # l_conf_neg = (l_neg.sum(-1).sum(-1) / nums_pos).mean() * 7

        # l_pos, l_neg = focalloss(pconf, gconf, mask_pos=mask_pos, mash_ignore=mash_ignore,
        #                          alpha=0.25, gamma=2,
        #                          reduction='none', is_debug=True)
        # loss_conf_pos = (l_pos.sum(-1) / nums_pos).mean() * cfg.LOSS_WEIGHT[0]
        # loss_conf_neg = l_neg.sum(-1).mean() * cfg.LOSS_WEIGHT[1]
        ''' ---------------- 回归损失 ----------------- '''
        # 正例筛选后计算
        gboxes_ltrb_m_pos = gretinas[:, :, s_:s_ + 4][mask_pos_2d]
        ancs_xywh_m_pos = self.anc_obj.ancs_xywh.unsqueeze(0).repeat(
            batch, 1, 1)[mask_pos_2d]
        gtxywh_pos = boxes_encode4ssd(cfg, ancs_xywh_m_pos,
                                      ltrb2xywh(gboxes_ltrb_m_pos))
        _loss_val = F.smooth_l1_loss(ptxywh[mask_pos_2d],
                                     gtxywh_pos,
                                     reduction="none")
        l_box = _loss_val.sum(-1).mean()

        log_dict = OrderedDict()
        loss_total = l_conf_pos + l_conf_neg + l_cls + l_box

        log_dict['l_total'] = loss_total.item()
        log_dict['l_conf_pos'] = l_conf_pos.item()
        log_dict['l_conf_neg'] = l_conf_neg.item()
        log_dict['loss_cls'] = l_cls.item()
        log_dict['l_box'] = l_box.item()

        log_dict['cls_max'] = pcls_sigmoid.max().item()
        log_dict['conf_max'] = pconf_sigmoid.max().item()

        log_dict['cls_mean'] = pcls_sigmoid.mean().item()
        log_dict['conf_mean'] = pconf_sigmoid.mean().item()

        log_dict['cls_min'] = pcls_sigmoid.min().item()
        log_dict['conf_min'] = pconf_sigmoid.min().item()

        return loss_total, log_dict
Beispiel #9
0
    def forward(self, pssd, targets, imgs_ts=None):
        '''

        :param pssd: preg, pcls = class+1 [2, 4, 8732]
        :param targets:
        :param imgs_ts:
        :return:
        '''
        cfg = self.cfg
        # pcls  classes+1 [b, 4, 8732]
        preg, pcls = pssd
        preg = preg.permute(0, 2, 1)  # [b, 4, 8732] -> [b, 8732, 4]
        device = preg.device
        batch, hw, c = preg.shape

        # cls_val-1, gltrb-4
        gdim = 1 + 4
        gssd = torch.empty((batch, hw, gdim), device=device)  # 每批会整体更新这里不需要赋0

        for i, target in enumerate(targets):  # batch遍历
            gboxes_ltrb_b = target['boxes']  # ltrb
            glabels_b = target['labels']

            boxes_index, mask_pos_b, mask_neg_b, mash_ignore_b = matchs_gt_b(
                cfg,
                gboxes_ltrb_b=gboxes_ltrb_b,
                glabels_b=glabels_b,
                anc_obj=self.anc_obj,
                mode='iou',
                ptxywh_b=preg[i],
                img_ts=imgs_ts[i],
                num_atss_topk=9)
            '''正反例设置 正例才匹配'''
            gssd[i][:, 0] = 0  # 是背景 这个要计算正反例 故需全fill 0
            gssd[i][mask_pos_b, 0] = glabels_b[boxes_index][mask_pos_b]
            gssd[i][mask_pos_b, 1:1 +
                    4] = gboxes_ltrb_b[boxes_index][mask_pos_b]  # gltrb-4
            '''可视化验证'''
            if cfg.IS_VISUAL:
                gssd_test = gssd[i].clone()
                # gssd_test = gssd_test.view(-1, gdim)
                gconf_one = gssd_test[:, 0]
                mask_pos_2d = gconf_one > 0
                flog.debug('mask_pos_2d 个数%s', mask_pos_2d.sum())
                # torch.Size([169, 4])
                anc_ltrb_pos = xywh2ltrb(self.anc_obj.ancs_xywh[mask_pos_2d])

                from f_tools.pic.enhance.f_data_pretreatment4pil import f_recover_normalization4ts
                img_ts = f_recover_normalization4ts(imgs_ts[i])
                from torchvision.transforms import functional as transformsF
                img_pil = transformsF.to_pil_image(img_ts).convert('RGB')
                import numpy as np
                img_np = np.array(img_pil)
                f_show_od_np4plt(
                    img_np,
                    gboxes_ltrb=gboxes_ltrb_b.cpu(),
                    pboxes_ltrb=anc_ltrb_pos.cpu(),  # ltrb
                    # other_ltrb=xywh2ltrb(self.anc_obj.ancs_xywh)[:100],
                    is_recover_size=True,
                    # grids=(h, w)
                )

        # cls_val-1, gltrb-4
        glabel = gssd[:, :, 0]  # 0为背景
        mask_pos_2d = glabel > 0
        nums_pos = (mask_pos_2d.sum(-1).to(
            torch.float)).clamp(min=torch.finfo(torch.float16).eps)
        # mask_neg_2d = glabel == 0 反例没用上
        # nums_neg = (mask_neg.sum(-1).to(torch.float)).clamp(min=torch.finfo(torch.float16).eps)
        ''' ---------------- 回归损失   ----------------- '''
        gboxes_ltrb_m_pos = gssd[:, :, 1:1 + 4][mask_pos_2d]
        ancs_xywh_m_pos = self.anc_obj.ancs_xywh.unsqueeze(0).repeat(
            batch, 1, 1)[mask_pos_2d]
        gtxywh_pos = boxes_encode4ssd(cfg, ancs_xywh_m_pos,
                                      ltrb2xywh(gboxes_ltrb_m_pos))
        _loss_val = F.smooth_l1_loss(preg[mask_pos_2d],
                                     gtxywh_pos,
                                     reduction="none")
        l_box = _loss_val.sum(-1).mean()
        ''' ---------------- 类别-cls损失 ---------------- '''
        # 自带softmax
        _loss_val = F.cross_entropy(pcls, glabel.long(), reduction="none")
        mask_neg_hard = f_ohem(_loss_val, nums_pos * 3, mask_pos=mask_pos_2d)
        l_conf_pos = ((_loss_val * mask_pos_2d).sum(-1) /
                      nums_pos).mean()  # 正例越多反例越多
        l_conf_neg = ((_loss_val * mask_neg_hard).sum(-1) / nums_pos).mean()

        log_dict = {}
        ''' ---------------- loss完成 ----------------- '''
        l_total = l_box + l_conf_pos + l_conf_neg

        log_dict['l_total'] = l_total.item()
        log_dict['l_conf_pos'] = l_conf_pos.item()
        log_dict['l_conf_neg'] = l_conf_neg.item()
        log_dict['l_box'] = l_box.item()

        # log_dict['p_max'] = pcls.max().item()
        # log_dict['p_min'] = pcls.min().item()
        # log_dict['p_mean'] = pcls.mean().item()
        return l_total, log_dict
Beispiel #10
0
    def forward(self, pyolos, targets, imgs_ts=None):
        '''

        :param pyolos: torch.Size([32, 6, 14, 14]) [conf-1,class-20,box4]
        :param targets:
        :param imgs_ts:
        :return:
        '''
        cfg = self.cfg
        device = pyolos.device
        batch, c, h, w = pyolos.shape  # torch.Size([32, 13,13, 8])
        # b,c,h,w -> b,c,hw -> b,hw,c  torch.Size([32, 169, 8])
        pyolos = pyolos.view(batch, c, -1).permute(0, 2, 1)
        s_ = 1 + cfg.NUM_CLASSES
        ptxywh = pyolos[..., s_:s_ + 4]  # torch.Size([32, 169, 4])

        # conf-1, cls-num_class, txywh-4, weight-1, gltrb-4
        gdim = 1 + cfg.NUM_CLASSES + 4 + 1 + 4
        gyolos = torch.empty((batch, h, w, gdim),
                             device=device)  # 每批会整体更新这里不需要赋0

        for i, target in enumerate(targets):  # batch遍历
            gboxes_ltrb_b = target['boxes']  # ltrb
            glabels_b = target['labels']
            '''
            yolo4
            1. 每层选一个匹配一个 anc与GT的IOU最大的一个
                技巧gt的xy可调整成 格子偏移与pxy匹配
            2. 其它的IOU>0.4忽略,除正例
            3. reg损失: 解码预测 pxy.sigmoid exp(pwh*anc) -> 进行IOU loss
                正例损失进行平均, 权重0.05
            4. cls损失: 
                label_smooth 标签平滑正则化, onehot* (1-0.01) + 0.01 /num_class
                pos_weight=0.5
                loss_weight=0.5 * num_classes / 80 = 0.01875
            5. conf损失:
                整体权重0.4  忽略的
            6. 每一层的损失全加起来
            '''
            gyolos[i] = fmatch4yolov1(
                gboxes_ltrb_b=gboxes_ltrb_b,
                glabels_b=glabels_b,
                grid=h,  # 7
                gdim=gdim,
                device=device,
                img_ts=imgs_ts[i],
                cfg=cfg,
                use_conf=True)
            '''可视化验证'''
            if cfg.IS_VISUAL:
                # conf-1, cls-num_class, txywh-4, weight-1, gltrb-4
                gyolo_test = gyolos[i].clone()  # torch.Size([32, 13, 13, 9])
                gyolo_test = gyolo_test.view(-1, gdim)
                gconf_one = gyolo_test[:, 0]
                mask_pos = gconf_one == 1  # [169]

                # torch.Size([169, 4])
                txywh_t = gyolo_test[:, 1 + cfg.NUM_CLASSES:1 +
                                     cfg.NUM_CLASSES + 4]

                # 这里是修复所有的xy
                zpxy_t = txywh_t[:, :2] + f_mershgrid(
                    h, w, is_rowcol=False).to(device)
                hw_ts = torch.tensor((h, w), device=device)
                zpxy = torch.true_divide(zpxy_t, hw_ts)
                zpwh = torch.exp(txywh_t[:, 2:]) / hw_ts
                zpxywh_pos = torch.cat([zpxy, zpwh], dim=-1)[mask_pos]

                from f_tools.pic.enhance.f_data_pretreatment4pil import f_recover_normalization4ts
                img_ts = f_recover_normalization4ts(imgs_ts[i])
                from torchvision.transforms import functional as transformsF
                img_pil = transformsF.to_pil_image(img_ts).convert('RGB')
                import numpy as np
                img_np = np.array(img_pil)
                f_show_od_np4plt(img_np,
                                 gboxes_ltrb=gboxes_ltrb_b.cpu(),
                                 pboxes_ltrb=xywh2ltrb(zpxywh_pos.cpu()),
                                 is_recover_size=True,
                                 grids=(h, w))

        gyolos = gyolos.view(batch, -1, gdim)  # b,hw,7
        gconf = gyolos[:, :, 0]  # torch.Size([5, 169])
        mask_pos = gconf > 0  # torch.Size([32, 169])
        # mask_pos = gconf == 1  # yolo1 gt 写死是1
        mask_neg = gconf == 0
        nums_pos = (mask_pos.sum(-1).to(
            torch.float)).clamp(min=torch.finfo(torch.float16).eps)
        nums_neg = (mask_neg.sum(-1).to(
            torch.float)).clamp(min=torch.finfo(torch.float16).eps)
        pyolos_pos = pyolos[mask_pos]  # torch.Size([32, 169, 13]) -> [nn, 13]
        gyolos_pos = gyolos[mask_pos]  # torch.Size([32, 169, 13]) -> [nn, 13]
        ''' ---------------- 类别-cls损失 ---------------- '''
        # # conf-1, cls-num_class, txywh-4, weight-1, gltrb-4
        pcls_sigmoid = pyolos[:, :, 1:s_].sigmoid()  # torch.Size([32, 169, 8])
        gcls = gyolos[:, :, 1:s_]  # torch.Size([32, 169, 13])
        _loss_val = x_bce(pcls_sigmoid, gcls, reduction="none")
        l_cls = ((_loss_val.sum(-1) * mask_pos).sum(-1) / nums_pos).mean()

        # pcls_sigmoid_pos = pyolos_pos[:, 1:s_].sigmoid()
        # gcls_pos = gyolos_pos[:, 1:s_]
        # _loss_val = x_bce(pcls_sigmoid_pos, gcls_pos, reduction="none")  # torch.Size([46, 3])
        # torch.Size([46, 3]) -> val
        # l_cls = _loss_val.sum(-1).mean()
        ''' ---------------- 类别-conf损失 ---------------- '''
        # conf-1, cls-num_class, txywh-4, weight-1, gltrb-4
        pconf_sigmoid = pyolos[:, :, 0].sigmoid()

        # ------------ conf-mse ------------''' 666666
        _loss_val = F.mse_loss(pconf_sigmoid, gconf,
                               reduction="none")  # 用MSE效果更好
        l_conf_pos = ((_loss_val * mask_pos).sum(-1) / nums_pos).mean() * 5.
        l_conf_neg = ((_loss_val * mask_neg).sum(-1) / nums_pos).mean() * 1.

        # 效果一样 169:1
        # pos_ = _loss_val[mask_pos]
        # l_conf_pos = pos_.mean() * 1
        # l_conf_neg = _loss_val[mask_neg].mean() * 3

        # ------------ conf_ohem  ap26_26 ------------'''
        # _loss_val = x_bce(pconf_sigmoid, gconf)
        # mask_ignore = torch.logical_not(torch.logical_or(mask_pos, mask_neg))
        # mask_neg_hard = f_ohem(_loss_val, nums_pos * 3, mask_pos=mask_pos, mash_ignore=mask_ignore)
        # l_conf_pos = ((_loss_val * mask_pos).sum(-1) / nums_pos).mean() * 3  # 正例越多反例越多
        # l_conf_neg = ((_loss_val * mask_neg_hard).sum(-1) / nums_pos).mean() * 3

        # ------------ focalloss   ------------
        # l_pos, l_neg = focalloss(pconf_sigmoid, gconf, mask_pos=mask_pos, is_debug=True, alpha=0.5)
        # l_conf_pos = (l_pos.sum(-1).sum(-1) / nums_pos).mean()
        # l_conf_neg = (l_neg.sum(-1).sum(-1) / nums_neg).mean() * 3

        log_dict = {}
        ''' ----------------回归损失   xy采用bce wh采用mes----------------- '''
        if cfg.MODE_TRAIN == 4:
            # ------------ iou损失   ------------
            # 解码pxywh 计算预测与 GT 的 iou 作为 gconf
            # preg_pos = pyolos_pos[:, s_:s_ + 4]
            # # 解码yolo1
            # pxy_pos_toff = preg_pos[..., :2].sigmoid()
            # pwh_pos = torch.exp(preg_pos[..., 2:])
            # pzxywh = torch.cat([pxy_pos_toff, pwh_pos], -1)

            # 这里是归一化的 gt
            gltrb_pos = gyolos_pos[:, s_ + 4 + 1:s_ + 4 + 1 + 4]

            ptxywh = pyolos[..., s_:s_ + 4]
            pltrb_pos = boxes_decode4yolo1(ptxywh, h, w, cfg)[mask_pos]

            iou_zg = bbox_iou4one(pltrb_pos, gltrb_pos, is_giou=True)
            # iou_zg = bbox_iou4y(xywh2ltrb4ts(pzxywh), gltrb_pos_tx, GIoU=True)
            # print(iou_zg)
            l_reg = (1 - iou_zg).mean() * 5
            ''' ---------------- loss完成 ----------------- '''
            l_total = l_conf_pos + l_conf_neg + l_cls + l_reg
            log_dict['l_reg'] = l_reg.item()
        else:
            # ------------ mse+bce   ------------ 666666
            # conf-1, cls-num_class, txywh-4, weight-1, gltrb-4
            # torch.Size([32, 169, 13])  9->实际是8
            ptxty_sigmoid = pyolos[:, :, s_:s_ + 2].sigmoid()  # 4:6
            ptwth = pyolos[:, :, s_ + 2:s_ + 4]  # 这里不需要归一

            weight = gyolos[:, :, s_ + 4]  # 这个是大小目标缩放比例
            gtxty = gyolos[:, :, s_:s_ + 2]  # torch.Size([5, 169, 2])
            gtwth = gyolos[:, :, s_ + 2:s_ + 4]

            # _loss_val = x_bce(ptxty_sigmoid, gtxty, reduction="none")
            _loss_val = F.mse_loss(ptxty_sigmoid, gtxty, reduction="none")
            l_txty = ((_loss_val.sum(-1) * mask_pos * weight).sum(-1) /
                      nums_pos).mean()
            _loss_val = F.mse_loss(ptwth, gtwth, reduction="none")
            l_twth = ((_loss_val.sum(-1) * mask_pos * weight).sum(-1) /
                      nums_pos).mean()
            ''' ---------------- loss完成 ----------------- '''
            l_total = l_conf_pos + l_conf_neg + l_cls + l_txty + l_twth
            log_dict['l_xy'] = l_txty.item()
            log_dict['l_wh'] = l_twth.item()

        log_dict['l_total'] = l_total.item()
        log_dict['l_conf_pos'] = l_conf_pos.item()
        log_dict['l_conf_neg'] = l_conf_neg.item()
        log_dict['l_cls'] = l_cls.item()

        log_dict['p_max'] = pconf_sigmoid.max().item()
        log_dict['p_min'] = pconf_sigmoid.min().item()
        log_dict['p_mean'] = pconf_sigmoid.mean().item()
        return l_total, log_dict
Beispiel #11
0
    ax = fig.add_subplot(111)
    plt.ylim(-p, size[0] + p)
    plt.xlim(-p, size[1] + p)
    ax.invert_yaxis()  # y轴反向
    plt.scatter(ww.reshape(-1), hh.reshape(-1))
    for a in anchors_xywh:  # 画矩形框
        # xy,w,h
        rect = plt.Rectangle((a[0], a[1]), a[2], a[3], color="r", fill=False)
        ax.add_patch(rect)
    plt.show()
    pass


if __name__ == '__main__':
    # tfanc()

    anc_obj = cre_ssd_ancs()
    anchors_xywh = anc_obj.ancs_xywh
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.invert_yaxis()
    p = 1
    plt.ylim(-p, p)
    plt.xlim(-p, p)
    for a in xywh2ltrb(anchors_xywh):  # 画矩形框
        # ltrb
        rect = plt.Rectangle((a[0], a[1]), a[2], a[3], color="r", fill=False)
        ax.add_patch(rect)
    plt.show()
    print()