思想:利用下标值操作
首先抠出原图中的候选目标的mask
这里有几点需要注意:
- 我们是通过下标操作,所以我们不需要得到原图的像素值。 仅仅得到原图对应像素值的下标即可
- 得到下标的同时需要进行判断是否超出边界。
gt_box_i = batched_inputs[select_image]['instances'].gt_boxes.tensor[i] # 这是已经转换了的box,coco数据集可能原始的是x,y,w,h格式
ori_mask = torch.zeros_like(batched_inputs[select_image]['image'][0,:,:]) # 得到和清晰度相同的0矩阵
mask_h, mask_w = ori_mask.shape
ori_mask[max(0, int(gt_box_i[0])): min(mask_w, int(gt_box_i[2])),
max(0, int(gt_box_i[1])): min(mask_h, int(gt_box_i[3]))] = 1 # 将挑选出来的bbox的mask值置为一
idx_all = torch.nonzero(ori_mask == 1, as_tuple=True) # 得到下标为1的位置(x, y)
在上述操作中,我们得到了下标为1的位置保存在idx_all中。 注意到在ori_mask中我们对相应的边界做了判断防止越界。
将结果贴到需要转换的图片上面
这一步十分的简单,直接使用下标值进行复制就可以了。结合后面的一起说明。
完整代码
images = [x["image"].to(self.device) for x in batched_inputs]
images = [(x - self.pixel_mean) / self.pixel_std for x in images]
images = ImageList.from_tensors(images,
self.backbone.size_divisibility)
if not self.training:
return images
select_image = random.randint(0, 0xfffffff) % len(batched_inputs)
select_Num = random.randint(0, 0xfffffff)
for i in range(len(batched_inputs[select_image]['instances'].gt_boxes.tensor)):
if i << 1 & select_Num:
# 把这个目标贴到其他的图上面去
gt_box_i = batched_inputs[select_image]['instances'].gt_boxes.tensor[i] # 这是已经转换了的box
ori_mask = torch.zeros_like(batched_inputs[select_image]['image'][0,:,:]) # 得到和清晰度相同的0矩阵
mask_h, mask_w = ori_mask.shape
ori_mask[max(0, int(gt_box_i[0])): min(mask_w, int(gt_box_i[2])),
max(0, int(gt_box_i[1])): min(mask_h, int(gt_box_i[3]))] = 1 # 将挑选出来的bbox的mask值置为一
idx_all = torch.nonzero(ori_mask == 1, as_tuple=True) # 得到下标为1的位置(x, y)
label_rgb = images.tensor[select_image]
label_id = batched_inputs[select_image]['instances'].gt_classes[i]
for img_idx in range(len(batched_inputs)):
if img_idx == select_image:
continue
rand_num = random.randint(0, 0xffffffff)
h, w = images.tensor[img_idx, ...].shape[-2:]
trans_x = idx_all[0] + rand_num % w # (x0, x1)
trans_y = idx_all[1] + rand_num % h # (y0, y1)
trans_x, trans_y = trans_x[trans_x >= 0], trans_y[trans_x >= 0]
trans_x, trans_y = trans_x[trans_x < w], trans_y[trans_x < w]
trans_x, trans_y = trans_x[trans_y >= 0], trans_y[trans_y >= 0]
trans_x, trans_y = trans_x[trans_y < h], trans_y[trans_y < h]
if trans_x.shape[0]> 10:
images.tensor[img_idx][:, trans_y, trans_x] = label_rgb[:, trans_y - rand_num % h, trans_x - rand_num % w]
gt_box_i = torch.Tensor([gt_box_i[0] + rand_num % w, gt_box_i[1] + rand_num % h,
gt_box_i[2] + rand_num % w, gt_box_i[3] + rand_num % h])
ious = box_iou(batched_inputs[img_idx]['instances'].gt_boxes.tensor, gt_box_i.unsqueeze(0))
batched_inputs[img_idx]['instances'].gt_boxes.tensor = batched_inputs[img_idx]['instances'].gt_boxes.tensor[(ious < 0.9).squeeze(1)]
batched_inputs[img_idx]['instances'].gt_classes = batched_inputs[img_idx]['instances'].gt_classes[
(ious < 0.9).squeeze(1)]
batched_inputs[img_idx]['instances'].gt_boxes.tensor = torch.cat((batched_inputs[img_idx]['instances'].gt_boxes.tensor, gt_box_i.unsqueeze(0)))
batched_inputs[img_idx]['instances'].gt_classes = torch.cat((batched_inputs[img_idx]['instances'].gt_classes, label_id.unsqueeze(0)))
return images
关于这个代码有几点需要说明一下:
- 对于输入进行了减去均值除以方差的操作
- 如果没有在训练时(即验证)不进行下面的操作直接返回。
流程说明:
- 首先我们从输入的batch中随机挑选出一张照片。通过生成一个随机数对batchsize取余得到select_image。
- 然后我们从该图片的label中随机挑选出子集,贴到其他的图片上面。通过生成随机数然后与i<<1判断是否选中。
- 在得到了原图中label的下标值之后,通过随机数rand_num得到其他图像的偏移。
- 最后判断得到的下标是否越界。
- 最后判断iou是否大于设定的阈值(0.9),来更新对应图片的label.
缺点:
- 由于笔者是做目标检测的,对于目标检测的评价指标可能比较熟悉一点。事实上,在得到原图label对应下标的时候用segmentation的标签比较好。可以防止大量背景信息导入。
在这里插入图片描述
![]() | ![]() |
可以看到,转换时把背景信息也提取出来了。所以用segmentation作为label的下标比较好。(这里我屏蔽了第一步的减去均值除以方差的操作)