用C++在CAFFE中设置输入层

Setting input layer in CAFFE with C++

本文关键字:设置 输入 CAFFE C++      更新时间:2023-10-16

我正在使用CAFFE编写C++代码来预测单个(目前)图像。该图像已经过预处理,为.png格式。我已经创建了一个Net对象,并读入了经过训练的模型。现在,我需要使用.png图像作为输入层并调用net。Forward()-但是有人能帮我弄清楚如何设置输入层吗?

我在网上找到了一些例子,但都不起作用,而且几乎所有的例子都使用了不推荐使用的功能。根据:Berkeley的Net API,使用"ForwardPrefilled"是不推荐的,而使用"Forward(vector,float*)"是不建议的。API指出应该"设置输入Blob,然后改用Forward()"。这是有道理的,但"设置输入Blob"部分没有展开,我找不到一个好的C++示例来说明如何做到这一点。

我不确定使用caffe::Datum是否是正确的方法,但我一直在玩这个:

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);

同样,我想遵循API的方向,设置输入blobs,然后使用(不推荐使用的)caffeNet.Forward(&lossVal)来获得结果,而不是使用不推荐的东西。

编辑:

基于下面的回答,我更新了包括以下内容:

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);

但现在对AddDatumVector的调用是seg断层。。我想知道这是否与我的prototxt格式有关?这是我的prototxt的顶部:

name: "deploy"  
input: "data"
input_shape {
dim: 1
dim: 3
dim: 100
dim: 100
}
layer {
  name: "conv1"
  type: "Convolution"
  bottom: "data"
  top: "conv1"

我将这部分问题建立在关于"源"字段在prototxt中的重要性的讨论之上。。。

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);

像这样的东西可能很有用。在这里,您必须使用MemoryData层作为输入层。我希望图层名称命名为data

使用datum变量的方式可能不正确。如果我的记忆是正确的,我想,你必须使用一个基准数据向量。

我认为这应该让你开始。

快乐酿造。:D

以下是我在C++代码中使用Caffe的代码摘录。我希望这能有所帮助。

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);

关于:

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();