使用lenet模型训练及预测自己的图片数据

https://blog.csdn.net/AP1005834/article/details/74783452

 

一、前言

本文主要尝试将自己的数据集制作成lmdb格式,送进lenet作训练和测试,参考了http://blog.csdn.net/liuweizj12/article/details/52149743http://blog.csdn.net/xiaoxiao_huitailang/article/details/51361036这两篇博文

二、从训练模型到使用模型预测图片分类

(1)自己准备的图像数据

由于主要是使用lenet模型训练自己的图片数据,我的图像数据共有10个类别,分别是0~9,相应地保存在名为0~9的文件夹,在/homg/您的用户名/下新建一文件夹char_images,用于保存图像数据,在/homg/您的用户名/char_images/下新建两个文件夹,名字分别为train和val,各自都包含了名为0~9的文件夹,例如文件夹0内存放的是字符”0”的图像,我的文件夹 如下:

(2)对图像数据作统一缩放至28*28,并生成txt标签

 

为了计算均值文件,需要将所有图片缩放至统一的尺寸,在train和val文件夹所在路径下创建python文件,命名getPath.py,并写入以下内容:

 

 
  1. #coding:utf-8

  2.  
  3. import cv2

  4. import os

  5.  
  6. def IsSubString( SubStrList , Str): #判断SubStrList的元素

  7. flag = True #是否在Str内

  8. for substr in SubStrList:

  9. if not ( substr in Str):

  10. flag = False

  11.  
  12. return flag

  13.  
  14. def GetFileList(FindPath,FlagStr=[]): #搜索目录下的子文件路径

  15. FileList=[]

  16. FileNames=os.listdir(FindPath)

  17. if len(FileNames)>0:

  18. for fn in FileNames:

  19. if len(FlagStr)>0:

  20. if IsSubString(FlagStr,fn): #不明白这里判断是为了啥

  21. fullfilename=os.path.join(FindPath,fn)

  22. FileList.append(fullfilename)

  23. else:

  24. fullfilename=os.path.join(FindPath,fn)

  25. FileList.append(fullfilename)

  26.  
  27. if len(FileList)>0:

  28. FileList.sort()

  29.  
  30. return FileList

  31.  
  32.  
  33. train_txt = open('train.txt' , 'w') #制作标签数据

  34. classList =['0','1','2','3','4','5','6','7','8','9']

  35. for idx in range(len(classList)) :

  36. imgfile=GetFileList('train/'+ classList[idx])#将数据集放在与.py文件相同目录下

  37. for img in imgfile:

  38. srcImg = cv2.imread( img);

  39. resizedImg = cv2.resize(srcImg , (28,28))

  40. cv2.imwrite( img ,resizedImg)

  41. strTemp=img+' '+classList[idx]+'\n' #用空格代替转义字符 \t

  42. train_txt.writelines(strTemp)

  43. train_txt.close()

  44.  
  45.  
  46. test_txt = open('val.txt' , 'w') #制作标签数据

  47. for idx in range(len(classList)) :

  48. imgfile=GetFileList('val/'+ classList[idx])

  49. for img in imgfile:

  50. srcImg = cv2.imread( img);

  51. resizedImg = cv2.resize(srcImg , (28,28))

  52. cv2.imwrite( img ,resizedImg)

  53. strTemp=img+' '+classList[idx]+'\n' #用空格代替转义字符 \t

  54. test_txt.writelines(strTemp)

  55. test_txt.close()

  56.  
  57. print("成功生成文件列表")

 

运行该py文件,可将所有图片缩放至28*28大小,并且在rain和val文件夹所在路径下生成训练和测试图像数据的标签txt文件,文件内容为:
         

 

(3)生成lmdb格式的数据集

首先于caffe路径下新建一文件夹My_File,并在My_File下新建两个文件夹Build_lmdb和Data_label,将(2)中生成文本文件train.txt和val.txt搬至Data_label下

  

将caffe路径下 examples/imagenet/create_imagenet.sh 复制一份到Build_lmdb文件夹下

打开create_imagenet.sh ,修改内容如下:

 

 
  1. #!/usr/bin/env sh

  2. # Create the imagenet lmdb inputs

  3. # N.B. set the path to the imagenet train + val data dirs

  4. set -e

  5.  
  6. EXAMPLE=My_File/Build_lmdb #生成的lmdb格式数据保存地址

  7. DATA=My_File/Data_label #两个txt标签文件所在路径

  8. TOOLS=build/tools #caffe自带工具,不用管

  9.  
  10. TRAIN_DATA_ROOT=/home/zjy/char_images/ #预先准备的训练图片路径,该路径和train.txt上写的路径合起来是图片完整路径

  11. VAL_DATA_ROOT=/home/zjy/char_images/ #预先准备的测试图片路径,...

  12.  
  13. # Set RESIZE=true to resize the images to 256x256. Leave as false if images have

  14. # already been resized using another tool.

  15. RESIZE=false

  16. if $RESIZE; then

  17. RESIZE_HEIGHT=28

  18. RESIZE_WIDTH=28

  19. else

  20. RESIZE_HEIGHT=0

  21. RESIZE_WIDTH=0

  22. fi

  23.  
  24. if [ ! -d "$TRAIN_DATA_ROOT" ]; then

  25. echo "Error: TRAIN_DATA_ROOT is not a path to a directory: $TRAIN_DATA_ROOT"

  26. echo "Set the TRAIN_DATA_ROOT variable in create_imagenet.sh to the path" \

  27. "where the ImageNet training data is stored."

  28. exit 1

  29. fi

  30.  
  31. if [ ! -d "$VAL_DATA_ROOT" ]; then

  32. echo "Error: VAL_DATA_ROOT is not a path to a directory: $VAL_DATA_ROOT"

  33. echo "Set the VAL_DATA_ROOT variable in create_imagenet.sh to the path" \

  34. "where the ImageNet validation data is stored."

  35. exit 1

  36. fi

  37.  
  38. echo "Creating train lmdb..."

  39.  
  40. GLOG_logtostderr=1 $TOOLS/convert_imageset \

  41. --resize_height=$RESIZE_HEIGHT \

  42. --resize_width=$RESIZE_WIDTH \

  43. --shuffle \

  44. --gray \ #灰度图像加上这个

  45. $TRAIN_DATA_ROOT \

  46. $DATA/train.txt \

  47. $EXAMPLE/train_lmdb #生成的lmdb格式训练数据集所在的文件夹

  48.  
  49. echo "Creating val lmdb..."

  50.  
  51. GLOG_logtostderr=1 $TOOLS/convert_imageset \

  52. --resize_height=$RESIZE_HEIGHT \

  53. --resize_width=$RESIZE_WIDTH \

  54. --shuffle \

  55. --gray \ #灰度图像加上这个

  56. $VAL_DATA_ROOT \

  57. $DATA/val.txt \

  58. $EXAMPLE/val_lmdb #生成的lmdb格式训练数据集所在的文件夹

  59.  
  60. echo "Done."

 

 

 

以上只是为了说明修改的地方才添加汉字注释,实际时sh文件不要出现汉字,运行该sh文件,可在Build_lmdb文件夹内生成2个文件夹train_lmdb和val_lmdb,里面各有2个lmdb格式的文件

 

(4)更改lenet_solver.prototxt和lenet_train_test.prototxt
将caffe/examples/mnist下的 train_lenet.sh 、lenet_solver.prototxt 、lenet_train_test.prototxt 这三个文件复制至 My_File,首先修改train_lenet.sh 如下,只改了solver.prototxt的路径

 

 
  1. #!/usr/bin/env sh

  2. set -e

  3.  
  4. ./build/tools/caffe train --solver=My_File/lenet_solver.prototxt $@ #改路径

然后再更改lenet_solver.prototxt,如下:

 

 
  1. # The train/test net protocol buffer definition

  2. net: "My_File/lenet_train_test.prototxt" #改这里

  3. # test_iter specifies how many forward passes the test should carry out.

  4. # In the case of MNIST, we have test batch size 100 and 100 test iterations,

  5. # covering the full 10,000 testing images.

  6. test_iter: 100

  7. # Carry out testing every 500 training iterations.

  8. test_interval: 500

  9. # The base learning rate, momentum and the weight decay of the network.

  10. base_lr: 0.01

  11. momentum: 0.9

  12. weight_decay: 0.0005

  13. # The learning rate policy

  14. lr_policy: "inv"

  15. gamma: 0.0001

  16. power: 0.75

  17. # Display every 100 iterations

  18. display: 100

  19. # The maximum number of iterations

  20. max_iter: 10000

  21. # snapshot intermediate results

  22. snapshot: 5000

  23. snapshot_prefix: "My_File/" #改这里

  24. # solver mode: CPU or GPU

  25. solver_mode: GPU

 

最后修改lenet_train_test.prototxt ,如下:

 

 
  1. name: "LeNet"

  2. layer {

  3. name: "mnist"

  4. type: "Data"

  5. top: "data"

  6. top: "label"

  7. include {

  8. phase: TRAIN

  9. }

  10. transform_param {

  11. scale: 0.00390625

  12. }

  13. data_param {

  14. source: "My_File/Build_lmdb/train_lmdb" #改成自己的

  15. batch_size: 64

  16. backend: LMDB

  17. }

  18. }

  19. layer {

  20. name: "mnist"

  21. type: "Data"

  22. top: "data"

  23. top: "label"

  24. include {

  25. phase: TEST

  26. }

  27. transform_param {

  28. scale: 0.00390625

  29. }

  30. data_param {

  31. source: "My_File/Build_lmdb/val_lmdb" #改成自己的

  32. batch_size: 100

  33. backend: LMDB

  34. }

  35. }

  36. layer {

  37. name: "conv1"

  38. type: "Convolution"

  39. bottom: "data"

  40. top: "conv1"

  41. param {

  42. lr_mult: 1

  43. }

  44. param {

  45. lr_mult: 2

  46. }

  47. convolution_param {

  48. num_output: 20

  49. kernel_size: 5

  50. stride: 1

  51. weight_filler {

  52. type: "xavier"

  53. }

  54. bias_filler {

  55. type: "constant"

  56. }

  57. }

  58. }

  59. layer {

  60. name: "pool1"

  61. type: "Pooling"

  62. bottom: "conv1"

  63. top: "pool1"

  64. pooling_param {

  65. pool: MAX

  66. kernel_size: 2

  67. stride: 2

  68. }

  69. }

  70. layer {

  71. name: "conv2"

  72. type: "Convolution"

  73. bottom: "pool1"

  74. top: "conv2"

  75. param {

  76. lr_mult: 1

  77. }

  78. param {

  79. lr_mult: 2

  80. }

  81. convolution_param {

  82. num_output: 50

  83. kernel_size: 5

  84. stride: 1

  85. weight_filler {

  86. type: "xavier"

  87. }

  88. bias_filler {

  89. type: "constant"

  90. }

  91. }

  92. }

  93. layer {

  94. name: "pool2"

  95. type: "Pooling"

  96. bottom: "conv2"

  97. top: "pool2"

  98. pooling_param {

  99. pool: MAX

  100. kernel_size: 2

  101. stride: 2

  102. }

  103. }

  104. layer {

  105. name: "ip1"

  106. type: "InnerProduct"

  107. bottom: "pool2"

  108. top: "ip1"

  109. param {

  110. lr_mult: 1

  111. }

  112. param {

  113. lr_mult: 2

  114. }

  115. inner_product_param {

  116. num_output: 500

  117. weight_filler {

  118. type: "xavier"

  119. }

  120. bias_filler {

  121. type: "constant"

  122. }

  123. }

  124. }

  125. layer {

  126. name: "relu1"

  127. type: "ReLU"

  128. bottom: "ip1"

  129. top: "ip1"

  130. }

  131. layer {

  132. name: "ip2"

  133. type: "InnerProduct"

  134. bottom: "ip1"

  135. top: "ip2"

  136. param {

  137. lr_mult: 1

  138. }

  139. param {

  140. lr_mult: 2

  141. }

  142. inner_product_param {

  143. num_output: 10

  144. weight_filler {

  145. type: "xavier"

  146. }

  147. bias_filler {

  148. type: "constant"

  149. }

  150. }

  151. }

  152. layer {

  153. name: "accuracy"

  154. type: "Accuracy"

  155. bottom: "ip2"

  156. bottom: "label"

  157. top: "accuracy"

  158. include {

  159. phase: TEST

  160. }

  161. }

  162. layer {

  163. name: "loss"

  164. type: "SoftmaxWithLoss"

  165. bottom: "ip2"

  166. bottom: "label"

  167. top: "loss"

  168. }

 

运行 My_File/train_lenet.sh ,得到最后的训练结果,在My_File下生成训练的caffemodel和solverstate。

 

(5)生成均值文件
均值文件主要用于图像预测的时候,由caffe/build/tools/compute_image_mean生成,在My_File文件夹下新建一文件夹Mean,用于存放均值文件,在caffe/下执行:
build/tools/compute_image_mean My_File/Build_lmdb/train_lmdb My_File/Mean/mean.binaryproto
可在My_File/Mean/下生成均值文件mean.binaryproto
(6)生成deploy.prototxt
deploy.prototxt是在lenet_train_test.prototxt的基础上删除了开头的Train和Test部分以及结尾的Accuracy、SoftmaxWithLoss层,并在开始时增加了一个data层描述,结尾增加softmax层,可以参照博文http://blog.csdn.net/lanxuecc/article/details/52474476 使用python生成,也可以直接由train_val.prototxt上做修改,在My_File文件夹下新建一文件夹Deploy,将 lenet_train_test.prototxt复制至文件夹Deploy下,并重命名为deploy.prototxt ,修改里面的内容如下:

 

 
  1. name: "LeNet"

  2. layer { #删去原来的Train和Test部分,增加一个data层

  3. name: "data"

  4. type: "Input"

  5. top: "data"

  6. input_param { shape: { dim: 1 dim: 1 dim: 28 dim: 28 } }

  7. }

  8. layer {

  9. name: "conv1"

  10. type: "Convolution"

  11. bottom: "data"

  12. top: "conv1"

  13. param {

  14. lr_mult: 1

  15. }

  16. param {

  17. lr_mult: 2

  18. }

  19. convolution_param {

  20. num_output: 20

  21. kernel_size: 5

  22. stride: 1

  23. weight_filler {

  24. type: "xavier"

  25. }

  26. bias_filler {

  27. type: "constant"

  28. }

  29. }

  30. }

  31. layer {

  32. name: "pool1"

  33. type: "Pooling"

  34. bottom: "conv1"

  35. top: "pool1"

  36. pooling_param {

  37. pool: MAX

  38. kernel_size: 2

  39. stride: 2

  40. }

  41. }

  42. layer {

  43. name: "conv2"

  44. type: "Convolution"

  45. bottom: "pool1"

  46. top: "conv2"

  47. param {

  48. lr_mult: 1

  49. }

  50. param {

  51. lr_mult: 2

  52. }

  53. convolution_param {

  54. num_output: 50

  55. kernel_size: 5

  56. stride: 1

  57. weight_filler {

  58. type: "xavier"

  59. }

  60. bias_filler {

  61. type: "constant"

  62. }

  63. }

  64. }

  65. layer {

  66. name: "pool2"

  67. type: "Pooling"

  68. bottom: "conv2"

  69. top: "pool2"

  70. pooling_param {

  71. pool: MAX

  72. kernel_size: 2

  73. stride: 2

  74. }

  75. }

  76. layer {

  77. name: "ip1"

  78. type: "InnerProduct"

  79. bottom: "pool2"

  80. top: "ip1"

  81. param {

  82. lr_mult: 1

  83. }

  84. param {

  85. lr_mult: 2

  86. }

  87. inner_product_param {

  88. num_output: 500

  89. weight_filler {

  90. type: "xavier"

  91. }

  92. bias_filler {

  93. type: "constant"

  94. }

  95. }

  96. }

  97. layer {

  98. name: "relu1"

  99. type: "ReLU"

  100. bottom: "ip1"

  101. top: "ip1"

  102. }

  103. layer {

  104. name: "ip2"

  105. type: "InnerProduct"

  106. bottom: "ip1"

  107. top: "ip2"

  108. param {

  109. lr_mult: 1

  110. }

  111. param {

  112. lr_mult: 2

  113. }

  114. inner_product_param {

  115. num_output: 10

  116. weight_filler {

  117. type: "xavier"

  118. }

  119. bias_filler {

  120. type: "constant"

  121. }

  122. }

  123. }

  124. layer { #增加softmax层

  125. name: "prob"

  126. type: "Softmax"

  127. bottom: "ip2"

  128. top: "prob"

  129. }

 

(7)预测图片
在My_File文件夹下创建一文件夹Pic,用于存放测试的图片;在My_File文件夹下创建另一文件夹Synset,在其中新建synset_words.txt文件,之后在里面输入:
0
1
2
3
4
5
6
7
8
9

 

看看My_File文件夹都有啥了

 

最后使用caffe/build/examples/cpp_classification/classification.bin对图片作预测,在终端输入:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值