要求
当使用自己的数据进行训练时,需要做到:1、数据的类别标号从0开始,中间要连续,即0,1,2...
2、数据集要打乱 3、列出对应图片名及其标签 生成对应的txt文件。对于这些要求 当数据很小时可以手动标记,制作一个txt文件,但是当数据很多时手动显然不合适。
实现
因此我想到之前学习mxnet时,mxnet提供了make_list.py(一个mxnet/tools/路径下)可以实现描述原生数据的列表文件,这个图像文件列表的格式如下:
integer_image_index \t label_index \t path_to_image
这个文件列表可以做到打乱数据集,也包括图片名及标签(只是标签在前,图片名字在后,与caffe的相反),对于标号从0开始,我是通过直接对每一类数据的文件夹按0、1命名的,即如下:
因此我只需要做简单的修改就能实现对caffe数据的贴标签(代码附在下面),在windows下代码运行命令:
即在cmd命令窗口中(见第一行),切换到make_list.py所在路径下 命令中的两个路径分别表示数据路径和输出txt路径 最后的recursive表示递归的搜索。运行输出的结果:
PS,LINUX下为:
总结
借助MxNet轻松实现caffe数据的贴标签。
代码
import fnmatch,os
import random
import numpy as np
import argparse
def list_image(root, recursive, exts):
image_list = []
if recursive:
cat = {}
for path, subdirs, files in os.walk(root):
print path
#print subdirs #注释掉
for fname in files:
fpath = os.path.join(path,fname)
suffix = os.path.splitext(fname)[1].lower()
if os.path.isfile(fpath) and (suffix in exts):
if path not in cat:
cat[path] = len(cat)
print cat[path]
image_list.append((os.path.relpath(fpath, root), cat[path]))
<span style="white-space:pre"> </span>#print fpath #注释掉
<span style="white-space:pre"> </span>#print (cat[path]) #注释掉
else:
for fname in os.listdir(root):
fpath = os.path.join(root, fname)
suffix = os.path.splitext(fname)[1].lower()
if os.path.isfile(fpath) and (suffix in exts):
image_list.append((os.path.relpath(fpath, root), 0))
return image_list
def write_list(path_out, image_list):
with open(path_out, 'w') as fout:
for i in xrange(len(image_list)):
#fout.write('%d \t %d \t %s\n'%(i, image_list[i][1], image_list[i][0]))
fout.write('%s\t%d\n'%(image_list[i][0], image_list[i][1])) #改为这样的格式
def make_list(prefix_out, root, recursive, exts, num_chunks, train_ratio):
image_list = list_image(root, recursive, exts)
random.shuffle(image_list)
N = len(image_list)
chunk_size = (N+num_chunks-1)/num_chunks
for i in xrange(num_chunks):
chunk = image_list[i*chunk_size:(i+1)*chunk_size]
if num_chunks > 1:
str_chunk = '_%d'%i
else:
str_chunk = ''
if train_ratio < 1:
sep = int(chunk_size*train_ratio)
write_list(prefix_out+str_chunk+'_train.txt', chunk[:sep]) #输出文件更改为txt
write_list(prefix_out+str_chunk+'_val.txt', chunk[sep:])
else:
write_list(prefix_out+str_chunk+'.txt', chunk)
def main():
parser = argparse.ArgumentParser(
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
description='Make image list files that are\
required by im2rec')
parser.add_argument('root', help='path to folder that contain images.')
parser.add_argument('prefix', help='prefix of output list files.')
parser.add_argument('--exts', type=list, default=['.bmp','.bmp'],
help='list of acceptable image extensions.') #注意图片的格式 我这里是bmp 根据实际更改
parser.add_argument('--chunks', type=int, default=1, help='number of chunks.')
parser.add_argument('--train_ratio', type=float, default=1.0,
help='Percent of images to use for training.')
parser.add_argument('--recursive', type=bool, default=True,
help='If true recursively walk through subdirs and assign an unique label\
to images in each folder. Otherwise only include images in the root folder\
and give them label 0.')
args = parser.parse_args()
make_list(args.prefix, args.root, args.recursive,
args.exts, args.chunks, args.train_ratio)
if __name__ == '__main__':
main()