optimize xml parser

This commit is contained in:
Neucrack
2021-03-01 18:36:07 +08:00
parent 18d08024eb
commit 762b9771f1
2 changed files with 113 additions and 71 deletions
+49 -51
View File
@@ -648,63 +648,61 @@ class Detector(Train_Base):
# decode xml
input_shape_checked = False
for xml_path in xmls:
with open(xml_path) as f:
xml = f.read()
ok, result = decode_pascal_voc_xml(xml)
if not ok:
result = f"decode xml {xml_path} fail, reason: {result}"
self.on_warning_message(result)
ok, result = decode_pascal_voc_xml(xml_path)
if not ok:
result = f"decode xml {xml_path} fail, reason: {result}"
self.on_warning_message(result)
continue
# shape
img_shape = (result['height'], result['width'], result['depth'])
# check first image shape, and switch to proper supported input_shape
if not input_shape_checked:
if not self._check_update_input_shape(img_shape) and not self.allow_reshape:
return False, "not supported input size, supported: {}".format(self.support_shapes), [], None, None, None
input_shape_checked = True
if img_shape != self.input_shape:
msg = f"decode xml {xml_path} ok, but shape {img_shape} not the same as expected: {self.input_shape}"
if not self.allow_reshape:
self.on_warning_message(msg)
continue
# shape
img_shape = (result['height'], result['width'], result['depth'])
# check first image shape, and switch to proper supported input_shape
if not input_shape_checked:
if not self._check_update_input_shape(img_shape) and not self.allow_reshape:
return False, "not supported input size, supported: {}".format(self.support_shapes), [], None, None, None
input_shape_checked = True
if img_shape != self.input_shape:
msg = f"decode xml {xml_path} ok, but shape {img_shape} not the same as expected: {self.input_shape}"
if not self.allow_reshape:
self.on_warning_message(msg)
continue
else:
msg += ", will automatically reshape"
self.on_warning_message(msg)
# load image
dir_name = os.path.split(os.path.split(result['path'])[0])[-1] # class1 / images
# images/class1/tututututut.jpg
img_path = os.path.join(img_dir, dir_name, result['filename'])
else:
msg += ", will automatically reshape"
self.on_warning_message(msg)
# load image
dir_name = os.path.split(os.path.split(result['path'])[0])[-1] # class1 / images
# images/class1/tututututut.jpg
img_path = os.path.join(img_dir, dir_name, result['filename'])
if os.path.exists(img_path):
img = np.array(Image.open(img_path), dtype='uint8')
else:
# images/tututututut.jpg
img_path = os.path.join(img_dir, result['filename'])
if os.path.exists(img_path):
img = np.array(Image.open(img_path), dtype='uint8')
else:
# images/tututututut.jpg
img_path = os.path.join(img_dir, result['filename'])
if os.path.exists(img_path):
img = np.array(Image.open(img_path), dtype='uint8')
else:
result = f"decode xml {xml_path}, can not find iamge: {result['path']}"
self.on_warning_message(result)
continue
# load bndboxes
y = []
for bbox in result['bboxes']:
if not bbox[4] in labels:
result = f"decode xml {xml_path}, can not find iamge: {result['path']}"
self.on_warning_message(result)
continue
label_idx = labels.index(bbox[4])
bbox[4] = label_idx # replace label text with label index
classes_data_counts[label_idx] += 1
# range to [0, 1]
y.append( bbox[:5])
if len(y) < 1:
result = f"decode xml {xml_path}, no object, skip"
result = f"decode xml {xml_path}, can not find iamge: {result['path']}"
self.on_warning_message(result)
continue
if img_shape != self.input_shape:
img, y = self._reshape_image(img, self.input_shape, y)
datasets_x.append(img)
datasets_y.append(y)
# load bndboxes
y = []
for bbox in result['bboxes']:
if not bbox[4] in labels:
result = f"decode xml {xml_path}, can not find iamge: {result['path']}"
self.on_warning_message(result)
continue
label_idx = labels.index(bbox[4])
bbox[4] = label_idx # replace label text with label index
classes_data_counts[label_idx] += 1
# range to [0, 1]
y.append( bbox[:5])
if len(y) < 1:
result = f"decode xml {xml_path}, no object, skip"
self.on_warning_message(result)
continue
if img_shape != self.input_shape:
img, y = self._reshape_image(img, self.input_shape, y)
datasets_x.append(img)
datasets_y.append(y)
return True, "ok", labels, classes_data_counts, datasets_x, datasets_y
def _decode_pbtxt_file(self, file_path):
+64 -20
View File
@@ -10,8 +10,10 @@
import re
def decode_pascal_voc_xml(xml):
def decode_pascal_voc_xml(xml_path, ordered = True):
'''
@ordered parse labelimg ordered xml by RE, or will use xml parser
@reuturn bool, info
res = {
"filename": ,
@@ -22,27 +24,69 @@ def decode_pascal_voc_xml(xml):
"bboxes": [(xmin, ymin, xmax, ymax, label, difficult)]
}
'''
if ordered:
with open(xml_path) as f:
xml = f.read()
try:
rule = "<filename>(.*)</filename>.*<path>(.*)</path>.*<size>.*<width>(.*)</width>.*<height>(.*)</height>.*<depth>(.*)</depth>.*</size>"
match = re.findall(rule, xml, re.MULTILINE|re.DOTALL)
if len(match) < 1:
return False, "decode error"
res = {
"filename": match[0][0].replace("\\", "/"),
"path": match[0][1].replace("\\", "/"),
"width": int(match[0][2]),
"height": int(match[0][3]),
"depth": int(match[0][4]),
"bboxes": []
}
rule = "<object>.*?<name>(.*?)</name>.*?<difficult>(.*?)</difficult>.*?<bndbox>.*?<xmin>(.*?)</xmin>.*?<ymin>(.*?)</ymin>.*?<xmax>(.*?)</xmax>.*?<ymax>(.*?)</ymax>.*?</bndbox>.*?</object>"
match = re.findall(rule, xml, re.MULTILINE|re.DOTALL)
if len(match) < 1:
return False, "no object in this iamge"
for bbox in match:
bbox = [int(bbox[2]), int(bbox[3]), int(bbox[4]), int(bbox[5]), bbox[0], int(bbox[1])]
res["bboxes"].append(bbox)
except Exception as e:
return False, "decode error {}".format(e)
return True, res
try:
rule = "<filename>(.*)</filename>.*<path>(.*)</path>.*<size>.*<width>(.*)</width>.*<height>(.*)</height>.*<depth>(.*)</depth>.*</size>"
match = re.findall(rule, xml, re.MULTILINE|re.DOTALL)
if len(match) < 1:
return False, "decode error"
from xml.etree.ElementTree import parse
tree = parse(xml_path)
root = tree.getroot()
filename = root.find("filename").text
path = root.find("path")
width = -1
height = -1
depth = -1
for elem in tree.iter():
if "width" in elem.tag:
width = int(elem.text)
elif "height" in elem.tag:
height = int(elem.text)
elif "depth" in elem.tag:
depth = int(elem.text)
obj_tags = root.findall("object")
res = {
"filename": match[0][0],
"path": match[0][1],
"width": int(match[0][2]),
"height": int(match[0][3]),
"depth": int(match[0][4]),
"filename": filename,
"path": filename if path is None else path.text,
"width": width,
"height": height,
"depth": depth,
"bboxes": []
}
rule = "<object>.*?<name>(.*?)</name>.*?<difficult>(.*?)</difficult>.*?<bndbox>.*?<xmin>(.*?)</xmin>.*?<ymin>(.*?)</ymin>.*?<xmax>(.*?)</xmax>.*?<ymax>(.*?)</ymax>.*?</bndbox>.*?</object>"
match = re.findall(rule, xml, re.MULTILINE|re.DOTALL)
if len(match) < 1:
return False, "no object in this iamge"
for bbox in match:
bbox = [int(bbox[2]), int(bbox[3]), int(bbox[4]), int(bbox[5]), bbox[0], int(bbox[1])]
res["filename"] = res["filename"].replace("\\", "/"),
res["path"] = res["path"].replace("\\", "/"),
for t in obj_tags:
name = t.find("name").text
box_tag = t.find("bndbox")
difficult = int(t.find("difficult").text)
x1 = int(float(box_tag.find("xmin").text))
y1 = int(float(box_tag.find("ymin").text))
x2 = int(float(box_tag.find("xmax").text))
y2 = int(float(box_tag.find("ymax").text))
bbox = [x1, y1, x2, y2, name, difficult ]
res["bboxes"].append(bbox)
except Exception:
return False, "decode error"
return True, res
return True, res
except Exception as e:
return False, "decode error {}".format(e)