x2voc.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. # Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. import cv2
  15. import json
  16. import os
  17. import os.path as osp
  18. import shutil
  19. from paddlex.utils import is_pic, get_encoding
  20. class X2VOC(object):
  21. def __init__(self):
  22. pass
  23. def convert(self, image_dir, json_dir, dataset_save_dir):
  24. """转换。
  25. Args:
  26. image_dir (str): 图像文件存放的路径。
  27. json_dir (str): 与每张图像对应的json文件的存放路径。
  28. dataset_save_dir (str): 转换后数据集存放路径。
  29. """
  30. assert osp.exists(image_dir), "The image folder does not exist!"
  31. assert osp.exists(json_dir), "The json folder does not exist!"
  32. if not osp.exists(dataset_save_dir):
  33. os.makedirs(dataset_save_dir)
  34. # Convert the image files.
  35. new_image_dir = osp.join(dataset_save_dir, "JPEGImages")
  36. if osp.exists(new_image_dir):
  37. raise Exception(
  38. "The directory {} is already exist, please remove the directory first".
  39. format(new_image_dir))
  40. os.makedirs(new_image_dir)
  41. for img_name in os.listdir(image_dir):
  42. if is_pic(img_name):
  43. shutil.copyfile(
  44. osp.join(image_dir, img_name),
  45. osp.join(new_image_dir, img_name))
  46. # Convert the json files.
  47. xml_dir = osp.join(dataset_save_dir, "Annotations")
  48. if osp.exists(xml_dir):
  49. raise Exception(
  50. "The directory {} is already exist, please remove the directory first".
  51. format(xml_dir))
  52. os.makedirs(xml_dir)
  53. self.json2xml(new_image_dir, json_dir, xml_dir)
  54. class LabelMe2VOC(X2VOC):
  55. """将使用LabelMe标注的数据集转换为VOC数据集。
  56. """
  57. def __init__(self):
  58. pass
  59. def json2xml(self, image_dir, json_dir, xml_dir):
  60. import xml.dom.minidom as minidom
  61. i = 0
  62. for img_name in os.listdir(image_dir):
  63. img_name_part = osp.splitext(img_name)[0]
  64. json_file = osp.join(json_dir, img_name_part + ".json")
  65. i += 1
  66. if not osp.exists(json_file):
  67. os.remove(osp.join(image_dir, img_name))
  68. continue
  69. xml_doc = minidom.Document()
  70. root = xml_doc.createElement("annotation")
  71. xml_doc.appendChild(root)
  72. node_folder = xml_doc.createElement("folder")
  73. node_folder.appendChild(xml_doc.createTextNode("JPEGImages"))
  74. root.appendChild(node_folder)
  75. node_filename = xml_doc.createElement("filename")
  76. node_filename.appendChild(xml_doc.createTextNode(img_name))
  77. root.appendChild(node_filename)
  78. with open(json_file, mode="r", \
  79. encoding=get_encoding(json_file)) as j:
  80. json_info = json.load(j)
  81. if 'imageHeight' in json_info and 'imageWidth' in json_info:
  82. h = json_info["imageHeight"]
  83. w = json_info["imageWidth"]
  84. else:
  85. img_file = osp.join(image_dir, img_name)
  86. im_data = cv2.imread(img_file)
  87. h, w, c = im_data.shape
  88. node_size = xml_doc.createElement("size")
  89. node_width = xml_doc.createElement("width")
  90. node_width.appendChild(xml_doc.createTextNode(str(w)))
  91. node_size.appendChild(node_width)
  92. node_height = xml_doc.createElement("height")
  93. node_height.appendChild(xml_doc.createTextNode(str(h)))
  94. node_size.appendChild(node_height)
  95. node_depth = xml_doc.createElement("depth")
  96. node_depth.appendChild(xml_doc.createTextNode(str(3)))
  97. node_size.appendChild(node_depth)
  98. root.appendChild(node_size)
  99. for shape in json_info["shapes"]:
  100. if 'shape_type' in shape:
  101. if shape["shape_type"] != "rectangle":
  102. continue
  103. (xmin, ymin), (xmax, ymax) = shape["points"]
  104. xmin, xmax = sorted([xmin, xmax])
  105. ymin, ymax = sorted([ymin, ymax])
  106. else:
  107. points = shape["points"]
  108. points_num = len(points)
  109. x = [points[i][0] for i in range(points_num)]
  110. y = [points[i][1] for i in range(points_num)]
  111. xmin = min(x)
  112. xmax = max(x)
  113. ymin = min(y)
  114. ymax = max(y)
  115. label = shape["label"]
  116. node_obj = xml_doc.createElement("object")
  117. node_name = xml_doc.createElement("name")
  118. node_name.appendChild(xml_doc.createTextNode(label))
  119. node_obj.appendChild(node_name)
  120. node_diff = xml_doc.createElement("difficult")
  121. node_diff.appendChild(xml_doc.createTextNode(str(0)))
  122. node_obj.appendChild(node_diff)
  123. node_box = xml_doc.createElement("bndbox")
  124. node_xmin = xml_doc.createElement("xmin")
  125. node_xmin.appendChild(xml_doc.createTextNode(str(xmin)))
  126. node_box.appendChild(node_xmin)
  127. node_ymin = xml_doc.createElement("ymin")
  128. node_ymin.appendChild(xml_doc.createTextNode(str(ymin)))
  129. node_box.appendChild(node_ymin)
  130. node_xmax = xml_doc.createElement("xmax")
  131. node_xmax.appendChild(xml_doc.createTextNode(str(xmax)))
  132. node_box.appendChild(node_xmax)
  133. node_ymax = xml_doc.createElement("ymax")
  134. node_ymax.appendChild(xml_doc.createTextNode(str(ymax)))
  135. node_box.appendChild(node_ymax)
  136. node_obj.appendChild(node_box)
  137. root.appendChild(node_obj)
  138. with open(osp.join(xml_dir, img_name_part + ".xml"), 'w') as fxml:
  139. xml_doc.writexml(
  140. fxml,
  141. indent='\t',
  142. addindent='\t',
  143. newl='\n',
  144. encoding="utf-8")
  145. class EasyData2VOC(X2VOC):
  146. """将使用EasyData标注的分割数据集转换为VOC数据集。
  147. """
  148. def __init__(self):
  149. pass
  150. def json2xml(self, image_dir, json_dir, xml_dir):
  151. import xml.dom.minidom as minidom
  152. for img_name in os.listdir(image_dir):
  153. img_name_part = osp.splitext(img_name)[0]
  154. json_file = osp.join(json_dir, img_name_part + ".json")
  155. if not osp.exists(json_file):
  156. os.remove(osp.join(image_dir, img_name))
  157. continue
  158. xml_doc = minidom.Document()
  159. root = xml_doc.createElement("annotation")
  160. xml_doc.appendChild(root)
  161. node_folder = xml_doc.createElement("folder")
  162. node_folder.appendChild(xml_doc.createTextNode("JPEGImages"))
  163. root.appendChild(node_folder)
  164. node_filename = xml_doc.createElement("filename")
  165. node_filename.appendChild(xml_doc.createTextNode(img_name))
  166. root.appendChild(node_filename)
  167. img = cv2.imread(osp.join(image_dir, img_name))
  168. h = img.shape[0]
  169. w = img.shape[1]
  170. node_size = xml_doc.createElement("size")
  171. node_width = xml_doc.createElement("width")
  172. node_width.appendChild(xml_doc.createTextNode(str(w)))
  173. node_size.appendChild(node_width)
  174. node_height = xml_doc.createElement("height")
  175. node_height.appendChild(xml_doc.createTextNode(str(h)))
  176. node_size.appendChild(node_height)
  177. node_depth = xml_doc.createElement("depth")
  178. node_depth.appendChild(xml_doc.createTextNode(str(3)))
  179. node_size.appendChild(node_depth)
  180. root.appendChild(node_size)
  181. with open(json_file, mode="r", \
  182. encoding=get_encoding(json_file)) as j:
  183. json_info = json.load(j)
  184. for shape in json_info["labels"]:
  185. label = shape["name"]
  186. xmin = shape["x1"]
  187. ymin = shape["y1"]
  188. xmax = shape["x2"]
  189. ymax = shape["y2"]
  190. node_obj = xml_doc.createElement("object")
  191. node_name = xml_doc.createElement("name")
  192. node_name.appendChild(xml_doc.createTextNode(label))
  193. node_obj.appendChild(node_name)
  194. node_diff = xml_doc.createElement("difficult")
  195. node_diff.appendChild(xml_doc.createTextNode(str(0)))
  196. node_obj.appendChild(node_diff)
  197. node_box = xml_doc.createElement("bndbox")
  198. node_xmin = xml_doc.createElement("xmin")
  199. node_xmin.appendChild(xml_doc.createTextNode(str(xmin)))
  200. node_box.appendChild(node_xmin)
  201. node_ymin = xml_doc.createElement("ymin")
  202. node_ymin.appendChild(xml_doc.createTextNode(str(ymin)))
  203. node_box.appendChild(node_ymin)
  204. node_xmax = xml_doc.createElement("xmax")
  205. node_xmax.appendChild(xml_doc.createTextNode(str(xmax)))
  206. node_box.appendChild(node_xmax)
  207. node_ymax = xml_doc.createElement("ymax")
  208. node_ymax.appendChild(xml_doc.createTextNode(str(ymax)))
  209. node_box.appendChild(node_ymax)
  210. node_obj.appendChild(node_box)
  211. root.appendChild(node_obj)
  212. with open(osp.join(xml_dir, img_name_part + ".xml"), 'w') as fxml:
  213. xml_doc.writexml(
  214. fxml,
  215. indent='\t',
  216. addindent='\t',
  217. newl='\n',
  218. encoding="utf-8")