您的位置:首页 > 其它

用ImageNet的数据集训练Faster R-CNN

2016-06-20 09:54 351 查看


用ImageNet的数据集训练Faster R-CNN问题汇总

    一 有些xml文件有问题,需要修改
  二  object的长宽比有要求,否则训练过程中报错

         anchor_target_layer.py”, line 137, in forward 

         gt_argmax_overlaps = overlaps.argmax(axis=0) 

         ValueError: attempt to get argmax of an empty sequence

    

    object的bounding box的宽高比:

        VOC2007:在0.117-15.500之间

        ImageNet(ILSVRC2014):在0.03-48.50之间

    把数据的宽高比至少约束在0.117-15.500才能保证训练

三 对图片的大小也有要求,不能太小

解决方法:

        1.不是所有图片都有xml,所以我先根据Imagenet 数据集中bbox_train_v2中的xml文件把对应的图片复制出来。下面是matlab代码%根据xml(在多个文件夹下)的名字找到该图片,保存这个图片
clc;
clear;

maindir = '/media/zc/A/Imagenet2012/bbox_train_v2'; %标签路径
maindir2 = '/media/zc/A/Imagenet2012/img_train'; %图片路径
a = dir(maindir); % a 里面包括多个文件夹
b = a(3:end); % a 中三个隐藏的文件夹不要
n = size(b); % n 就是1000个文件夹
%num = 1; %xml一共有50多万个,如果不需要全部的,可以打开这几行注释,例如:从每个文件夹中拿出300个
for m = 1:n
name = b(m).name; % bbox_train_v2下的第一个文件名
str1 = strcat(maindir,'/',name); % 第一个文件下的所有xml 文件
dirs = dir(str1);
c = dirs(3:end); %有2个隐藏文件
for num = 1: length(c)
name2 = c(num).name; % bbox_train_v2下的第一个文件中的第一个xml文件
name3 = name2(1:end-4); % 去掉后缀

str2 = strcat(maindir2,'/',b(m).name,'/',name3,'.JPEG'); % 找到这个图片的位置

outpath = '<span style="font-family: 'microsoft yahei';">/media/zc/A/Imagenet2012/img_train_all</span><span style="font-family: 'microsoft yahei';">'; % 输出位置</span>
out = [outpath,'/',name3,'.JPEG'];
disp(out);
copyfile(str2,out);
% num = num + 1;
% if num == 300;
% break;
%end
end
end 
   2.把bbox_train_v2中1000个xml文件夹合并成一个allAnnotations文件夹

matlab代码如下,和上面的代码功能差不多%复制xml(在多个文件夹下)到一个文件夹下
clc;
clear;
maindir = '/media/zc/A/Imagenet2012/bbox_train_v2'; %标签路径

a = dir(maindir); % a 里面包括多个文件夹
b = a(3:end); % a 中三个隐藏的文件夹不要
n = size(b); % n 就是多个文件夹
for m = 1:n
name = b(m).name; % bbox_train_v2下的第一个文件名
str1 = strcat(maindir,'/',name); % 第一个文件下的所有xml 文件
dirs = dir(str1);
c = dirs(3:end);
for num = 1: length(c)
name2 = c(num).name;
str2 = strcat(maindir,'/',b(m).name,'/',name2);

outpath = '/media/zc/A/Imagenet2012/allAnnotations'; % 输出位置
out = [outpath,'/',name2];
disp(out);
copyfile(str2,out);
end
end

3.修改xml,挑出符合上述三个问题的xml

%更改xml中的name属性,顺便选取符合对象长宽比,图片不能太小的xml
clc;
clear;
path = '/media/zc/A/Imagenet2012/allAnnotations/'; %第二步中的文件
path2 = '/home/zc/py/data/VOCdevkit2007/VOC2007/Annotations'; %保存路径
str1 = strcat(path,'/','*.xml'); % 第一个文件夹下的所有xml 文件
dirs = dir(str1);
n = size(dirs);
for m = 1:n
name = dirs(m).name; % 一个xml文件名字
name2 = name(1:9); %这个名字的前九位,即类名
str2 = [path,'/',name]; %xml的读取绝对路径
str3 = [path2,'/',name]; %xml的保存绝对路径
xmlDoc = xmlread(str2); % 读取这个xml文件

%% Extract ID
IDArray = xmlDoc.getElementsByTagName('filename'); % 将所有filename节点放入数组IDArray
nodeContent = char(IDArray.item(0).getFirstChild.getData) % 提取当前节点的内容

Size = xmlDoc.getElementsByTagName('size'); %将所有size节点放入数组IDArray
thisItemS = Size.item(0);
childNodeS = thisItemS.getFirstChild ;

childNodeS = childNodeS.getNextSibling;
childNodeNm = char(childNodeS.getTagName) % 当前节点的名字,width
width = char(childNodeS.getFirstChild.getData) % 当前节点的内容 ,500

childNodeSS = childNodeS.getNextSibling.getNextSibling; %下一个属性
childNodeNm = char(childNodeSS.getTagName) % 当前节点的名字,height
height = char(childNodeSS.getFirstChild.getData) % 当前节点的内容 ,353

FDsObject = xmlDoc.getElementsByTagName('object'); % 将所有objetc节点放入数组FDsArray
A = [];
x = 0;
z = 0;
for i = 0 : FDsObject.getLength-1 % object有的xml文件中不止一个
thisItem = FDsObject.item(i);
childNode = thisItem.getFirstChild ;
childNode = childNode.getNextSibling;

childNodeNm = char(childNode.getTagName) % 当前节点的名字,name
childNodeData = char(childNode.getFirstChild.getData) % 当前节点的内容,n02111889,这个实例本身是正确的。有的内容是dog,需要改成对应的n0xxxxxxx
childNode.setTextContent(name2); %把n02111889 改成文件名字的前九位

FDsB = xmlDoc.getElementsByTagName('bndbox');
thisItemB = FDsB.item(0);
childNodeB = thisItemB.getFirstChild ;

childNodeB = childNodeB.getNextSibling;
childNodeNm = char(childNodeB.getTagName) % 当前节点的名字,xmin
xmin = char(childNodeB.getFirstChild.getData) % 当前节点的内容,177

childNodeC = childNodeB.getNextSibling.getNextSibling;
childNodeNm = char(childNodeC.getTagName) % 当前节点的名字,ymin
ymin = char(childNodeC.getFirstChild.getData) % 当前节点的内容,100

childNodeD = childNodeB.getNextSibling.getNextSibling.getNextSibling.getNextSibling;
childNodeNm = char(childNodeD.getTagName) % 当前节点的名字,xmax
xmax = char(childNodeD.getFirstChild.getData) % 当前节点的内容,274

childNodeE = childNodeB.getNextSibling.getNextSibling.getNextSibling.getNextSibling.getNextSibling.getNextSibling;
childNodeNm = char(childNodeE.getTagName) % 当前节点的名字,ymax
ymax = char(childNodeE.getFirstChild.getData) % 当前节点的内容,289

A = [A,(str2num(xmax) -str2num(xmin)) / (str2num(ymax) - str2num(ymin))]; % 把每个object的长宽比计算出来 保存在A 中
x = x + 1;
end
for y = 1 : x
if A(y) >0.177 && A(y) <15.5 && str2num(width) >200 && str2num(height) >200; %根据这几行 把object 长宽比正确的 以及 图片大小符合要求的保存到新的文件中
z = z + 1;
end
end
if x == z
xmlwrite(str3,xmlDoc);
end
end4.再根据Annotations找到对应的图片

%根据xml(在一个文件夹下)的名字找到该图片,保存这个图片
clc;
clear;

maindir = '/home/zc/py/data/VOCdevkit2007/VOC2007/Annotations/*.xml'; %标签路径
<span style="font-family: 'microsoft yahei';">maindir2 = '/media/zc/A/Imagenet2012/img_train_all';  </span> %第一步得到的
a = dir(maindir);
n = size(a);
for m = 1:n
name = a(m).name;
name2 = name(1:end-4);
str2 = strcat(maindir2,'/',name2,'.JPEG');
outpath = '/home/zc/py/data/VOCdevkit2007/VOC2007/JPEGImages/'; % 输出位置
out = [outpath,name2,'.JPEG'];
disp(out);
copyfile(str2,out);
end
5.我知道上面步骤比较麻烦,有的步骤可以合并,还能减少内存占用,但时间比较短,懒得把代码合并了。好了,经过修改,且满足要求的xml和对应的图片都选出来了,下面生成四个txt文件。我把图片,xml直接替换到VOC2007中。就像这篇博客中所说的那样http://blog.csdn.net/qq_26569761/article/details/51398656

有什么不懂,就把这篇博客看仔细点

把图片的名字保存到txt中  在shell中用这条语句

find /home/zc/py/data/VOCdevkit2007/VOC2007/JPEGImage -type f -exec echo {} \; > /home/zc/py/data/VOCdevkit2007/VOC2007/ImageSets/Main/all.txt 

第一条路径是图片位置,第二条是txt保存位置

Main 下应该是train.txt   val.txt   trainval.txt   test.txt

all.txt有几十万行,我是这样做的,把奇数行给test.txt.偶数行给trainval.txt

再把trainval.txt中的奇数行给train.txt.偶数行给val.txt

%把一个txt中的奇偶行分开保存到新的txt中
clc;
clear;

fidin=fopen('/home/zc/py/data/VOCdevkit2007/VOC2007/ImageSets/Main/trainval.txt');
fidout=fopen('/home/zc/py/data/VOCdevkit2007/VOC2007/ImageSets/Main/val.txt','w');

i = 0; %-1是奇 0是偶
while ~feof(fidin) % 判断是否为文件末尾
tline=fgetl(fidin); % 从文件读行
i = i + 1;
if rem(i,2) == 0;
fprintf(fidout,'%s\n',tline);
end
end
fclose(fidout);
fclose(fidin);然后就是修改其他文件,上面博客中都有。

有两个文件要改,要不然会出现assert (boxes[:, 2] >= boxes[:, 0]).all()  报错

一个是pascal_voc.py



    x1 = float(bbox.find('xmin').text) - 1

    y1 = float(bbox.find('ymin').text) - 1

    x2 = float(bbox.find('xmax').text) - 1

    y2 = float(bbox.find('ymax').text) - 1

的下面添加

            if x1 < 0:  

                x1 = 0

            if y1 < 0:

                y1 = 0

另一个imdb.py



     boxes[:, 2] = widths[i] - oldx1 - 1

的下面添加

     for b in range(len(boxes)):

                if boxes[b][2] < boxes[b][0]:

                   boxes[b][0] = 0
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: