当前位置:   article > 正文

LabelImg标注的VOC格式xml标签与YOLO格式txt标签相互转换_labelimg怎么转成yolo模式

labelimg怎么转成yolo模式

1、VOC标签格式说明

VOC数据格式,会直接把每张图片标注的标签信息保存到一个xml文件中。

xml中的信息如下:

  1. <annotation>
  2. <folder>矿区图像</folder>
  3. <filename>0066.jpg</filename>
  4. <path>/home/zhy/Documents/智能驾驶项目/标注/矿区图像/0066.jpg</path>
  5. <source>
  6. <database>Unknown</database>
  7. </source>
  8. <size>
  9. <width>1280</width>
  10. <height>720</height>
  11. <depth>3</depth>
  12. </size>
  13. <segmented>0</segmented>
  14. <object>
  15. <name>car</name>
  16. <pose>Unspecified</pose>
  17. <truncated>1</truncated>
  18. <difficult>0</difficult>
  19. <bndbox>
  20. <xmin>812</xmin>
  21. <ymin>223</ymin>
  22. <xmax>1280</xmax>
  23. <ymax>557</ymax>
  24. </bndbox>
  25. </object>
  26. </annotation>

xml文件中的关键信息说明:

 0066.jpg: 是图片名称,则xml文件名为0066.xml;

 /home/zhy/Documents/智能驾驶项目/标注/矿区图像/0066.jpg: 是存放该图片的绝对路径;

 1280*720: 是图片分辨率,3代表三通道图片;

car: 是类别名;

 xmin,ymin,xmax,ymax,定义了每个目标的标定框坐标:即左上角的坐标和右下角的坐标;

2、YOLO标签格式说明

YOLO标签格式,会直接把每张图片标注的标签信息保存到一个txt文件中。

图片名称为1.jpg,则对应的txt文件名称为1.txt。

txt中的信息如下:
 

3 0.286328 0.475694 0.132031 0.123611

txt文件中的关键信息说明:

    每一行代表标注的一个目标,张图中只标注了一个目标,所以只有一行;
    第一个数字0代表标注目标的类别;
    后面四个数字代表标注框的中心坐标和标注框的相对宽和高(进行了归一化处理);
    五个数据从左到右依次为:(class_id,  x_center,  y_center,  width,  height)

同时还会生成一个classes.txt,里面内容如下:\

car

3. VOC转YOLO

voctoyolo.py的目的就是把voc数据格式转换为yolo格式:

    voc格式标签:图片的实际宽高,标注框的左上角和右下角坐标;
    yolo格式标签:标注框的中心坐标(归一化),标注框的宽和高(归一化)。

voc格式转换为yolo格式计算公式:

   框中心的实际坐标(x,y),一般可能还会在后面减1

      x_center=(xmax+xmin)/2

      y_center=(ymax+ymin)/2

  

    归一化以后的中心坐标(x,y)

     x=x_center/width

     y=y_center/height

 

    框的高和宽(归一化后)

    w=(xmax-xmin)/width

    h=(ymax-ymin)/height

 voc格式的xml标签文件转化yolo格式的txt标签文件代码:voctoyolo.py

  1. # -*- coding:utf8 -*-
  2. import os
  3. import xml.etree.ElementTree as ET
  4. import io
  5. find_path = '/home/zhy/Documents/Perception/camera_data/mine_obstacle_image/label/3/' # xml所在的文件
  6. savepath = '/home/zhy/Documents/Perception/camera_data/mine_obstacle_image/label/4/' # 保存文件
  7. classes = ['car','Truck','person','bicycle','bus']
  8. class Voc_Yolo(object):
  9. def __init__(self, find_path):
  10. self.find_path = find_path
  11. def Make_txt(self, outfile):
  12. out = open(outfile, 'w')
  13. print("创建成功:{}".format(outfile))
  14. return out
  15. def Work(self, count):
  16. # 找到文件路径
  17. for root, dirs, files in os.walk(self.find_path):
  18. # 找到文件目录中每一个xml文件
  19. for file in files:
  20. # 记录处理过的文件
  21. count += 1
  22. # 输入、输出文件定义
  23. input_file = find_path + file
  24. outfile = savepath + file[:-4] + '.txt'
  25. # 新建txt文件,确保文件正常保存
  26. out = self.Make_txt(outfile)
  27. # 分析xml树,取出w_image、h_image
  28. tree = ET.parse(input_file)
  29. root = tree.getroot()
  30. size = root.find('size')
  31. w_image = float(size.find('width').text)
  32. h_image = float(size.find('height').text)
  33. # 继续提取有效信息来计算txt中的四个数据
  34. for obj in root.iter('object'):
  35. # 将类型提取出来,不同目标类型不同,本文仅有一个类别->0
  36. classname = obj.find('name').text
  37. # 如果类别不是对应在我们预定好的class文件中,或difficult==1则跳过
  38. if classname not in classes == 1:
  39. continue
  40. # 通过类别名称找到id
  41. cls_id = classes.index(classname)
  42. xmlbox = obj.find('bndbox')
  43. x_min = float(xmlbox.find('xmin').text)
  44. x_max = float(xmlbox.find('xmax').text)
  45. y_min = float(xmlbox.find('ymin').text)
  46. y_max = float(xmlbox.find('ymax').text)
  47. # 计算公式
  48. x_center = ((x_min + x_max) / 2 - 1) / w_image
  49. y_center = ((y_min + y_max) / 2 - 1) / h_image
  50. w = (x_max - x_min) / w_image
  51. h = (y_max - y_min) / h_image
  52. # 文件写入
  53. out.write(
  54. str(cls_id) + " " + str(x_center) + " " + str(y_center) + " " + str(w) + " " + str(h) + '\n')
  55. out.close()
  56. return count
  57. if __name__ == "__main__":
  58. data = Voc_Yolo(find_path)
  59. number = data.Work(0)
  60. print(number)

4、yolo格式转化为voc格式

voc格式中保存的信息为:xmin,ymin,xmax,ymax,所以只要根据上面的公式,就可以推导出这四个值。

yolo格式的txt标签文件转化voc格式的xml标签文件代码:yolotovoc.py

  1. # -*- coding:utf8 -*-
  2. from xml.dom.minidom import Document
  3. import os
  4. import cv2
  5. def makexml(picPath, txtPath, xmlPath):
  6. dic = {'0': "car",
  7. '1': "lightTruck",
  8. '2': "person",
  9. '3': "tipperTruck",
  10. '4': "construction",
  11. '5': "tricycle",
  12. '6': "train",
  13. '7': "bicycle",
  14. }
  15. files = os.listdir(txtPath)
  16. for i, name in enumerate(files):
  17. print(name)
  18. xmlBuilder = Document()
  19. annotation = xmlBuilder.createElement("annotation")
  20. xmlBuilder.appendChild(annotation)
  21. txtFile = open(txtPath + name)
  22. txtList = txtFile.readlines()
  23. img = cv2.imread(picPath + name[0:-4] + ".jpg")
  24. Pheight, Pwidth, Pdepth = img.shape
  25. folder = xmlBuilder.createElement("folder")
  26. foldercontent = xmlBuilder.createTextNode("driving_annotation_dataset")
  27. folder.appendChild(foldercontent)
  28. annotation.appendChild(folder)
  29. filename = xmlBuilder.createElement("filename")
  30. filenamecontent = xmlBuilder.createTextNode(name[0:-4] + ".jpg")
  31. filename.appendChild(filenamecontent)
  32. annotation.appendChild(filename)
  33. size = xmlBuilder.createElement("size")
  34. width = xmlBuilder.createElement("width")
  35. widthcontent = xmlBuilder.createTextNode(str(Pwidth))
  36. width.appendChild(widthcontent)
  37. size.appendChild(width)
  38. height = xmlBuilder.createElement("height")
  39. heightcontent = xmlBuilder.createTextNode(str(Pheight))
  40. height.appendChild(heightcontent)
  41. size.appendChild(height)
  42. depth = xmlBuilder.createElement("depth")
  43. depthcontent = xmlBuilder.createTextNode(str(Pdepth))
  44. depth.appendChild(depthcontent)
  45. size.appendChild(depth)
  46. annotation.appendChild(size)
  47. for j in txtList:
  48. oneline = j.strip().split(" ")
  49. object = xmlBuilder.createElement("object")
  50. picname = xmlBuilder.createElement("name")
  51. namecontent = xmlBuilder.createTextNode(dic[oneline[0]])
  52. picname.appendChild(namecontent)
  53. object.appendChild(picname)
  54. pose = xmlBuilder.createElement("pose") # pose标签
  55. posecontent = xmlBuilder.createTextNode("Unspecified")
  56. pose.appendChild(posecontent)
  57. object.appendChild(pose) # pose标签结束
  58. truncated = xmlBuilder.createElement("truncated") # truncated标签
  59. truncatedContent = xmlBuilder.createTextNode("0")
  60. truncated.appendChild(truncatedContent)
  61. object.appendChild(truncated) # truncated标签结束
  62. difficult = xmlBuilder.createElement("difficult") # difficult标签
  63. difficultcontent = xmlBuilder.createTextNode("0")
  64. difficult.appendChild(difficultcontent)
  65. object.appendChild(difficult) # difficult标签结束
  66. bndbox = xmlBuilder.createElement("bndbox") # bndbox标签
  67. xmin = xmlBuilder.createElement("xmin") # xmin标签
  68. mathData = int(((float(oneline[1])) * Pwidth + 1) - (float(oneline[3])) * 0.5 * Pwidth)
  69. xminContent = xmlBuilder.createTextNode(str(mathData))
  70. xmin.appendChild(xminContent)
  71. bndbox.appendChild(xmin) # xmin标签结束
  72. ymin = xmlBuilder.createElement("ymin") # ymin标签
  73. mathData = int(((float(oneline[2])) * Pheight + 1) - (float(oneline[4])) * 0.5 * Pheight)
  74. yminContent = xmlBuilder.createTextNode(str(mathData))
  75. ymin.appendChild(yminContent)
  76. bndbox.appendChild(ymin) # ymin标签结束
  77. xmax = xmlBuilder.createElement("xmax") # xmax标签
  78. mathData = int(((float(oneline[1])) * Pwidth + 1) + (float(oneline[3])) * 0.5 * Pwidth)
  79. xmaxContent = xmlBuilder.createTextNode(str(mathData))
  80. xmax.appendChild(xmaxContent)
  81. bndbox.appendChild(xmax) # xmax标签结束
  82. ymax = xmlBuilder.createElement("ymax") # ymax标签
  83. mathData = int(((float(oneline[2])) * Pheight + 1) + (float(oneline[4])) * 0.5 * Pheight)
  84. ymaxContent = xmlBuilder.createTextNode(str(mathData))
  85. ymax.appendChild(ymaxContent)
  86. bndbox.appendChild(ymax) # ymax标签结束
  87. object.appendChild(bndbox) # bndbox标签结束
  88. annotation.appendChild(object) # object标签结束
  89. f = open(xmlPath + name[0:-4] + ".xml", 'w')
  90. xmlBuilder.writexml(f, indent='\t', newl='\n', addindent='\t', encoding='utf-8')
  91. f.close()
  92. if __name__ == "__main__":
  93. picPath = "/home/zhy/Documents/Perception/camera_data/mine_obstacle_image/deepsort_data/image/" # 图片所在文件夹路径,后面的/一定要带上
  94. txtPath = "/home/zhy/Documents/Perception/camera_data/mine_obstacle_image/deepsort_data/labels/" # txt所在文件夹路径,后面的/一定要带上
  95. xmlPath = "/home/zhy/Documents/Perception/camera_data/mine_obstacle_image/deepsort_data/xml/" # xml文件保存路径,后面的/一定要带上
  96. makexml(picPath, txtPath, xmlPath)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/722274
推荐阅读
相关标签
  

闽ICP备14008679号