caffe训练自己的数据集——1. 数据准备

本文详细介绍车牌数据的处理流程,包括数据重命名、标签制作、数据转换为LMDB格式等关键步骤,并提供了具体实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、重命名数据

1. 参数说明:

  1. rootPath:指定根目录,default=”J:/datasets/car/”,仅对于存在二级目录的时候生效
  2. inputPath:输入目录,default=”J:/datasets/carPlate/test/”,是核心函数singleFileRename的第一个参数
  3. outputPath:输出目录,default=”J:/datasets/carPlate/test/”,设置输出目录与输出目录相同,即重命名会覆盖源文件。也是核心函数singleFileRename的参数之一
  4. prefix:文件名的前缀,default=”,默认不指定前缀,仅用数字进行重命名
  5. suffix:文件名的后缀,default=”,默认不指定后缀,仅用数字进行重命名
  6. digit:数字形式的文件名所用到的位数,default=6,即用6位数对数据进行重命名
  7. picFormat:一般是图片数据,default=’.jpg’

2. 使用方法

  1. 对于单个文件夹:运行python rename.py 调用rename.singleFileRename(args.inputPath,args.outputPath)
    a. 如果inputPath和outputPath均为单个文件,则直接将inputPath重命名成outputPath
    b. 否则,如果均为文件夹,则将该文件夹下所有文件或文件夹,按照digit的长度进行重命名。
    c. rootPath对于单个文件夹不起作用

  2. 对于第二级目录:运行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. 批量复制
  1. 管道法
for i in `ls`; do fn=`echo $i | awk -F'.' '{print $1}'`; cp $fn.txt $fn"_bak.jpg"; done
  1. 傻瓜式
#!/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
  1. 复制多次
#!/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. 参数介绍:
  1. root为根目录,可以是直接包含图片数据的一级目录,也可以是包含文件夹的二级目录。default=”M:/datasets/carPlate/train/”注意斜杠
  2. prefix为train.txt文件的存放目录,default=”M:/datasets/carPlate/train/”注意斜杠
  3. exts用于判断读取到的文件是否是图片格式,default=[‘.bmp’, ‘.jpg’]
  4. chunks表示将一组数据分成多少个小段,help=’number of chunks.例如100个数据集,分成4个chunks,每个chunks25个数据’)
  5. train_ratio:如果小于1,则会设置train_ratio比例的数据集作为训练集,其余作为测试集,分别存放在_train.txt_val.txt中,如果chunks不等于1,’例如4个chunks,对于每个chunks会按照train_ratio分成两组,生发到成_0_train.txt和_1_val_txt,一共生成8个文件’,)
  6. 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.’
  7. 程序这条语句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或者将正负样本分开

  1. 代码如下
#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.mdblock.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. 训练及测试

参见我写的另一篇博客

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值