code: def translate_info(
      file_names: list,
      save_root: str,
      class_dict: dict,
      train_val="train",
  ):
      """
      将对应xml文件信息转为yolo中使用的txt文件信息
      :param file_names:
      :param save_root:
      :param class_dict:
      :param train_val:
      :return:
      """
      save_txt_path = os.path.join(save_root, train_val, "labels")
      if os.path.exists(save_txt_path) is False:
          os.makedirs(save_txt_path)
      save_images_path = os.path.join(save_root, train_val, "images")
      if os.path.exists(save_images_path) is False:
          os.makedirs(save_images_path)
  
      for file in tqdm(
          file_names, desc="translate {} file...".format(train_val)
      ):
          # 检查下图像文件是否存在
          img_path = os.path.join(voc_images_path, file + ".jpg")
          assert os.path.exists(
              img_path
          ), "file:{} not exist...".format(img_path)
  
          # 检查xml文件是否存在
          xml_path = os.path.join(voc_xml_path, file + ".xml")
          assert os.path.exists(
              xml_path
          ), "file:{} not exist...".format(xml_path)
  
          # read xml
          with open(xml_path) as fid:
              xml_str = fid.read()
          xml = etree.fromstring(xml_str)
          data = parse_xml_to_dict(xml)["annotation"]
          img_height = int(data["size"]["height"])
          img_width = int(data["size"]["width"])
  
          # write object info into txt
          assert (
              "object" in data.keys()
          ), "file: '{}' lack of object key.".format(xml_path)
          if len(data["object"]) == 0:
              # 如果xml文件中没有目标就直接忽略该样本
              print(
                  "Warning: in '{}' xml, there are no objects.".format(
                      xml_path
                  )
              )
              continue
  
          with open(
              os.path.join(save_txt_path, file + ".txt"), "w"
          ) as f:
              for index, obj in enumerate(data["object"]):
                  # 获取每个object的box信息
                  xmin = float(obj["bndbox"]["xmin"])
                  xmax = float(obj["bndbox"]["xmax"])
                  ymin = float(obj["bndbox"]["ymin"])
                  ymax = float(obj["bndbox"]["ymax"])
                  class_name = obj["name"]
                  class_index = class_dict[class_name] - 1  # 目标id从0开始
  
                  # 进一步检查数据，有的标注信息中可能有w或h为0的情况，这样的数据会导致计算回归loss为nan
                  if xmax <= xmin or ymax <= ymin:
                      print(
                          "Warning: in '{}' xml, there are some bbox w/h <=0".format(
                              xml_path
                          )
                      )
                      continue
  
                  # 将box信息转换到yolo格式
                  xcenter = xmin + (xmax - xmin) / 2
                  ycenter = ymin + (ymax - ymin) / 2
                  w = xmax - xmin
                  h = ymax - ymin
  
                  # 绝对坐标转相对坐标，保存6位小数
                  xcenter = round(xcenter / img_width, 6)
                  ycenter = round(ycenter / img_height, 6)
                  w = round(w / img_width, 6)
                  h = round(h / img_height, 6)
  
                  info = [
                      str(i)
                      for i in [class_index, xcenter, ycenter, w, h]
                  ]
  
                  if index == 0:
                      f.write(" ".join(info))
                  else:
                      f.write("\n" + " ".join(info))
  
          # copy image into save_images_path
          path_copy_to = os.path.join(
              save_images_path, img_path.split(os.sep)[-1]
          )
          if os.path.exists(path_copy_to) is False:
              shutil.copyfile(img_path, path_copy_to)
  
file_path: deep-learning-for-image-processing/pytorch_object_detection/yolov3_spp/trans_voc2yolo.py
imports: import os
  from tqdm import tqdm
  from lxml import etree
  import json
  import shutil
label_desc: Use image node_id 2 for calling a global function with example usage: translate_info(file_names, save_root, class_dict, train_val) without return types