SSD在训练前需要在终端运行create_list.sh来生成trainval.txt, test.txt和test_name_size.txt三个文件,详见SSD官方说明。
create_list.sh代码解析如下:
#!/bin/bash
root_dir=$HOME/data/VOCdevkit/ #存放数据的根目录
sub_dir=ImageSets/Main #存放ImageSets数据集的索引
bash_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" #dirname "${BASH_SOURCE[0]}"进行提取bash命令中第一个参数(这里是creat_list.sh文件所在的路径),详见https://blog.csdn.net/davidhopper/article/details/78989369
for dataset in trainval test #for循环(在trainval和test中循环各一次)(格式为for...do...done,详见https://www.cnblogs.com/hshanghai/p/3267211.html)
do
dst_file=$bash_dir/$dataset.txt
if [ -f $dst_file ] #-f filename 如果 filename为常规文件,则为真 (格式为if...then...fi),详见https://blog.csdn.net/xungjhj/article/details/73613883
then
rm -f $dst_file #删除该文件(上述if为真的情况下),详见http://man.linuxde.net/rm
fi #搭配if用的(表示if结束)
for name in VOC2007 VOC2012
do
if [[ $dataset == "test" && $name == "VOC2012" ]]
then
continue
fi
echo "Create list for $name $dataset..." #在终端打印出当前执行的结果
dataset_file=$root_dir/$name/$sub_dir/$dataset.txt #要提取的数据集索引文件路径
#以下对图像索引进行处理
img_file=$bash_dir/$dataset"_img.txt"
cp $dataset_file $img_file #将dataset_file复制给img_file,详见http://man.linuxde.net/cp
#sed用法详见https://www.cnblogs.com/lzeffort/p/7237268.html
#-i表示直接修改文件内容;s表示用后面的替换;^表示行首;/g表示搜索到的全部替换(与s联用);此句代码表示用$name\/JPEGImages\/替换掉所有行首
sed -i "s/^/$name\/JPEGImages\//g" $img_file
sed -i "s/$/.jpg/g" $img_file #$表示行尾;此句代码的意思是用.jpg替换掉所有行尾
#以下对图像对应的标签进行处理
label_file=$bash_dir/$dataset"_label.txt"
cp $dataset_file $label_file
sed -i "s/^/$name\/Annotations\//g" $label_file
sed -i "s/$/.xml/g" $label_file
paste -d' ' $img_file $label_file >> $dst_file #paste将文件进行合并;-d<间隔字符>表示用指定的间隔字符取代跳格字符;并写入dst_file中,详见http://www.runoob.com/linux/linux-comm-paste.html
rm -f $label_file
rm -f $img_file
done
# Generate image name and size infomation.
if [ $dataset == "test" ]
then
$bash_dir/../../build/tools/get_image_size $root_dir $dst_file $bash_dir/$dataset"_name_size.txt" #后三者为get_image_size这个函数的输入(详细参见/tools/get_image_size.cpp文件)
fi
# Shuffle trainval file. 随机重置顺序
if [ $dataset == "trainval" ]
then
rand_file=$dst_file.random
cat $dst_file | perl -MList::Util=shuffle -e 'print shuffle(<STDIN>);' > $rand_file
mv $rand_file $dst_file #覆盖,详见http://man.linuxde.net/mv
fi
done
代码本身是先获取VOC2007或VOC2012/ImageSets/Main下的trainval.txt和test.txt文档中的所有内容,如下图:
文件里的内容都是图片的索引号,如下图:
然后利用以下语句(上面代码中摘抄出来的),将所有图片的索引和对应的标签文件索引写入同一个txt文档:
img_file=$bash_dir/$dataset"_img.txt"
cp $dataset_file $img_file
sed -i "s/^/$name\/JPEGImages\//g" $img_file
sed -i "s/$/.jpg/g" $img_file
label_file=$bash_dir/$dataset"_label.txt"
cp $dataset_file $label_file
sed -i "s/^/$name\/Annotations\//g" $label_file
sed -i "s/$/.xml/g" $label_file
paste -d' ' $img_file $label_file >> $dst_file
结果如下图:
即同一行所表示的是一张图像的路径及其对应的标签文件的路径。
在此基础上,进一步获取测试集中图像的索引号和长宽,写入test_name_size.txt文件中,结果如下:
最后再对训练集(生成的trainval.txt文件,其实叫训练验证集更合适)中的每一行进行随机打散重排(增强随机性)。