http://blog.csdn.net/dcxhun3/article/details/52923310
本文的主要目的是生成VOC2007格式的Annotations,ImageSets和JPEGImages數(shù)據(jù)集,以便用faster rcnn訓(xùn)練。?
需要做的前期工作有兩個:下載ImageNet數(shù)據(jù)集下預(yù)訓(xùn)練得到的模型參數(shù)(用來初始化)和下載VOC2007數(shù)據(jù)集。?
在此基礎(chǔ)上開始生成VOC2007格式的Annotations,ImageSets和JPEGImages數(shù)據(jù)集。
下載ImageNet數(shù)據(jù)集下預(yù)訓(xùn)練得到的模型參數(shù)(用來初始化)?
可以直接利用faster rcnn自帶的腳本下載
cd $FRCN_ROOT
./data/scripts/fetch_imagenet_models.sh
也可以在一個百度云上下載,地址:http://pan.baidu.com/s/1hsxx8OW?
解壓,然后將該文件放在py-faster-rcnn\data下
下載VOC2007數(shù)據(jù)集
下載VOC2007數(shù)據(jù)集?
提供一個百度云地址:http://pan.baidu.com/s/1mhMKKw4?
解壓,然后,將該數(shù)據(jù)集放在py-faster-rcnn\data下,用你的數(shù)據(jù)集替換VOC2007數(shù)據(jù)集。Annotations,ImageSets和JPEGImages的格式分別如下:?

用自己的數(shù)據(jù)生成Annotations,ImageSets和JPEGImages,復(fù)制到 VOC2007文件下, VOC2007原來的文件夾都加了_ori 而沒有直接的替換,即如下圖所示:

因此我們現(xiàn)在在需要準備的就是生成VOC2007格式的Annotations,ImageSets和JPEGImages
雖然說圖片名對訓(xùn)練沒什么影響,但建議還是按VOC2007那樣,如“000001.jpg”這種形式。至于圖片格式, 我的也是jpg格式的。
批量修改圖片名字為VOC2007格式,可以參考Matlab程序(RenamePic.m),代碼如下:
%%
clc;
clear;
maindir='H:\medical_data\voctest\JPEGImage\';
name_long=6; %圖片名字的長度,如000001.jpg為6,最多9位,可修改
num_begin=1; %圖像命名開始的數(shù)字如000123.jpg開始的話就是123
subdir = dir(maindir);
%%
% dir得到的為結(jié)構(gòu)體數(shù)組每個元素都是如下形式的結(jié)構(gòu)體:
%? ? ? ? name? ? -- filename
%? ? ? ? date? ? ? -- modification date
%? ? ? ? bytes? ? -- number of bytes allocated to the file
%? ? ? ? isdir? ? ? -- 1 if name is a directory and 0 if not
%? ? ? ? datenum -- modification date as a MATLAB serial date number
%%
n=1;
for i = 1:length(subdir)
? if ~strcmp(subdir(i).name ,'.') && ~strcmp(subdir(i).name,'..')
? ? ? ? ? ? img=imread([maindir,subdir(i).name]);
? ? ? ? ? ? imshow(img);
? ? ? ? ? ? str=num2str(num_begin,'%09d');
? ? ? ? ? ? newname=strcat(str,'.jpg');
? ? ? ? ? ? newname=newname(end-(name_long+3):end);
? ? ? ? ? ? system(['rename ' [maindir,subdir(i).name] ' ' newname]);
? ? ? ? ? ? num_begin=num_begin+1;
? ? ? ? ? ? fprintf('已經(jīng)處理%d張圖片\n',n);
? ? ? ? ? ? n=n+1;
? ? ? ? ? pause(0.1);%可以把暫停去掉
? ? ? ? end
? ? end
2.目標(biāo)信息保存
我的CT肺數(shù)據(jù)已經(jīng)了結(jié)節(jié)輪廓的標(biāo)注信息,因此我只需要記錄左上右下的坐標(biāo)位置就好,格式如下:
000005.jpg nodule 86 44 129 66
000006.jpg nodule 94 48 142 73
000007.jpg nodule 86 150 129 172
000008.jpg nodule 87 44 130 66
000009.jpg nodule 60 52 90 78
000010.jpg nodule 66 57 100 86
000011.jpg nodule 60 73 90 99
前面是圖片名,中間是目標(biāo)類別,最后是目標(biāo)的包圍框坐標(biāo)(左上角和右下角坐標(biāo))。這個保存為txt格式,如out.txt。
做成VOC2007格式的xml,程序可參考matlab程序(VOC2007xml.m),代碼如下:
%%
%該代碼可以做voc2007數(shù)據(jù)集中的xml文件,
%txt文件每行格式為:000002.jpg nodule 44 28 132 121
%即每行由圖片名、目標(biāo)類型、包圍框坐標(biāo)組成,空格隔開
%包圍框坐標(biāo)為左上角和右下角
%作者:dcx
%%
clc;
clear;
%注意修改下面四個變量
imgpath='\img1\';%圖像存放文件夾
txtpath='\out.txt';%txt文件
xmlpath_new='Annotations/';%修改后的xml保存文件夾
foldername='VOC2007';%xml的folder字段名
fidin=fopen(txtpath,'r');
lastname='begin';
while ~feof(fidin)
? ? tline=fgetl(fidin);
? ? str = regexp(tline, ' ','split');
? ? filepath=[imgpath,str{1}];
? ? if exist(filepath,'file')
? ? 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','0')));
? ? ? ? ? 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;%根節(jié)點
? ? ? ? ? ? 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('VOC2007')));
? ? ? ? ? ? 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('dcx')));
? ? ? ? ? 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','0')));
? ? ? ? ? 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
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
4.保存xml到Annotations
新建一個文件夾,名字為Annotations,將xml文件全部放到該文件夾里。
新建一個文件夾,名字為JPEGImages,將所有的訓(xùn)練圖片放到該文件夾里。
新建文件夾,命名為ImageSets,在ImageSets里再新建文件夾,命名為Main。?
我們可以通過xml名字(或圖片名),生成四個txt文件,即:?

txt文件中的內(nèi)容為:
000035
000037
000041
000043
000044
000045
000046
000049
000050
即圖片名字(無后綴),test.txt是測試集,train.txt是訓(xùn)練集,val.txt是驗證集,trainval.txt是訓(xùn)練和驗證集.VOC2007中,trainval大概是整個數(shù)據(jù)集的50%,test也大概是整個數(shù)據(jù)集的50%;train大概是trainval的50%,val大概是trainval的50%??蓞⒖糾atlab程序(VOCSet.m),代碼如下:
%%
%該代碼根據(jù)已生成的xml,制作VOC2007數(shù)據(jù)集中的trainval.txt;train.txt;test.txt和val.txt
%trainval占總數(shù)據(jù)集的50%,test占總數(shù)據(jù)集的50%;train占trainval的50%,val占trainval的50%;
%上面所占百分比可根據(jù)自己的數(shù)據(jù)集修改,如果數(shù)據(jù)集比較少,test和val可少一些
%%
%注意修改下面四個值
xmlfilepath='.\Annotations';
txtsavepath='.\ImageSets\Main\';
trainval_percent=0.5;%trainval占整個數(shù)據(jù)集的百分比,剩下部分就是test所占百分比
train_percent=0.5;%train占trainval的百分比,剩下部分就是val所占百分比
%%
xmlfile=dir(xmlfilepath);
numOfxml=length(xmlfile)-2;%減去.和..? 總的數(shù)據(jù)集大小
trainval=sort(randperm(numOfxml,floor(numOfxml*trainval_percent)));
test=sort(setdiff(1:numOfxml,trainval));
trainvalsize=length(trainval);%trainval的大小
train=sort(trainval(randperm(trainvalsize,floor(trainvalsize*train_percent))));
val=sort(setdiff(trainval,train));
ftrainval=fopen([txtsavepath 'trainval.txt'],'w');
ftest=fopen([txtsavepath 'test.txt'],'w');
ftrain=fopen([txtsavepath 'train.txt'],'w');
fval=fopen([txtsavepath 'val.txt'],'w');
for i=1:numOfxml
? ? if ismember(i,trainval)
? ? ? ? fprintf(ftrainval,'%s\n',xmlfile(i+2).name(1:end-4));
? ? ? ? if ismember(i,train)
? ? ? ? ? ? fprintf(ftrain,'%s\n',xmlfile(i+2).name(1:end-4));
? ? ? ? else
? ? ? ? ? ? fprintf(fval,'%s\n',xmlfile(i+2).name(1:end-4));
? ? ? ? end
? ? else
? ? ? ? fprintf(ftest,'%s\n',xmlfile(i+2).name(1:end-4));
? ? end
end
fclose(ftrainval);
fclose(ftrain);
fclose(fval);
fclose(ftest);
這四個txt放在ImageSets\Main中。
替換voc2007數(shù)據(jù)集中的Annotations、ImageSets和JPEGImages,免去一些訓(xùn)練的修改。
準備好數(shù)據(jù)集后開始訓(xùn)練,具體訓(xùn)練方法參見我的博客:基于Faster RCNN的醫(yī)學(xué)圖像檢測(肺結(jié)節(jié)檢測)