-
-
Save kyamagu/31a4b6f782670a28098b to your computer and use it in GitHub Desktop.
| // Caffe proto converter. | |
| // | |
| // Build. | |
| // | |
| // mex -I/path/to/matlab-lmdb/include ... | |
| // -I/path/to/caffe/build/src/caffe/proto ... | |
| // caffe_proto_.cc ... | |
| // /path/to/caffe/build/src/caffe/proto/caffe.pb.o ... | |
| // -lprotobuf CXXFLAGS="$CXXFLAGS -std=c++11" | |
| // | |
| // Usage. | |
| // | |
| // fid = fopen('cat.jpg', 'r'); | |
| // jpg_image = fread(fid, inf, 'uint8=>uint8'); | |
| // fclose(fid); | |
| // datum = caffe_proto_('toEncodedDatum', jpg_image, label); | |
| // [jpg_image, label] = caffe_proto_('fromDatum', datum); | |
| // | |
| // image = imread('cat.jpg'); | |
| // label = 1; | |
| // datum = caffe_proto_('toDatum', image, label); | |
| // [image, label] = caffe_proto_('fromDatum', datum); | |
| // | |
| // Importing into LMDB database. | |
| // | |
| // addpath('/path/to/matlab-lmdb'); | |
| // image_files = { | |
| // '/path/to/image-1.jpg', ... | |
| // '/path/to/image-2.jpg', ... | |
| // ... | |
| // }; | |
| // database = lmdb.DB('/path/to/lmdb'); | |
| // for i = 1:numel(image_files) | |
| // label = 0; | |
| // fid = fopen(image_files{i}, 'r'); | |
| // jpg_image = fread(fid, inf, 'uint8=>uint8'); | |
| // fclose(fid); | |
| // datum = caffe_proto_('toEncodedDatum', jpg_image, label); | |
| // database.put(image_files{i}, datum); | |
| // end | |
| // clear database; | |
| // | |
| #include "caffe.pb.h" | |
| #include "mexplus.h" | |
| using namespace std; | |
| using namespace mexplus; | |
| #define ASSERT(condition, ...) \ | |
| if (!(condition)) mexErrMsgIdAndTxt("caffe_proto:error", __VA_ARGS__) | |
| MEX_DEFINE(toEncodedDatum) (int nlhs, mxArray* plhs[], | |
| int nrhs, const mxArray* prhs[]) { | |
| InputArguments input(nrhs, prhs, 2); | |
| OutputArguments output(nlhs, plhs, 1); | |
| caffe::Datum datum; | |
| MxArray array(input.get(0)); | |
| datum.set_data(array.getData<uint8_t>(), array.size()); | |
| datum.set_label(input.get<int>(1)); | |
| datum.set_encoded(true); | |
| output.set(0, datum.SerializeAsString()); | |
| } | |
| MEX_DEFINE(toDatum) (int nlhs, mxArray* plhs[], | |
| int nrhs, const mxArray* prhs[]) { | |
| InputArguments input(nrhs, prhs, 2); | |
| OutputArguments output(nlhs, plhs, 1); | |
| caffe::Datum datum; | |
| MxArray array(input.get(0)); | |
| datum.set_label(input.get<int>(1)); | |
| vector<mwSize> dimensions = array.dimensions(); | |
| int width = dimensions[1]; | |
| int height = dimensions[0]; | |
| int channels = 1; | |
| for (int i = 2; i < dimensions.size(); ++i) | |
| channels *= dimensions[i]; | |
| datum.set_channels(channels); | |
| datum.set_width(width); | |
| datum.set_height(height); | |
| vector<mwIndex> subscripts(3); | |
| if (array.isUint8()) { | |
| datum.mutable_data()->reserve(array.size()); | |
| for (int k = channels - 1; k >= 0; --k) { // RGB to BGR order. | |
| subscripts[2] = k; | |
| for (int i = 0; i < height; ++i) { | |
| subscripts[0] = i; | |
| for (int j = 0; j < width; ++j) { | |
| subscripts[1] = j; | |
| datum.mutable_data()->push_back(array.at<uint8_t>(subscripts)); | |
| } | |
| } | |
| } | |
| } | |
| else { | |
| datum.mutable_float_data()->Reserve(array.size()); | |
| for (int k = channels - 1; k >= 0; --k) { // RGB to BGR order. | |
| subscripts[2] = k; | |
| for (int i = 0; i < height; ++i) { | |
| subscripts[0] = i; | |
| for (int j = 0; j < width; ++j) { | |
| subscripts[1] = j; | |
| datum.add_float_data(array.at<float>(subscripts)); | |
| } | |
| } | |
| } | |
| } | |
| output.set(0, datum.SerializeAsString()); | |
| } | |
| MEX_DEFINE(fromDatum) (int nlhs, mxArray* plhs[], | |
| int nrhs, const mxArray* prhs[]) { | |
| InputArguments input(nrhs, prhs, 1); | |
| OutputArguments output(nlhs, plhs, 2); | |
| caffe::Datum datum; | |
| ASSERT(datum.ParseFromString(input.get<string>(0)), | |
| "Failed to parse datum."); | |
| if (datum.has_encoded() && datum.encoded()) { | |
| output.set(0, datum.data()); | |
| } | |
| else { | |
| vector<mwIndex> dimensions(3); | |
| dimensions[0] = (datum.has_height()) ? datum.height() : 0; | |
| dimensions[1] = (datum.has_width()) ? datum.width() : 0; | |
| dimensions[2] = (datum.has_channels()) ? datum.channels() : 0; | |
| MxArray array; | |
| vector<mwIndex> subscripts(3); | |
| int index = 0; | |
| if (datum.has_data()) { | |
| array.reset(mxCreateNumericArray(dimensions.size(), | |
| &dimensions[0], | |
| mxUINT8_CLASS, | |
| mxREAL)); | |
| const string& data = datum.data(); | |
| for (int k = dimensions[2] - 1; k >= 0; --k) { // BGR to RGB order. | |
| subscripts[2] = k; | |
| for (int i = 0; i < dimensions[0]; ++i) { | |
| subscripts[0] = i; | |
| for (int j = 0; j < dimensions[1]; ++j) { | |
| subscripts[1] = j; | |
| array.set(subscripts, data[index++]); | |
| } | |
| } | |
| } | |
| } | |
| else if (datum.float_data_size() > 0) { | |
| array.reset(mxCreateNumericArray(dimensions.size(), | |
| &dimensions[0], | |
| mxSINGLE_CLASS, | |
| mxREAL)); | |
| for (int k = dimensions[2] - 1; k >= 0; --k) { // BGR to RGB order. | |
| subscripts[2] = k; | |
| for (int i = 0; i < dimensions[0]; ++i) { | |
| subscripts[0] = i; | |
| for (int j = 0; j < dimensions[1]; ++j) { | |
| subscripts[1] = j; | |
| array.set(subscripts, datum.float_data(index++)); | |
| } | |
| } | |
| } | |
| } | |
| output.set(0, array.release()); | |
| } | |
| output.set(1, (datum.has_label()) ? datum.label() : 0); | |
| } | |
| MEX_DISPATCH |
Hi, I've tried compiling this using the following command
mex -I"/path/to/matlab-lmdb-master/include" -I"/path/to/caffe/src/caffe/proto" caffe_proto_.cc -lprotobuf CXXFLAGS="$CXXFLAGS -std=c++11 -fPIC"
But I have the following error(s)
Building with 'g++'.
/tmp/mex_22659658470642_18000/caffe_proto_.o: In functionOperation_toDatum::operator()(int, mxArray_tag**, int, mxArray_tag const**)': caffe_proto_.cc:(.text+0x2fd): undefined reference tocaffe::Datum::Datum()'
caffe_proto_.cc:(.text+0x807): undefined reference tocaffe::Datum::~Datum()' caffe_proto_.cc:(.text+0x90a): undefined reference tocaffe::Datum::~Datum()'
/tmp/mex_22659658470642_18000/caffe_proto_.o: In functionOperation_toEncodedDatum::operator()(int, mxArray_tag**, int, mxArray_tag const**)': caffe_proto_.cc:(.text+0xa0a): undefined reference tocaffe::Datum::Datum()'
caffe_proto_.cc:(.text+0xb85): undefined reference tocaffe::Datum::~Datum()' caffe_proto_.cc:(.text+0xc06): undefined reference tocaffe::Datum::~Datum()'
/tmp/mex_22659658470642_18000/caffe_proto_.o: In functionOperation_fromDatum::operator()(int, mxArray_tag**, int, mxArray_tag const**)': caffe_proto_.cc:(.text+0xcbc): undefined reference tocaffe::Datum::Datum()'
caffe_proto_.cc:(.text+0x1126): undefined reference tocaffe::Datum::~Datum()' caffe_proto_.cc:(.text+0x11d3): undefined reference tocaffe::Datum::~Datum()'
collect2: error: ld returned 1 exit status
I suspect it could be because my command doesn't try to build
/path/to/caffe/build/src/caffe/proto/caffe.pb.o
Unfortunately, I am unable to locate this particular file and I have no idea how to generate it. I have alrady tried rebuilding caffe (make clean, make all). Can anyone help?
Hi folks, Github gist doesn't notify me any new comment and I didn't know so many discussions happening here!
@peerajak You can encode and decode to check if they are identical.
@201power I believe your encoded datum is not in the expected binary format. Just check if you can fwrite the binary to a file and able to open. My implementation does not do encoding/decoding but only conversion, because Matlab can imread/imwrite for decoding/encoding. That's why there is fread in the example.
@amir-abdi You have to compile caffe first to link. Make sure your relative path is correctly pointing to the caffe.pb.o object.
@cedricseah You must correctly specify /path/to/caffe. Check the caffe directory.
Hi, Thank you for posting this.
Could you provide example usage for using 'fromDatum' to read from an existing database? I tried
datum = read_db.get(filename);
[im, label] = caffe_proto_('fromDatum',datum)
based on your example and received this error:
Error using caffe_proto_
Failed to parse datum.
@amir-abdi, thanks. I checked you can open issues in my repository.
It's great it worked for you, although I am not sure the bug. For me, it always shows "cannot decode"