0


【T-Rex Label基础教程】全新的自动化图片标注工具/软件 提高效率必备 可在线

文章目录

  • 0 数据准备
  • 1 图片导入
  • 2 数据标注
  • 3 标注导出
  • 4 格式转换
  1. T-Rex Label

是一种自动化辅助图片标注的工具,它可以使人们脱离繁琐的传统标注流程(如LabelImg),极大地提高标注的效率。

在这里插入图片描述
话不多说,先来看一看自动化辅助标注的震撼效果:


那么该如何获取呢? T-Rex Label Github官网提供了在线和本地两种方式,这里为了避免繁琐的环境配置过程,选择T-Rex Label在线工具进行说明。(点击即可跳转)

以下从数据准备、图片导入、数据标注、标注导出、格式转换五个小节来说明

  1. T-Rex Label

的使用流程。

0 数据准备

人们总是对例子情有独钟,为了帮助你更好的理解操作流程,我将通过一个案例来说明。

我们手中有如下的数据目录,Annotations_voc存放VOC格式的xml标注文件,Annotations_yolo存放YOLO格式的txt标注文件,当然目前还没有开始标注,他们都是空的,而pic中存放的是此次要标注的5张图片。

我们的目的是在

  1. T-Rex Label

在线工具上对pic进行标注(把所有人头head标注出来),获得相应的Annotations_yolo标注文件(因为目前只支持导出COCO和YOLO格式),再使用yolo2voc.py(后续会提供)将YOLO格式转化为VOC格式,从而获取Annotations_voc 标注文件。

1 图片导入

打开在线工具链接后,在以下界面选择要导入的图片即可,目前最多支持一次导入200张图片并对其进行标注。

可以看到导入图片后如下,接着点击开始标注即可。

2 数据标注

下面用动图演示标注过程如下:

  1. {\color{#E16B8C}{①}}
  2. 过程中因为预先没有定义分类,先按**A**键进入智能标注模式时,会提示你创建一个分类(e.g. head);

  1. {\color{#E16B8C}{②}}
  2. 创建完成后,接着**左键**划标注框
  3. \rightarrow
  4. →**Enter**确定,这样一张图片的标注就完成了;

  1. {\color{#E16B8C}{③}}
  2. 过程中如果有划错的标注框,可以按**Ctrl+Z**回撤,也可以按**D**键进入选择模式,点击要删除的标定框后按**Del**键即可;
  3. {\color{#E16B8C}{④}}
  4. 过程中如果有AI漏标的对象,可以按**R**键进入手动标注模式进行框定;
  5. {\color{#E16B8C}{⑤}}
  6. 另外可以用小键盘上的**左右方向键**切换图片;
  7. {\color{#E16B8C}{⑥}}
  8. 建议先用智能标注完成一遍所有导入图片的粗标注,再用手动标注的方式进行精标注。

3 标注导出

所有图片都标注完成后导出标注即可。这里只可选择COCO或YOLO格式,我们先选择YOLO格式。

接着你会得到一个压缩包,解压后的文件目录如下,其中images是上传的原始图片,labels是YOLO格式的标注,classes是定义的分类。
在这里插入图片描述

到这儿,如果你需要的是YOLO或COCO格式,那么标注过程就完成了,如果你需要VOC格式,请看格式转换一节。

4 格式转换

首先创建一个如下图所示的项目目录:
在这里插入图片描述

  1. {\color{#E16B8C}{①}}
  2. ①**data**在**图片导入**一节中已经讲解过了;
  3. {\color{#E16B8C}{②}}
  4. 将下载解压得到的images中的图片放入**pic**中,将labels中的文件放入**Annotations_yolo**中,此时**Annotations_voc**仍为空;
  5. {\color{#E16B8C}{③}}
  6. 接着创建**yolo2voc.py**的转换函数(主要更改__main__的部分),运行即可在**Annotations_voc**中看到VOC格式的标注文件;
  1. # yolo2voc.py文件的内容 from xml.dom.minidom import Document
  2. import os
  3. import cv2
  4. # 可以修改makexml定制化要写入xml的内容defmakexml(picPath, txtPath, xmlPath,
  5. folder_name="pic",#图片文件建的名称
  6. dirpath=".\\data\\pic\\",#图片目录):"""此函数用于将yolo格式txt标注文件转换为voc格式xml标注文件
  7. """
  8. dic ={'0':"head"}# 创建字典用来对类型进行转换
  9. files = os.listdir(txtPath)for name in files:
  10. xmlBuilder = Document()
  11. annotation = xmlBuilder.createElement("annotation")
  12. xmlBuilder.appendChild(annotation)
  13. txtFile =open(os.path.join(txtPath, name))
  14. txtList = txtFile.readlines()
  15. img = cv2.imread(os.path.join(picPath, name[0:-4]+".jpg"))
  16. Pheight, Pwidth, Pdepth = img.shape
  17. folder = xmlBuilder.createElement("folder")
  18. foldercontent = xmlBuilder.createTextNode(folder_name)
  19. folder.appendChild(foldercontent)
  20. annotation.appendChild(folder)
  21. filename = xmlBuilder.createElement("filename")
  22. filenamecontent = xmlBuilder.createTextNode(name[0:-4]+".jpg")
  23. filename.appendChild(filenamecontent)
  24. annotation.appendChild(filename)
  25. path = xmlBuilder.createElement("path")
  26. pathcontent = xmlBuilder.createTextNode(dirpath + name[0:-4]+".jpg")
  27. path.appendChild(pathcontent)
  28. annotation.appendChild(path)
  29. source = xmlBuilder.createElement("source")
  30. annotation.appendChild(source)
  31. database = xmlBuilder.createElement("database")
  32. databasecontent = xmlBuilder.createTextNode("Unknown")
  33. database.appendChild(databasecontent)
  34. source.appendChild(database)
  35. size = xmlBuilder.createElement("size")
  36. width = xmlBuilder.createElement("width")
  37. widthcontent = xmlBuilder.createTextNode(str(Pwidth))
  38. width.appendChild(widthcontent)
  39. size.appendChild(width)
  40. height = xmlBuilder.createElement("height")
  41. heightcontent = xmlBuilder.createTextNode(str(Pheight))
  42. height.appendChild(heightcontent)
  43. size.appendChild(height)
  44. depth = xmlBuilder.createElement("depth")
  45. depthcontent = xmlBuilder.createTextNode(str(Pdepth))
  46. depth.appendChild(depthcontent)
  47. size.appendChild(depth)
  48. annotation.appendChild(size)
  49. segmented = xmlBuilder.createElement("segmented")
  50. segmentedcontent = xmlBuilder.createTextNode("0")
  51. segmented.appendChild(segmentedcontent)
  52. annotation.appendChild(segmented)for j in txtList:
  53. oneline = j.strip().split(" ")object= xmlBuilder.createElement("object")
  54. picname = xmlBuilder.createElement("name")
  55. namecontent = xmlBuilder.createTextNode(dic[oneline[0]])
  56. picname.appendChild(namecontent)object.appendChild(picname)
  57. pose = xmlBuilder.createElement("pose")
  58. posecontent = xmlBuilder.createTextNode("Unspecified")
  59. pose.appendChild(posecontent)object.appendChild(pose)
  60. truncated = xmlBuilder.createElement("truncated")
  61. truncatedContent = xmlBuilder.createTextNode("0")
  62. truncated.appendChild(truncatedContent)object.appendChild(truncated)
  63. difficult = xmlBuilder.createElement("difficult")
  64. difficultcontent = xmlBuilder.createTextNode("0")
  65. difficult.appendChild(difficultcontent)object.appendChild(difficult)
  66. bndbox = xmlBuilder.createElement("bndbox")
  67. xmin = xmlBuilder.createElement("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)
  72. ymin = xmlBuilder.createElement("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)
  77. xmax = xmlBuilder.createElement("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)
  82. ymax = xmlBuilder.createElement("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)object.appendChild(bndbox)
  87. annotation.appendChild(object)# 使用字符串方式写入 XML 文件,避免生成 XML 声明# 使用临时文件写入 XML
  88. temp_xml_path = os.path.join(xmlPath, name[0:-4]+"_temp.xml")withopen(temp_xml_path,'w', encoding='utf-8')as temp_file:
  89. xmlBuilder.writexml(temp_file, indent='\t', newl='\n', addindent='\t', encoding='utf-8')# 读取临时 XML 文件并处理withopen(temp_xml_path,'r', encoding='utf-8')as temp_file:
  90. lines = temp_file.readlines()# 删除第一行并缩进后面的行withopen(os.path.join(xmlPath, name[0:-4]+".xml"),'w', encoding='utf-8')as final_file:for line in lines[1:]:# 从第二行开始写入
  91. final_file.write(line[1:])# 去掉每一行的第一个缩进# 删除临时文件
  92. os.remove(temp_xml_path)if __name__ =="__main__":
  93. picPath ="data/pic/"# 图片所在文件夹路径,后面的/一定要带上
  94. txtPath ="data/Annotations_yolo/"# txt所在文件夹路径,后面的/一定要带上
  95. xmlPath ="data/Annotations_voc/"# xml文件保存路径,后面的/一定要带上
  96. makexml(picPath, txtPath, xmlPath,
  97. folder_name="pic",
  98. dirpath=".\\data\\pic\\")
  1. {\color{#E16B8C}{④}}
  2. 为了验证转换的正确性,使用**demo.py**文件(主要更改__main__的部分)可视化VOC标注的效果。
  1. # demo.py文件的内容import os
  2. import xml.etree.ElementTree as ET
  3. from PIL import Image, ImageDraw
  4. defparse_voc_xml(xml_file):"""解析 VOC 格式的 XML 文件,提取检测框信息"""
  5. tree = ET.parse(xml_file)
  6. root = tree.getroot()
  7. boxes =[]for obj in root.findall('object'):
  8. name = obj.find('name').text
  9. xmlbox = obj.find('bndbox')
  10. xmin =int(xmlbox.find('xmin').text)
  11. ymin =int(xmlbox.find('ymin').text)
  12. xmax =int(xmlbox.find('xmax').text)
  13. ymax =int(xmlbox.find('ymax').text)
  14. boxes.append((name, xmin, ymin, xmax, ymax))return boxes
  15. defvisualize_boxes(image_path, boxes):"""在图片上绘制检测框"""
  16. image = Image.open(image_path)
  17. draw = ImageDraw.Draw(image)for box in boxes:
  18. name, xmin, ymin, xmax, ymax = box
  19. draw.rectangle([xmin, ymin, xmax, ymax], outline='red', width=3)
  20. draw.text((xmin, ymin), name, fill='red')return image
  21. defmain(image_path, xml_path):# 解析 XML 文件,获取检测框
  22. boxes = parse_voc_xml(xml_path)# 可视化检测框
  23. visualized_image = visualize_boxes(image_path, boxes)# 显示图片
  24. visualized_image.show()if __name__ =="__main__":# 输入图片和对应的 XML 文件路径
  25. image_path ="data/pic/002861.jpg"# 替换为你的图片路径
  26. xml_path ="data/Annotations_voc/002861.xml"# 替换为你的 XML 文件路径
  27. main(image_path, xml_path)

可以看到运行后的可视化效果如下,说明YOLO格式转VOC格式成功。
在这里插入图片描述


本文转载自: https://blog.csdn.net/luokang21/article/details/142501950
版权归原作者 斑斓GORGEOUS 所有, 如有侵权,请联系我们删除。

“【T-Rex Label基础教程】全新的自动化图片标注工具/软件 提高效率必备 可在线”的评论:

还没有评论