1. 概述
1.1 什么是数据标签?
数据标签就是图像数据在训练模型中的一个标志,设置标签有利于Caffe读取的时候提高速度也便于训练模型的标准化。
1.2 常用的数据标签类型
- lmdb
- HDF5
LMDB 是一个闪电般的内存映射型数据库管理器,在Caffe中的作用主要是提供数据管理,将形形色色的原始数据转换为统一的Key-Value存储,便于Caffe的DataLayer获取这些数据。
HDF5 是用于存储和分发科学数据的一种自我描述、多对象文件格式。HDF 是由美国国家超级计算应用中心(NCSA)创建的,以满足不同群体的科学家在不同工程项目领域之需要。HDF 可以表示出科学数据存储和分布的许多必要条件。
2. 制作lmdb标签
2.1 生成列表清单
清单的格式如下:
图片路径[中间一个空格]标记序号
我们可以用python来编写脚本生成,create_labels.py 如下:
import os, sys
import argparse
import random
import numpy as np
from tqdm import tqdm
import time
import shutil
def shuffle_in_unison(a, b):
assert len(a) == len(b)
shuffled_a = np.empty(a.shape, dtype=a.dtype)
shuffled_b = np.empty(b.shape, dtype=b.dtype)
permutation = np.random.permutation(len(a))
for old_index, new_index in enumerate(permutation):
shuffled_a[new_index] = a[old_index]
shuffled_b[new_index] = b[old_index]
return shuffled_a, shuffled_b
def move_files(input, output):
'''
Input: 数据集文件夹,不同分类的数据存储在不同子文件夹中
Output: 输出的所有文件,文件命名格式为 class_number.jpg; 输出必须是绝对路径
'''
index = -1
for root, dirs, files in os.walk(input):
if index != -1:
print 'Working with path', root
print 'Path index', index
filenum = 0
for file in (files if index == -1 else tqdm(files)):
fileName, fileExtension = os.path.splitext(file)
if fileExtension == '.jpg' or fileExtension == '.JPG' or fileExtension == '.png' or fileExtension == '.PNG':
full_path = os.path.join(root, file)
# print full_path
if (os.path.isfile(full_path)):
file = os.path.basename(os.path.normpath(root)) + str(filenum) + fileExtension
try:
test = int(file.split('_')[0])
except:
file = str(index) + '_' + file
# print os.path.join(output, file)
shutil.copy(full_path, os.path.join(output, file))
filenum += 1
index += 1
def create_text_file(input_path, percentage):
'''
为 Caffe 创建 train.txt 和 val.txt 文件
'''
images, labels = [], []
os.chdir(input_path)
for item in os.listdir('.'):
if not os.path.isfile(os.path.join('.', item)):
continue
try:
label = int(item.split('_')[0])
images.append(item)
labels.append(label)
except:
continue
images = np.array(images)
labels = np.array(labels)
images, labels = shuffle_in_unison(images, labels)
X_train = images[0:int(len(images) * percentage)]
y_train = labels[0:int(len(labels) * percentage)]
X_test = images[int(len(images) * percentage):]
y_test = labels[int(len(labels) * percentage):]
os.chdir('..')
trainfile = open("train.txt", "w")
for i, l in zip(X_train, y_train):
trainfile.write(i + " " + str(l) + "\n")
testfile = open("test.txt", "w")
for i, l in zip(X_test, y_test):
testfile.write(i + " " + str(l) + "\n")
trainfile.close()
testfile.close()
def main():
# CMD 指令参数
parser = argparse.ArgumentParser(description='Create label files for an image dataset')
parser.add_argument("--input", action = "store", help = "Input images dir")
parser.add_argument("--output", action = "store", help = "Output images dir")
parser.add_argument("--percentage", action = "store", help = "Test/Train split", type=float, default=0.85)
#测试数据占训练数据的比重
# Parse CMD args
args = parser.parse_args()
if (args.input == None or args.output == None):
parser.print_help()
sys.exit(1)
move_files(args.input, args.output)
create_text_file(args.output, args.percentage)
print('Finished processing all images\n')
if __name__ == '__main__':
main()
在根目录编写批处理文件create_lists.bat :
python create_labels.py --input data/ --output lmdbin/
pause
运行脚本,根目录会生成两个文件 train.txt 和 test.txt:
现在已经得到了训练数据的清单
2.2 生成lmdb
生成LMDB格式数据需要使用Caffe自带的函数 convert_imageset
convert_imageset [FLAGS] ROOTFOLDER/ LISTFILE DB_NAME
函数的四个参数功能如下:
FLAGS: 图片参数组
FLAGS这个参数组的内容:
-gray: 是否以灰度图的方式打开图片。程序调用opencv库中的imread()函数来打开图片,默认为false
-shuffle: 是否随机打乱图片顺序。默认为false
-backend:需要转换成的db文件格式,可选为leveldb或lmdb,默认为lmdb
-resize_width/resize_height: 改变图片的大小。在运行中,要求所有图片的尺寸一致,因此需要改变图片大小。 程序调用opencv库的resize()函数来对图片放大缩小,默认为0,不改变
-check_size: 检查所有的数据是否有相同的尺寸。默认为false,不检查
-encoded: 是否将原图片编码放入最终的数据中,默认为false
-encode_type: 与前一个参数对应,将图片编码为哪一个格式:‘png','jpg'......
ROOTFOLDER/: 图片存放的绝对路径,lmdbin的路径
LISTFILE: 图片文件列表清单,一般为一个txt文件,一行一张图片
DB_NAME: 最终生成的db文件存放目录
执行脚本文件:
convert_imageset --shuffle D:/OPenMV_Network/lmdbin/ train.txt train_lmdb
echo.
convert_imageset --shuffle D:/OPenMV_Network/lmdbin/ test.txt test_lmdb
pause
输出内容:
D:\OPenMV_Network>convert_imageset --shuffle D:/OPenMV_Network/lmdbin/ train.txt train_lmdb
I0722 15:41:52.749094 26240 convert_imageset.cpp:86] Shuffling data
I0722 15:41:55.834518 26240 common.cpp:36] System entropy source not available, using fallback algorithm to generate seed instead.
I0722 15:41:55.835505 26240 common.cpp:36] System entropy source not available, using fallback algorithm to generate seed instead.
I0722 15:41:55.835505 26240 convert_imageset.cpp:89] A total of 850 images.
I0722 15:41:55.839476 26240 db_lmdb.cpp:40] Opened lmdb train_lmdb
I0722 15:41:57.151973 26240 convert_imageset.cpp:153] Processed 850 files.
D:\OPenMV_Network>echo.
D:\OPenMV_Network>convert_imageset --shuffle D:/OPenMV_Network/lmdbin/ test.txt test_lmdb
I0722 15:41:57.818193 25668 convert_imageset.cpp:86] Shuffling data
I0722 15:41:58.476425 25668 common.cpp:36] System entropy source not available, using fallback algorithm to generate seed instead.
I0722 15:41:58.478422 25668 common.cpp:36] System entropy source not available, using fallback algorithm to generate seed instead.
I0722 15:41:58.478422 25668 convert_imageset.cpp:89] A total of 150 images.
I0722 15:41:58.481415 25668 db_lmdb.cpp:40] Opened lmdb test_lmdb
I0722 15:41:58.760684 25668 convert_imageset.cpp:153] Processed 150 files.
D:\OPenMV_Network>pause
根目录里生成了test_lmdb文件夹和train_lmdb文件夹,
上述两个文件夹下各生成两个数据包:
这个数据包存储了我们所有的训练图片数据,查一下这个文件的大小是否符合预期大小,如果文件的大小才几k而已,那么就代表你没有打包成功,估计是因为路径设置错误。
到此,lmdb的数据集准备完成!
最后的最后,如果有需要,可以执行脚本生成均值文件:
优点:图片减去均值再训练,会提高训练速度和精度。因此,一般都会有这个操作。
但是必须保证所有图片的规格大小一致
脚本需在根目录运行
compute_image_mean -backend=lmdb train_lmdb mean.binaryproto
pause
参考链接:
深度学习caffe平台--制作自己.lmdb格式数据集及分类标签文件
Caffe学习系列(11):图像数据转换成db(leveldb/lmdb)文件