提取xml文件的目标名,xmin,ymin,xmax,ymax,在图上把框框出来并保存。
使用try except避免xml文件中可能存在的标注错误。
xml文件提取:
使用xml.dom.minidom.parse(xml_path)获得DOMTree。
使用DOMTree.documentElement获得DOMTree元素集合。
使用.getElementsByTagName(tagname)获得标签名是tagname的元素的列表。
通过列表索引获得列表某个元素。
通过.childNodes[0]或.firstchild获得第一个子节点。
通过.childNodes[0].nodeValue或firstchild.data获得第一个子节点的值。
画框:
cv2.rectangle(img, (xmin,ymin), (xmax,ymax),颜色,厚度)
框上写字:
cv2.putText(img, 文字内容,坐标,字体,大小,颜色,厚度)
保存图像:
cv2.imwrite(路径,图像)
'''
xml文件示例:
<annotations>
<filename>test_00000335.jpg</filename>
<size>
<width>305</width>
<height>458</height>
<depth>3</depth>
</size>
<object>
<name>face_mask</name>
<bndbox>
<xmin>138</xmin>
<ymin>126</ymin>
<xmax>207</xmax>
<ymax>203</ymax>
</bndbox>
</object>
<object>
<name>face</name>
<bndbox>
<xmin>123</xmin>
<ymin>316</ymin>
<xmax>187</xmax>
<ymax>379</ymax>
</bndbox>
</object>
</annotation>
'''
import cv2
from xml.dom.minidom import parse
import xml.dom.minidom
import os
def img_draw_bndbox(img_path, xml_path, out_path, img_draw_name):
'''
:param img_path: str, 原图像的地址
:param xml_path: str, xml文件的地址
:param out_path: 保存图像的地址
:param img_draw_name:保存图像的名称
:return: None
'''
image = cv2.imread(img_path)
# 使用minidom解析器打开 XML 文档
DOMTree = xml.dom.minidom.parse(xml_path)
collection = DOMTree.documentElement
# print(collection)
'''
获得左上角坐标(xmin, ymin),右下角坐标(xmax, ymax)
x.firstchild.data:获取元素第一个子节点的数据;
x.childNodes[0]::获取元素第一个子节点;
x.childNodes[0].nodeValue.:也是获取元素第一个子节点值的意思
'''
# 示例:提取图片名称、宽、高
filename = collection.getElementsByTagName('filename')[0].firstChild.data
width = collection.getElementsByTagName('width')[0].firstChild.data
height = collection.getElementsByTagName('height')[0].childNodes[0].nodeValue
# print(filename)
# print(width)
# print(height)
object_elements =collection.getElementsByTagName('object')
for object_element in object_elements:
# 获得类别名称
object_name = object_element.getElementsByTagName('name')[0].firstChild.data
# print('object name: ', object_name)
# 获得第一个 bndbox,一个object下只有一个bndbox,第一个就是,他的下标是0
bndbox_element = object_element.getElementsByTagName('bndbox')[0]
xmin = bndbox_element.getElementsByTagName('xmin')[0].firstChild.data
ymin = bndbox_element.getElementsByTagName('ymin')[0].firstChild.data
xmax = bndbox_element.getElementsByTagName('xmax')[0].firstChild.data
ymax = bndbox_element.getElementsByTagName('ymax')[0].firstChild.data
# 用红框把图像中的人脸框出,红色 (0, 0, 255)。
'''
import cv2
cv2.rectangle(img, (x1, y1), (x2, y2), (255,0,0), 2)
(xmin,ymin) -----------
| |
| |
| |
------------(xmax,ymax)
'''
try:
xmin, ymin, xmax, ymax = int(xmin), int(ymin), int(xmax), int(ymax)
image = cv2.rectangle(image, (xmin, ymin), (xmax, ymax), (255, 0, 0), 2)
font = cv2.FONT_HERSHEY_SIMPLEX # 定义字体
# cv2.putText()参数依次是:图像,文字内容,坐标(左上角坐标) ,字体,大小,颜色,字体厚度
# 用黄色字体在图像中写出类别名称,黄色 (0, 255, 255)
image = cv2.putText(image, object_name, (xmin, ymin), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 255), 2)
except:
print("data invalid!")
cv2.imwrite(os.path.join(out_path, img_draw_name), image)
return
if __name__ == '__main__':
img_path = './test_00000335.jpg'
xml_path = './test_00000335.xml'
out_path = './'
img_draw_name = 'test_00000335_draw.jpg'
img_draw_bndbox(img_path, xml_path, out_path, img_draw_name)