labelme2voc.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. #!/usr/bin/env python
  2. from __future__ import print_function
  3. import argparse
  4. import glob
  5. import os
  6. import os.path as osp
  7. import sys
  8. import imgviz
  9. import labelme
  10. try:
  11. import lxml.builder
  12. import lxml.etree
  13. except ImportError:
  14. print("Please install lxml:\n\n pip install lxml\n")
  15. sys.exit(1)
  16. def main():
  17. parser = argparse.ArgumentParser(
  18. formatter_class=argparse.ArgumentDefaultsHelpFormatter
  19. )
  20. parser.add_argument("input_dir", help="input annotated directory")
  21. parser.add_argument("output_dir", help="output dataset directory")
  22. parser.add_argument("--labels", help="labels file", required=True)
  23. parser.add_argument("--noviz", help="no visualization", action="store_true")
  24. args = parser.parse_args()
  25. if osp.exists(args.output_dir):
  26. print("Output directory already exists:", args.output_dir)
  27. sys.exit(1)
  28. os.makedirs(args.output_dir)
  29. os.makedirs(osp.join(args.output_dir, "JPEGImages"))
  30. os.makedirs(osp.join(args.output_dir, "Annotations"))
  31. if not args.noviz:
  32. os.makedirs(osp.join(args.output_dir, "AnnotationsVisualization"))
  33. print("Creating dataset:", args.output_dir)
  34. class_names = []
  35. class_name_to_id = {}
  36. for i, line in enumerate(open(args.labels).readlines()):
  37. class_id = i - 1 # starts with -1
  38. class_name = line.strip()
  39. class_name_to_id[class_name] = class_id
  40. if class_id == -1:
  41. assert class_name == "__ignore__"
  42. continue
  43. elif class_id == 0:
  44. assert class_name == "_background_"
  45. class_names.append(class_name)
  46. class_names = tuple(class_names)
  47. print("class_names:", class_names)
  48. out_class_names_file = osp.join(args.output_dir, "class_names.txt")
  49. with open(out_class_names_file, "w") as f:
  50. f.writelines("\n".join(class_names))
  51. print("Saved class_names:", out_class_names_file)
  52. for filename in glob.glob(osp.join(args.input_dir, "*.json")):
  53. print("Generating dataset from:", filename)
  54. label_file = labelme.LabelFile(filename=filename)
  55. base = osp.splitext(osp.basename(filename))[0]
  56. out_img_file = osp.join(args.output_dir, "JPEGImages", base + ".jpg")
  57. out_xml_file = osp.join(args.output_dir, "Annotations", base + ".xml")
  58. if not args.noviz:
  59. out_viz_file = osp.join(
  60. args.output_dir, "AnnotationsVisualization", base + ".jpg"
  61. )
  62. img = labelme.utils.img_data_to_arr(label_file.imageData)
  63. imgviz.io.imsave(out_img_file, img)
  64. maker = lxml.builder.ElementMaker()
  65. xml = maker.annotation(
  66. maker.folder(),
  67. maker.filename(base + ".jpg"),
  68. maker.database(), # e.g., The VOC2007 Database
  69. maker.annotation(), # e.g., Pascal VOC2007
  70. maker.image(), # e.g., flickr
  71. maker.size(
  72. maker.height(str(img.shape[0])),
  73. maker.width(str(img.shape[1])),
  74. maker.depth(str(img.shape[2])),
  75. ),
  76. maker.segmented(),
  77. )
  78. bboxes = []
  79. labels = []
  80. for shape in label_file.shapes:
  81. if shape["shape_type"] != "rectangle":
  82. print(
  83. "Skipping shape: label={label}, " "shape_type={shape_type}".format(
  84. **shape
  85. )
  86. )
  87. continue
  88. class_name = shape["label"]
  89. class_id = class_names.index(class_name)
  90. (xmin, ymin), (xmax, ymax) = shape["points"]
  91. # swap if min is larger than max.
  92. xmin, xmax = sorted([xmin, xmax])
  93. ymin, ymax = sorted([ymin, ymax])
  94. bboxes.append([ymin, xmin, ymax, xmax])
  95. labels.append(class_id)
  96. xml.append(
  97. maker.object(
  98. maker.name(shape["label"]),
  99. maker.pose(),
  100. maker.truncated(),
  101. maker.difficult(),
  102. maker.bndbox(
  103. maker.xmin(str(xmin)),
  104. maker.ymin(str(ymin)),
  105. maker.xmax(str(xmax)),
  106. maker.ymax(str(ymax)),
  107. ),
  108. )
  109. )
  110. if not args.noviz:
  111. captions = [class_names[label] for label in labels]
  112. viz = imgviz.instances2rgb(
  113. image=img,
  114. labels=labels,
  115. bboxes=bboxes,
  116. captions=captions,
  117. font_size=15,
  118. )
  119. imgviz.io.imsave(out_viz_file, viz)
  120. with open(out_xml_file, "wb") as f:
  121. f.write(lxml.etree.tostring(xml, pretty_print=True))
  122. if __name__ == "__main__":
  123. main()