SSD 위치의 손실을 시각적으로 표시

SSD 모델의 학습에 사용된 손실은 이미지의 분류와 위치를 합한 것입니다.이것은 포위함과 교정 후의 기본 상자의 위치 손실을 보여 줍니다.SSD를 사용하는 파이썬 설치amdegroot/ssd.pytorch를 설치합니다.
SSD의 하드 앤 드롭 결과를 시각화해 보십시오. 코드의 재등재는 교사 데이터를 SSD 모델이 계산한 위치 정보와 라벨 정보와 같은 형식으로 변환하는 양을 계산한다.loc_t는 위치에 대한 정보conf_t로 이미지의 분류 정보이다.
image_size = 300
batch_size = 1
n_class =  len(VOC_CLASSES) + 1
dataset = VOCDetection(root = '/path/to/root', 
                          transform=BaseTransform(image_size, MEANS))
data_loader = data.DataLoader(dataset, batch_size = batch_size, num_workers=0, shuffle=False, collate_fn = detection_collate)
torch.set_default_tensor_type('torch.cuda.FloatTensor')
images, targets = next(iter(data_loader))
images = images.cuda()
targets = [ann.cuda() for ann in targets]
priors = PriorBox(voc).forward()
num_priors = priors.size(0)
loc_t = torch.Tensor(batch_size, num_priors,  priors.size(1))
conf_t = torch.LongTensor(batch_size, num_priors)
# loc_t: DBoxからBBoxまでの差分とconf_t: jaccard係数 0.5を閾値としたときのラベル付けを計算
for idx in range(batch_size):
    match(threshold = 0.5, 
          truths = targets[idx][:, :-1].data,  
          priors = priors.data, 
          variances = [0.1, 0.2], 
          labels = targets[idx][:, -1].data, 
          loc_t = loc_t, 
          conf_t = conf_t, 
          idx = idx)
다음으로 학습 모드에서 SSD 네트워크를 생성하여 이미지 정보에서 위치 정보를 출력합니다.
net = build_ssd('train', image_size, n_class)
net.load_state_dict(torch.load('/path/to/weight')
net = net.cuda()
net.train()
loc_data, _ , _ = net(images)
긍정적 기본 상자에 분류된 위치 정보만 추출합니다.loc_p SSD로 추정한 결과loc_t는 교사 데이터가 됐다.
pos = conf_t > 0
pos_idx = pos.unsqueeze(pos.dim()).expand_as(loc_data)
loc_p = loc_data[pos_idx].view(-1, 4)
loc_t = loc_t[pos_idx].view(-1, 4)
함수를 통해 위치 정보와 관련된 손실을 평가한다smooth_l1_loss.이 함수는 평균절대오차(MAE)와 균방오차(MSE)에 속하는 함수로, 미세한 차이는 있지만 연속값 변수 오차를 계산하는 함수다.모든 기본 상자의 손실은 4개의 변수의 합이다.그리고 평균치loss_l는 학습에 사용되는 위치 정보를 손실시킬 수 있다.
l_losses = F.smooth_l1_loss(loc_p, loc_t, reduction='none')
l_losses = torch.sum(l_losses, 1)
l_losses = l_losses.to('cpu').detach().numpy().copy()
# 位置情報に関する損失
loss_l = np.average(l_losses) 
print(loss_l)
한 이미지의 위치에 대한 손실은 적극적인 기본 상자에만 기여하기 때문에 모든 기본 상자에 대한 손실, 기본 상자와 포위 상자를 표시합니다.
# ポジティブデフォルトボックスのindex
indices = [i for i, v in enumerate(list(pos.to('cpu').detach().numpy().copy()[0])) if v]
plt.figure(figsize=(16, 12))
image = (images[0].to('cpu').detach().numpy().transpose(1, 2, 0) + (MEANS[2], MEANS[1], MEANS[0])).astype(np.uint8).copy()   
for i, idx in enumerate(indices):   
    img = cv2.resize(image.copy(), (image_size, image_size))
    cx_d, cy_d, w_d, h_d = priors[idx].to('cpu').detach().numpy().copy()
    xmin_d = int((cx_d - w_d / 2) * image_size)
    ymin_d = int((cy_d - h_d / 2) * image_size)
    xmax_d = int((cx_d + w_d / 2) * image_size)
    ymax_d = int((cy_d + h_d / 2) * image_size)
    pt1_d = (xmin_d, ymin_d)
    pt2_d = (xmax_d, ymax_d)
    #デフォルトボックスを描画する処理
    #見えやすいとは言えないので、ここではコメントアウト 
    #cv2.rectangle(img, pt1=pt1_d, pt2=pt2_d, color=(0, 255, 0), thickness=2)
    loc = loc_data.view(-1, 4)[idx].to('cpu').detach().numpy().copy()
    cx_p = cx_d * (1 + 0.1 * loc[0])
    cy_p = cy_d * (1 + 0.1 * loc[1])
    w_p = w_d * np.exp(0.2 * loc[2])
    h_p = h_d * np.exp(0.2 * loc[3])
    xmin_p = int((cx_p - w_p / 2) * image_size)
    ymin_p = int((cy_p - h_p / 2) * image_size)
    xmax_p = int((cx_p + w_p / 2) * image_size)
    ymax_p = int((cy_p + h_p / 2) * image_size)
    pt1_p = (xmin_p, ymin_p)
    pt2_p = (xmax_p, ymax_p)    
    cv2.rectangle(img, pt1=pt1_p, pt2=pt2_p, color=(255, 0, 0), thickness=2)
    for box in targets[0]:
        label = int(box[4])
        pt1 =  (int(box[0] * image_size), int(box[1] * image_size) )
        pt2 = (int(box[2] * image_size), int(box[3] * image_size))
        jaccard = calc_jaccard((pt1_p[0], pt1_p[1], pt2_p[0], pt2_p[1]), (pt1[0], pt1[1], pt2[0], pt2[1]))
        cv2.putText(img, f"J:{jaccard: .2f}", (200, 30), cv2.FONT_HERSHEY_PLAIN, 1.5, (0, 255, 0), 2)
        cv2.putText(img, f"L:{l_losses[i]: .2f}", (200, 60), cv2.FONT_HERSHEY_PLAIN, 1.5, (0, 255, 0), 2)
        cv2.rectangle(img, pt1=pt1, pt2=pt2, color=(0, 0, 255), thickness=2)
    plt.subplot(3 , 4, i + 1)
    plt.axis('off')
    plt.imshow(img)
plt.show()
학습을 시작할 때의 무게를 사용할 때 기본 상자와 포위함이 기본적으로 표시됩니다.그림 속 J: 0.54 은jaccard 계수 L: 4.64 로 손실입니다.

이미 배운 모델이라면 기본 상자에 위치 교정을 넣은 상자는 포위함과 거의 일치합니다.

여기에 사용된 원본 이미지는 여기. (Pixabay License: 상업용 무료 귀속 표시 필요 없음) 640x426 사이즈로 다운로드한 것이다.

좋은 웹페이지 즐겨찾기