caffe+opencv3.3dnn模塊 完成手寫數字圖片識別


最近由於項目需要用到caffe,學習了下caffe的用法,在使用過程中也是遇到了些問題,通過上網搜索和問老師的方法解決了,在此記錄下過程,方便以后查看,也希望能為和我一樣的新手們提供幫助。
順帶附上老師寫的教程


安裝Caffe並運行Mnist例程

我主要參考了這篇教程: Mac極簡安裝Caffe並訓練MNIST。然后進行了examples文件夾里的Mnist的訓練,期間並沒有碰到什么問題。

將圖片轉換為LMDB文件

Mnist中已經給出了現成的LMDB數據文件,在實際項目中,需要我們將圖片文件轉換為LMDB文件。可以參考下examples里的imagenet,里面的readme寫了完整的過程,也可以參考上面貼的教程。在這里就不復述了,主要說下注意點:
轉換文件只要參考imagenet的create_imagenet.sh並更改相應路徑即可,如下:

set -e
#生成的lmdb文件夾位置
EXAMPLE=examples/myMnistTest
#train.txt和val.txt位置
DATA=examples/myMnistTest/MNIST_Dataset
#tools文件夾位置,寫相對位置的話要在caffe根目錄運行
TOOLS=build/tools
#train圖片位置
TRAIN_DATA_ROOT=/Users/messier/caffe/examples/myMnistTest/MNIST_Dataset/train_images/
#val圖片位置
VAL_DATA_ROOT=/Users/messier/caffe/examples/myMnistTest/MNIST_Dataset/train_images/

# Set RESIZE=true to resize the images to 256x256. Leave as false if images have
# already been resized using another tool.
#這邊寫成false,我寫了true結果生成了10個多GB的lmdb...不過訓練出來的模型還是能用的
RESIZE=true
if $RESIZE; then
  RESIZE_HEIGHT=256
  RESIZE_WIDTH=256
else
  RESIZE_HEIGHT=0
  RESIZE_WIDTH=0

開始訓練

這一步之前可以選擇進行計算圖像均值的操作。然后去mnist文件夾中把之前用到過的prototxt拿過來,更改路徑,按之前的操作進行即可。
要注意的是,沒進行過均值操作的話,要把所有的mean_pixel注釋掉。

在opencv中調用訓練好的模型

opencv3.3中將dnn模塊從contrib中提到了主倉庫中,可以直接調用caffe訓練好的模型,且不需要任意依賴。
這里我主要參考了opencv中一個用caffe模型識別航空飛機的sample
稍加修改即可。
首先要把幾個文件的路徑改下,如下:

    String modelTxt = "lenet_deploy.prototxt";
    String modelBin = "_iter_6714.caffemodel";
    String imageFile = (argc > 1) ? argv[1] : "3_00715.jpg";

需要注意的是,當時訓練用的模型文件不能在這里直接用了,要把輸入和輸出改下,如下:

  1. 更改輸入
    原來:
name: "LeNet"
layer {
  name: "mnist"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TRAIN
  }
  transform_param {
    scale: 0.00390625
  }
  data_param {
    source: "./train_lmdb"
    batch_size: 64
    backend: LMDB
  }
}

更改為:

name: "LeNet"
input: "data"
input_dim: 1    #每次輸入圖片數
input_dim: 1    #channels
input_dim: 256  #width
input_dim: 256  #height

2.更改輸出:
原來:

layer {
  name: "loss"
  type: "SoftmaxWithLoss"
  bottom: "ip2"
  bottom: "label"
  top: "loss"
}

更改為:

layer {
name: "prob"
type: "Softmax"
bottom: "ip2"
top: "prob"
}

在這里推薦下老師告訴我的caffe網絡可視化工具Netscope
看下更改前后的網絡:
更改前
更改后

最后程序運行結果如下:


12.12更新:程序源碼已經上傳了,直接用cmake構建工程即可。

順帶再略微解析下程序的流程:
1、 載入模型文件
readNetFromCaffe(modelTxt, modelBin);
2、 讀取圖片,轉換為blob的數據格式。
Mat inputBlob = blobFromImage(img, 0.00390625f, Size(256, 256), Scalar(), false); //Convert Mat to batch of images
看下這個函數,第一個參數是圖片,第二個參數是訓練時的特征縮放系數,這里是1/256,第三個參數是blob對應的圖片大小,之前說過,我在訓練時誤把圖像縮放到了256* 256,這里輸入圖像大小還是28 * 28的,但作為輸入要縮放到256*256,第四個參數是各通道均值,我沒作均值處理所以給默認值,第六個參數的意思是是否交換R B通道,這里是單通道圖片所以不交換。
3、 前向傳播,計算各個label的prob,結果用一個10維向量保存。

Mat prob;
    cv::TickMeter t;
    for (int i = 0; i < 10; i++)
    {
        CV_TRACE_REGION("forward");
        net.setInput(inputBlob, "data");        //set the network input
        t.start();
        prob = net.forward("prob");                          //compute output
        t.stop();
    }

4、 找出prob最大的label,輸出結果。

getMaxClass(prob, &classId, &classProb);


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM