准备WIDER FACE数据集

  WIDER FACE数据集是一个面部检测基准数据集,其图像是从可公开获得的WIDER数据集中选择的。 我们选择了32,203张图像,并标记了393,703张在比例,姿势和遮挡方面具有高度可变性的面部。对于每个事件类别,我们随机选择40% / 10% / 50%数据作为训练,验证和测试集。

  首先从WIDERFACE处下载数据文件,其中包括了训练集、验证集和测试集。实际上我们真正用到的只有训练集和测试集两个部分,同时我们还需要下载一个Face annotations文件,这个压缩文件是数据集的注释,里面有数据的标注格式说明和具体标注文件。

# The format of txt ground truth.
# File name
# Number of bounding box
# x1, y1, w, h, blur, expression, illumination, invalid, occlusion, pose
# 也就是第一行是文件夹,文件名
# 第二行是图中人脸的数量
# 再下面是人脸信息的参数。
# x1, y1, w, h, 代表人脸框的位置(检测算法一般都要画个框框把人脸圈出来)
# blur:是模糊度,分三档:0,清晰;1:一般般;2:人鬼难分
# express:表达
# illumination:曝光,分正常和过曝
# occlusion:遮挡,分三档。0,无遮挡;1,小遮挡;2,大遮挡;
# invalid:(没弄明白)
# pose:典型和非典型姿态
# ----------------------------------------------------
0--Parade/0_Parade_marchingband_1_849.jpg
1
449 330 122 149 0 0 0 0 0 0 

将WIDER_FACE数据集转成VOC数据集格式

VOC数据集格式

  在PASCAL VOC2012数据集中,当下载解压数据集后可以在解压文件夹下得到下面几个文件夹。
VOCdevikit2012
  其中,对于检测识别任务我们需要关注的只有AnnotationsImageSetsJPEGImages这三个文件夹,另外的SegmentationClassSegmentationObject则是做分割任务时需要用到的。下面进一步说明这三个文件夹的结构和作用。

Annotations
  Annotations文件夹中存放的是所有图像的标注文件,格式是.xml,文件名和对应的图像文件名相同,xml文件和图像文件一一对应。
生成得到的xml文件
其中一个标注文件的内容如下:



    widerface
    0--Parade_0_Parade_marchingband_1_356.jpg // 文件名
     // 图像来源(不重要)
        wider face Database
        PASCAL VOC2007
        flickr
        -1
    
     // 制作者姓名,可以修改
        yanyu
        yanyu
    
     // 图像尺寸,包括图像宽高和通道数
        1624
        1625
        3
    
    0 // 数据集是否用于图像分割,0否1是
     // 检测到的物体信息
        face // 物体类别
        Unspecified // 拍摄角度,这里暂时不用理会
        1 // 物体是否被截断,0否1是
        0 // 目标是否难以识别,0表示容易识别
         // bounding-box,包含标注的左上角和右下角坐标信息
            614
            552
            728
            638
        
     // 如果有多个目标的话会有多个object节点

对应的图片为:
0-Parade_0_Parade_marchingband_1_356.jpg

JPEGImages
  JPEGImages文件夹中包含了数据集中的所有文件,不论是训练集还是测试集图像

ImageSets
  在这个文件夹下面存放有数据集所有图片的文件名的文件,有四个文件夹分别是:Action,Layout,Main,Segmentation。其中聚焦检测识别任务只需要关注Main文件夹即可。其中Segmentation文件夹中存放的是与分割相关的文件,Layout文件夹下存放的是具有人体部位的数据(人的head、hand、feet等等,这也是VOC challenge的一部分),Action文件夹中存放的是人的动作(例如running、jumping等等,这也是VOC challenge的一部分)
  在Main文件夹下面全是***_train.txt或者是***_val.txt亦或是***_trainval.txt的文件,其中文件的每一行都对应了一个图片的文件名 其后跟随一个一 1/-1 的标志,表示对应的图像文件是这一类的 正/负 样本。***_trainval.txt是训练和验证集的集合。

  以上就是将WIDER_FACE数据集转成VOC数据集格式书需要了解的关于VOC数据集格式的前置要点。详细的可以参阅这篇博文,本章节的部分内容来源于此:PASCAL VOC数据集分析

转成VOC数据集格式

  我将工具上传至github,链接地址为https://github.com/HuColin/wider-face-pascal-voc-annotations,其中convert2voc.py文件是有效的,convert.py文件不能够生成有效的文件树结构,当然也更加灵活,推荐新手使用convert2voc.py文件进行转换。

import numpy as np
from xml.dom.minidom import Document
rootdir="/root/data/WIDER_FACE" # rootdir填写数据集的根目录,在我这里rootdir目录下存放有 WIDER_train和WIDER_val两个数据集原始文件
convert2vocformat=True

#最小取30大小的脸,并且补齐
minsize2select=30
usepadding=True

datasetprefix="/root/data/WIDER_FACE" # 这里填写生成的得到的images文件夹所在的路径,对应VOC数据集中JPEGImage文件夹所在的位置

  运行后可以在$rootdir路径下得到类似VOC数据集结构的文件夹结构

rootdir
|----Annotations
|----images
|----ImageSets
|    |----Main
|         |----test.txt
|         |----trainval.txt
|----labels
|----test.txt
|----trainval.txt

至此,WIDER_FACE数据集就转换成了VOC数据集的格式,接下来就是生成lmdb文件的工作了。

将VOC格式的WIDER_FACE数据集制作成LMDB格式的数据集

  接下来使用到的是caffe自带的一些工具了,可以从caffe的安装目录下的./data/VOC0712文件夹中找到,这里建议将文件夹拷贝至数据集的文件夹下。

修改labelmap_voc.prototxt文件

  这个文件主要是输入标签与文本的对应关系,以WIDER_FACE数据集为例,只用识别人脸,加上还有一个背景,所以是一共是2个分类,在我的xml文件中的标签人脸为face,里边的 name 要和你自己的数据集的 xml 文件名保持一致。所以内容改为下面就可以了:
```
item {
name: "none_of_the_above"
label: 0
display_name: "background"
}
item {
name: "face"
label: 1
display_name: "face"
}

## 修改create_list.sh文件并执行
  这个文件主要是根据我们刚才的 /ImageSets/Main/ 文件夹下的 4 个txt 文件 进一步生成转换 lmdb 需要用的形式, 为下一步 create_data.sh 文件的运行提供方便。 主要修改部分就是后面带有备注的几行。根据自己的情况修改对应路径及文件名称就可以了。内容如下:
  ```bash
#!/bin/bash

root_dir=$HOME/data/ # 数据集所在的位置,可以自己试着运行一下看看能否找到对应的文件
sub_dir=ImageSets/Main # 刚才新建的文件夹路径,用以读取刚才 classfiy.py 生成的 txt 文件
bash_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
for dataset in trainval test
do
  dst_file=$bash_dir/$dataset.txt
  if [ -f $dst_file ]
  then
    rm -f $dst_file
  fi
  for name in WIDER_FACE # WIDER_FACE 是我存放 images 和 Annotations 的文件夹名称
  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
    sed -i "s/^/$name\/images\//g" $img_file # 这里因为用的目录名称不是VOC默认的JPEGImages,改成是我们自己用的images文件名
    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

    rm -f $label_file
    rm -f $img_file
  done

  # Generate image name and size infomation.
  if [ $dataset == "test" ]
  then
    $Caffe_ROOT/build/tools/get_image_size $root_dir $dst_file $bash_dir/$dataset"_name_size.txt"
  fi

  # Shuffle trainval file.
  if [ $dataset == "trainval" ]
  then
    rand_file=$dst_file.random
    cat $dst_file | perl -MList::Util=shuffle -e 'print shuffle();' > $rand_file
    mv $rand_file $dst_file
  fi
done

  可以看见在 create_list.sh 所在的路径下会生成train.txt, test.txt, trainval.txt, val.txt, test_name_size.txt 这五个txt文件,但是这里用到的只有trainval.txttest.txt两个文件。

# test.txt文件内容示意
WIDER_FACE/images/0--Parade_0_Parade_Parade_0_194.jpg WIDER_FACE/Annotations/0--Parade_0_Parade_Parade_0_194.xml
WIDER_FACE/images/0--Parade_0_Parade_Parade_0_470.jpg WIDER_FACE/Annotations/0--Parade_0_Parade_Parade_0_470.xml
WIDER_FACE/images/0--Parade_0_Parade_marchingband_1_1045.jpg WIDER_FACE/Annotations/0--Parade_0_Parade_marchingband_1_1045.xml
WIDER_FACE/images/0--Parade_0_Parade_marchingband_1_556.jpg WIDER_FACE/Annotations/0--Parade_0_Parade_marchingband_1_556.xml
WIDER_FACE/images/0--Parade_0_Parade_Parade_0_829.jpg WIDER_FACE/Annotations/0--Parade_0_Parade_Parade_0_829.xml

可以看见这里就是图片与对应 xml 路径的一一对应,以便后面读取。

修改create_data.sh文件并执行

  这里就是构建数据集的最后一步了。同上主要修改部分是我添加标注的几行。内容如下:

#!/bin/bash

cur_dir=$(cd $( dirname ${BASH_SOURCE[0]} ) && pwd )
root_dir=$Caffe_ROOT # 这里填写你的caffe安装路径

cd $root_dir

redo=1
data_root_dir="$HOME/data" # WIDER_FACE数据集存放路径,也就是存放Annotations文件的文件夹所在的目录
dataset_name="WIDER_FACE_VOC" # 生成的数据集的名字(自定就好)
mapfile="/root/data/WIDER_FACE/VOC0712/labelmap_voc.prototxt"  # 刚刚修改完的prototxt文件的路径(推荐写绝对路径)
anno_type="detection"
db="lmdb"
min_dim=0
max_dim=0
width=0
height=0

extra_cmd="--encode-type=jpg --encoded"
if [ $redo ]
then
  extra_cmd="$extra_cmd --redo"
fi
for subset in test trainval # 这里只需要用到 test 和 trainval 两个部分的训练集
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/data/WIDER_FACE/VOC0712/$subset.txt \ # 这里填写create_list.sh 生成的 test.txt, trainval.txt 两个文件的绝对路径
      $data_root_dir/$dataset_name/$db/$dataset_name"_"$subset"_"$db \ # 这个部分是关于生成lmdb文件的路径及名称
      $root_dir/examples/$dataset_name
done

根据上面的修改,会在 $data_root_dir/$dataset_name 对应路径下生成lmdb的文件夹

  自此WIDER_FACE数据集就转成了Caffe可用的LMDB数据集。

参考文献

  1. caffe-SSD配置及用caffe-MobileNet-SSD训练自己的数据集
  2. MobileNetv2-SSDLite训练自己的数据集
  3. Wider Face 转VOC格式制作LMDB数据集
最后修改日期:2019年10月7日

作者

留言

撰写回覆或留言

发布留言必须填写的电子邮件地址不会公开。