code: import cv2
  from model.fcos import FCOSDetector
  import torch
  from torchvision import transforms
  import numpy as np
  from dataset.VOC_dataset import VOCDataset
  import time
  import matplotlib.patches as patches
  import matplotlib.pyplot as plt
  from matplotlib.ticker import NullLocator
  
  
  def preprocess_img(image, input_ksize):
      """
      resize image and bboxes
      Returns
      image_paded: input_ksize
      bboxes: [None,4]
      """
      min_side, max_side = input_ksize
      h, w, _ = image.shape
  
      smallest_side = min(w, h)
      largest_side = max(w, h)
      scale = min_side / smallest_side
      if largest_side * scale > max_side:
          scale = max_side / largest_side
      nw, nh = int(scale * w), int(scale * h)
      image_resized = cv2.resize(image, (nw, nh))
  
      pad_w = 32 - nw % 32
      pad_h = 32 - nh % 32
  
      image_paded = np.zeros(shape=[nh + pad_h, nw + pad_w, 3], dtype=np.uint8)
      image_paded[:nh, :nw, :] = image_resized
      return image_paded
  
  
  def convertSyncBNtoBN(module):
      module_output = module
      if isinstance(module, torch.nn.modules.batchnorm._BatchNorm):
          module_output = torch.nn.BatchNorm2d(module.num_features,
                                               module.eps, module.momentum,
                                               module.affine,
                                               module.track_running_stats)
          if module.affine:
              module_output.weight.data = module.weight.data.clone().detach()
              module_output.bias.data = module.bias.data.clone().detach()
          module_output.running_mean = module.running_mean
          module_output.running_var = module.running_var
      for name, child in module.named_children():
          module_output.add_module(name, convertSyncBNtoBN(child))
      del module
      return module_output
  
  
  if __name__ == "__main__":
      cmap = plt.get_cmap('tab20b')
      colors = [cmap(i) for i in np.linspace(0, 1, 20)]
  
  
      class Config():
          # backbone
          pretrained = False
          freeze_stage_1 = True
          freeze_bn = True
  
          # fpn
          fpn_out_channels = 256
          use_p5 = True
  
          # head
          class_num = 80
          use_GN_head = True
          prior = 0.01
          add_centerness = True
          cnt_on_reg = False
  
          # training
          strides = [8, 16, 32, 64, 128]
          limit_range = [[-1, 64], [64, 128], [128, 256], [256, 512], [512, 999999]]
  
          # inference
          score_threshold = 0.3
          nms_iou_threshold = 0.4
          max_detection_boxes_num = 300
  
  
      model = FCOSDetector(mode="inference", config=Config)
      # model=torch.nn.SyncBatchNorm.convert_sync_batchnorm(model)
      # print("INFO===>success convert BN to SyncBN")
      model = torch.nn.DataParallel(model)
      model.load_state_dict(torch.load("./checkpoint/voc_77.8.pth", map_location=torch.device('cpu')))
      # model=convertSyncBNtoBN(model)
      # print("INFO===>success convert SyncBN to BN")
      model = model.eval()
      model.to("cuda")
      print("===>success loading model")
  
      import os
  
      root = "./test_images/"
      names = os.listdir(root)
      for name in names:
          img_bgr = cv2.imread(root + name)
          img_pad = preprocess_img(img_bgr, [800, 1333])
          img = cv2.cvtColor(img_pad.copy(), cv2.COLOR_BGR2RGB)
          img1 = transforms.ToTensor()(img)
          img1 = transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225], inplace=True)(img1)
          img1 = img1.to("cuda")
  
          start_t = time.time()
          with torch.no_grad():
              out = model(img1.unsqueeze_(dim=0))
          end_t = time.time()
          cost_t = 1000 * (end_t - start_t)
          print("===>success processing img, cost time %.2f ms" % cost_t)
          # print(out)
          scores, classes, boxes = out
  
          boxes = boxes[0].cpu().numpy().tolist()
          classes = classes[0].cpu().numpy().tolist()
          scores = scores[0].cpu().numpy().tolist()
          plt.figure()
          fig, ax = plt.subplots(1)
          ax.imshow(img)
          for i, box in enumerate(boxes):
              pt1 = (int(box[0]), int(box[1]))
              pt2 = (int(box[2]), int(box[3]))
              img_pad = cv2.rectangle(img_pad, pt1, pt2, (0, 255, 0))
              b_color = colors[int(classes[i]) - 1]
              bbox = patches.Rectangle((box[0], box[1]), width=box[2] - box[0], height=box[3] - box[1], linewidth=1,
                                       facecolor='none', edgecolor=b_color)
              ax.add_patch(bbox)
              plt.text(box[0], box[1], s="%s %.3f" % (VOCDataset.CLASSES_NAME[int(classes[i])], scores[i]), color='white',
                       verticalalignment='top',
                       bbox={'color': b_color, 'pad': 0})
          plt.axis('off')
          plt.gca().xaxis.set_major_locator(NullLocator())
          plt.gca().yaxis.set_major_locator(NullLocator())
          plt.savefig('out_images/{}'.format(name), bbox_inches='tight', pad_inches=0.0)
          plt.close()
   import torch
  import xml.etree.ElementTree as ET
  import os
  import cv2
  import numpy as np
  from torchvision import transforms
  from PIL import Image
  import random
  
  
  def flip(img, boxes):
      img = img.transpose(Image.FLIP_LEFT_RIGHT)
      w = img.width
      if boxes.shape[0] != 0:
          xmin = w - boxes[:, 2]
          xmax = w - boxes[:, 0]
          boxes[:, 2] = xmax
          boxes[:, 0] = xmin
      return img, boxes
  
  
  class VOCDataset(torch.utils.data.Dataset):
      CLASSES_NAME = (
          "__background__ ",
          "aeroplane",
          "bicycle",
          "bird",
          "boat",
          "bottle",
          "bus",
          "car",
          "cat",
          "chair",
          "cow",
          "diningtable",
          "dog",
          "horse",
          "motorbike",
          "person",
          "pottedplant",
          "sheep",
          "sofa",
          "train",
          "tvmonitor",
      )
  
      def __init__(self, root_dir, resize_size=[800, 1333], split='trainval', use_difficult=False, is_train=True,
                   augment=None):
          self.root = root_dir
          self.use_difficult = use_difficult
          self.imgset = split
  
          self._annopath = os.path.join(self.root, "Annotations", "%s.xml")
          self._imgpath = os.path.join(self.root, "JPEGImages", "%s.jpg")
          self._imgsetpath = os.path.join(self.root, "ImageSets", "Main", "%s.txt")
  
          with open(self._imgsetpath % self.imgset) as f:
              self.img_ids = f.readlines()
          self.img_ids = [x.strip() for x in self.img_ids]
          self.name2id = dict(zip(VOCDataset.CLASSES_NAME, range(len(VOCDataset.CLASSES_NAME))))
          self.id2name = {v: k for k, v in self.name2id.items()}
          self.resize_size = resize_size
          self.mean = [0.485, 0.456, 0.406]
          self.std = [0.229, 0.224, 0.225]
          self.train = is_train
          self.augment = augment
          print("INFO=====>voc dataset init finished  ! !")
  
      def __len__(self):
          return len(self.img_ids)
  
      def __getitem__(self, index):
  
          img_id = self.img_ids[index]
          img = Image.open(self._imgpath % img_id)
  
          anno = ET.parse(self._annopath % img_id).getroot()
  
          boxes = []
          classes = []
          for obj in anno.iter("object"):
              difficult = int(obj.find("difficult").text) == 1
              if not self.use_difficult and difficult:
                  continue
              _box = obj.find("bndbox")
              # Make pixel indexes 0-based
              # Refer to "https://github.com/rbgirshick/py-faster-rcnn/blob/master/lib/datasets/pascal_voc.py#L208-L211"
              box = [
                  _box.find("xmin").text,
                  _box.find("ymin").text,
                  _box.find("xmax").text,
                  _box.find("ymax").text,
              ]
              TO_REMOVE = 1
              box = tuple(
                  map(lambda x: x - TO_REMOVE, list(map(float, box)))
              )
              boxes.append(box)
  
              name = obj.find("name").text.lower().strip()
              classes.append(self.name2id[name])
  
          boxes = np.array(boxes, dtype=np.float32)
          if self.train:
              if random.random() < 0.5:
                  img, boxes = flip(img, boxes)
              if self.augment is not None:
                  img, boxes = self.augment(img, boxes)
  
          img = np.array(img)
          img, boxes = self.preprocess_img_boxes(img, boxes, self.resize_size)
  
          img = transforms.ToTensor()(img)
          boxes = torch.from_numpy(boxes)
          classes = torch.LongTensor(classes)
  
          return img, boxes, classes
  
      def preprocess_img_boxes(self, image, boxes, input_ksize):
          """
          resize image and bboxes
          Returns
          image_paded: input_ksize
          bboxes: [None,4]
          """
          min_side, max_side = input_ksize
          h, w, _ = image.shape
  
          smallest_side = min(w, h)
          largest_side = max(w, h)
          scale = min_side / smallest_side
          if largest_side * scale > max_side:
              scale = max_side / largest_side
          nw, nh = int(scale * w), int(scale * h)
          image_resized = cv2.resize(image, (nw, nh))
  
          pad_w = 32 - nw % 32
          pad_h = 32 - nh % 32
  
          image_paded = np.zeros(shape=[nh + pad_h, nw + pad_w, 3], dtype=np.uint8)
          image_paded[:nh, :nw, :] = image_resized
  
          if boxes is None:
              return image_paded
          else:
              boxes[:, [0, 2]] = boxes[:, [0, 2]] * scale
              boxes[:, [1, 3]] = boxes[:, [1, 3]] * scale
              return image_paded, boxes
  
      def collate_fn(self, data):
          imgs_list, boxes_list, classes_list = zip(*data)
          assert len(imgs_list) == len(boxes_list) == len(classes_list)
          batch_size = len(boxes_list)
          pad_imgs_list = []
          pad_boxes_list = []
          pad_classes_list = []
  
          h_list = [int(s.shape[1]) for s in imgs_list]
          w_list = [int(s.shape[2]) for s in imgs_list]
          max_h = np.array(h_list).max()
          max_w = np.array(w_list).max()
          for i in range(batch_size):
              img = imgs_list[i]
              pad_imgs_list.append(transforms.Normalize(self.mean, self.std, inplace=True)(
                  torch.nn.functional.pad(img, (0, int(max_w - img.shape[2]), 0, int(max_h - img.shape[1])), value=0.)))
  
          max_num = 0
          for i in range(batch_size):
              n = boxes_list[i].shape[0]
              if n > max_num: max_num = n
          for i in range(batch_size):
              pad_boxes_list.append(
                  torch.nn.functional.pad(boxes_list[i], (0, 0, 0, max_num - boxes_list[i].shape[0]), value=-1))
              pad_classes_list.append(
                  torch.nn.functional.pad(classes_list[i], (0, max_num - classes_list[i].shape[0]), value=-1))
  
          batch_boxes = torch.stack(pad_boxes_list)
          batch_classes = torch.stack(pad_classes_list)
          batch_imgs = torch.stack(pad_imgs_list)
  
          return batch_imgs, batch_boxes, batch_classes
  
  
  if __name__ == "__main__":
      pass
      eval_dataset = VOCDataset(root_dir='../VOCdevkit/VOC2012', resize_size=[800, 1333],
                                split='trainval_demoData', use_difficult=False, is_train=False, augment=None)
      print(len(eval_dataset.CLASSES_NAME))
      # dataset=VOCDataset("/home/data/voc2007_2012/VOCdevkit/VOC2012",split='trainval')
      # for i in range(100):
      #     img,boxes,classes=dataset[i]
      #     img,boxes,classes=img.numpy().astype(np.uint8),boxes.numpy(),classes.numpy()
      #     img=np.transpose(img,(1,2,0))
      #     print(img.shape)
      #     print(boxes)
      #     print(classes)
      #     for box in boxes:
      #         pt1=(int(box[0]),int(box[1]))
      #         pt2=(int(box[2]),int(box[3]))
      #         img=cv2.rectangle(img,pt1,pt2,[0,255,0],3)
      #     cv2.imshow("test",img)
      #     if cv2.waitKey(0)==27:
      #         break
      # imgs,boxes,classes=eval_dataset.collate_fn([dataset[105],dataset[101],dataset[200]])
      # print(boxes,classes,"\n",imgs.shape,boxes.shape,classes.shape,boxes.dtype,classes.dtype,imgs.dtype)
      # for index,i in enumerate(imgs):
      #     i=i.numpy().astype(np.uint8)
      #     i=np.transpose(i,(1,2,0))
      #     i=cv2.cvtColor(i,cv2.COLOR_RGB2BGR)
      #     print(i.shape,type(i))
      #     cv2.imwrite(str(index)+".jpg",i)
  
apis: torch.nn.BatchNorm2d numpy.zeros matplotlib.pyplot.figure matplotlib.pyplot.axis torch.no_grad matplotlib.pyplot.gca matplotlib.pyplot.subplots torch.device matplotlib.patches.Rectangle matplotlib.pyplot.get_cmap matplotlib.pyplot.close torch.nn.DataParallel numpy.linspace matplotlib.ticker.NullLocator
apis: torch.stack numpy.zeros torch.nn.functional.pad torch.from_numpy numpy.array torch.LongTensor