文章目录

  • 前言
  • 一、CVAT导出的xml格式
  • 二、使用步骤
  • 1.引入库
  • 2.读入xml文件信息,获取所有的image标签
  • 3.numpy对数据进行重组,并保存
  • 4.结果
  • 三、验证坐标点信息



前言

最近要弄人脸坐标点数据集,在使用CVAT对人脸坐标点进行标记后,将数据以CVAT for images 1.1格式进行导出,坐标点的信息保存在xml中。我需要的是与300W数据集相同的格式,通过python的xml.dom进行操作,提取出每张照片对应的人脸坐标点信息,保存为txt文件。并通过绘制图像,验证标注点信息是否正确。


一、CVAT导出的xml格式

python xml元素转字符串 python xml转txt_numpy

从图中可以看到,主要的信息标签在image下,image标签下嵌入了points标签(这个为需要的内容)

python xml元素转字符串 python xml转txt_ci_02

二、使用步骤

1.引入库

import os
import numpy as np
import pandas as pd

# 使用dom
from xml.dom.minidom import parse
import xml.dom.minidom

2.读入xml文件信息,获取所有的image标签

# 保存信息
data = []

# 使用minidom解析器打开 XML 文档
DOMTree = xml.dom.minidom.parse("./data/Face_points/annotations.xml")
collection = DOMTree.documentElement

# 在集合中获取所有image
images = collection.getElementsByTagName("image")

# 打印每部电影的详细信息
for image in images:
    print ("*****image*****")
    if image.hasAttribute("id"):
        print ("id: %s" % image.getAttribute("id"))
        
    if image.hasAttribute("name"):
        print ("name: %s" % image.getAttribute("name"))
        data.append(image.getAttribute("name"))
        
    if image.hasAttribute("width"):
        print ("width: %s" % image.getAttribute("width"))
    if image.hasAttribute("height"):
        print ("height: %s" % image.getAttribute("height"))

    
    points = image.getElementsByTagName('points')
    for point in points:
        if point.hasAttribute("points"):
            print ("point: %s" % point.getAttribute("points"))
            data.append(point.getAttribute("points"))

3.numpy对数据进行重组,并保存

data = np.array(data).reshape((-1,2))

for i in range(0,data.shape[0]):
    points_str = data[i][1]
    points_str = points_str.replace(";",",")
    points_list = points_str.split(',')
    points = np.array(points_list).reshape(-1,2)
    file_name = data[i][0]
    np.savetxt(os.path.join('./data/Face_points/images/',file_name.replace(".png",".txt")),points, fmt="%s")

4.结果


三、验证坐标点信息

import os
import pandas as pd
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
from torchvision import transforms, utils
import cv2

from skimage import io, transform

# Ignore warnings
import warnings
warnings.filterwarnings("ignore")


image = cv2.imread('./images/indoor_003.png', 1)  # 1 彩色,0 灰色
 
# 读取对应的pts文件
with open('./images/indoor_003.txt') as file_obj:
    contents = file_obj.readlines();


#i = 0
landmarks = []
for line in contents:
    TT = line.strip("\n")  # strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。
    # print TT
    TT_temp = TT.split(" ")
    x = float(TT_temp[0])
    y = float(TT_temp[1].strip("\r"))  # \r :回车
    landmarks.append((x, y))
    #i += 1
print(landmarks, len(landmarks))

#  将关键点标在图片上
'''
cv2.circle(image, center_coordinates, radius, color, thickness)
    image:它是要在其上绘制圆的图像。
    center_coordinates:它是圆的中心坐标。坐标表示为两个值的元组,即(X坐标值,Y坐标值)。
    radius:它是圆的半径。
    color:它是要绘制的圆的边界线的颜色。对于BGR,我们通过一个元组。例如:(255,0,0)为蓝色。
    thickness:它是圆边界线的粗细像素。厚度-1像素将以指定的颜色填充矩形形状。

    返回值:它返回一个图像。
    
cv2.putText(img, text, org, fontFace, fontScale, color, thickness=None, lineType=None, bottomLeftOrigin=None)
    各参数依次是:图片,添加的文字,左上角坐标,字体,字体大小,颜色,字体粗细
'''
m = 0  # 标号初始为0
for point in landmarks:
    # print(point[0],point[1])
    cv2.circle(image, (int(point[0]), int(point[1])), 2, (0, 255, 0), -1)  # 颜色顺序:BGR (0, 255, 0)绿色,-1 实心圆
    m += 1
    cv2.putText(image, str(m), (int(point[0]), int(point[1])), cv2.FONT_HERSHEY_SIMPLEX, 0.25, (0, 0, 255),
                1)  # 每个关键点上标号
#     plt.scatter(np.transpose(point)[0], np.transpose(point)[1])  # 散点图
# plt.show()
cv2.imshow("pointImg", image)
cv2.waitKey()

python xml元素转字符串 python xml转txt_python_03