一、重命名数据
1. 参数说明:
- rootPath:指定根目录,default=”J:/datasets/car/”,仅对于存在二级目录的时候生效
- inputPath:输入目录,default=”J:/datasets/carPlate/test/”,是核心函数singleFileRename的第一个参数
- outputPath:输出目录,default=”J:/datasets/carPlate/test/”,设置输出目录与输出目录相同,即重命名会覆盖源文件。也是核心函数singleFileRename的参数之一
- prefix:文件名的前缀,default=”,默认不指定前缀,仅用数字进行重命名
- suffix:文件名的后缀,default=”,默认不指定后缀,仅用数字进行重命名
- digit:数字形式的文件名所用到的位数,default=6,即用6位数对数据进行重命名
- picFormat:一般是图片数据,default=’.jpg’
2. 使用方法
对于单个文件夹:运行
python rename.py
调用rename.singleFileRename(args.inputPath,args.outputPath)
a. 如果inputPath和outputPath均为单个文件,则直接将inputPath重命名成outputPath
b. 否则,如果均为文件夹,则将该文件夹下所有文件或文件夹,按照digit的长度进行重命名。
c. rootPath对于单个文件夹不起作用对于第二级目录:运行
python rename.py
调用rename._2_recursiveRename(args.rootPath)
rootPath = "J:/datasets/carPlate/test/"
test/no:
1.jpg
2.jpg
test/has:
11.jpg
22.jpg
a. rootPath="J:/datasets/carPlate/test/",inputPath和outputPath会自动查找到,不需要赋值。
b. 次函数作用是将第二级目录下,所有文件夹所包含的图片重命名。
3. 对于第三级目录:运行python rename.py
调用rename._3_recursiveRename(args.rootPath)
rootPath = "J:/datasets/carPlate/"
carPlate/train:
no:
1.jpg
2.jpg
has:
11.jpg
22.jpg
carPlate/test:
no:
1.jpg
has:
2.jpg
a. rootPath="J:/datasets/carPlate/",inputPath和outputPath会自动查找到,不需要赋值。
b. 此函数作用是将第三级目录下的第二级目录中所包含的图片重命名。
3. 代码如下
#coding: UTF-8
import os
import argparse
class rename:
def __init__(self, rootPath, inputPath, outputPath, prefix='', suffix='', digit=5, picFormat = '.jpg'):
self.rootPath = rootPath
self.inputPath = inputPath
self.outputPath = outputPath
self.prefix = prefix
self.suffix = suffix
self.digit = digit
self.picFormat = picFormat
def singleFileRename(self,inputPath,outputPath):
#获取该目录下所有文件,存入列表中
if os.path.isfile(inputPath): #如果是已存在的图片
os.rename(inputPath, outputPath)
print(inputPath, '========>', outputPath)
else: #如果是路径
files = os.listdir(inputPath)
num = 0
for file in files:
oldname = inputPath + files[num]
ex = os.path.splitext(file)
newname = outputPath + '{0}{1:0{3}d}{2}'.format(self.prefix, num, self.suffix, self.digit) + self.picFormat
os.rename(oldname,newname)
print(oldname,'========>',newname)
num+=1
#二级目录重命名
def _2_recursiveRename(self,rootPath):
rootPath = self.rootPath
#获取该路径下所有的目录,存入列表
dirs = os.listdir(rootPath)
for name in dirs:
inputPath = os.path.join(rootPath, name) + "/"
if (name[0] == '.'): #排除隐藏文件
pass
else:
if os.path.isdir(inputPath): #判断是否是目录
outputPath = inputPath
self.singleFileRename(inputPath,outputPath)
#三级目录重命名
def _3_recursiveRename(self,rootPath):
rootPath = self.rootPath
# 获取该路径下所有的目录,存入列表
dirs = os.listdir(rootPath)
for _name in dirs:
_rootPath = os.path.join(rootPath, _name) + "/"
if (_name[0] == '.'): # 排除隐藏文件
pass
else:
if os.path.isdir(_rootPath):
self.rootPath = _rootPath
self._2_recursiveRename(self.rootPath)
def get_args():
parser = argparse.ArgumentParser()
parser.add_argument("--rootPath", type=str, default="J:/datasets/car/",help="rootPath with '/' at the end")
parser.add_argument("--inputPath", type = str, default="J:/datasets/carPlate/test/",
help="inputPath with '/' at the end or ‘J:/datasets/carPlate/test/0000000.jpg’")
parser.add_argument("--outputPath", type = str, default="J:/datasets/carPlate/test/",
help= "outputPath with '/' at the end or 'J:/datasets/carPlate/test/aaaaaa.jpg'")
parser.add_argument("--prefix", default='', help="文件名的前缀")
parser.add_argument("--suffix", default='', help="文件名的后缀")
parser.add_argument("--digit", default= 6 , help="文件名的数字总长度: [1,~]")
parser.add_argument("--picFormat", default='.jpg',help="图片的格式")
args = parser.parse_args()
return args
if __name__== '__main__':
args = get_args()
rename = rename(args.rootPath, args.inputPath,args.outputPath,args.prefix,args.suffix,args.digit,args.picFormat)
#rename.singleFileRename(args.inputPath,args.outputPath)
#rename._2_recursiveRename(args.rootPath)
rename._3_recursiveRename(args.rootPath)
二、制作数据
I. 准备原始数据
1. 批量复制
- 管道法
for i in `ls`; do fn=`echo $i | awk -F'.' '{print $1}'`; cp $fn.txt $fn"_bak.jpg"; done
- 傻瓜式
#!/bin/bash
cd /home/hsy/datasets/carPlate/train/3
for file in $(ls *)
do
echo $file
echo ${file%.*}"_back.jpg"
cp $file ./${file%.*}"_back.jpg"
done
- 复制多次
#!/bin/bash
curPath=pwd
cd /home/hsy/datasets/carPlate/test/a
for file in $(ls *)
do
echo $file
echo ${file%.*}"_back.jpg"
fn=`echo $file | awk -F'.' '{print $1}'`
cp $file ./$fn"_back_1.jpg"
cp $file ./$fn"_bach_2.jpg"
#cp $file ./${file%.*}"_back_1.jpg"
done
2. 备份数据
tar -zcvf carPlate_train.tar.gz train
II. 制作标签
1. 参数介绍:
- root为根目录,可以是直接包含图片数据的一级目录,也可以是包含文件夹的二级目录。default=”M:/datasets/carPlate/train/”注意斜杠
- prefix为
train.txt
文件的存放目录,default=”M:/datasets/carPlate/train/”注意斜杠 - exts用于判断读取到的文件是否是图片格式,default=[‘.bmp’, ‘.jpg’]
- chunks表示将一组数据分成多少个小段,help=’number of chunks.例如100个数据集,分成4个chunks,每个chunks25个数据’)
- train_ratio:如果小于1,则会设置train_ratio比例的数据集作为训练集,其余作为测试集,分别存放在
_train.txt
和_val.txt
中,如果chunks不等于1,’例如4个chunks,对于每个chunks会按照train_ratio分成两组,生发到成_0_train.txt和_1_val_txt,一共生成8个文件’,) - recursive,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.’ - 程序这条语句
random.shuffle(image_list)
设置了数据打乱机制,并未作为参数写出来,是为了将来对数据本身进行有针对性的数据增广
2. 使用说明
a. 目录结构如下:可以将root和prefix设置为相同路径,train.txt会保存在这个路径,但是在运行程序之前请确保这个文件不存在于这个路径,因为会重新创建。
J:\datasets\carPlate\test
a:
1.jpg
2.jpg
b:
1.jpg
2.jpg
b. 运行python make_list_linux.py
,在代码中打开image_list.append((os.path.relpath(fpath, root), cat[path]))
可以生成如下格式的相对路径:
/home/hsy/datasets/carPlate/test/a/000000.jpg 1
/home/hsy/datasets/carPlate/test/b/000001.jpg 0
/home/hsy/datasets/carPlate/test/b/000003.jpg 0
/home/hsy/datasets/carPlate/test/b/000004.jpg 0
/home/hsy/datasets/carPlate/test/a/000001.jpg 1
/home/hsy/datasets/carPlate/test/a/000004.jpg 1
/home/hsy/datasets/carPlate/test/b/000002.jpg 0
/home/hsy/datasets/carPlate/test/a/000002.jpg 1
/home/hsy/datasets/carPlate/test/a/000003.jpg 1
/home/hsy/datasets/carPlate/test/b/000000.jpg 0
c. 使用train_ratio参数,可以先选出一小部分数据集用于预训练,但如果shuffle之后,可能出现正负样本失衡且不可控的情况,所以选择小样本时,最好不要shuffle或者将正负样本分开
- 代码如下
#coding: UTF-8
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) #表示第n个文件夹
print cat[path]
# os.path.relpath(fpath, root)返回从root到fpath的相对路径
#image_list.append((os.path.relpath(fpath, root), cat[path]))
#将图片的绝对路径写入到train.txt,但有时候还会报奇怪的unexpected indent错误,应该是空格问题
image_list.append((os.path.relpath(fpath, root), cat[path]))
print fpath #注释掉
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 %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)
# num_chunks表示数据的段数,chunk_size表示每段数据的个数
# N+ (num_chunks-1)是为了保证所有数据都被用上,如果不加,最后计算得到的余数个数据就不会被计算进去
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 + 'train.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', default="M:/datasets/carPlate/train/", help='path to folder that contain images.')
parser.add_argument('--prefix',default="M:/datasets/carPlate/train/", help='prefix of output list files.')
parser.add_argument('--exts', type=list, default=['.bmp', '.jpg'],
help='list of acceptable image extensions.') # 注意图片的格式 我这里是bmp 根据实际更改
parser.add_argument('--chunks', type=int, default=1, help='number of chunks.例如100个数据集,分成4个chunks,每个chunks25个数据')
parser.add_argument('--train_ratio', type=float, default=1, help='Percent of images to use for training.'
'例如4个chunks,对于每个chunks会按照train_ratio分成两组,生发到成_0_train.txt和_1_val_txt,一共生成8个文件',)
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()
III. 生成标签
0. 数据说明
这里的数据集来自于:
N:\项目\车牌项目\唐佩君师姐的资料\training(clib,6.26号,准确度95%)
N:\项目\车牌项目\唐佩君师姐的资料\testing
黄色:2000 蓝色:2000 白色:2000 非车牌:13438
正样本一共6000张
负样本一共13438张
总共19438张
蓝:0 黄:1 白:2 非:3
1. 重命名
这个步骤速度还挺快的
a. 利用第一部分代码(名为```rename_linux.py```)中的rename._2_recursiveRename(args.rootPath)函数,
b. 设置位数digit=6,rootPath="/home/hsy/datasets/carPlate/train/",inputPath和outputPath不用设置
c. 运行python rename_linux.py即可对train下的多个文件夹下的图片进行重命名。
2. 生成样本标签
分三批生成样本,分别占总样本数量的10%,30%,100%,每次都利用代码中random.shuffle(image_list)
打乱数据
a. 设置路径:root=prefix="/home/hsy/datasets/carPlate/train/"
b. 设置chunks=1, train_ratio=0.1,生成第一批,并改名为train_10.txt
c. 设置chunks=1, train_ratio=0.3,生成第二批,并改名为train_30.txt
d. 设置chunks=1, train_ratio=1.0,生成第三批,并改名为train_100.txt
每两次之间,记得把生成的train_xx.txt移动到其他文件夹,否则会报错。
IV 数据转换
参考链接http://blog.youkuaiyun.com/AlexQiweek/article/details/51281240
1. 示例说明
/opt/caffe/build/tools/convert_imageset \
--resize_height=32 \
--resize_width=32 \
/home/datasets/carPlate/train/ #训练文件的根目录
/home/datasets/carPlate/train/train_10.txt #标签所在目录
/home/datasets/carPlate/train_test_labels/train_10 #生成的lmdb存放目录,必须是未存在过的目录
#--gray=ture #生成灰度图
#--shuffle #随机排序
运行之后会在“/home/datasets/carPlate/train_test_labels/train_10 ”路径下生成data.mdb
和lock.mdb
两个文件
2. 批量转换
/opt/caffe/build/tools/convert_imageset --resize_height=32 --resize_width=32 /home/datasets/carPlate/train/ /home/datasets/carPlate/train_test_labels/train_10.txt /home/datasets/carPlate/train_test_labels/train_10
1381 /opt/caffe/build/tools/convert_imageset --resize_height=32 --resize_width=32 /home/datasets/carPlate/train/ /home/datasets/carPlate/train_test_labels/train_50.txt /home/datasets/carPlate/train_test_labels/train_50
1382 /opt/caffe/build/tools/convert_imageset --resize_height=32 --resize_width=32 /home/datasets/carPlate/train/ /home/datasets/carPlate/train_test_labels/train_30.txt /home/datasets/carPlate/train_test_labels/train_30
1383 /opt/caffe/build/tools/convert_imageset --resize_height=32 --resize_width=32 /home/datasets/carPlate/train/ /home/datasets/carPlate/train_test_labels/train_100.txt /home/datasets/carPlate/train_test_labels/train_100
1384 /opt/caffe/build/tools/convert_imageset --resize_height=32 --resize_width=32 /home/datasets/carPlate/test/G1-5/G1/ /home/datasets/carPlate/train_test_labels/val_G1.txt /home/datasets/carPlate/train_test_labels/val_G1
1385 /opt/caffe/build/tools/convert_imageset --resize_height=32 --resize_width=32 /home/datasets/carPlate/test/G1-5/G2/ /home/datasets/carPlate/train_test_labels/val_G2.txt /home/datasets/carPlate/train_test_labels/val_G2
1386 /opt/caffe/build/tools/convert_imageset --resize_height=32 --resize_width=32 /home/datasets/carPlate/test/G1-5/G3/ /home/datasets/carPlate/train_test_labels/val_G3.txt /home/datasets/carPlate/train_test_labels/val_G3
1387 /opt/caffe/build/tools/convert_imageset --resize_height=32 --resize_width=32 /home/datasets/carPlate/test/G1-5/G4/ /home/datasets/carPlate/train_test_labels/val_G4.txt /home/datasets/carPlate/train_test_labels/val_G4
1388 /opt/caffe/build/tools/convert_imageset --resize_height=32 --resize_width=32 /home/datasets/carPlate/test/G1-5/G5/ /home/datasets/carPlate/train_test_labels/val_G5.txt /home/datasets/carPlate/train_test_labels/val_G5
3. 求取均值
#训练集
/opt/caffe/build/tools/compute_image_mean \
/home/datasets/carPlate/train_test_labels/train_10 \ #lmdb文件所在路径
/home/datasets/carPlate/train_test_labels/train_10/train_10_mean.binaryproto\ #生成的均值文件所在路径
#测试集
/opt/caffe/build/tools/compute_image_mean \
/home/datasets/carPlate/train_test_labels/val_G1 \
/home/datasets/carPlate/train_test_labels/val_G1/val_G1_mean.binaryproto
V. 训练及测试
参见我写的另一篇博客。