├── CMakeLists.txt ├── build ├── lenet.prototxt └── lenet_iter_10000.caffemodel ├── main.cpp └── readme.md /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | project(caffe_mint) 3 | 4 | set(CMAKE_CXX_STANDARD 11) 5 | 6 | 7 | include_directories(include) 8 | link_directories("/home/yd/.local/caffe/lib") 9 | 10 | include_directories("/usr/local/cuda/include") 11 | link_directories("/usr/local/cuda/lib64") 12 | 13 | set(SOURCE_FILES main.cpp) 14 | add_executable(caffe_mint ${SOURCE_FILES}) 15 | 16 | find_package(OpenCV REQUIRED) 17 | target_link_libraries(caffe_mint ${OpenCV_LIBS} ) 18 | target_link_libraries(caffe_mint caffe cublas boost_system glog) 19 | -------------------------------------------------------------------------------- /build/lenet.prototxt: -------------------------------------------------------------------------------- 1 | name: "LeNet" 2 | layer { 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 { 125 | name: "prob" 126 | type: "Softmax" 127 | bottom: "ip2" 128 | top: "prob" 129 | } 130 | -------------------------------------------------------------------------------- /build/lenet_iter_10000.caffemodel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ydar95/CPP_Caffe_LeNet/4ac09c8520387ab9590fe69ff32343c873627127/build/lenet_iter_10000.caffemodel -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ydar95/CPP_Caffe_LeNet/4ac09c8520387ab9590fe69ff32343c873627127/main.cpp -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # C++ 调用 Caffe 训练好的网络(样例:LeNet) 2 | 3 | ## 1. 说明 4 | 5 | 我们用Caffe可以很方便的训练我们的网络,但是当真正的拿去用到C++之类的工程的时候就不知道怎么做了.于是我打算介绍下C++ 如何调用 Caffe 训练好的网络和API . 6 | 7 | 前期准备: g++ ( 支持 C++11 版本 ) cmake opencv ,还有Caffe ( 我在这里就不介绍Caffe 的安装使用了) 8 | 9 | ## 2. 一些 caffe API 的介绍 10 | 官方文档: http://caffe.berkeleyvision.org/doxygen/index.html 11 | ### 2.1 caffe::net 12 | 13 | 这个类是我们调用Caffe API 的核心.它提供很方便的使用方式,只要我们提供正确 caffemodel 和 net(网络结构) ,就可以自动帮我们生成好用于预测的网络. 14 | 15 | ### 2.2 caffe::Caffe::set_mode(); 16 | 17 | 这个是用于设置,我们使用CPU进行运算还是GPU进行运行.默认情况下caffe是使用CPU运行的. 18 | 使用方式如下 19 | 20 | ```c++ 21 | using namespace caffe; 22 | Caffe::set_mode(Caffe::CPU); // 设置为CPU模式 23 | Caffe::set_mode(Caffe::GPU); // 设置为GPU模式 24 | ``` 25 | 26 | ### 2.3 caffe::Blob 27 | 这个是caffe 放置 网络模型运行时所有数据的class.我们的网络的输入和输出也是使用这个class管理. 28 | 29 | ## 3. 代码 30 | 31 | main.cpp 32 | 33 | ```c++ 34 | #include 35 | #include 36 | #include 37 | #include 38 | using namespace caffe; 39 | using namespace std; 40 | int main(int argc,char* argv[]) { 41 | typedef float type; 42 | type ary[28*28]; 43 | 44 | //在28*28的图片颜色为RGB(255,255,255)背景上写RGB(0,0,0)数字. 45 | cv::Mat gray(28,28,CV_8UC1,cv::Scalar(255)); 46 | cv::putText(gray,argv[3],cv::Point(4,22),5,1.4,cv::Scalar(0),2); 47 | 48 | //将图像的数值从uchar[0,255]转换成float[0.0f,1.0f],的数, 且颜色取相反的 . 49 | for(int i=0;i<28*28;i++){ 50 | // f_val =(255-uchar_val)/255.0f 51 | ary[i] = static_cast(gray.data[i]^0xFF)*0.00390625; 52 | } 53 | 54 | cv::imshow("x",gray); 55 | cv::waitKey(); 56 | 57 | //set cpu running software 58 | Caffe::set_mode(Caffe::CPU); 59 | 60 | //load net file , caffe::TEST 用于测试时使用 61 | Net lenet(argv[1],caffe::TEST); 62 | 63 | //load net train file caffemodel 64 | lenet.CopyTrainedLayersFrom(argv[2]); 65 | 66 | 67 | 68 | Blob *input_ptr = lenet.input_blobs()[0]; 69 | input_ptr->Reshape(1,1,28,28); 70 | 71 | Blob *output_ptr= lenet.output_blobs()[0]; 72 | output_ptr->Reshape(1,10,1,1); 73 | 74 | //copy data from to 75 | input_ptr->set_cpu_data(ary); 76 | 77 | //begin once predict 78 | lenet.Forward(); 79 | 80 | 81 | const type* begin = output_ptr->cpu_data(); 82 | 83 | // get the maximum index 84 | int index=0; 85 | for(int i=1;i<10;i++){ 86 | if(begin[index]