【caffe】使用自己的图像数据训练lenet并用opencv进行预测
前面已經(jīng)介紹了使用使用mnist數(shù)據(jù)集進(jìn)行訓(xùn)練lenet,并使用opencv加在caffemodel進(jìn)行預(yù)測。更進(jìn)一步也是最終的目的,還是要學(xué)會使用自己的數(shù)據(jù)集訓(xùn)練caffemodel并進(jìn)行預(yù)測。這里先以訓(xùn)練lenet為例進(jìn)行說明。
1、數(shù)據(jù)格式的轉(zhuǎn)換(images to lmdb)
通過前面幾篇介紹,我們已經(jīng)知道,可直接用于caffe訓(xùn)練的數(shù)據(jù)格式有l(wèi)mdb和leveldb兩種,但lmdb的效率更高,因此這里需要先將原始圖像數(shù)據(jù)轉(zhuǎn)換為lmdb。
1.1 在工作目錄細(xì)新建一個文件夾,這里命名為images_to_lmdb,圖像格式的轉(zhuǎn)換將在這個文件夾下進(jìn)行。將分好類的訓(xùn)練數(shù)據(jù)(這里包括前景(車輛)和背景數(shù)據(jù),二者合適的比例為1:3,一部分用于訓(xùn)練,一部分測試)也拷貝到這個文件夾下,分別創(chuàng)建train.txt和test.txt兩個文本文件,指定源圖像的路徑(如果不是剪切好的圖像,需要指定目標(biāo)所在的區(qū)域)和類別(這里前景設(shè)為0, 背景設(shè)為1),如下圖所示。
1.2 在當(dāng)前目錄下新建兩個文本文件,分別重命名為images_to_train_lmdb.bat 和?images_to_test_lmdb.bat.分別輸入以下內(nèi)容(注意路徑輸入正確):
D:\Libraries\caffe\msvc2013_64\bin\convert_imageset.exe --shuffle --gray --resize_width=28 --resize_height=28 images\ train.txt train_lmdb -backend=lmdb pauseD:\Libraries\caffe\msvc2013_64\bin\convert_imageset.exe --shuffle --gray --resize_width=28 --resize_height=28 images\ test.txt test_lmdb -backend=lmdb pause
1.3 雙擊images_to_train_lmdb.bat執(zhí)行,可以得到訓(xùn)練數(shù)據(jù),保存在文件夾train_lmdb中。執(zhí)行過程如下:
同樣,雙擊images_to_test_lmdb.bat可得到訓(xùn)練數(shù)據(jù)。
2、計算均值
在當(dāng)前文件夾下新建文本文件,并命名為computer_image_mean.bat,并輸入如下內(nèi)容:
D:\Libraries\caffe\msvc2013_64\bin\compute_image_mean.exe train_lmdb mean.binaryproto --backend=lmdb pause
保存,雙擊執(zhí)行,得到文件mean.binaryproto。
至此,訓(xùn)練數(shù)據(jù)準(zhǔn)備完畢,下面進(jìn)行訓(xùn)練。
3、設(shè)置訓(xùn)練參數(shù)
3.1 在工程目錄下新建文件夾,并命名為glnet_train_test,訓(xùn)練工作將在這個文件夾下進(jìn)行,將上兩步得到的訓(xùn)練數(shù)據(jù),即兩個文件夾train_lmdb和test_lmdb,以文件mean.binaryproto拷貝到當(dāng)前文件夾下。
3.2 新建兩個文本文件,分別命名為lenet_solver.prototxt和lenet_train_test.prototxt。
向lenet_solver.prototxt輸入如下內(nèi)容,并保存。
# The train/test net protocol buffer definition net: "lenet_train_test.prototxt" # test_iter specifies how many forward passes the test should carry out. # In the case of MNIST, we have test batch size 100 and 100 test iterations, # covering the full 10,000 testing images. test_iter: 100 # Carry out testing every 500 training iterations. test_interval: 500 # The base learning rate, momentum and the weight decay of the network. base_lr: 0.01 momentum: 0.9 weight_decay: 0.0005 # The learning rate policy lr_policy: "inv" gamma: 0.0001 power: 0.75 # Display every 100 iterations display: 100 # The maximum number of iterations max_iter: 10000 # snapshot intermediate results snapshot: 5000 snapshot_prefix: "lenet" # solver mode: CPU or GPU solver_mode: GPU
向lenet_train_test.prototxt輸入如下內(nèi)容,并保存
name: "LeNet" layer {name: "myNet"type: "Data"top: "data"top: "label"include {phase: TRAIN}transform_param {#mean_file:"mean.binaryproto"scale: 0.00390625}data_param {source: "train_lmdb"batch_size: 64backend: LMDB} } layer {name: "myNet"type: "Data"top: "data"top: "label"include {phase: TEST}transform_param {scale: 0.00390625#mean_file:"mean.binaryproto"}data_param {source: "test_lmdb"batch_size: 100backend: LMDB} } layer {name: "conv1"type: "Convolution"bottom: "data"top: "conv1"param {lr_mult: 1}param {lr_mult: 2}convolution_param {num_output: 20kernel_size: 5stride: 1weight_filler {type: "xavier"}bias_filler {type: "constant"}} } layer {name: "pool1"type: "Pooling"bottom: "conv1"top: "pool1"pooling_param {pool: MAXkernel_size: 2stride: 2} } layer {name: "conv2"type: "Convolution"bottom: "pool1"top: "conv2"param {lr_mult: 1}param {lr_mult: 2}convolution_param {num_output: 50kernel_size: 5stride: 1weight_filler {type: "xavier"}bias_filler {type: "constant"}} } layer {name: "pool2"type: "Pooling"bottom: "conv2"top: "pool2"pooling_param {pool: MAXkernel_size: 2stride: 2} } layer {name: "ip1"type: "InnerProduct"bottom: "pool2"top: "ip1"param {lr_mult: 1}param {lr_mult: 2}inner_product_param {num_output: 500weight_filler {type: "xavier"}bias_filler {type: "constant"}} } layer {name: "relu1"type: "ReLU"bottom: "ip1"top: "ip1" } layer {name: "ip2"type: "InnerProduct"bottom: "ip1"top: "ip2"param {lr_mult: 1}param {lr_mult: 2}inner_product_param {num_output: 2 ####根據(jù)訓(xùn)練的目標(biāo)種類進(jìn)行設(shè)定,這里設(shè)置為2weight_filler {type: "xavier"}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"top: "loss" }
參數(shù)設(shè)置完畢,下面進(jìn)行訓(xùn)練和測試。
4、訓(xùn)練和測試
4.1 在當(dāng)前文件夾下新建文本文件,命名為train.bat,輸入如下內(nèi)容,并保存。
D:\Libraries\caffe\msvc2013_64\bin\caffe.exe train --solver=lenet_solver.prototxt pause
雙擊執(zhí)行,過程如下:
最終得到如下訓(xùn)練模型:
4.2 下面進(jìn)行測試,新建文本文件并命名為test.bat,并輸入如下內(nèi)容并保存。
D:\Libraries\caffe\msvc2013_64\bin\caffe.exe test --model lenet_train_test.prototxt -weights=lenet_iter_10000.caffemodel pause
雙擊執(zhí)行,測試結(jié)果如下:
5、使用opencv加在caffemodel
5.1上面已經(jīng)得到了caffemodel,在使用opencv進(jìn)行預(yù)測前,需要先新建一個文本文件并命名為lenet.prototxt,輸入如下內(nèi)容,并保存。
name: "LeNet" input: "data" input_dim: 64 #訓(xùn)練的bacth_size input_dim: 1 #通道數(shù) input_dim: 28 #長 input_dim: 28 #寬 layer {name: "conv1"type: "Convolution"bottom: "data"top: "conv1"param {lr_mult: 1}param {lr_mult: 2}convolution_param {num_output: 20kernel_size: 5stride: 1weight_filler {type: "xavier"}bias_filler {type: "constant"}} } layer {name: "pool1"type: "Pooling"bottom: "conv1"top: "pool1"pooling_param {pool: MAXkernel_size: 2stride: 2} } layer {name: "conv2"type: "Convolution"bottom: "pool1"top: "conv2"param {lr_mult: 1}param {lr_mult: 2}convolution_param {num_output: 50kernel_size: 5stride: 1weight_filler {type: "xavier"}bias_filler {type: "constant"}} } layer {name: "pool2"type: "Pooling"bottom: "conv2"top: "pool2"pooling_param {pool: MAXkernel_size: 2stride: 2} } layer {name: "ip1"type: "InnerProduct"bottom: "pool2"top: "ip1"param {lr_mult: 1}param {lr_mult: 2}inner_product_param {num_output: 500weight_filler {type: "xavier"}bias_filler {type: "constant"}} } layer {name: "relu1"type: "ReLU"bottom: "ip1"top: "ip1" } layer {name: "ip2"type: "InnerProduct"bottom: "ip1"top: "ip2"param {lr_mult: 1}param {lr_mult: 2}inner_product_param {num_output: 2 #和lenet_train_test.prototxt中保持一致。weight_filler {type: "xavier"}bias_filler {type: "constant"}} } layer {name: "prob"type: "Softmax"bottom: "ip2"top: "prob" }
5.2 使用opencv加在模型進(jìn)行預(yù)測(具體參考 OpenCV Load caffe model)
這里直接附上代碼:
#include <opencv2/dnn.hpp> #include <opencv2/imgproc.hpp> #include <opencv2/highgui.hpp> #include <fstream> #include <iostream> #include <cstdlib> /* Find best class for the blob (i. e. class with maximal probability) */ void getMaxClass(cv::dnn::Blob &probBlob, int *classId, double *classProb) {cv::Mat probMat = probBlob.matRefConst().reshape(1, 1); //reshape the blob to 1x1000 matrix cv::Point classNumber;cv::minMaxLoc(probMat, NULL, classProb, NULL, &classNumber);*classId = classNumber.x; }std::vector<cv::String> readClassNames(const char *filename = "label.txt") {std::vector<cv::String> classNames;std::ifstream fp(filename);if (!fp.is_open()){std::cerr << "File with classes labels not found: " << filename << std::endl;exit(-1);}std::string name;while (!fp.eof()){std::getline(fp, name);if (name.length())classNames.push_back(name.substr(name.find(' ') + 1));}fp.close();return classNames; }int main(int argc, char **argv) {void cv::dnn::initModule();cv::String modelTxt = "lenet.prototxt";cv::String modelBin = "lenet_iter_10000.caffemodel";cv::String imageFile = "0001.png";cv::dnn::Net net = cv::dnn::readNetFromCaffe(modelTxt, modelBin);if (net.empty()){std::cerr << "Can't load network by using the following files: " << std::endl;std::cerr << "prototxt: " << modelTxt << std::endl;std::cerr << "caffemodel: " << modelBin << std::endl;exit(-1);}//! [Prepare blob] cv::Mat img = cv::imread(imageFile, cv::IMREAD_GRAYSCALE);if (img.empty()){std::cerr << "Can't read image from the file: " << imageFile << std::endl;exit(-1);}cv::resize(img, img, cv::Size(28, 28));//cv::dnn::Blob inputBlob = cv::dnn::Blob(img); //Convert Mat to dnn::Blob image batch cv::dnn::Blob inputBlob = cv::dnn::Blob::fromImages(img);//! [Prepare blob] //! [Set input blob] net.setBlob(".data", inputBlob); //set the network input //! [Set input blob] //! [Make forward pass] net.forward(); //compute output //! [Make forward pass] //! [Gather output] cv::dnn::Blob prob = net.getBlob("prob"); //gather output of "prob" layer int classId;double classProb;getMaxClass(prob, &classId, &classProb);//find the best class //! [Gather output] //! [Print results] std::vector<cv::String> classNames = readClassNames();std::cout << "Best class: #" << classId << " '" << classNames.at(classId) << "'" << std::endl;std::cout << "Probability: " << classProb * 100 << "%" << std::endl;//! [Print results] return 0; } //main
測試結(jié)果如下:
DONE!
2017.08.01
總結(jié)
以上是生活随笔為你收集整理的【caffe】使用自己的图像数据训练lenet并用opencv进行预测的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【caffe】OpenCV Load c
- 下一篇: 【caffe】使用draw_net绘制n