基于caffe的SSD目标检测——训练集生成和lmdb文件的制作

基于caffe的SSD目标检测——训练集生成和lmdb文件的制作

https://github.com/weiliu89/caffe/tree/ssd

一级目录:

build       cmake           CONTRIBUTING.md  data        docker  examples  INSTALL.md  LICENSE   Makefile.config          matlab  python     scripts  tools
caffe.cloc  CMakeLists.txt  CONTRIBUTORS.md  distribute  docs    include   jobs        Makefile  Makefile.config.example  models  README.md  src

data目录中包含对数据集的生成脚本,进入打他中的VOC0712文件夹,文件如下:

coco_voc_map.txt  create_data.sh  create_list.sh  labelmap_voc.prototxt  

其中coco_voc_map.txt是mscoco数据集与voc数据集的类别对应关系。create_list.sh 是生成训练数据和样本对list的txt文件。create_data.sh是用来根据list生成trainval和test的lmdb文件的脚本。labelmap_voc.prototxt是VOC数据集的labelmap,即类别与名称的对应关系,是以prototxt的形式写成的,形式如下:

item {
  name: "none_of_the_above"
  label: 0
  display_name: "background"
}
item {
  name: "aeroplane"
  label: 1
  display_name: "aeroplane"
}
item {
  name: "bicycle"
  label: 2
  display_name: "bicycle"
}
item {
  name: "bird"
  label: 3
  display_name: "bird"
}

下面详细分析一下create_list.sh文件的操作:

#!/bin/bash

root_dir=$HOME/data/VOCdevkit/
# $HOME是家目录,相当于将当前的home目录,如/home接在文件路径之前。
sub_dir=ImageSets/Main
# 以上是VOC数据集中的结构
bash_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# BASH_SOURCE是当前执行shell文件的所在路径,dirname显示相对于pwd的相对路径的dirname
# 上面一句得到的是bash_dir,即shell文件的绝对路径
for dataset in trainval test
# 生成两个文件,分别为trainval用来训练和test留出来做测试集
do
  dst_file=$bash_dir/$dataset.txt
  # 生成的trainval.txt和test.txt的路径
  if [ -f $dst_file ]
  # 如果要生成的txt文件已经存在, -f指的是文件是否存在,-d表示文件夹,-x表示是否存在且具有执行权限
  then
    rm -f $dst_file
    # 如果有,先清除,重新生成
  fi
  for name in VOC2007 VOC2012
  # 对于VOC2007和VOC2012两个数据集
  do
    if [[ $dataset == "test" && $name == "VOC2012" ]]
      # 如果是生成test.txt,那么不用VOC2012中的数据
    then
      continue
    fi
    echo "Create list for $name $dataset..."
    # print一下进程状态,name 和 dataset 分别为VOC的数据集和trainval/test
    dataset_file=$root_dir/$name/$sub_dir/$dataset.txt
    echo $dataset_file
    # trainval.txt和test.txt,内容是图片的数字序号,注意这里的trainval.txt或test.txt存在了ImageSets/Main下面
    img_file=$bash_dir/$dataset"_img.txt"
    # 生成xxx/trainval_img.txt,这个是在当前目录下
    cp $dataset_file $img_file
    # 把trainval.txt copy到 trainval_img.txt
    sed -i "s/^/$name\/JPEGImages\//g" $img_file
    # sed是替换命令,在前面添加VOC2007/JPEGImages,如VOC2007/JPEGImages/000001
    sed -i "s/$/.jpg/g" $img_file
    # 后面添加.jpg,得到如:VOC2007/JPEGImages/000001.jpg,即VOC数据集中的相对路径

    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
    # 此段同上,得到xml文件的路径,如VOC2007/Annotations/000001.xml

    paste -d' ' $img_file $label_file >> $dst_file
    # 将上面的两个trainval_img.txt和trainval_label.txt合并成一个文件,即当前目录下的trainval.txt

    rm -f $label_file
    rm -f $img_file
    # 删掉两个临时文件,img和label

  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"
    # 对于测试集的数据,生成实际的size文件,利用build/tools中的get_image_size
  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
    # 随机重排训练集的数据
  fi
done

生成好trainval.txt和test.txt之后,就可以根据这个路径把xml和jpg文件做成lmdb文件了,即create_data.sh的操作:

cur_dir=$(cd $( dirname ${BASH_SOURCE[0]} ) && pwd )
# bash的绝对路径
root_dir=$cur_dir/../..
# bash是存放在~cafferoot~/data/VOC0712下,所以向上两级就是cafferoot
cd $root_dir
# 进入cafferoot目录
redo=1
# 是否重新生成lmdb
# data_root_dir="$HOME/data/VOCdevkit"
data_root_dir="/data/datasets/VOCdevkit"
dataset_name="VOC0712"
mapfile="$root_dir/data/$dataset_name/labelmap_voc.prototxt"
# 各种路径
anno_type="detection"
# 如果标签type是detection的话,就要读入labelmap,并用caffe转成label_map = caffe_pb2.LabelMap()
db="lmdb"
# 生成的子路径为“lmdb”
min_dim=0
max_dim=0
width=300
height=300
# 传入参数
extra_cmd="--encode-type=jpg --encoded"
if [ $redo ]
then
  extra_cmd="$extra_cmd --redo"
fi
# 额外参数
for subset in test trainval
# 对trainval 和 test 分别运行create_annoset.py的脚本,该脚本对这里的参数进行解析,并调用build/tool/里的create_annoset的caffe程序,进行lmdb的生成
do
  python $root_dir/scripts/create_annoset.py --anno-type=$anno_type --label-map-file=$mapfile --min-dim=$min_dim --max-dim=$max_dim --resize-width=$width --resize-height=$height --check-label $extra_cmd $data_root_dir $root_dir/data/$dataset_name/$subset.txt $data_root_dir/$dataset_name/$db/$dataset_name"_"$subset"_"$db examples/$dataset_name
done

之后的create_annoset.py的作用就是解析参数,生成命令行,并在命令行中调用caffe的函数来制作lmdb文件。

2018年8月14日16:37:52

现在的社会不适合我们了,因为我们太怀旧了。 —— 导演,贾樟柯

posted @ 2018-08-14 16:39  毛利小九郎  阅读(236)  评论(0编辑  收藏  举报