我们数据集标注的文件如下
每一个image对应一个txt,每个txt内容如下
每一行有8个数据,每个数据代表的含义如下图所示
VOC2007格式必须为JPG格式,并且图片是统一的六位数字,从000001开始。那我们也需要将所有训练图片重命名
python代码如下:
# -*- coding: utf-8 -*-
import os
path = "E:\\study_materials\\ECCV Vision Meets Drones Challenge\\datasets\\VisDrone2018-DET-train\\VisDrone2018-DET-train\\images_rename"
filelist = os.listdir(path) #该文件夹下所有的文件(包括文件夹)
count=1
for file in filelist:
print(file)
for file in filelist: #遍历所有文件
Olddir=os.path.join(path,file) #原来的文件路径
if os.path.isdir(Olddir): #如果是文件夹则跳过
continue
filename=os.path.splitext(file)[0] #文件名
filetype=os.path.splitext(file)[1] #文件扩展名
Newdir=os.path.join(path,str(count).zfill(6)+filetype) #用字符串函数zfill 以0补全所需位数
os.rename(Olddir,Newdir)#重命名
count+=1
运行代码之后:
变成了:
我们制作数据集的时候,其实是把我们自己的数据格式转换为PASCAL VOC数据集的格式。
格式如下:
即每行由图片名、目标类型、包围框坐标组成,空格隔开
如果一张图片有多个目标,则格式如下:(比如两个目标)
DG00003L005.jpg iris 187 168 350 253
DG00003L005.jpg iris 232 86 412 168
四个坐标点为包围框坐标的左上角和右下角。
所以现在要做的就是把txt文件中的信息先变成如上图所示的格式
小处理:
转化代码如下:
#include
#include
#include
#include
#include
using namespace std;
const string baseFilePath = "E:\\study_materials\\ECCV Vision Meets Drones Challenge\\datasets\\VisDrone2018-DET-train\\VisDrone2018-DET-train\\annotations1\\";
/************************************************************************/
/* 获取文件夹下所有文件名
输入:
path : 文件夹路径
exd : 所要获取的文件名后缀,如jpg、png等;如果希望获取所有
文件名, exd = ""
输出:
files : 获取的文件名列表
*/
/************************************************************************/
void getFiles(string path, string exd, vector& files)
{
//文件句柄
long hFile = 0;
//文件信息
struct _finddata_t fileinfo;
string pathName, exdName;
if (0 != strcmp(exd.c_str(), ""))
{
exdName = "\\*." + exd;
}
else
{
exdName = "\\*";
}
if ((hFile = _findfirst(pathName.assign(path).append(exdName).c_str(), &fileinfo)) != -1)
{
do
{
//如果是文件夹中仍有文件夹,迭代之
//如果不是,加入列表
if ((fileinfo.attrib & _A_SUBDIR))
{
if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
getFiles(pathName.assign(path).append("\\").append(fileinfo.name), exd, files);
}
else
{
if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
files.push_back(pathName.assign(/*path).append("\\").append(*/fileinfo.name));
}
} while (_findnext(hFile, &fileinfo) == 0);
_findclose(hFile);
}
}
int main(){
vector files;
vector totalStr;
getFiles(baseFilePath, "txt", files);
for (int i = 0; i < files.size(); i++){
std::cout << files[i] << endl;
ifstream inf;
inf.open(baseFilePath+"\\"+files[i], ifstream::in);
ofstream outf("xml1\\" + files[i]);
//outf.open("xml\\" + files[k], ifstream::out);
const int cnt = 8;
string line;
string str = "";
string clsStr = "";
int j = 0;
size_t comma = 0;
size_t comma1 = 0;
size_t comma2 = 0;
while (!inf.eof()){
comma1 = files[i].find('.', 0);
totalStr.push_back(files[i].substr(0, comma1) + ".jpg");
//outf << files[i].substr(0, comma1)+".jpg" << ' ';
getline(inf, line);
comma = line.find(',', 0);
str =line.substr(0, comma);
totalStr.push_back(str);
//outf << str << ' ';
while (comma < line.size() && j != cnt - 1){
comma2 = line.find(',', comma + 1);
str = line.substr(comma + 1, comma2 - comma - 1);
totalStr.push_back(str);
//outf << str << ' ';
++j;
comma = comma2;
}
//ignored regions (0), pedestrian (1), people (2), bicycle (3), car (4), van (5),
//truck (6), tricycle (7), awning-tricycle (8), bus (9), motor (10), others (11))
clsStr = "";
switch (atoi(totalStr[6].c_str())){
case 0:
clsStr = "ignored regions";
break;
case 1:
clsStr = "pedestrian";
break;
case 2:
clsStr = "people";
break;
case 3:
clsStr = "bicycle";
break;
case 4:
clsStr = "car";
break;
case 5:
clsStr = "van";
break;
case 6:
clsStr = "truck";
break;
case 7:
clsStr = "tricycle";
break;
case 8:
clsStr = "awning-tricycle";
break;
case 9:
clsStr = "bus";
break;
case 10:
clsStr = "motor";
break;
case 11:
clsStr = "others";
break;
}
totalStr[6] = clsStr;
//忽略第5个参数 score为0的
if (totalStr[5] == "0"){
totalStr.clear();
j = 0;
}
else{
outf << totalStr[0] << ' ' << totalStr[6] << ' ' << totalStr[1] << ' ' << totalStr[2] << ' '
<< to_string(atoi(totalStr[1].c_str()) + atoi(totalStr[3].c_str())) << ' '
<< to_string(atoi(totalStr[2].c_str()) + atoi(totalStr[4].c_str())) << ' '
<< totalStr[7] << endl;
totalStr.clear();
j = 0;
}
}
inf.close();
outf.close();
}
return 0;
}
相关链接:
https://blog.csdn.net/Best_Coder/article/details/76577544?locationNum=8&fps=1
执行步骤:
代码下载后,打开VOC2007xml.m,根据自己情况修改代码,根据在img中提供好的*.jpg 文件与output.txt就可以生成Annotations的xml 文件,如果要生成自己的xml文件,则只需要将img中的图片替换为自己的图片,output.txt根据格式修改就可以了。
注意点:
因为这个matlab代码是把所有的txt文件内容合并到一个output.txt里面了,然后根据每行的jpg名称生成对应的xml格式,所以现在需要把所有的txt文件内容合并或者更改matlab代码内容(依次读取所有txt文件)。此处更改了matlab代码。
VOC2007xml.m修改之后的代码如下
%%
clc;
clear;
%注意修改下面四个变量
imgpath='img\';%图像存放文件夹
xmlpath_new='Annotations/';%修改后的xml保存文件夹
foldername='VisDrone2018';%xml的folder字段名
num_begin=1;
namepath=num2str(num_begin,'%06d');
suffix='.txt';
for j=1:6471 %批量处理6471个训练图片(从000001.txt到006471.txt)
txtpath=[imgpath,namepath,suffix];%txt文件
fidin=fopen(txtpath,'r');
lastname='begin';
while ~feof(fidin)
tline=fgetl(fidin);
%if strcmp(tline,'')
%continue;
%end
str = regexp(tline, ' ','split');
filepath=[imgpath,str{1}];
img=imread(filepath);
[h,w,d]=size(img);
imshow(img);
rectangle('Position',[str2double(str{3}),str2double(str{4}),str2double(str{5})-str2double(str{3}),str2double(str{6})-str2double(str{4})],'LineWidth',4,'EdgeColor','r');
pause(0.1);
if strcmp(str{1},lastname)%如果文件名相等,只需增加object
object_node=Createnode.createElement('object');
Root.appendChild(object_node);
node=Createnode.createElement('name');
node.appendChild(Createnode.createTextNode(sprintf('%s',str{2})));
object_node.appendChild(node);
node=Createnode.createElement('pose');
node.appendChild(Createnode.createTextNode(sprintf('%s','Unspecified')));
object_node.appendChild(node);
node=Createnode.createElement('truncated');
node.appendChild(Createnode.createTextNode(sprintf('%s',str{7})));
object_node.appendChild(node);
node=Createnode.createElement('difficult');
node.appendChild(Createnode.createTextNode(sprintf('%s','0')));
object_node.appendChild(node);
bndbox_node=Createnode.createElement('bndbox');
object_node.appendChild(bndbox_node);
node=Createnode.createElement('xmin');
node.appendChild(Createnode.createTextNode(sprintf('%s',num2str(str{3}))));
bndbox_node.appendChild(node);
node=Createnode.createElement('ymin');
node.appendChild(Createnode.createTextNode(sprintf('%s',num2str(str{4}))));
bndbox_node.appendChild(node);
node=Createnode.createElement('xmax');
node.appendChild(Createnode.createTextNode(sprintf('%s',num2str(str{5}))));
bndbox_node.appendChild(node);
node=Createnode.createElement('ymax');
node.appendChild(Createnode.createTextNode(sprintf('%s',num2str(str{6}))));
bndbox_node.appendChild(node);
else %如果文件名不等,则需要新建xml
copyfile(filepath, 'JPEGImages');
%先保存上一次的xml
if exist('Createnode','var')
tempname=lastname;
tempname=strrep(tempname,'.jpg','.xml');
xmlwrite(tempname,Createnode);
end
Createnode=com.mathworks.xml.XMLUtils.createDocument('annotation');
Root=Createnode.getDocumentElement;%根节点
node=Createnode.createElement('folder');
node.appendChild(Createnode.createTextNode(sprintf('%s',foldername)));
Root.appendChild(node);
node=Createnode.createElement('filename');
node.appendChild(Createnode.createTextNode(sprintf('%s',str{1})));
Root.appendChild(node);
source_node=Createnode.createElement('source');
Root.appendChild(source_node);
node=Createnode.createElement('database');
node.appendChild(Createnode.createTextNode(sprintf('My Database')));
source_node.appendChild(node);
node=Createnode.createElement('annotation');
node.appendChild(Createnode.createTextNode(sprintf('VisDrone2018-DET-train')));
source_node.appendChild(node);
node=Createnode.createElement('image');
node.appendChild(Createnode.createTextNode(sprintf('flickr')));
source_node.appendChild(node);
node=Createnode.createElement('flickrid');
node.appendChild(Createnode.createTextNode(sprintf('NULL')));
source_node.appendChild(node);
owner_node=Createnode.createElement('owner');
Root.appendChild(owner_node);
node=Createnode.createElement('flickrid');
node.appendChild(Createnode.createTextNode(sprintf('NULL')));
owner_node.appendChild(node);
node=Createnode.createElement('name');
node.appendChild(Createnode.createTextNode(sprintf('zhangyuqin')));
owner_node.appendChild(node);
size_node=Createnode.createElement('size');
Root.appendChild(size_node);
node=Createnode.createElement('width');
node.appendChild(Createnode.createTextNode(sprintf('%s',num2str(w))));
size_node.appendChild(node);
node=Createnode.createElement('height');
node.appendChild(Createnode.createTextNode(sprintf('%s',num2str(h))));
size_node.appendChild(node);
node=Createnode.createElement('depth');
node.appendChild(Createnode.createTextNode(sprintf('%s',num2str(d))));
size_node.appendChild(node);
node=Createnode.createElement('segmented');
node.appendChild(Createnode.createTextNode(sprintf('%s','0')));
Root.appendChild(node);
object_node=Createnode.createElement('object');
Root.appendChild(object_node);
node=Createnode.createElement('name');
node.appendChild(Createnode.createTextNode(sprintf('%s',str{2})));
object_node.appendChild(node);
node=Createnode.createElement('pose');
node.appendChild(Createnode.createTextNode(sprintf('%s','Unspecified')));
object_node.appendChild(node);
node=Createnode.createElement('truncated');
node.appendChild(Createnode.createTextNode(sprintf('%s',str{7})));
object_node.appendChild(node);
node=Createnode.createElement('difficult');
node.appendChild(Createnode.createTextNode(sprintf('%s','0')));
object_node.appendChild(node);
bndbox_node=Createnode.createElement('bndbox');
object_node.appendChild(bndbox_node);
node=Createnode.createElement('xmin');
node.appendChild(Createnode.createTextNode(sprintf('%s',num2str(str{3}))));
bndbox_node.appendChild(node);
node=Createnode.createElement('ymin');
node.appendChild(Createnode.createTextNode(sprintf('%s',num2str(str{4}))));
bndbox_node.appendChild(node);
node=Createnode.createElement('xmax');
node.appendChild(Createnode.createTextNode(sprintf('%s',num2str(str{5}))));
bndbox_node.appendChild(node);
node=Createnode.createElement('ymax');
node.appendChild(Createnode.createTextNode(sprintf('%s',num2str(str{6}))));
bndbox_node.appendChild(node);
lastname=str{1};
end
%处理最后一行
if feof(fidin)
tempname=lastname;
tempname=strrep(tempname,'.jpg','.xml');
xmlwrite(tempname,Createnode);
end
end
fclose(fidin);
file=dir(pwd);
for i=1:length(file)
if length(file(i).name)>=4 && strcmp(file(i).name(end-3:end),'.xml')
fold=fopen(file(i).name,'r');
fnew=fopen([xmlpath_new file(i).name],'w');
line=1;
while ~feof(fold)
tline=fgetl(fold);
if line==1
line=2;
continue;
end
expression = ' ';
replace=char(9);
newStr=regexprep(tline,expression,replace);
fprintf(fnew,'%s\n',newStr);
end
fprintf('已处理%s\n',file(i).name);
fclose(fold);
fclose(fnew);
delete(file(i).name);
end
end
num_begin=num_begin+1;
namepath=num2str(num_begin,'%06d'); %从000001变为000002
%disp(namepath);
end