code: def build_targets(p, targets, model):
      # Build targets for compute_loss(), input targets(image_idx,class,x,y,w,h)
      nt = targets.shape[0]
      tcls, tbox, indices, anch = [], [], [], []
      gain = torch.ones(
          6, device=targets.device
      ).long()  # normalized to gridspace gain
  
      multi_gpu = type(model) in (
          nn.parallel.DataParallel,
          nn.parallel.DistributedDataParallel,
      )
      for i, j in enumerate(model.yolo_layers):  # j: [89, 101, 113]
          # 获取该yolo predictor对应的anchors
          # 注意anchor_vec是anchors缩放到对应特征层上的尺度
          anchors = (
              model.module.module_list[j].anchor_vec
              if multi_gpu
              else model.module_list[j].anchor_vec
          )
          # p[i].shape: [batch_size, 3, grid_h, grid_w, num_params]
          gain[2:] = torch.tensor(p[i].shape)[[3, 2, 3, 2]]  # xyxy gain
          na = anchors.shape[0]  # number of anchors
          # [3] -> [3, 1] -> [3, nt]
          at = (
              torch.arange(na).view(na, 1).repeat(1, nt)
          )  # anchor tensor, same as .repeat_interleave(nt)
  
          # Match targets to anchors
          a, t, offsets = [], targets * gain, 0
          if nt:  # 如果存在target的话
              # 通过计算anchor模板与所有target的wh_iou来匹配正样本
              # j: [3, nt] , iou_t = 0.20
              j = (
                  wh_iou(anchors, t[:, 4:6]) > model.hyp["iou_t"]
              )  # iou(3,n) = wh_iou(anchors(3,2), gwh(n,2))
              # t.repeat(na, 1, 1): [nt, 6] -> [3, nt, 6]
              # 获取正样本对应的anchor模板与target信息
              a, t = at[j], t.repeat(na, 1, 1)[j]  # filter
  
          # Define
          # long等于to(torch.int64), 数值向下取整
          b, c = t[:, :2].long().T  # image_idx, class
          gxy = t[:, 2:4]  # grid xy
          gwh = t[:, 4:6]  # grid wh
          gij = (gxy - offsets).long()  # 匹配targets所在的grid cell左上角坐标
          gi, gj = gij.T  # grid xy indices
  
          # Append
          # gain[3]: grid_h, gain[2]: grid_w
          # image_idx, anchor_idx, grid indices(y, x)
          indices.append(
              (
                  b,
                  a,
                  gj.clamp_(0, gain[3] - 1),
                  gi.clamp_(0, gain[2] - 1),
              )
          )
          tbox.append(
              torch.cat((gxy - gij, gwh), 1)
          )  # gt box相对anchor的x,y偏移量以及w,h
          anch.append(anchors[a])  # anchors
          tcls.append(c)  # class
          if c.shape[0]:  # if any targets
              # 目标的标签数值不能大于给定的目标类别数
              assert c.max() < model.nc, (
                  "Model accepts %g classes labeled from 0-%g, however you labelled a class %g. "
                  "See https://github.com/ultralytics/yolov3/wiki/Train-Custom-Data"
                  % (model.nc, model.nc - 1, c.max())
              )
  
      return tcls, tbox, indices, anch
  
imports: import glob
  import math
  import os
  import random
  import time
  import cv2
  import matplotlib
  import numpy
  import torch
  import torch.nn
  import torchvision
  from tqdm import tqdm
  from build_utils import torch_utils
label_desc: Use image node_id 12 for calling a global function with example usage: build_targets(p, targets, model) and returns: tcls,  tbox,  indices,  anch