我也参考了别人的文章,其实也算不上原创,只是自我感觉能从头到尾的走一遍挺好的。
lmdb数据集的制作
以imagenet数据集为例,我们只制作label范围为[0-10)的数据集,这个只是为了演示如何制作数据集。
数据准备
- 新建一个名为train的目录及子目录和一个val的目录及子目录:
train文件存放训练数据,val文件存放验证数据。然后我们在train文件下面,把训练数据按分类放在一个子目录下面, 目录名分别为0,1,2, ... , 9, 一共有10个子目录,这些子目录分别存放label [0-10)的图像。
同样的我们在val文件下面也创建相应的子目录。
- 获取train数据,并放入对应的子目录下:
从imagenet数据集中获取图像和对应的label,基于label,把图片放入对应的目录下;
代码实现如下:
#!/usr/bin/env python
import caffe from caffe.proto import caffe_pb2 import lmdb import cv2 import numpy as np
lmdb_env = lmdb.open('/data_4/songqing/caffe_official/caffe/imagenet_dataset/ilsvrc12_train_lmdb', readonly=True) lmdb_txn = lmdb_env.begin() lmdb_cursor = lmdb_txn.cursor() datum = caffe_pb2.Datum() index = 0
for key, value in lmdb_cursor: datum.ParseFromString(value) label = datum.label print label data = caffe.io.datum_to_array(datum) print data.shape print datum.channels image = data.transpose(1, 2, 0) #cv2.imshow('cv2.png', image) #cv2.waitKey(0) print key if label < 10: #in_txn.put(key, value) FilePath = "/data_4/songqing/caffe_official/caffe/imagenet_dataset/train/%d/%d.jpg" % (label, index) index = index + 1 cv2.imwrite( FilePath , image) #cv2.destroyAllWindows() lmdb_env.close() |
- 获取validation数据,并放入对应的子目录下:
类似于train数据,放入相应的子目录下。
标签文件.txt文件制作.
接着我们需要制作一个train.txt、val.txt文件,这两个文件分别包含了我们上面的训练数据的图片路径,以及其对应的标签,如下所示。
/data_4/songqing/caffe_official/caffe/imagenet_dataset/train/9/988.jpg 9
/data_4/songqing/caffe_official/caffe/imagenet_dataset/train/9/9918.jpg 9
基于子目录的目录名设置标签。标签数据文件txt的生成可以通过如下代码,通过各个子目录下面的图片,得到标签文件train.txt和val.txt:
- 制作train的标签文件
Python脚本实现如下:
#!/usr/bin/env python
import os import numpy as np from matplotlib import pyplot as plt import cv2 import shutil
#scan files in FindPath, if FlagStr not null, get this file only def GetFileList(FindPath,FlagStr=[]): import os FileList=[] FileNames=os.listdir(FindPath) #get files in the FindPath if len(FileNames)>0: for fn in FileNames: #scan subdirs if len(FlagStr)>0: if IsSubString(FlagStr,fn): fullfilename=os.path.join(FindPath,fn) FileList.append(fullfilename) else: fullfilename=os.path.join(FindPath,fn) FileList.append(fullfilename) if len(FileList)>0: FileList.sort() #sort the FileList return FileList
def IsSubString(SubStrList,Str): flag=True for substr in SubStrList: if not(substr in Str): flag=False return flag
txtFile=open('/data_4/songqing/caffe_official/caffe/imagenet_dataset/train.txt','w') subdirList = GetFileList("/data_4/songqing/caffe_official/caffe/imagenet_dataset/train/"); print subdirList for dirName in subdirList: tmpList = dirName.split('/')#获取子目录的文件名 print tmpList print tmpList[7]#子目录的文件名 print dirName imgFileList=GetFileList(dirName) for imgFile in imgFileList: tmpFileList = imgFile.split("/") print tmpFileList[7] #这是个比较蠢笨的办法,因为Python水平有限就先这个搞吧 print tmpFileList[8] strImageAndTag= tmpFileList[7]+'/'+tmpFileList[8] +' '+tmpList[7]+'\n'#\t -> ' ' print strImageAndTag txtFile.writelines(strImageAndTag)
txtFile.close()
|
把生成的标签文件,和train\val文件夹放在同一个目录下面:
- 制作val的标签文件
同train标签文件制作相同,只是路径不同。
需要注意,我们标签数据文件里的文件路径和图片的路径要对应的起来,比如val.txt文件的某一行的图片路径,是否在val目录下面:
生成lmdb数据并读取验证
接着我们的目的就是要通过上面的四个文件,把图片的数据和其对应的标签打包起来,打包成lmdb数据格式。
- 打包train数据到lmdb格式
使用sh实现打包脚本如下:
#!/usr/bin/env sh # Create the imagenet lmdb inputs # N.B. set the path to the imagenet train + val data dirs
EXAMPLE=/data_4/songqing/caffe_official/caffe/imagenet_dataset # 生成模型训练数据 DATA=/data_4/songqing/caffe_official/caffe/imagenet_dataset # python脚步处理后数据路径 TOOLS=/data_4/songqing/caffe_official/caffe/.build_release/tools # caffe的工具库
TRAIN_DATA_ROOT=/data_4/songqing/caffe_official/caffe/imagenet_dataset/train/ #待处理的训练数据
# Set RESIZE=true to resize the images to 256x256. Leave as false if images have # already been resized using another tool. RESIZE=false if $RESIZE; then 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
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 "Done." |
通过运行上面的脚本,我们即将得到文件夹train_lmdb。
- 验证该数据集是否正确
我们打开train_lmdb文件目录,并查看一下文件data.mdb数据的大小,如果这个数据包好了我们所有的训练图片数据,查一下这个文件的大小是否符合预期大小,如果文件的大小才几k而 已,那么就代表你没有打包成功,估计是因为路径设置错误。
我们也可以通过如下的代码读取上面打包好的数据,把图片、和标签打印出来,查看一下,查看 lmdb数据请参考下面的代码:
python lmdb数据验证:
#!/usr/bin/env python
import caffe from caffe.proto import caffe_pb2 import lmdb import cv2 import numpy as np
lmdb_env = lmdb.open('/data_4/songqing/caffe_official/caffe/imagenet_dataset/train_lmdb', readonly=True) lmdb_txn = lmdb_env.begin() lmdb_cursor = lmdb_txn.cursor() datum = caffe_pb2.Datum()
for key, value in lmdb_cursor: datum.ParseFromString(value) label = datum.label print label data = caffe.io.datum_to_array(datum) print data.shape print datum.channels image = data.transpose(1, 2, 0) cv2.imshow('cv2.png', image) cv2.waitKey(0) print key #if label < 10: # in_txn.put(key, value)
#cv2.destroyAllWindows() lmdb_env.close() |
通过上面的函数,我们可以是读取相关的lmdb数据文件。
使用已有的lmdb生成新的lmdb
某些情况下,我们可能只训练一个数据集中的一小部分,例如,我们只训练imagenet数据集中的标签为[0,10)的数据。那么,我们就要把这些标签的数据读取并生成新的数据集。
实现代码如下:
#!/usr/bin/env python
import caffe from caffe.proto import caffe_pb2 import lmdb import cv2 import numpy as np
lmdb_env = lmdb.open('/data_4/songqing/caffe_official/caffe/examples/imagenet_songqing/ilsvrc12_train_lmdb', readonly=True) lmdb_txn = lmdb_env.begin() lmdb_cursor = lmdb_txn.cursor() datum = caffe_pb2.Datum()
in_db = lmdb.Environment("/data_4/songqing/caffe_official/caffe/examples/imagenet_songqing/sub10_train_lmdb/", map_size=int(1e12))
with in_db.begin(write=True) as in_txn: for key, value in lmdb_cursor: datum.ParseFromString(value) label = datum.label print label data = caffe.io.datum_to_array(datum) print data.shape print datum.channels image = data.transpose(1, 2, 0) #cv2.imshow('cv2.png', image) #cv2.waitKey(0) print key if label < 10: in_txn.put(key, value)
in_db.close() #cv2.destroyAllWindows() lmdb_env.close() |
制作均值文件
这个是为了图片归一化而生成的图片平均值文件,把所有的图片相加起来,做平均,具体的sh脚本如下:
#!/usr/bin/env sh # Compute the mean image from the imagenet training lmdb # N.B. this is available in data/ilsvrc12
EXAMPLE=/data_4/songqing/caffe_official/caffe/imagenet_dataset DATA=/data_4/songqing/caffe_official/caffe/imagenet_dataset TOOLS=/data_4/songqing/caffe_official/caffe/.build_release/tools
$TOOLS/compute_image_mean $EXAMPLE/train_lmdb \ $DATA/train_mean.binaryproto
echo "Done." |
验证集的制作同训练集的制作是相同的。