// caffe::Caffe functions so that one could easily call it from matlab.
// Note that for matlab, we will simply use float as the data type.
+#include <string>
+#include <vector>
+
#include "mex.h"
#include "caffe/caffe.hpp"
#define MEX_ARGS int nlhs, mxArray **plhs, int nrhs, const mxArray **prhs
-using namespace caffe;
+namespace caffe {
// The pointer to the internal caffe::Net instance
static shared_ptr<Net<float> > net_;
// matlab uses RGB color channel order
// images need to have the data mean subtracted
//
-// Data coming in from matlab needs to be in the order
-// [batch_images, channels, height, width]
+// Data coming in from matlab needs to be in the order
+// [batch_images, channels, height, width]
// where width is the fastest dimension.
// Here is the rough matlab for putting image data into the correct
// format:
// If you have multiple images, cat them with cat(4, ...)
//
// The actual forward function. It takes in a cell array of 4-D arrays as
-// input and outputs a cell array.
+// input and outputs a cell array.
static mxArray* do_forward(const mxArray* const bottom) {
vector<Blob<float>*>& input_blobs = net_->input_blobs();
- CHECK_EQ(static_cast<unsigned int>(mxGetDimensions(bottom)[0]),
+ CHECK_EQ(static_cast<unsigned int>(mxGetDimensions(bottom)[0]),
input_blobs.size());
for (unsigned int i = 0; i < input_blobs.size(); ++i) {
const mxArray* const elem = mxGetCell(bottom, i);
- const float* const data_ptr =
+ const float* const data_ptr =
reinterpret_cast<const float* const>(mxGetPr(elem));
switch (Caffe::mode()) {
case Caffe::CPU:
const vector<Blob<float>*>& output_blobs = net_->ForwardPrefilled();
mxArray* mx_out = mxCreateCellMatrix(output_blobs.size(), 1);
for (unsigned int i = 0; i < output_blobs.size(); ++i) {
- mxArray* mx_blob = mxCreateNumericMatrix(output_blobs[i]->count(),
+ mxArray* mx_blob = mxCreateNumericMatrix(output_blobs[i]->count(),
1, mxSINGLE_CLASS, mxREAL);
mxSetCell(mx_out, i, mx_blob);
float* data_ptr = reinterpret_cast<float*>(mxGetPr(mx_blob));
}
// The caffe::Caffe utility functions.
-static void set_mode_cpu(MEX_ARGS) {
- Caffe::set_mode(Caffe::CPU);
+static void set_mode_cpu(MEX_ARGS) {
+ Caffe::set_mode(Caffe::CPU);
}
-static void set_mode_gpu(MEX_ARGS) {
- Caffe::set_mode(Caffe::GPU);
+static void set_mode_gpu(MEX_ARGS) {
+ Caffe::set_mode(Caffe::GPU);
}
-static void set_phase_train(MEX_ARGS) {
- Caffe::set_phase(Caffe::TRAIN);
+static void set_phase_train(MEX_ARGS) {
+ Caffe::set_phase(Caffe::TRAIN);
}
-static void set_phase_test(MEX_ARGS) {
- Caffe::set_phase(Caffe::TEST);
+static void set_phase_test(MEX_ARGS) {
+ Caffe::set_phase(Caffe::TEST);
}
-static void set_device(MEX_ARGS) {
+static void set_device(MEX_ARGS) {
if (nrhs != 1) {
LOG(ERROR) << "Only given " << nrhs << " arguments";
mexErrMsgTxt("Wrong number of arguments");
}
int device_id = static_cast<int>(mxGetScalar(prhs[0]));
- Caffe::SetDevice(device_id);
+ Caffe::SetDevice(device_id);
}
static void init(MEX_ARGS) {
mxFree(cmd);
}
}
+
+} // namespace caffe
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
-#include <boost/python.hpp>
-#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
-#include <numpy/arrayobject.h>
+#include <string>
+#include <vector>
+
+#include "boost/python.hpp"
+#include "boost/python/suite/indexing/vector_indexing_suite.hpp"
+#include "numpy/arrayobject.h"
#include "caffe/caffe.hpp"
// Temporary solution for numpy < 1.7 versions: old macro, no promises.
#define PyArray_SetBaseObject(arr, x) (PyArray_BASE(arr) = (x))
#endif
-
-using namespace caffe;
using boost::python::extract;
using boost::python::len;
using boost::python::list;
using boost::python::handle;
using boost::python::vector_indexing_suite;
+namespace caffe {
// wrap shared_ptr<Blob<float> > in a class that we construct in C++ and pass
// to Python
class CaffeBlob {
public:
-
CaffeBlob(const shared_ptr<Blob<float> > &blob, const string& name)
: blob_(blob), name_(name) {}
- CaffeBlob(const shared_ptr<Blob<float> > &blob)
+ explicit CaffeBlob(const shared_ptr<Blob<float> > &blob)
: blob_(blob) {}
CaffeBlob()
int width() const { return blob_->width(); }
int count() const { return blob_->count(); }
- bool operator == (const CaffeBlob &other)
- {
+ bool operator == (const CaffeBlob &other) {
return this->blob_ == other.blob_;
}
// is not freed while still being used in Python
class CaffeBlobWrap : public CaffeBlob {
public:
- CaffeBlobWrap(PyObject *p, shared_ptr<Blob<float> > &blob)
+ CaffeBlobWrap(PyObject *p, const shared_ptr<Blob<float> > &blob)
: CaffeBlob(blob), self_(p) {}
CaffeBlobWrap(PyObject *p, const CaffeBlob &blob)
: CaffeBlob(blob), self_(p) {}
- object get_data()
- {
+ object get_data() {
npy_intp dims[] = {num(), channels(), height(), width()};
PyObject *obj = PyArray_SimpleNewFromData(4, dims, NPY_FLOAT32,
return object(h);
}
- object get_diff()
- {
+ object get_diff() {
npy_intp dims[] = {num(), channels(), height(), width()};
PyObject *obj = PyArray_SimpleNewFromData(4, dims, NPY_FLOAT32,
// A simple wrapper over CaffeNet that runs the forward process.
-struct CaffeNet
-{
+struct CaffeNet {
CaffeNet(string param_file, string pretrained_param_file) {
net_.reset(new Net<float>(param_file));
net_->CopyTrainedLayersFrom(pretrained_param_file);
// The actual forward function. It takes in a python list of numpy arrays as
// input and a python list of numpy arrays as output. The input and output
- // should all have correct shapes, are single-precisionabcdnt- and c contiguous.
+ // should all have correct shapes, are single-precisionabcdnt- and
+ // c contiguous.
void Forward(list bottom, list top) {
vector<Blob<float>*>& input_blobs = net_->input_blobs();
CHECK_EQ(len(bottom), input_blobs.size());
LOG(FATAL) << "Unknown Caffe mode.";
} // switch (Caffe::mode())
}
- //LOG(INFO) << "Start";
+ // LOG(INFO) << "Start";
const vector<Blob<float>*>& output_blobs = net_->ForwardPrefilled();
- //LOG(INFO) << "End";
+ // LOG(INFO) << "End";
for (int i = 0; i < output_blobs.size(); ++i) {
object elem = top[i];
PyArrayObject* arr = reinterpret_cast<PyArrayObject*>(elem.ptr());
LOG(FATAL) << "Unknown Caffe mode.";
} // switch (Caffe::mode())
}
- //LOG(INFO) << "Start";
+ // LOG(INFO) << "Start";
net_->Backward();
- //LOG(INFO) << "End";
+ // LOG(INFO) << "End";
for (int i = 0; i < input_blobs.size(); ++i) {
object elem = bottom_diff[i];
PyArrayObject* arr = reinterpret_cast<PyArrayObject*>(elem.ptr());
int ix = 0;
for (int i = 0; i < net_->layers().size(); ++i) {
for (int j = 0; j < net_->layers()[i]->blobs().size(); ++j) {
- result.push_back(CaffeBlob(net_->params()[ix], net_->layer_names()[i]));
+ result.push_back(
+ CaffeBlob(net_->params()[ix], net_->layer_names()[i]));
ix++;
}
}
// The boost python module definition.
-BOOST_PYTHON_MODULE(pycaffe)
-{
-
+BOOST_PYTHON_MODULE(pycaffe) {
boost::python::class_<CaffeNet>(
"CaffeNet", boost::python::init<string, string>())
.def("Forward", &CaffeNet::Forward)
.def("set_phase_test", &CaffeNet::set_phase_test)
.def("set_device", &CaffeNet::set_device)
.def("blobs", &CaffeNet::blobs)
- .def("params", &CaffeNet::params)
- ;
+ .def("params", &CaffeNet::params);
boost::python::class_<CaffeBlob, CaffeBlobWrap>(
"CaffeBlob", boost::python::no_init)
.add_property("width", &CaffeBlob::width)
.add_property("count", &CaffeBlob::count)
.add_property("data", &CaffeBlobWrap::get_data)
- .add_property("diff", &CaffeBlobWrap::get_diff)
- ;
+ .add_property("diff", &CaffeBlobWrap::get_diff);
boost::python::class_<vector<CaffeBlob> >("BlobVec")
.def(vector_indexing_suite<vector<CaffeBlob>, true>());
import_array();
-
}
+
+} // namespace caffe