
不过那个代码我看着不太习惯,所以之前自己稍微写了一个简易的版本,不知道怎么上传附件,懒人一个就直接把代码贴在最后了。
先简单解释一下如何使用,把这个代码复制到一个头文件中,然后放在examples里面一个自己创建的文件夹里面,然后写一个main函数调用这个类就可以了,比如:
复制,保存到caffe/examples/myproject/net_operator.hpp,然后同目录下写一个main.cpp,在main函数里面#include “net_operator.hpp”,就可以使用这个类了:
const string net_prototxt = “…” // 你的网络的prototxt文件,用绝对路径,下面同理
const string pre_trained_file = “…”// 你训练好的。caffemodel文件
const string img_path = “…”// 你要测试的图片路径
// 创建NetOperator对象
NetOperator net_operator(net_prototxt, pre_trained_file);
Blob<float>*blob = net_operator.processImage(img_path);
// blob就得到了最后一层的输出结果,至于blob里面是怎么存放数据的,你需要去看看对它的定义
写完main.cpp之后,到caffe目录下,make,然后它会编译你写的文件,对应生成的可执行文件。比如按我上面写的那样,make之后就会在caffe/build/examples/myproject文件夹里面生成一个main.bin,执行这个文件就可以了。因为生成的可执行文件并不是直接在代码目录下,所以前面我建议你写的路径用绝对路径
另外如果你要获取的不是最后一层的输出,你需要修改一下processImage函数的返回值,通过NetOperator的成员变量net_来获取你需要的blob,比如有个blob名称为“label”,你想获取这个blob,可以通过net_->blob_by_name(“label”)来获取,当然获取到的是shared_ptr<Blob<float>>类型的,搜一下boost shared_ptr就知道跟普通指针有什么不同了
好了,接下来是贴代码了:
#include <caffe/caffe.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iosfwd>
#include <memory>
#include <string>
#include <utility>
#include <vector>
using namespace caffe // NOLINT(build/namespaces)
using std::string
class NetOperator
{
public:
NetOperator(const string net_prototxt);
NetOperator(const string net_prototxt, const string trained_file);
~NetOperator() { }
int batch_size() { return batch_size_}
Blob<float>* processImage(const string img_path, bool is_color = true);
Blob<float>* processImages(const vector<string>img_paths, bool is_color = true);
private:
void createNet(const string net_prototxt);
// read the image and store it in the idx position of images in the blob
void readImageToBlob(const string img_path, int idx = 0, bool is_color = true);
shared_ptr<Net<float>>net_
cv::Size input_geometry_
int batch_size_
int num_channels_
Blob<float>* input_blob_
TransformationParameter transform_param_
shared_ptr<DataTransformer<float>>data_transformer_
Blob<float>transformed_data_
}
NetOperator::NetOperator(const string net_prototxt) {
createNet(net_prototxt);
}
NetOperator::NetOperator(const string net_prototxt, const string trained_file) {
createNet(net_prototxt);
net_->CopyTrainedLayersFrom(trained_file);
}
void NetOperator::createNet(const string net_prototxt) {
#ifdef CPU_ONLY
Caffe::set_mode(Caffe::CPU);
#else
Caffe::set_mode(Caffe::GPU);
#endif
net_.reset(new Net<float>(net_prototxt, TEST));
CHECK_EQ(net_->num_inputs(), 1) 《 “Network should have exactly one input.”
CHECK_EQ(net_->num_outputs(), 1) 《 “Network should have exactly one output.”
Blob<float>* input_layer = net_->input_blobs()[0]
batch_size_ = input_layer->num();
num_channels_ = input_layer->channels();
CHECK(num_channels_ == 3 || num_channels_ == 1)
《 “Input layer should have 1 or 3 channels.”
input_geometry_ = cv::Size(input_layer->width(), input_layer->height());
// reshape the output shape of the DataTransformer
vector<int>top_shape(4);
top_shape[0] = 1
top_shape[1] = num_channels_
top_shape[2] = input_geometry_.height
top_shape[3] = input_geometry_.width
this->transformed_data_.Reshape(top_shape);
}
Blob<float>* NetOperator::processImage(const string img_path, bool is_color) {
// reshape the net for the input
input_blob_ = net_->input_blobs()[0]
input_blob_->Reshape(1, num_channels_,
input_geometry_.height, input_geometry_.width);
net_->Reshape();
readImageToBlob(img_path, 0, is_color);
net_->ForwardPrefilled();
return net_->output_blobs()[0]
}
Blob<float>* NetOperator::processImages(const vector<string>img_paths, bool is_color) {
int img_num = img_paths.size();
// reshape the net for the input
input_blob_ = net_->input_blobs()[0]
input_blob_->Reshape(img_num, num_channels_,
input_geometry_.height, input_geometry_.width);
net_->Reshape();
for (int i=0i<img_numi++) {
readImageToBlob(img_paths[i], i, is_color);
}
net_->ForwardPrefilled();
return net_->output_blobs()[0]
}
void NetOperator::readImageToBlob(const string img_path, int idx, bool is_color) {
// read the image and resize to the target size
cv::Mat img
int cv_read_flag = (is_color ? CV_LOAD_IMAGE_COLOR :
CV_LOAD_IMAGE_GRAYSCALE);
cv::Mat cv_img_origin = cv::imread(img_path, cv_read_flag);
if (!cv_img_origin.data) {
LOG(ERROR) 《 “Could not open or find file ” 《 img_path
return
}
if (input_geometry_.height >0 input_geometry_.width >0) {
cv::resize(cv_img_origin, img, input_geometry_);
} else {
img = cv_img_origin
}
// transform the image to a blob using DataTransformer
// create a DataTransformer using default TransformationParameter (no transformation)
data_transformer_.reset(
new DataTransformer<float>(transform_param_, TEST));
data_transformer_->InitRand();
// set the output of DataTransformer to the idx image of the input blob
int offset = input_blob_->offset(idx);
this->transformed_data_.set_cpu_data(input_blob_->mutable_cpu_data() + offset);
// transform the input image
data_transformer_->Transform(img, (this->transformed_data_));
}
2.安装Visual Studio 2013;3.如果与需要使用NVIDIA显卡的请安装Cuda和CuDNN,不需要可以不装;
4.将.\windows\CommonSettings.props.example 复制一份并修改为 .\windows\CommonSettings.props,然后打开做如下修改:
1)如果不使用GPU,不安装CUDA和CuDNN,将CpuOnlyBuild 改为 true ,并且 UseCuDNN 改为 false;
2)安装CuDNN的情况下,将CuDNND路径复制到CuDnnPath;
3)选择支持Python或者MATLAB接口,当然也可以两个都支持,设置PythonSupport或者MatlabSupport为true,同时将Python或者MATLAB路径分别粘过来PythonDir和MatlabDir。
第二步,编译
打开.\windows\Caffe.sln,编译Caffe/convert_imageset、caffe、libcaffe、convert_mnist_data等,可以根据提示和需要进行,生成的caffe.exe为训练与测试的主程序,convert_imageset为将训练和测试数据生成LMDB使用的程序。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)