XML文件
关于这个文件格式,其实我接触并不多。
具体介绍见XML文件结构和基本语法
类似的有YAML。
为什么要写XML文件
最近头疼依然是在做数据集标记,因为原始LableImage工具生成的是XML文件,因为装不上这个工具,所以用Matlab标记了,需要将数据写进XML,和那个工具生成一样的格式。
从同事那里拿来工具生成的标准XML文件,开始有点懵。
标准文件是这个样子:
- 椭圆画出部分是当前图片的基本信息,宽、高、深度、路径等;
- 方框画出的部分为每个被标记目标的位置信息、类别等。
LableImage最显著特点是一张图片可以标记多个目标,所以可以看到有很多的目标信息。
这个解脱了每次裁剪数据集的烦恼,同时有可能算法中将背景作为负模板训练,效果更佳。
自写XML
随便找了个教程,把图片基本信息写进去,照猫画虎,然后,原始XML文件长这个样子:
对比和标准格式的差别,发现自己的数据没有那么层层被包含,当然,也没有写全。
观察发现:宽高等信息,在size中包围,看起来像是它的子集;而size,又是object的子集。
于是,找了另一个例程,看如何生成这种分叉,一直衍生子集。
思索之后,代码就出来了,长得和标准文件基本一样,就不用贴图了,直接上代码:
%标记文件,数据生成XML
numofpic=length(positiveInstances);
class=0;
for i=1:numofpic
rectPosition=positiveInstances(i).objectBoundingBoxes;
siz=size(rectPosition,1);
path=positiveInstances(i).imageFilename;
fullpath = 'label';
% create document
docNode = com.mathworks.xml.XMLUtils.createDocument('annotation');
% document element
docRootNode = docNode.getDocumentElement();
img=imread(path);
depth=numel(size(img));
width_pic=size(img,2);
height_pic=size(img,1);
%folder
folderNode=docNode.createElement('folder');
folderNode.appendChild(docNode.createTextNode('train'));
docRootNode.appendChild(folderNode);
% filename
fileNode = docNode.createElement('filename');
fileNode.appendChild(docNode.createTextNode(path));
docRootNode.appendChild(fileNode);
% pathname
fileNode = docNode.createElement('path');
fileNode.appendChild(docNode.createTextNode(path));
docRootNode.appendChild(fileNode);
sourceNode= docNode.createElement('source');
docRootNode.appendChild(sourceNode);
databaseNode=docNode.createElement('database');
%data_out='UnKnown';
databaseNode.appendChild(docNode.createTextNode('UnKnown'));
sourceNode.appendChild(databaseNode);
%size
%size是root生成的分叉,见第二句话,给root节点添加一个子节点
sizeNode=docNode.createElement('size');
docRootNode.appendChild(sizeNode);
%宽高是size的分叉,所以给sizeNode添加子节点
% size-width
widthNode = docNode.createElement('width');
%由于添加进去是字符一类,所以数字进行类型转换
width_out=num2str(width_pic);
widthNode.appendChild(docNode.createTextNode(width_out));
sizeNode.appendChild(widthNode);
% size-height
heightNode = docNode.createElement('height');
height_out=num2str(height_pic);
heightNode.appendChild(docNode.createTextNode(height_out));
sizeNode.appendChild(heightNode);
% size-depth
depthNode = docNode.createElement('depth');
depth_out=num2str(depth);
%子节点中写入数据
depthNode.appendChild(docNode.createTextNode(depth_out));
%将子节点写入被分叉节点
sizeNode.appendChild(depthNode);
%由于每张图多个位置标记,所以文件基本信息写在之前,每个类别遍历写入
for j=1: siz
x0=rectPosition(j,1);
y0=rectPosition(j,2);
width=rectPosition(j,3);
height=rectPosition(j,4);
x1=x0+width;
y1=y0+height;
objectNode=docNode.createElement('object');
docRootNode.appendChild(objectNode);
% class
classNode = docNode.createElement('name');
class_out=num2str(class);
classNode.appendChild(docNode.createTextNode(class_out));
objectNode.appendChild(classNode);
%pose
poseNode=docNode.createElement('pose');
poseNode.appendChild(docNode.createTextNode('Unspecified'));
objectNode.appendChild(poseNode);
%truncated
trunNode=docNode.createElement('truncated');
trun_out=num2str('0');
trunNode.appendChild(docNode.createTextNode(trun_out));
objectNode.appendChild(trunNode);
%difficult
diffNode=docNode.createElement('difficult');
diff_out=num2str('0');
diffNode.appendChild(docNode.createTextNode(diff_out));
objectNode.appendChild(diffNode);
%bndbox
boundNode=docNode.createElement('bndbox');
objectNode.appendChild(boundNode);
% bndbox-xmin
xminNode = docNode.createElement('xmin');
xmin_out=num2str(x0);
xminNode.appendChild(docNode.createTextNode(xmin_out));
boundNode.appendChild(xminNode);
% bndbox-ymin
yminNode = docNode.createElement('ymin');
ymin_out=num2str(y0);
yminNode.appendChild(docNode.createTextNode(ymin_out));
boundNode.appendChild(yminNode);
% bndbox-xmax
xmaxNode = docNode.createElement('xmax');
xmax_out=num2str(x1);
xmaxNode.appendChild(docNode.createTextNode(xmax_out));
boundNode.appendChild(xmaxNode);
% bndbox-ymax
ymaxNode = docNode.createElement('ymax');
ymax_out=num2str(y1);
ymaxNode.appendChild(docNode.createTextNode(ymax_out));
boundNode.appendChild(ymaxNode);
%segmented
segNode=docNode.createElement('segmented');
seg_out=num2str('0');
segNode.appendChild(docNode.createTextNode(seg_out));
docRootNode.appendChild(segNode);
% xmlwrite
xmlFileName = [path,'.xml'];
xmlwrite(xmlFileName,docNode);
end
end
进行这样的操作后,每张图片生成一个标记文件:
节点关系
这个文件自己在写的时候,数据量不大,关系也不是太复杂,不过还是觉得,下次再写类似关系时候,一定注意生成关系:即谁是谁的子节点。
所以,建议再写XML文件时,提前搭建一个节点关系,刚才写的文件,自己写了个框架关系,就很了然了。