Caffe下将mnist手写图片数据转化成lmdb格式

来源:互联网 发布:淘宝ifashion入驻入口 编辑:程序博客网 时间:2024/05/17 23:43

参考博客链接:

http://blog.csdn.net/u010417185/article/details/52119863

http://blog.csdn.net/hjimce/article/details/49248231


lmdb格式在读取效率上比一般的jpg、png格式的图片要高,所以在Caffe下训练网络时,一般会将自己的图片转化为lmdb数据格式。

当然,通过Python写出输入层,直接输入图片也是一个解决方案。

其实在Caffe的作者已经提供了相应的转换程序并编译成可执行文件这里我们只需要调用他的程序,就可以轻松的完成数据的转换。网上的教程很多,本文主要是进行再次总结,以便日后使用。


一.数据准备以及标签文件制作

分为训练集和测试集两个文件夹

手写识别共有10个label,这里图片是分多个文件夹存放的

通过Python程序来进行图片与label标签文件的制作,在该文件夹下创建make_labeltxt.py文件输入以下代码:


#coding=utf-8import os  import numpy as np  from matplotlib import pyplot as plt  import cv2  import shutil# 搜索文件夹下的所有文件 def GetFileList(FindPath):           FileList=[]      FileNames=os.listdir(FindPath)      if len(FileNames) > 0:          for fn in FileNames:                fullfilename=os.path.join(FindPath,fn)              FileList.append(fullfilename)          if len(FileList) > 0:          FileList.sort()        return FileList def make_label(txt, flag):    for i in range(10):        # 0到9,分别进行标注        s = str(i)        if flag == 1:            # 此处路径可自己修改,如果train,test文件夹与py程序不在同一目录下            imgfile=GetFileList('train/'+s)        else            imgfile=GetFileList('test/'+s)                   for img in imgfile:            img_label = img + ' ' + s + '\n'            txt.writelines(img_label)def main():    # 打开文件    txt1 = open('train.txt','w')    txt2 = open('test.txt','w')    make_label(txt1, 1)    make_label(txt2, 0)    txt1.close()    txt2.close()if __name__ == '__main__':    main()


运行python程序,可在当前路径下得到train.txt和test.txt两个文件,打开文件查看是否加上标签。

二.转化成lmdb数据

接着我们可以把图片的数据和其对应的标签打包成lmdb数据格式。其实这里用到的脚本程序是Caffe根目下

examples/imagenet/create_imagenet.sh 这个shell脚本进行修改而成的。其中调用了已编译好的C++程序,在根

目录下build/tools/convert_imageset 这个可执行文件。

转化lmdb的shell脚本 create_lmdb.sh 如下:


#!/usr/bin/env sh   set -e  # 涉及到路径的地方都需要根据文件位置进行修改# 否则会出现找不到文件的情况# .代表当前路径      ..代表上一路径  EXAMPLE=mnist/          # 生成模型训练数据文化夹  TOOLS=./build/tools     # caffe的工具库  DATA=mnist/                  # python脚步处理后数据路径    TRAIN_DATA_ROOT=/home/yours/cyw/caffe/mnist/  #待处理的训练数据  VAL_DATA_ROOT=/home/yours/cyw/caffe/mnist/      # 带处理的验证数据      # 是否需要对图片进行resize RESIZE=falseif $RESIZE; then  # resize后的大小    RESIZE_HEIGHT=256    RESIZE_WIDTH=256  else    RESIZE_HEIGHT=0    RESIZE_WIDTH=0  fi  # 如果找不到文件就会报错  if [ ! -d "$TRAIN_DATA_ROOT" ]; then    echo "Error: TRAIN_DATA_ROOT is not a path to a directory: $TRAIN_DATA_ROOT"    echo "Set the TRAIN_DATA_ROOT variable in create_imagenet.sh to the path" \         "where the ImageNet training data is stored."    exit 1  fi    if [ ! -d "$VAL_DATA_ROOT" ]; then    echo "Error: VAL_DATA_ROOT is not a path to a directory: $VAL_DATA_ROOT"    echo "Set the VAL_DATA_ROOT variable in create_imagenet.sh to the path" \         "where the ImageNet validation data is stored."    exit 1  fi  rm -rf $EXAMPLE/train_lmdb  rm -rf $EXAMPLE/val_lmdb    #删除已存在的lmdb格式文件,若在已存在lmdb格式的文件夹下再添加lmdb文件,会出现错误  echo "Creating train lmdb..."    GLOG_logtostderr=1 $TOOLS/convert_imageset \  --resize_height=$RESIZE_HEIGHT \  --resize_width=$RESIZE_WIDTH \  --shuffle \  $TRAIN_DATA_ROOT \  $DATA/train.txt \  $EXAMPLE/train_lmdb    echo "Creating val lmdb..."    GLOG_logtostderr=1 $TOOLS/convert_imageset \    --resize_height=$RESIZE_HEIGHT \    --resize_width=$RESIZE_WIDTH \    --shuffle \    $VAL_DATA_ROOT \    $DATA/test.txt \    $EXAMPLE/test_lmdb    echo "Done."


在实际操作中遇到几个问题:
1. 代码中\表示的是换行,要\后面直接回车,不可以有空格,否则无法正常运行
2. 找不到路径。一般就是路径错了,最直接的解决办法就是用绝对路径,这样可以保证不出错。

3. 由于我的linux系统原因,每次生成的文件夹都是root用户下的,具有权限,普通用户无法打开。得通过 sudo chmod a+x 的方式解除权限


如果没有遇到问题,可以得到train_lmdb和test_lmdb两个文件夹;打开文件夹可以看到data.mdb和lock.mdb两个文件。正常文件大小为几十M或者几百M,如果不是说明转化错误。


三.测试数据是否正确

为了验证转化数据是否正确,通过代码将lmdb中的图像信息显示出来,即通过Python代码,将lmdb中的图像在重塑出来,同时也可以观察到图像的信息。具体代码show_lmdb.py如下:

如果提示缺少库,就用pip的方式进行安装。如果找不到caffe,应该将程序放到caffe/python文件夹下运行,或者Python可以导入caffe库的路径,这个不少博客都有提到,百度即可。


#coding:utf-8    import matplotlib.pyplot as plt  import sys  from caffe.proto import caffe_pb2  import lmdb  import numpy  # import ipdb      # 编写一个函数,将二进制的均值转换为python的均值  def read_lmdb(path,visualize = False):      env = lmdb.open(path,readonly=True)             x=[]      y=[]      with env.begin() as txn:          cursor = txn.cursor()                    for key,value in cursor:              # ipdb.set_trace()            print 'key:',key              datum = caffe_pb2.Datum()#datum类型              #转换维datum              datum.ParseFromString(value)                  #转换成numpy              #flat_x=numpy.fromstring(datum.dta,dtype=numpy.uint8)              flat_x=numpy.array(bytearray(datum.data))              #reshape大小              img_data = flat_x.reshape(datum.channels,datum.height,datum.width)                            #读取datum数据              print img_data.shape              x.append(img_data)              y.append(datum.label)              if visualize:                  img_data=img_data.transpose([1,2,0])                  img_data = img_data[:,:,::-1]                  plt.imshow(img_data)                  plt.show()                  print datum.label                        #调用read_lmdb  read_lmdb("/home/yours/cyw/caffe/mnist/train_lmdb",True)

注意,代码中的路径还是得自己重新设置;如果需要调试代码看运行过程中变量的值,可以importipdb,没有ipdb库建议去pipinstall一个。然后在某行加入ipdb.set_trace()这一句(相当于断点),就可以运行到这一行。具体ipdb的使用见如下链接:

https://www.zhihu.com/question/21572891

  http://blog.csdn.net/wangran51/article/details/8156881

 

最后要把数据放到Caffe中跑一遍,测试正确率。

修改lenet_train_test.prototxt中data层的source路径(prototxt中#表示注释)

layer {

  name: "mnist"

  type: "Data"

  top: "data"

  top: "label"

  include {

phase: TRAIN

}

  transform_param {

    scale: 0.00390625

  }

  data_param {

    source:"examples/mnist/train_lmdb"

    batch_size: 64

    # root_folder:"/home/yours/cyw/caffe/"

    backend: LMDB

  }

}


在caffe根目录下,执行./example/mnist/train_lenet.sh等待程序执行完毕,得到相应的caffemodel,观察正确率和loss。

最后遇到了一个问题,就是换到另一台配置好caffe的电脑上不能直接识别转化出的lmdb数据,需要重新运行转化程序。初步推测是lmdb等版本不一致的原因,每台机器的环境配置尽量得一样,要不然最后会被坑。有空研究研究docker好了。

第一次尝试写,格式和内容上都难免有出入,请多多见谅!


 


0 0
原创粉丝点击