SIPE中如何求取原型

原型(prototype)是通过以下步骤求取的:

  1. 获取种子(seed):
    在前面的代码中,通过get_seed方法计算了种子(seed)张量,它代表了每个目标类别在输入图像中的初始分割掩码。这些种子是通过对归一化类激活图(norm_cam)和标签掩码(label)的处理得到的,以确保种子仅出现在输入图像的有效区域。
    def get_seed(self, norm_cam, label, feature):
        
        n,c,h,w = norm_cam.shape

        # iou evalution
        seeds = torch.zeros((n,h,w,c)).cuda()
        feature_s = feature.view(n,-1,h*w)
        # 将特征图展平为向量,方便后续计算
        feature_s = feature_s/(torch.norm(feature_s,dim=1,keepdim=True)+1e-5) 
		# 归一化特征向量,防止爆炸
        correlation = F.relu(torch.matmul(feature_s.transpose(2,1), feature_s),inplace=True).unsqueeze(1) #[n,1,h*w,h*w]
        # 计算特征向量的互相关矩阵,通过ReLU去掉负相关性,添加batch维,扩为4维张量
        # correlation = correlation/torch.max(correlation, dim=-1)[0].unsqueeze(-1) #[n,1,h*w,h*w]
        cam_flatten = norm_cam.view(n,-1,h*w).unsqueeze(2) #[n,21,1,h*w]
        # 将CAM展平,扩为4维
        inter = (correlation * cam_flatten).sum(-1)
        # 计算CAM和互相关的点积,得到交集
        union = correlation.sum(-1) + cam_flatten.sum(-1) - inter
        miou = (inter/union).view(n,self.num_cls,h,w) #[n,21,h,w]
        # 计算交并比,得到各类mIoU图
        miou[:,0] = miou[:,0]*0.5
        # 背景类mIoU乘0.5
        probs = F.softmax(miou, dim=1)
        # 对mIoU softmax,得到概率图
        belonging = miou.argmax(1)
        # 求mIoU最大类属地图
        seeds = seeds.scatter_(-1, belonging.view(n,h,w,1), 1).permute(0,3,1,2).contiguous()
        # scatter_ 按照第4维belonging中的类别索引,在seeds中填入1,得到种子图
        seeds = seeds * label
        # 与标签乘积,过滤背景区域
        return seeds, probs
  1. 提取裁剪特征:
    使用计算得到的种子,将它们与相应的特征图(hie_fea)相乘,得到裁剪特征(crop_feature)。这个过程相当于将特征图中除了种子对应位置的其他区域都置为零。

  2. 计算原型:
    将裁剪特征进行自适应平均池化操作,将裁剪特征图的每个通道的平均值作为该通道对应目标类别的原型特征。具体地,对裁剪特征执行自适应平均池化操作,将其尺寸从[n, c, h, w]缩减到[n, c, 1, 1],其中n表示批次大小(batch size),c表示通道数,hw分别表示裁剪特征的高度和宽度。最终,原型张量的形状为[n, num_classes, c, 1, 1],其中num_classes表示目标类别的数量。

    def get_prototype(self, seeds, feature):
    # 通过在特征图上使用种子进行截取,对每个类别进行自适应池化,生成了原型向量,即该类别对应的典型特征表示
        n,c,h,w = feature.shape
        seeds = F.interpolate(seeds, feature.shape[2:], mode='nearest')
        # seeds nearest方式插值到feature大小
        crop_feature = seeds.unsqueeze(2) * feature.unsqueeze(1)  # seed:[n,21,1,h,w], feature:[n,1,c,h,w], crop_feature:[n,21,c,h,w]
        # 两者按位乘,得到类别对应的特征区域
        prototype = F.adaptive_avg_pool2d(crop_feature.view(-1,c,h,w), (1,1)).view(n, self.num_cls, c, 1, 1) # prototypes:[n,21,c,1,1]
        # 展平concat,送入自适应池化层,池化生成原型向量,并reshape到[n, num_cls, c, 1, 1]
        return prototype
  1. 原型使用:
    通过得到的原型特征张量,可以进一步使用reactivate方法对类激活图(CAM)进行改进。原型用于计算类激活图中每个像素与每个类别原型的余弦相似度。最终的Interpretable Semantic CAM(IS_CAM)是通过使用余弦相似度对裁剪特征进行插值得到的。
    def reactivate(self, prototype, feature):
        IS_cam = F.relu(torch.cosine_similarity(feature.unsqueeze(1), prototype, dim=2)) # feature:[n,1,c,h,w], prototypes:[n,21,c,1,1], crop_feature:[n,21,h,w]
        # 计算特征图feature和原型prototype的余弦相似度,relu激活,获得相似度图
        IS_cam = F.interpolate(IS_cam, feature.shape[2:], mode='bilinear', align_corners=True)
        # 双线性插值到feature大小
        return IS_cam
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Env1sage

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值