Caffe系列2——Windows10制作LMDB数据详细过程(手把手教你制作LMDB)

Windows10制作LMDB详细教程

原创不易,转载请注明出处:https://www.cnblogs.com/xiaoboge/p/10678658.html

摘要:

  当我们在使用Caffe做深度学习项目时,经常需要制作Caffe常用的数据类型lmdb、leveldb以及hdf5等(尽管可以使用原始图片,效率低),而不是我们常见的JPG、PNG、TIF。因此,我们需要对我们采集的数据进行格式转换,即通过输入我们自己的图片目录(包含有训练集和验证集的大量图片)转换成一个lmdb库文件的输出;这个过程一般是有Caffe工具中的convert_imageset.exe,该工具在编译过的Caffe中,具体位置是:D:你的根目录caffecaffe-windowsBuildx64Releaseconvert_imageset.exe。

 

开始正文:

   格式转换的4个必要条件:

   (1)编译好Caffe,而且convert_imageset.exe存在;

  (2)需要被转换的图像和目录,注意它们是有要求的(请看稍后的文件目录架构);

  (3)在将图像转换为lmdb格式之前,首先生成两个标签文件train.txt和val.txt(具体格式见下文);

  (4)运行编辑修改好的create_imagenet.sh(最好将其制到你的项目文件夹下,不修改原始文件)生成lmdb文件。

      所在位置:D:你的caffe根目录caffecaffe-windowsexamplesimagenet 

 

 1. 数据集的组织架构(文件目录结构)

  接下来,我将会使用一个例子详细介绍即将要使用的数据集的目录结构。这里制作的是一个分类数据集,主要包括两个类别:dog和cat,我们用数字0表示dog的类别,数字1来表示cat类别。在总目录data_set文件夹下,包括两个子文件夹分别是train和val,它们分别存储着训练集和验证集的所有图片。在train文件夹下 也包含两个子文件夹,它们分别是“0”和“1”,里面分别存储的是dog和cat的所有图像。在val的文件夹下没有子文件夹(其实也可以像train一样),直接是将要用于验证的图像数据,我们可以根据图像的名字知道它所属的类别,便于写出val.txt文件。鉴于这一步是格式转换的基础,我将整个目录详细结构用图展示如下:

 (1)数据集根目录所在路径:C:UsersAdministratorDesktop

 (2)data_set的子文件夹:C:UsersAdministratorDesktopdata_set

3)train的子文件夹:C:UsersAdministratorDesktopdata_set rain

  (a)“0”文件夹下的文件:C:UsersAdministratorDesktopdata_set rain

    这里图片文件的名字其实可以随意,因为文件夹就指出了它所属的类别。

  (b)“1”文件夹下的文件:C:UsersAdministratorDesktopdata_set rain1

    这里图片文件的名字其实可以随意,因为文件夹就指出了它所属的类别。

(4)val的子文件夹:C:UsersAdministratorDesktopdata_setval

    这里的图像文件的名字必须可以判断它所属的类别,我们使用python中的split()函数可以将文件名以“_”分隔开来获取图像所属类别,具体见程序。

  至此,我已经详细介绍了整个数据集的详细目录结构,我相信这已经足够详细啦!接下来,我们开始更至关重要的一步操作。

 

 2. 如何制作train.txt和val.txt

  如果想要将图像数据转换为LMDB数据格式,不仅要使用上述的数据集文件目录,还需要这些图片存放的路径以及该图片的标签(属于哪个类);一般情况下,标签文件有两个,一个是描述训练集合的train.txt,另一个是描述验证集的val.txt,这两个文件的格式稍微有点差别,具体格式如下:

  (1)train.txt的文件格式

  注意:该文件中分别存储了图像的路径和所属的类别,“0”表示dog,“1”表示cat。这里也没有打乱图像的顺序,可以在制作LMDB的时候打乱。

  (2)val.txt的文件格式

  注意:这里的验证集的标签文件无需分类存储(像train一样分成两个文件夹),但是我们必须可以判断每张图片的所属类别。

  到目前为止,我们已经知道了所要制作的train.txt和val.txt的格式要求了;接下来就是怎样从我们的数据集出发,制作属于自己数据集的train.txt和val.txt,这个制作的过程并不是固定的,每个人可以根据自己的习惯使用熟悉的语言(例如,python、c++)去完成这一步骤。还有根据项目的实际不同需求,可能要写的程序也是不完全一样的,但是我想这一编程实现输出train.txt和val.txt对于一个程序员来说是非常基础操作。我在这里针对这个例子写一段python代码来实现这个操作,虽然写的不是很好,但是能够实现我们的需求,我也对它进行了详细的注释。代码展示如下(python语言所示),程序的名称是:generate_txt.py

 1 # -*- coding: utf-8 -*-
 2 # @Time    : 2018/12/9 0009 12:04
 3 # @Author  : sunjianbo
 4 # @Email   : 1871593109@qq.com
 5 # @Software: PyCharm
 6 import os
 7 #数据集根目录所在路径
 8 root_data_path = r"C:UsersAdministratorDesktopdata_set"
 9 #输出的TXT文件路径
10 traintxt_path = root_data_path + "\" + "train.txt"
11 valtxt_path = root_data_path + "\" + "val.txt"
12 
13 #如果存在之前生成的TXT文件,先把它们删除
14 if os.path.exists(traintxt_path):
15     os.remove(traintxt_path)
16 if os.path.exists(valtxt_path):
17     os.remove(valtxt_path)
18 #返回数据集文件夹下的子文件夹
19 filenames = os.listdir(root_data_path)    #["train", "val"]
20 
21 #打开要存储的TXT文件
22 file_train = open(traintxt_path, "w")
23 file_val = open(valtxt_path, "w")
24 
25 if len(filenames) > 0:
26     for fn in filenames:
27         #数据集根目录下的子文件夹路径,train和val的绝对路径
28         full_filename = os.path.join(root_data_path, fn)
29         
30         # 判断是训练集文件夹,还是验证集文件夹
31         if fn == "train":
32             #找出训练集文件夹下的子文件夹名字,是每个类别的文件夹,0表示狗,1表示猫
33             file = os.listdir(full_filename)   #["0", "1"]
34             for name in file:
35                 #获得train文件夹下的子文件夹“0”和“1”的绝对路径
36                 temp = os.path.join(full_filename, name)
37                 for img in os.listdir(temp):    #分别遍历两个文件夹["0", "1"]下的所有图像
38                     #将图像的信息写入到train.txt文件
39                     file_train.write(name + "/" + img + " " + name + "
")
40         elif fn == "val":        #当进入到val文件夹后
41             for img in os.listdir(full_filename):   #遍历所有的图像
42                 category = img.split('_')           #对图像的名字进行分割,返回的是一个列表
43                 if category[0] == "dog":            #当分割的结果可以判断是dog时,类别是“0”
44                     file_val.write(img + " " + "0" + "
")
45                 elif category[0] == "cat":           #当分割的结果可以判断是cat时,类别是“1”
46                     file_val.write(img + " " + "1" + "
")
47                 else:
48                     print("验证集中图片名字有误")
49         else:
50             print("存在错误文件夹")
51 else:
52     print("该文件夹下不存在子文件夹")
53 
54 file_train.close()
55 file_val.close()

  运行上面的程序:generate_txt.py,可以在数据集所在目录(data_set文件夹下面)生成两个train.txt和val.txt文件。生成之后的目录结构如下:

  其中,两条黄色线连接的部分就是运行上面的generate_txt.py生成的。

  现在,我们已经完成了转换LMDB数据格式最重要的一步了。接下来的步骤将很简单,我们继续往下走。

 

 3. 开始制作LMDB格式的数据

  在完成以上的工作的基础上,我们通过上面的4个文件(两个train和val的图像库,两个train.txt和val.txt标签列表),把图像的数据和其对应的标签打包起来,生成我们需要的LMDB格式的数据。

  首先,我们需要找到制作LMDB格式的create_imagenet.sh,它的原始地址在D:program_filescaffecaffe-windowsexamplesimagenet,找到该文件之后将其复制到自己的项目文件夹(可以修改名称),我这里把它放在了data_set的文件夹下,然后进行相应的路径设置就可以运行create_imagenet.sh(或者是修改后的名称)。下面展示了原始的create_imagenet.sh文件,但是我对参数进行了注释和说明,并且添加了关于判断是否已经生成过LMDB文件的一步,如果存在删除它生成最新的。

 (1)原始的create_imagenet.sh文件

 

 1 #!/usr/bin/env sh
 2 # Create the imagenet lmdb inputs    #创建LMDB格式的文件输入
 3 # N.B. set the path to the imagenet train + val data dirs    #为train和val数据目录设置路径
 4 
 5 EXAMPLE=examples/imagenet                     #生成模型训练数据的文件夹,即create_imagenet.sh(这里名字可以修改)所在文件夹,也就是最终的LMDB数据存储的位置。                 
 6 DATA=data/ilsvrc12                            #python脚本处理完的数据存储路径,也就是train.txt和val.txt的存储路径
 7 TOOLS=build/tools                             #caffe的工具库,需要找到自己编译过的convert_imageset.exe,具体位置在D:/program_files/caffe/caffe-windows/Build/x64/Release
 8 
 9 TRAIN_DATA_ROOT=/path/to/imagenet/train/      #待处理的图像训练数据的路径
10 VAL_DATA_ROOT=/path/to/imagenet/val/          #待处理的图像验证数据的路径
11 
12 # Set RESIZE=true to resize the images to 256x256. Leave as false if images have
13 # already been resized using another tool.
14 RESIZE=false                                  #是否对图片进行resize操作,如果是设置为True
15 if $RESIZE; then
16   RESIZE_HEIGHT=256                           #resize的尺寸是256*256
17   RESIZE_WIDTH=256
18 else
19   RESIZE_HEIGHT=0
20   RESIZE_WIDTH=0
21 fi
22 
23 if [ ! -d "$TRAIN_DATA_ROOT" ]; then
24   echo "Error: TRAIN_DATA_ROOT is not a path to a directory: $TRAIN_DATA_ROOT"
25   echo "Set the TRAIN_DATA_ROOT variable in create_imagenet.sh to the path" 
26        "where the ImageNet training data is stored."
27   exit 1
28 fi
29 
30 if [ ! -d "$VAL_DATA_ROOT" ]; then
31   echo "Error: VAL_DATA_ROOT is not a path to a directory: $VAL_DATA_ROOT"
32   echo "Set the VAL_DATA_ROOT variable in create_imagenet.sh to the path" 
33        "where the ImageNet validation data is stored."
34   exit 1
35 fi
36 
37 
38 echo "if train.txt and val.txt are exist in EXAMPLE dir. clear all"
39 #删除已存在的lmdb格式文件,若在已存在lmdb格式的文件夹下再添加lmdb文件,会出现错误
40 rm -rf $EXAMPLE/train_lmdb  
41 rm -rf $EXAMPLE/val_lmdb      
42 
43 
44 echo "Creating train lmdb..."
45 
46 GLOG_logtostderr=1 $TOOLS/convert_imageset      #调用convert_imageset进行格式转换
47     --resize_height=$RESIZE_HEIGHT              #将图片调整到固定尺寸
48     --resize_width=$RESIZE_WIDTH 
49     --shuffle                                   #打乱图像的顺序
50     $TRAIN_DATA_ROOT 
51     $DATA/train.txt                            #这里的DATA是存放train.txt的路径
52     $EXAMPLE/ilsvrc12_train_lmdb                #这里修改输出的训练集的LMDB的名称
53 
54 echo "Creating val lmdb..."
55 
56 GLOG_logtostderr=1 $TOOLS/convert_imageset      #调用convert_imageset进行格式转换
57     --resize_height=$RESIZE_HEIGHT              #将图片调整到固定尺寸
58     --resize_width=$RESIZE_WIDTH 
59     --shuffle                                   #打乱图像的顺序
60     $VAL_DATA_ROOT 
61     $DATA/val.txt                              #这里的DATA是存放val.txt的路径
62     $EXAMPLE/ilsvrc12_val_lmdb                  #这里修改输出的验证集的LMDB的名称
63 
64 echo "Done."

(2)基于本例子的修改后的create_imagenet.sh文件如下,名称改为:convert_my_LMDB.sh

 1 #!/usr/bin/env sh
 2 # Create the imagenet lmdb inputs    #创建LMDB格式的文件输入
 3 # N.B. set the path to the imagenet train + val data dirs    #为train和val数据目录设置路径
 4 
 5 EXAMPLE=C:/Users/Administrator/Desktop/data_set                   #生成模型训练数据的文件夹,即create_imagenet.sh(这里名字可以修改)所在文件夹。                 
 6 DATA=C:/Users/Administrator/Desktop/data_set                      #python脚本处理完的数据存储路径,也就是train.txt和val.txt的存储路径
 7 TOOLS=D:/program_files/caffe/caffe-windows/Build/x64/Release       #caffe的工具库,找到自己的编译过的convert_imageset.exe所在的位置
 8 
 9 TRAIN_DATA_ROOT=C:/Users/Administrator/Desktop/data_set/train/      #待处理的训练数据的路径
10 VAL_DATA_ROOT=C:/Users/Administrator/Desktop/data_set/val/          #待处理的验证数据的路径
11 
12 # Set RESIZE=true to resize the images to 256x256. Leave as false if images have
13 # already been resized using another tool.
14 RESIZE=true                                 #是否对图片进行resize操作,如果是设置为True
15 if $RESIZE; then
16   RESIZE_HEIGHT=256                           #resize的尺寸是256*256
17   RESIZE_WIDTH=256
18 else
19   RESIZE_HEIGHT=0
20   RESIZE_WIDTH=0
21 fi
22 
23 if [ ! -d "$TRAIN_DATA_ROOT" ]; then
24   echo "Error: TRAIN_DATA_ROOT is not a path to a directory: $TRAIN_DATA_ROOT"
25   echo "Set the TRAIN_DATA_ROOT variable in create_imagenet.sh to the path" 
26        "where the ImageNet training data is stored."
27   exit 1
28 fi
29 
30 if [ ! -d "$VAL_DATA_ROOT" ]; then
31   echo "Error: VAL_DATA_ROOT is not a path to a directory: $VAL_DATA_ROOT"
32   echo "Set the VAL_DATA_ROOT variable in create_imagenet.sh to the path" 
33        "where the ImageNet validation data is stored."
34   exit 1
35 fi
36 
37 
38 echo "if train.txt and val.txt are exist in EXAMPLE dir. clear all"
39 #删除已存在的lmdb格式文件,若在已存在lmdb格式的文件夹下再添加lmdb文件,会出现错误
40 rm -rf $EXAMPLE/train_lmdb  
41 rm -rf $EXAMPLE/val_lmdb      
42 
43 
44 echo "Creating train lmdb..."
45 
46 GLOG_logtostderr=1 $TOOLS/convert_imageset      #调用convert_imageset进行格式转换
47     --resize_height=$RESIZE_HEIGHT              #将图片调整到固定尺寸
48     --resize_width=$RESIZE_WIDTH 
49     --shuffle                                   #打乱图像的顺序
50     $TRAIN_DATA_ROOT 
51     $DATA/train.txt                            #这里的DATA是存放train.txt的路径
52     $EXAMPLE/train_lmdb                         #这里修改输出的训练集的LMDB的名称
53 
54 echo "Creating val lmdb..."
55 
56 GLOG_logtostderr=1 $TOOLS/convert_imageset      #调用convert_imageset进行格式转换
57     --resize_height=$RESIZE_HEIGHT              #将图片调整到固定尺寸
58     --resize_width=$RESIZE_WIDTH 
59     --shuffle                                   #打乱图像的顺序
60     $VAL_DATA_ROOT 
61     $DATA/val.txt                              #这里的DATA是存放val.txt的路径
62     $EXAMPLE/val_lmdb                           #这里修改输出的验证集的LMDB的名称
63 
64 echo "Done."
read #最后加一行read,可以让窗口暂停等待,相当于pause。

  这里修改的位置有:第5行、第6行、第9行、第10行、第14行、第52行、第62行。最终,在data_set文件夹下面生成了两个文件夹train_lmdb和val_lmdb,它们分别存储了训练集和测试集的转换数据和标签。在windows系统上不可以直接运行sh文件,因此我们需要去安装一下Git,并将安装好的Git的bin文件路径加入到环境变量,就可以双击执行sh文件啦。当sh文件运行完成之后(这里的运行其实是调用了D:program_filescaffecaffe-windowsBuildx64Releaseconvert_imageset.exe格式转换可执行程序),文件的目录结构图如下所示:

  至此,我们的LMDB的数据格式就真正做完了,是不是并不是很难!

 

4. 另一种制作LMDB数据格式的方法(windows下不需要安装Git) 

   首先,我们看一下转换数据之前的文件目录结构(和之前一样):

  在以上四个文件的基础上进行转换,首先在data_set文件夹下创建一个convert_my_lmdb.txt文件,在该文件中写入一段批处理文件(详细内容如下),然后将文件格式修改为批处理文件即convert_my_lmdb.bat,他可以在windows环境下双击直接运行。

1 D:program_filescaffecaffe-windowsBuildx64Releaseconvert_imageset.exe --gray --resize_width=144 --resize_height=144   ./train/ train.txt  train_lmdb -backend=lmdb
2 D:program_filescaffecaffe-windowsBuildx64Releaseconvert_imageset.exe --gray --resize_width=144 --resize_height=144   ./val/ val.txt  val_lmdb -backend=lmdb
3 pause

  其中,D:program_filescaffecaffe-windowsBuildx64Releaseconvert_imageset.exe,表示编译好之后的转换程序,及其所在的位置;

  --gray,表示灰度化处理;

  --resize_width=144 ,--resize_height=144,表示图像的resize处理;

   ./train/ train.txt,表示使用相对路径来获得train.txt位置,还有val.txt位置;

   train_lmd,bval_lmdb,分别表示生成的训练集和验证集的LMDB格式文件夹的名称;

   -backend=lmdb,表示转换的格式是LMDB

  运行上述编辑好的convert_my_lmdb.bat,可以在data_set文件夹下生成我们想要的LMDB格式数据,结果如下所示:

  OK,基本上结束了!接下来我会写一下注意事项!

 

5. 注意事项

  (1)注意windows系统中路径问题,复制的路径是“”,在程序中需要的是“/”,注意对其修改,生成的train.txt和val.txt中的路径也是“/”。

  (2)必须保证你的caffe编译成功

  (3)修改convert_imageset.sh时,一定要注意路径问题,这里就是配置路径的很容易出错(具体请看上面的详细过程)。

  (4)图像的名字中不要出现空格,否则会有问题(深刻的痛)。

  (5)生成的train.txt文件中的图像路径问题:路径从train文件夹之后开始写,不包括train文件夹名称。

  (6)如果之前生成过文件(不管是train.txt和val.txt,还是train_lmdb和val_lmdb),想重新生成,最好先删除之前的,有可能会有错误。

  (7)请严格按照上述步骤一步一步进行,否则也可能会报错。

 

 转载请注明:https://www.cnblogs.com/xiaoboge/p/10678658.html

 

原文地址:https://www.cnblogs.com/xiaoboge/p/10678658.html