Setting input layer in CAFFE with C++

喜欢而已 提交于 2019-12-12 09:49:22

问题


I'm writing C++ code using CAFFE to predict a single (for now) image. The image has already been preprocessed and is in .png format. I have created a Net object and read in the trained model. Now, I need to use the .png image as an input layer and call net.Forward() - but can someone help me figure out how to set the input layer?

I found a few examples on the web, but none of them work, and almost all of them use deprecated functionality. According to: Berkeley's Net API, using "ForwardPrefilled" is deprecated, and using "Forward(vector, float*)" is deprecated. API indicates that one should "set input blobs, then use Forward() instead". That makes sense, but the "set input blobs" part is not expanded on, and I can't find a good C++ example on how to do that.

I'm not sure if using a caffe::Datum is the right way to go or not, but I've been playing with this:

float lossVal = 0.0;
caffe::Datum datum;
caffe::ReadImageToDatum("myImg.png", 1, imgDims[0], imgDims[1], &datum);
caffe::Blob< float > *imgBlob = new caffe::Blob< float >(1, datum.channels(), datum.height(), datum.width());
//How to get the image data into the blob, and the blob into the net as input layer???
const vector< caffe::Blob< float >* > &result = caffeNet.Forward(&lossVal);

Again, I'd like to follow the API's direction of setting the input blobs and then using the (non-deprecated) caffeNet.Forward(&lossVal) to get the result as opposed to making use of the deprecated stuff.

EDIT:

Based on an answer below, I updated to include this:

caffe::MemoryDataLayer<unsigned char> *memory_data_layer = (caffe::MemoryDataLayer<unsigned char> *)caffeNet.layer_by_name("input").get();
vector< caffe::Datum > datumVec;
datumVec.push_back(datum);
memory_data_layer->AddDatumVector(datumVec);

but now the call to AddDatumVector is seg faulting.. I wonder if this is related to my prototxt format? here's the top of my prototxt:

name: "deploy"  

input: "data"
input_shape {
dim: 1
dim: 3
dim: 100
dim: 100
}

layer {
  name: "conv1"
  type: "Convolution"
  bottom: "data"
  top: "conv1"

I base this part of the question on this discussion about a "source" field being important in the prototxt...


回答1:


caffe::Datum datum;
caffe::ReadImageToDatum("myImg.png", 1, imgDims[0], imgDims[1], &datum);
MemoryDataLayer<float> *memory_data_layer = (MemoryDataLayer<float> *)caffeNet->layer_by_name("data").get();
memory_data_layer->AddDatumVector(datum);
const vector< caffe::Blob< float >* > &result = caffeNet.Forward(&lossVal);

Something like this could be useful. Here you will have to use MemoryData layer as the input layer. I am expecting the layer name to be named data.

The way of using datum variable may not be correct. If my memory is correct, I guess, you have to use a vector of datum data.

I think this should get you started.

Happy brewing. :D




回答2:


Here is an excerpt from my code located here where I used Caffe in my C++ code. I hope this helps.

Net<float> caffe_test_net("models/sudoku/deploy.prototxt", caffe::TEST);

caffe_test_net.CopyTrainedLayersFrom("models/sudoku/sudoku_iter_10000.caffemodel");

// Get datum
Datum datum;
if (!ReadImageToDatum("examples/sudoku/cell.jpg", 1, 28, 28, false, &datum)) {
     LOG(ERROR) << "Error during file reading";
}


// Get the blob
Blob<float>* blob = new Blob<float>(1, datum.channels(), datum.height(), datum.width());

// Get the blobproto
BlobProto blob_proto;
blob_proto.set_num(1);
blob_proto.set_channels(datum.channels());
blob_proto.set_height(datum.height());
blob_proto.set_width(datum.width());
int size_in_datum = std::max<int>(datum.data().size(),
                                          datum.float_data_size());

for (int ii = 0; ii < size_in_datum; ++ii) {
     blob_proto.add_data(0.);
}
const string& data = datum.data();
if (data.size() != 0) {
     for (int ii = 0; ii < size_in_datum; ++ii) {
         blob_proto.set_data(ii, blob_proto.data(ii) + (uint8_t)data[ii]);
     }
}

// Set data into blob
blob->FromProto(blob_proto);

// Fill the vector
vector<Blob<float>*> bottom;
bottom.push_back(blob);
float type = 0.0;

const vector<Blob<float>*>& result =  caffe_test_net.Forward(bottom, &type);



回答3:


What about:

Caffe::set_mode(Caffe::CPU);
caffe_net.reset(new caffe::Net<float>("your_arch.prototxt", caffe::TEST));
caffe_net->CopyTrainedLayersFrom("your_model.caffemodel");

Blob<float> *your_blob = caffe_net->input_blobs()[0];
your_blob->set_cpu_data(your_image_data_as_pointer_to_float);

caffe_net->Forward();


来源:https://stackoverflow.com/questions/38637053/setting-input-layer-in-caffe-with-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!