转载自:https://blog.csdn.net/sst___/article/details/79847697
请移步原作者文章,我已按照原作的方法成功做出了识别,本文仅做备份
准备工具linux系统,caffe框架,淘宝上获取的图片。
整个过程分为,三部分,一、是对数据进行处理,转化为caffe能应用的数据类型。二、搭建网络,进行训练。三、利用训练好的数据进行分类。
一、下载数据集
首先从网上下载需要的数据集。下载地址,百度网盘:https://pan.baidu.com/s/1o77w1wI
下载完后解压,里面会有四个文件,如图所示
只保留train和val即可,因为我们后面用这两个文件来自己生成train.txt和val.txt.
在caffe的examples文件夹下新建一个myfile4文件夹,在这个文件加下建立一个data文件夹,把刚才下载的train和val保存到data文件夹中。
二、生成.txt文件
首先在myfile4下面建立一个.sh文件,我的文件名为:create_filelist.sh。内容如下:
#!/usr/bin/env sh
DATA=examples/myfile4/data #数据来源的路径
MY=examples/myfile4/data #生成的txt文件存储位置
echo "Create train.txt..."
rm -rf $MY/train.txt #先把文件中原有的同名文件删除
find $DATA/train -name 15001*.jpg | cut -d '/' -f4-5 | sed "s/$/ 0/">>$MY/train.txt
find $DATA/train -name 15059*.jpg | cut -d '/' -f4-5 | sed "s/$/ 1/">>$MY/train.txt
find $DATA/train -name 62047*.jpg | cut -d '/' -f4-5 | sed "s/$/ 2/">>$MY/train.txt
find $DATA/train -name 68021*.jpg | cut -d '/' -f4-5 | sed "s/$/ 3/">>$MY/train.txt
find $DATA/train -name 73018*.jpg | cut -d '/' -f4-5 | sed "s/$/ 4/">>$MY/train.txt
find $DATA/train -name 73063*.jpg | cut -d '/' -f4-5 | sed "s/$/ 5/">>$MY/train.txt
find $DATA/train -name 80012*.jpg | cut -d '/' -f4-5 | sed "s/$/ 6/">>$MY/train.txt
find $DATA/train -name 92002*.jpg | cut -d '/' -f4-5 | sed "s/$/ 7/">>$MY/train.txt
find $DATA/train -name 92017*.jpg | cut -d '/' -f4-5 | sed "s/$/ 8/">>$MY/train.txt
find $DATA/train -name 95005*.jpg | cut -d '/' -f4-5 | sed "s/$/ 9/">>$MY/train.txt
echo "Create test.txt..."
rm -rf $MY/val.txt
find $DATA/val -name 15001*.jpg | cut -d '/' -f4-5 | sed "s/$/ 0/">>$MY/val.txt
find $DATA/val -name 15059*.jpg | cut -d '/' -f4-5 | sed "s/$/ 1/">>$MY/val.txt
find $DATA/val -name 62047*.jpg | cut -d '/' -f4-5 | sed "s/$/ 2/">>$MY/val.txt
find $DATA/val -name 68021*.jpg | cut -d '/' -f4-5 | sed "s/$/ 3/">>$MY/val.txt
find $DATA/val -name 73018*.jpg | cut -d '/' -f4-5 | sed "s/$/ 4/">>$MY/val.txt
find $DATA/val -name 73063*.jpg | cut -d '/' -f4-5 | sed "s/$/ 5/">>$MY/val.txt
find $DATA/val -name 80012*.jpg | cut -d '/' -f4-5 | sed "s/$/ 6/">>$MY/val.txt
find $DATA/val -name 92002*.jpg | cut -d '/' -f4-5 | sed "s/$/ 7/">>$MY/val.txt
find $DATA/val -name 92017*.jpg | cut -d '/' -f4-5 | sed "s/$/ 8/">>$MY/val.txt
find $DATA/val -name 95005*.jpg | cut -d '/' -f4-5 | sed "s/$/ 9/">>$MY/val.txt
echo "All done"
对一些语句进行解释:
find $DATA/train -name 15001*.jpg 是在文件加下找到所有前几位名为15001的图片
cut -d ‘/’ -f4-5 是以’/'为分界符,找到第四至五段的内容截取下来
sed “s/$/ 0/” 在截取的文件名后面加一个空格和一个标签0
MY/train.txt 存储到train.txt中
在caffe目录下运行该文件,命令为:./examples/myfile4/create_filelist.sh。运行完后,会在myfile4/data文件夹下生成train.txt和val.txt文件。得到的train.txt的内容如下:
三、转化为db文件
接着把.txt文件转换成caffe能识别的db文件。还是在myfile4下建立该文件,文件名为create_lmdb.sh。内容如下:
#!/usr/bin/env sh
MY=examples/myfile4
TRAIN_DATA_ROOT=/home/sst/caffe/examples/myfile4/data/
VAL_DATA_ROOT=/home/sst/caffe/examples/myfile4/data/
echo "Create train lmdb.."
rm -rf $MY/img_train_lmdb
build/tools/convert_imageset \
--resize_height=32 \
--resize_width=32 \
--shuffle \
$TRAIN_DATA_ROOT \
$MY/data/train.txt \
$MY/img_train_lmdb
echo "Create test lmdb.."
rm -rf $MY/img_val_lmdb
build/tools/convert_imageset \
--resize_height=32 \
--resize_width=32 \
--shuffle \
$VAL_DATA_ROOT \
$MY/data/val.txt \
$MY/img_val_lmdb
echo "All Done.."
对代码进行一些解释:
MY=examples/myfile4设置lmdb文件要存储的位置。
TRAIN_DATA_ROOT=/home/sst/caffe/examples/myfile4/data/ 该图片存储的绝对路径。是从linux的根目录开始的
VAL_DATA_ROOT=/home/sst/caffe/examples/myfile4/data/ 数据列表的存储位置
build/tools/convert_imageset 这句是利用caffe自带的图片处理工具对图片进行处理。
convert_imageset命令行使用格式 convert_imageset [FLAGS] ROOTFOLDER/ LISTFILE DB_NAME FLAGS是处理的参数,像图片的大小,随机抽取还是怎么样。ROOTFOLDER是图片存放的绝对目录。LISTFILE是文件列表清单。DB_NAME是生成的文件存放的位置。想要了解更详细的自行百度,我也不太清楚。
运行这个文件./examples/myfile4/create_lmdb.sh运行完后会在myfile4文件夹下生成img_val_lmdb和img_train_lmdb文件夹里面就是我们想要的caffe能识别的db文件。
四、计算均值
计算均值的原因是保证所有特征都在0附近,在大多数情况下,我们并不关心所输入图像的整体明亮程度,比如对象识别任务中,图像的整体明亮程度,并不会影响图像中存在的是什么物体,我们对图像的平均亮度感兴趣,所以可以减去这个值来进行均值规整化。
创建的文件名为,create_meanfile.sh 代码如下:
EXAMPLE=examples/myfile4
DATA=examples/myfile4/
TOOLS=build/tools
$TOOLS/compute_image_mean $EXAMPLE/img_train_lmdb $DATA/mean1.binaryproto
echo "Done."
也是利用caffe自带的均值处理工具进行处理。
EXAMPLE/img_train_lmdb要处理的文件的位置,$DATA/mean1.binaryproto文件的存储位置
像上面一样运行该文件,就会得到均值文件。
至此,图像的前期处理已经结束。接下来便是正式的训练
五、构建网络
在myfile4下建立一个.prototxt文件,来搭建网络。文件名为:myfile4_train_test.prototxt 构建的网络内容如下:
name: "myfile4"
layer {
name: "data"
type: "Data"
top: "data"
top: "label"
include {
phase: TRAIN
}
transform_param{
mean_file:"examples/myfile4/mean.binaryproto"
}
data_param {
source: "examples/myfile4/img_train_lmdb"
batch_size: 50
backend: LMDB
}
}
layer {
name: "data"
type: "Data"
top: "data"
top: "label"
include {
phase: TEST
}
transform_param{
mean_file:"examples/myfile4/mean1.binaryproto"
}
data_param {
source: "examples/myfile4/img_val_lmdb"
batch_size: 50
backend: LMDB
}
}
layer {
name: "conv1"
type: "Convolution"
bottom: "data"
top: "conv1"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 32
pad:2
kernel_size: 5
stride: 1
weight_filler {
type:"gaussian"
std:0.0001
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "pool1"
type: "Pooling"
bottom: "conv1"
top: "pool1"
pooling_param {
pool: MAX
kernel_size: 3
stride: 2
}
}
layer {
name:"relu1"
type:"ReLU"
bottom:"pool1"
top:"pool1"
}
layer {
name: "conv2"
type: "Convolution"
bottom: "pool1"
top: "conv2"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 32
pad:2
kernel_size: 5
stride: 1
weight_filler {
type: "gaussian"
std:0.01
}
bias_filler {
type: "constant"
}
}
}
layer {
name:"relu2"
type:"ReLU"
bottom:"conv2"
top:"conv2"
}
layer {
name: "pool2"
type: "Pooling"
bottom: "conv2"
top: "pool2"
pooling_param {
pool: AVE
kernel_size: 3
stride: 2
}
}
layer {
name:"conv3"
type:"Convolution"
bottom:"pool2"
top:"conv3"
param{
lr_mult:1
}
param{
lr_mult:2
}
convolution_param {
num_output:64
pad:2
kernel_size:5
stride:1
weight_filler {
type:"gaussian"
std:0.01
}
bias_filler{
type:"constant"
}
}
}
layer {
name:"relu3"
type:"ReLU"
bottom:"conv3"
top:"conv3"
}
layer {
name:"pool3"
type:"Pooling"
bottom:"conv3"
top:"pool3"
pooling_param {
pool:AVE
kernel_size:3
stride:2
}
}
layer {
name: "ip1"
type: "InnerProduct"
bottom: "pool3"
top: "ip1"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 64
weight_filler {
type: "gaussian"
std:0.1
}
bias_filler {
type: "constant"
}
}
}
layer {
name: "ip2"
type: "InnerProduct"
bottom: "ip1"
top: "ip2"
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 10
weight_filler {
type: "gaussian"
std:0.1
}
bias_filler {
type: "constant"
}
}
}
layer {
name:"accuracy"
type:"Accuracy"
bottom:"ip2"
bottom:"label"
top:"accuracy"
include {
phase:TEST
}
}
layer {
name: "loss"
type: "SoftmaxWithLoss"
bottom: "ip2"
bottom: "label"
}
接下来要设置网络的训练形式,也是建立一个.prototxt文件。文件名为myfile4_solver.prototxt,内容如下:
net: "examples/myfile4/myfile4_train_test.prototxt"
test_iter: 2
test_interval: 50
base_lr: 0.001
lr_policy: "step"
gamma: 0.1
stepsize:400
momentum:0.9
weight_decay:0.004
display:10
max_iter: 2000
snapshot: 2000
snapshot_prefix: "examples/myfile4"
solver_mode: CPU
在caffe的根目录下执行 build/tools/caffe train -solver examples/myfile4/myfile4_solver.prototxt
就会得到想要的模型
注意:有的训练网络TEST,有的训练网络不带测试,就是加不加下面这段
如果不加这段的网络,需要在solver文件中把有关测试的设置去掉否则会出错。需要去掉的语句是test_iter还有test_interval等语句。
至此训练也已经完成,接下来需要做的就是用已经训练好的模型去识别想要识别的数据。
六、使用训练好的模型
前两篇博客已经把模型训练好了,本次就是使用已经训练好的模型参数识别图片。
首先在myfile4文件夹下新建images文件夹,把想要检测的图片放入文件夹中,可以用下载的淘宝图片测试。
1、在myfile4文件夹中新建deploy.prototxt文件,内容如下:
name: “myfile4”
layer {
name: “data”
type: “Input”
top: “data”
input_param{shape:{dim:1 dim:3 dim:32 dim:32}}
}
layer {
name: “conv1”
type: “Convolution”
bottom: “data”
top: “conv1”
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 32
pad:2
kernel_size: 5
stride: 1
}
}
layer {
name: “pool1”
type: “Pooling”
bottom: “conv1”
top: “pool1”
pooling_param {
pool: MAX
kernel_size: 3
stride: 2
}
}
layer {
name:“relu1”
type:“ReLU”
bottom:“pool1”
top:“pool1”
}
layer {
name: “conv2”
type: “Convolution”
bottom: “pool1”
top: “conv2”
param {
lr_mult: 1
}
param {
lr_mult: 2
}
convolution_param {
num_output: 32
pad:2
kernel_size: 5
stride: 1
}
}
layer {
name:“relu2”
type:“ReLU”
bottom:“conv2”
top:“conv2”
}
layer {
name: “pool2”
type: “Pooling”
bottom: “conv2”
top: “pool2”
pooling_param {
pool: AVE
kernel_size: 3
stride: 2
}
}
layer {
name:“conv3”
type:“Convolution”
bottom:“pool2”
top:“conv3”
param{
lr_mult:1
}
param{
lr_mult:2
}
convolution_param {
num_output:64
pad:2
kernel_size:5
stride:1
}
}
layer {
name:“relu3”
type:“ReLU”
bottom:“conv3”
top:“conv3”
}
layer {
name:“pool3”
type:“Pooling”
bottom:“conv3”
top:“pool3”
pooling_param {
pool:AVE
kernel_size:3
stride:2
}
}
layer {
name: “ip1”
type: “InnerProduct”
bottom: “pool3”
top: “ip1”
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 64
}
}
layer {
name: “ip2”
type: “InnerProduct”
bottom: “ip1”
top: “ip2”
param {
lr_mult: 1
}
param {
lr_mult: 2
}
inner_product_param {
num_output: 10
}
}
layer {
name: “prob”
type: “Softmax”
bottom: “ip2”
top: “prob”
}
2、在myfile4文件夹中新建文件synset_work.txt,内容如下:
biao
fajia
kuzi
xiangzi
yizi
dianshi
suannai
xiangshui
hufupin
xiezi
3、在myfile4文件夹下新建demo.sh。内容如下:
./build/examples/cpp_classification/classification.bin examples/myfile4/deploy.prototxt examples/myfile4/my_iter_2000.caffemodel examples/myfile4/mean.binaryproto examples/myfile4/synset_words.txt examples/myfile4/images/222.jpg
4、在caffe目录下运行examples/myfile4/demo.sh
完成后就会出现识别的结果。自此便完成了自己数据集的训练与识别。