From d3d7d07be981ab046da99e1ad5d84217bf0ec4c3 Mon Sep 17 00:00:00 2001 From: Ronghang Hu Date: Thu, 28 May 2015 16:24:30 +0800 Subject: [PATCH] Clean up old matcaffe wrapper and rename caffe.reset to caffe.reset_all Remove old matlab wrapper but keep the classification demo and hdf5 demo Change 'caffe.reset()' to 'caffe.reset_all()' to avoid potential name conflict. Otherwise, Matlab R2015a complains: Warning: Function reset has the same name as a MATLAB builtin. We suggest you rename the function to avoid a potential name conflict. --- Makefile | 25 +- docs/tutorial/interfaces.md | 8 +- .../imagenet}/ilsvrc_2012_mean.mat | Bin matlab/+caffe/reset.m | 8 - matlab/+caffe/reset_all.m | 8 + matlab/+caffe/run_tests.m | 4 +- matlab/CMakeLists.txt | 12 +- matlab/caffe/matcaffe.cpp | 421 ------------------ matlab/caffe/matcaffe_batch.m | 75 ---- matlab/caffe/matcaffe_demo_vgg.m | 96 ---- matlab/caffe/matcaffe_demo_vgg_mean_pix.m | 102 ----- matlab/caffe/matcaffe_init.m | 41 -- matlab/caffe/prepare_batch.m | 41 -- matlab/caffe/print_cell.m | 42 -- matlab/caffe/read_cell.m | 21 - .../matcaffe_demo.m => classification_demo.m} | 64 ++- matlab/{caffe => }/hdf5creation/.gitignore | 0 matlab/{caffe => }/hdf5creation/demo.m | 0 matlab/{caffe => }/hdf5creation/store2hdf5.m | 0 19 files changed, 63 insertions(+), 905 deletions(-) rename matlab/{caffe => +caffe/imagenet}/ilsvrc_2012_mean.mat (100%) delete mode 100644 matlab/+caffe/reset.m create mode 100644 matlab/+caffe/reset_all.m delete mode 100644 matlab/caffe/matcaffe.cpp delete mode 100644 matlab/caffe/matcaffe_batch.m delete mode 100644 matlab/caffe/matcaffe_demo_vgg.m delete mode 100644 matlab/caffe/matcaffe_demo_vgg_mean_pix.m delete mode 100644 matlab/caffe/matcaffe_init.m delete mode 100644 matlab/caffe/prepare_batch.m delete mode 100644 matlab/caffe/print_cell.m delete mode 100644 matlab/caffe/read_cell.m rename matlab/{caffe/matcaffe_demo.m => classification_demo.m} (56%) rename matlab/{caffe => }/hdf5creation/.gitignore (100%) rename matlab/{caffe => }/hdf5creation/demo.m (100%) rename matlab/{caffe => }/hdf5creation/store2hdf5.m (100%) diff --git a/Makefile b/Makefile index 74b167763c3..3748b52ca47 100644 --- a/Makefile +++ b/Makefile @@ -65,7 +65,6 @@ NONGEN_CXX_SRCS := $(shell find \ src/$(PROJECT) \ include/$(PROJECT) \ python/$(PROJECT) \ - matlab/$(PROJECT) \ matlab/+$(PROJECT)/private \ examples \ tools \ @@ -80,15 +79,12 @@ NONEMPTY_LINT_REPORT := $(BUILD_DIR)/$(LINT_EXT) PY$(PROJECT)_SRC := python/$(PROJECT)/_$(PROJECT).cpp PY$(PROJECT)_SO := python/$(PROJECT)/_$(PROJECT).so PY$(PROJECT)_HXX := include/$(PROJECT)/python_layer.hpp -# MAT$(PROJECT)_SRC is the matlab wrapper for $(PROJECT) -MAT$(PROJECT)_SRC := matlab/$(PROJECT)/mat$(PROJECT).cpp -# MAT$(PROJECT)_PKG_SRC is the mex entrance point of matlab package for $(PROJECT) -MAT$(PROJECT)_PKG_SRC := matlab/+$(PROJECT)/private/$(PROJECT)_.cpp +# MAT$(PROJECT)_SRC is the mex entrance point of matlab package for $(PROJECT) +MAT$(PROJECT)_SRC := matlab/+$(PROJECT)/private/$(PROJECT)_.cpp ifneq ($(MATLAB_DIR),) MAT_SO_EXT := $(shell $(MATLAB_DIR)/bin/mexext) endif -MAT$(PROJECT)_SO := matlab/$(PROJECT)/$(PROJECT).$(MAT_SO_EXT) -MAT$(PROJECT)_PKG_SO := matlab/+$(PROJECT)/private/$(PROJECT)_.$(MAT_SO_EXT) +MAT$(PROJECT)_SO := matlab/+$(PROJECT)/private/$(PROJECT)_.$(MAT_SO_EXT) ############################## # Derive generated files @@ -451,7 +447,7 @@ $(PY$(PROJECT)_SO): $(PY$(PROJECT)_SRC) $(PY$(PROJECT)_HXX) | $(DYNAMIC_NAME) mat$(PROJECT): mat -mat: $(MAT$(PROJECT)_SO) $(MAT$(PROJECT)_PKG_SO) +mat: $(MAT$(PROJECT)_SO) $(MAT$(PROJECT)_SO): $(MAT$(PROJECT)_SRC) $(STATIC_NAME) @ if [ -z "$(MATLAB_DIR)" ]; then \ @@ -464,18 +460,6 @@ $(MAT$(PROJECT)_SO): $(MAT$(PROJECT)_SRC) $(STATIC_NAME) CXX="$(CXX)" \ CXXFLAGS="\$$CXXFLAGS $(MATLAB_CXXFLAGS)" \ CXXLIBS="\$$CXXLIBS $(STATIC_LINK_COMMAND) $(LDFLAGS)" -output $@ - -$(MAT$(PROJECT)_PKG_SO): $(MAT$(PROJECT)_PKG_SRC) $(STATIC_NAME) - @ if [ -z "$(MATLAB_DIR)" ]; then \ - echo "MATLAB_DIR must be specified in $(CONFIG_FILE)" \ - "to build mat$(PROJECT)."; \ - exit 1; \ - fi - @ echo MEX $< - $(Q)$(MATLAB_DIR)/bin/mex $(MAT$(PROJECT)_PKG_SRC) \ - CXX="$(CXX)" \ - CXXFLAGS="\$$CXXFLAGS $(MATLAB_CXXFLAGS)" \ - CXXLIBS="\$$CXXLIBS $(STATIC_LINK_COMMAND) $(LDFLAGS)" -output $@ runtest: $(TEST_ALL_BIN) $(TOOL_BUILD_DIR)/caffe @@ -601,7 +585,6 @@ clean: @- $(RM) -rf $(DISTRIBUTE_DIR) @- $(RM) $(PY$(PROJECT)_SO) @- $(RM) $(MAT$(PROJECT)_SO) - @- $(RM) $(MAT$(PROJECT)_PKG_SO) supercleanfiles: $(eval SUPERCLEAN_FILES := $(strip \ diff --git a/docs/tutorial/interfaces.md b/docs/tutorial/interfaces.md index f824c7cc54b..a57e17339b0 100644 --- a/docs/tutorial/interfaces.md +++ b/docs/tutorial/interfaces.md @@ -67,7 +67,7 @@ Compile pycaffe by `make pycaffe`. The module dir caffe/python/caffe should be i ## MATLAB -The MATLAB interface -- matcaffe -- is a `caffe` package in caffe/matlab in which you can integrate Caffe in your Matlab code. +The MATLAB interface -- matcaffe -- is the `caffe` package in caffe/matlab in which you can integrate Caffe in your Matlab code. In MatCaffe, you can @@ -84,7 +84,7 @@ In MatCaffe, you can * Run for a certain number of iterations and give back control to Matlab * Intermingle arbitrary Matlab code to with gradient steps -A MATLAB demo is in caffe/matlab/matcaffe_demo.m +An ILSVRC image classification demo is in caffe/matlab/classification_demo.m ### Build MatCaffe @@ -181,7 +181,7 @@ To get a layer's type (string): #### Forward and backward -Forward pass can be done using `net.forward` or `net.forward_prefilled`. After creating some data for input blobs like `data = rand(net.blobs('data').shape);` you can run +Forward pass can be done using `net.forward` or `net.forward_prefilled`. Function `net.forward` takes in a cell array of N-D arrays containing data of input blob(s) and outputs a cell array containing data from output blob(s). Function `net.forward_prefilled` uses existing data in input blob(s) during forward pass, takes no input and produces no output. After creating some data for input blobs like `data = rand(net.blobs('data').shape);` you can run res = net.forward({data}); prob = res{1}; @@ -274,4 +274,4 @@ We do not provide extra functions for data output as Matlab itself is already qu #### Clear nets and solvers -Call `caffe.reset()` to clear all solvers and stand-alone nets you have created. +Call `caffe.reset_all()` to clear all solvers and stand-alone nets you have created. diff --git a/matlab/caffe/ilsvrc_2012_mean.mat b/matlab/+caffe/imagenet/ilsvrc_2012_mean.mat similarity index 100% rename from matlab/caffe/ilsvrc_2012_mean.mat rename to matlab/+caffe/imagenet/ilsvrc_2012_mean.mat diff --git a/matlab/+caffe/reset.m b/matlab/+caffe/reset.m deleted file mode 100644 index c1cfea41a76..00000000000 --- a/matlab/+caffe/reset.m +++ /dev/null @@ -1,8 +0,0 @@ -function reset() -% reset() -% reset Caffe to initial status - -caffe_('reset'); -is_valid_handle('get_new_init_key'); - -end diff --git a/matlab/+caffe/reset_all.m b/matlab/+caffe/reset_all.m new file mode 100644 index 00000000000..a8b33dee8d5 --- /dev/null +++ b/matlab/+caffe/reset_all.m @@ -0,0 +1,8 @@ +function reset_all() +% reset_all() +% clear all solvers and stand-alone nets and reset Caffe to initial status + +caffe_('reset'); +is_valid_handle('get_new_init_key'); + +end diff --git a/matlab/+caffe/run_tests.m b/matlab/+caffe/run_tests.m index afdd8f3309d..8773c9f638b 100644 --- a/matlab/+caffe/run_tests.m +++ b/matlab/+caffe/run_tests.m @@ -3,7 +3,7 @@ % run all tests in this caffe matlab wrapper package % reset caffe before testing -caffe.reset(); +caffe.reset_all(); % put all test cases here results = [... @@ -11,6 +11,6 @@ run(caffe.test.test_solver) ]; % reset caffe after testing -caffe.reset(); +caffe.reset_all(); end diff --git a/matlab/CMakeLists.txt b/matlab/CMakeLists.txt index 63182abcc44..4b0d549f07f 100644 --- a/matlab/CMakeLists.txt +++ b/matlab/CMakeLists.txt @@ -31,10 +31,8 @@ function(caffe_fetch_and_set_proper_mexext mexfile_variable) endfunction() # global settings -file(GLOB Matlab_srcs caffe/matcaffe.cpp) -file(GLOB Matlab_pkg_srcs +caffe/private/caffe_.cpp) -set(Matlab_caffe_mex ${PROJECT_SOURCE_DIR}/matlab/caffe/caffe.mex) -set(Matlab_caffe_pkg_mex ${PROJECT_SOURCE_DIR}/matlab/+caffe/private/caffe_.mex) +file(GLOB Matlab_srcs +caffe/private/caffe_.cpp) +set(Matlab_caffe_mex ${PROJECT_SOURCE_DIR}/matlab/+caffe/private/caffe_.mex) caffe_get_current_cflags(cflags) caffe_parse_linker_libs(Caffe_LINKER_LIBS folders libflags macos_frameworks) @@ -52,15 +50,9 @@ if(build_using MATCHES "Matlab") ARGS -output ${Matlab_caffe_mex} ${Matlab_srcs} ${cflags} ${link_folders} ${libflags} DEPENDS caffe COMMENT "Building Matlab interface: ${Matlab_caffe_mex}" VERBATIM) add_custom_target(matlab ALL DEPENDS ${Matlab_caffe_mex} SOURCES ${Matlab_srcs}) - caffe_fetch_and_set_proper_mexext(Matlab_caffe_pkg_mex) - add_custom_command(OUTPUT ${Matlab_caffe_pkg_mex} COMMAND ${Matlab_mex} - ARGS -output ${Matlab_caffe_pkg_mex} ${Matlab_pkg_srcs} ${cflags} ${link_folders} ${libflags} - DEPENDS caffe COMMENT "Building Matlab interface: ${Matlab_caffe_pkg_mex}" VERBATIM) - add_custom_target(matlab ALL DEPENDS ${Matlab_caffe_pkg_mex} SOURCES ${Matlab_pkg_srcs}) elseif(build_using MATCHES "Octave") - # Note: Matlab Caffe package cannot be used in Octave, so we don't build it if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") set(libflags -Wl,-force_load,$ ${libflags}) elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") diff --git a/matlab/caffe/matcaffe.cpp b/matlab/caffe/matcaffe.cpp deleted file mode 100644 index da37d920b20..00000000000 --- a/matlab/caffe/matcaffe.cpp +++ /dev/null @@ -1,421 +0,0 @@ -// -// matcaffe.cpp provides a wrapper of the caffe::Net class as well as some -// 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 -#include -#include - -#include "mex.h" - -#include "caffe/caffe.hpp" - -#define MEX_ARGS int nlhs, mxArray **plhs, int nrhs, const mxArray **prhs - -// Log and throw a Mex error -inline void mex_error(const std::string &msg) { - LOG(ERROR) << msg; - mexErrMsgTxt(msg.c_str()); -} - -using namespace caffe; // NOLINT(build/namespaces) - -// The pointer to the internal caffe::Net instance -static shared_ptr > net_; -static int init_key = -2; - -// Five things to be aware of: -// caffe uses row-major order -// matlab uses column-major order -// caffe uses BGR color channel order -// 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 -// [width, height, channels, images] -// where width is the fastest dimension. -// Here is the rough matlab for putting image data into the correct -// format: -// % convert from uint8 to single -// im = single(im); -// % reshape to a fixed size (e.g., 227x227) -// im = imresize(im, [IMAGE_DIM IMAGE_DIM], 'bilinear'); -// % permute from RGB to BGR and subtract the data mean (already in BGR) -// im = im(:,:,[3 2 1]) - data_mean; -// % flip width and height to make width the fastest dimension -// im = permute(im, [2 1 3]); -// -// 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. - -static mxArray* do_forward(const mxArray* const bottom) { - const vector*>& input_blobs = net_->input_blobs(); - if (static_cast(mxGetDimensions(bottom)[0]) != - input_blobs.size()) { - mex_error("Invalid input size"); - } - for (unsigned int i = 0; i < input_blobs.size(); ++i) { - const mxArray* const elem = mxGetCell(bottom, i); - if (!mxIsSingle(elem)) { - mex_error("MatCaffe require single-precision float point data"); - } - if (mxGetNumberOfElements(elem) != input_blobs[i]->count()) { - std::string error_msg; - error_msg += "MatCaffe input size does not match the input size "; - error_msg += "of the network"; - mex_error(error_msg); - } - - const float* const data_ptr = - reinterpret_cast(mxGetPr(elem)); - switch (Caffe::mode()) { - case Caffe::CPU: - caffe_copy(input_blobs[i]->count(), data_ptr, - input_blobs[i]->mutable_cpu_data()); - break; - case Caffe::GPU: - caffe_copy(input_blobs[i]->count(), data_ptr, - input_blobs[i]->mutable_gpu_data()); - break; - default: - mex_error("Unknown Caffe mode"); - } // switch (Caffe::mode()) - } - const vector*>& output_blobs = net_->ForwardPrefilled(); - mxArray* mx_out = mxCreateCellMatrix(output_blobs.size(), 1); - for (unsigned int i = 0; i < output_blobs.size(); ++i) { - // internally data is stored as (width, height, channels, num) - // where width is the fastest dimension - mwSize dims[4] = {output_blobs[i]->width(), output_blobs[i]->height(), - output_blobs[i]->channels(), output_blobs[i]->num()}; - mxArray* mx_blob = mxCreateNumericArray(4, dims, mxSINGLE_CLASS, mxREAL); - mxSetCell(mx_out, i, mx_blob); - float* data_ptr = reinterpret_cast(mxGetPr(mx_blob)); - switch (Caffe::mode()) { - case Caffe::CPU: - caffe_copy(output_blobs[i]->count(), output_blobs[i]->cpu_data(), - data_ptr); - break; - case Caffe::GPU: - caffe_copy(output_blobs[i]->count(), output_blobs[i]->gpu_data(), - data_ptr); - break; - default: - mex_error("Unknown Caffe mode"); - } // switch (Caffe::mode()) - } - - return mx_out; -} - -static mxArray* do_backward(const mxArray* const top_diff) { - const vector*>& output_blobs = net_->output_blobs(); - const vector*>& input_blobs = net_->input_blobs(); - if (static_cast(mxGetDimensions(top_diff)[0]) != - output_blobs.size()) { - mex_error("Invalid input size"); - } - // First, copy the output diff - for (unsigned int i = 0; i < output_blobs.size(); ++i) { - const mxArray* const elem = mxGetCell(top_diff, i); - const float* const data_ptr = - reinterpret_cast(mxGetPr(elem)); - switch (Caffe::mode()) { - case Caffe::CPU: - caffe_copy(output_blobs[i]->count(), data_ptr, - output_blobs[i]->mutable_cpu_diff()); - break; - case Caffe::GPU: - caffe_copy(output_blobs[i]->count(), data_ptr, - output_blobs[i]->mutable_gpu_diff()); - break; - default: - mex_error("Unknown Caffe mode"); - } // switch (Caffe::mode()) - } - // LOG(INFO) << "Start"; - net_->Backward(); - // LOG(INFO) << "End"; - mxArray* mx_out = mxCreateCellMatrix(input_blobs.size(), 1); - for (unsigned int i = 0; i < input_blobs.size(); ++i) { - // internally data is stored as (width, height, channels, num) - // where width is the fastest dimension - mwSize dims[4] = {input_blobs[i]->width(), input_blobs[i]->height(), - input_blobs[i]->channels(), input_blobs[i]->num()}; - mxArray* mx_blob = mxCreateNumericArray(4, dims, mxSINGLE_CLASS, mxREAL); - mxSetCell(mx_out, i, mx_blob); - float* data_ptr = reinterpret_cast(mxGetPr(mx_blob)); - switch (Caffe::mode()) { - case Caffe::CPU: - caffe_copy(input_blobs[i]->count(), input_blobs[i]->cpu_diff(), data_ptr); - break; - case Caffe::GPU: - caffe_copy(input_blobs[i]->count(), input_blobs[i]->gpu_diff(), data_ptr); - break; - default: - mex_error("Unknown Caffe mode"); - } // switch (Caffe::mode()) - } - - return mx_out; -} - -static mxArray* do_get_weights() { - const vector > >& layers = net_->layers(); - const vector& layer_names = net_->layer_names(); - - // Step 1: count the number of layers with weights - int num_layers = 0; - { - string prev_layer_name = ""; - for (unsigned int i = 0; i < layers.size(); ++i) { - vector > >& layer_blobs = layers[i]->blobs(); - if (layer_blobs.size() == 0) { - continue; - } - if (layer_names[i] != prev_layer_name) { - prev_layer_name = layer_names[i]; - num_layers++; - } - } - } - - // Step 2: prepare output array of structures - mxArray* mx_layers; - { - const mwSize dims[2] = {num_layers, 1}; - const char* fnames[2] = {"weights", "layer_names"}; - mx_layers = mxCreateStructArray(2, dims, 2, fnames); - } - - // Step 3: copy weights into output - { - string prev_layer_name = ""; - int mx_layer_index = 0; - for (unsigned int i = 0; i < layers.size(); ++i) { - vector > >& layer_blobs = layers[i]->blobs(); - if (layer_blobs.size() == 0) { - continue; - } - - mxArray* mx_layer_cells = NULL; - if (layer_names[i] != prev_layer_name) { - prev_layer_name = layer_names[i]; - const mwSize dims[2] = {static_cast(layer_blobs.size()), 1}; - mx_layer_cells = mxCreateCellArray(2, dims); - mxSetField(mx_layers, mx_layer_index, "weights", mx_layer_cells); - mxSetField(mx_layers, mx_layer_index, "layer_names", - mxCreateString(layer_names[i].c_str())); - mx_layer_index++; - } - - for (unsigned int j = 0; j < layer_blobs.size(); ++j) { - // internally data is stored as (width, height, channels, num) - // where width is the fastest dimension - mwSize dims[4] = {layer_blobs[j]->width(), layer_blobs[j]->height(), - layer_blobs[j]->channels(), layer_blobs[j]->num()}; - - mxArray* mx_weights = - mxCreateNumericArray(4, dims, mxSINGLE_CLASS, mxREAL); - mxSetCell(mx_layer_cells, j, mx_weights); - float* weights_ptr = reinterpret_cast(mxGetPr(mx_weights)); - - switch (Caffe::mode()) { - case Caffe::CPU: - caffe_copy(layer_blobs[j]->count(), layer_blobs[j]->cpu_data(), - weights_ptr); - break; - case Caffe::GPU: - caffe_copy(layer_blobs[j]->count(), layer_blobs[j]->gpu_data(), - weights_ptr); - break; - default: - mex_error("Unknown Caffe mode"); - } - } - } - } - - return mx_layers; -} - -static void get_weights(MEX_ARGS) { - plhs[0] = do_get_weights(); -} - -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_device(MEX_ARGS) { - if (nrhs != 1) { - ostringstream error_msg; - error_msg << "Expected 1 argument, got " << nrhs; - mex_error(error_msg.str()); - } - - int device_id = static_cast(mxGetScalar(prhs[0])); - Caffe::SetDevice(device_id); -} - -static void get_init_key(MEX_ARGS) { - plhs[0] = mxCreateDoubleScalar(init_key); -} - -static void init(MEX_ARGS) { - if (nrhs != 3) { - ostringstream error_msg; - error_msg << "Expected 3 arguments, got " << nrhs; - mex_error(error_msg.str()); - } - - char* param_file = mxArrayToString(prhs[0]); - char* model_file = mxArrayToString(prhs[1]); - char* phase_name = mxArrayToString(prhs[2]); - - Phase phase; - if (strcmp(phase_name, "train") == 0) { - phase = TRAIN; - } else if (strcmp(phase_name, "test") == 0) { - phase = TEST; - } else { - mex_error("Unknown phase."); - } - - net_.reset(new Net(string(param_file), phase)); - net_->CopyTrainedLayersFrom(string(model_file)); - - mxFree(param_file); - mxFree(model_file); - mxFree(phase_name); - - init_key = random(); // NOLINT(caffe/random_fn) - - if (nlhs == 1) { - plhs[0] = mxCreateDoubleScalar(init_key); - } -} - -static void reset(MEX_ARGS) { - if (net_) { - net_.reset(); - init_key = -2; - LOG(INFO) << "Network reset, call init before use it again"; - } -} - -static void forward(MEX_ARGS) { - if (nrhs != 1) { - ostringstream error_msg; - error_msg << "Expected 1 argument, got " << nrhs; - mex_error(error_msg.str()); - } - - plhs[0] = do_forward(prhs[0]); -} - -static void backward(MEX_ARGS) { - if (nrhs != 1) { - ostringstream error_msg; - error_msg << "Expected 1 argument, got " << nrhs; - mex_error(error_msg.str()); - } - - plhs[0] = do_backward(prhs[0]); -} - -static void is_initialized(MEX_ARGS) { - if (!net_) { - plhs[0] = mxCreateDoubleScalar(0); - } else { - plhs[0] = mxCreateDoubleScalar(1); - } -} - -static void read_mean(MEX_ARGS) { - if (nrhs != 1) { - mexErrMsgTxt("Usage: caffe('read_mean', 'path_to_binary_mean_file'"); - return; - } - const string& mean_file = mxArrayToString(prhs[0]); - Blob data_mean; - LOG(INFO) << "Loading mean file from: " << mean_file; - BlobProto blob_proto; - bool result = ReadProtoFromBinaryFile(mean_file.c_str(), &blob_proto); - if (!result) { - mexErrMsgTxt("Couldn't read the file"); - return; - } - data_mean.FromProto(blob_proto); - mwSize dims[4] = {data_mean.width(), data_mean.height(), - data_mean.channels(), data_mean.num() }; - mxArray* mx_blob = mxCreateNumericArray(4, dims, mxSINGLE_CLASS, mxREAL); - float* data_ptr = reinterpret_cast(mxGetPr(mx_blob)); - caffe_copy(data_mean.count(), data_mean.cpu_data(), data_ptr); - mexWarnMsgTxt("Remember that Caffe saves in [width, height, channels]" - " format and channels are also BGR!"); - plhs[0] = mx_blob; -} - -/** ----------------------------------------------------------------- - ** Available commands. - **/ -struct handler_registry { - string cmd; - void (*func)(MEX_ARGS); -}; - -static handler_registry handlers[] = { - // Public API functions - { "forward", forward }, - { "backward", backward }, - { "init", init }, - { "is_initialized", is_initialized }, - { "set_mode_cpu", set_mode_cpu }, - { "set_mode_gpu", set_mode_gpu }, - { "set_device", set_device }, - { "get_weights", get_weights }, - { "get_init_key", get_init_key }, - { "reset", reset }, - { "read_mean", read_mean }, - // The end. - { "END", NULL }, -}; - - -/** ----------------------------------------------------------------- - ** matlab entry point: caffe(api_command, arg1, arg2, ...) - **/ -void mexFunction(MEX_ARGS) { - mexLock(); // Avoid clearing the mex file. - if (nrhs == 0) { - mex_error("No API command given"); - return; - } - - { // Handle input command - char *cmd = mxArrayToString(prhs[0]); - bool dispatched = false; - // Dispatch to cmd handler - for (int i = 0; handlers[i].func != NULL; i++) { - if (handlers[i].cmd.compare(cmd) == 0) { - handlers[i].func(nlhs, plhs, nrhs-1, prhs+1); - dispatched = true; - break; - } - } - if (!dispatched) { - ostringstream error_msg; - error_msg << "Unknown command '" << cmd << "'"; - mex_error(error_msg.str()); - } - mxFree(cmd); - } -} diff --git a/matlab/caffe/matcaffe_batch.m b/matlab/caffe/matcaffe_batch.m deleted file mode 100644 index f6d1aa83b84..00000000000 --- a/matlab/caffe/matcaffe_batch.m +++ /dev/null @@ -1,75 +0,0 @@ -function [scores,list_im] = matcaffe_batch(list_im, use_gpu) -% scores = matcaffe_batch(list_im, use_gpu) -% -% Demo of the matlab wrapper using the ILSVRC network. -% -% input -% list_im list of images files -% use_gpu 1 to use the GPU, 0 to use the CPU -% -% output -% scores 1000 x num_images ILSVRC output vector -% -% You may need to do the following before you start matlab: -% $ export LD_LIBRARY_PATH=/opt/intel/mkl/lib/intel64:/usr/local/cuda/lib64 -% $ export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libstdc++.so.6 -% Or the equivalent based on where things are installed on your system -% -% Usage: -% scores = matcaffe_batch({'peppers.png','onion.png'}); -% scores = matcaffe_batch('list_images.txt', 1); -if nargin < 1 - % For test purposes - list_im = {'peppers.png','onions.png'}; -end -if ischar(list_im) - %Assume it is a file contaning the list of images - filename = list_im; - list_im = read_cell(filename); -end -% Adjust the batch size and dim to match with models/bvlc_reference_caffenet/deploy.prototxt -batch_size = 10; -dim = 1000; -disp(list_im) -if mod(length(list_im),batch_size) - warning(['Assuming batches of ' num2str(batch_size) ' images rest will be filled with zeros']) -end - -% init caffe network (spews logging info) -if exist('use_gpu', 'var') - matcaffe_init(use_gpu); -else - matcaffe_init(); -end - -d = load('ilsvrc_2012_mean'); -IMAGE_MEAN = d.image_mean; - -% prepare input - -num_images = length(list_im); -scores = zeros(dim,num_images,'single'); -num_batches = ceil(length(list_im)/batch_size) -initic=tic; -for bb = 1 : num_batches - batchtic = tic; - range = 1+batch_size*(bb-1):min(num_images,batch_size * bb); - tic - input_data = prepare_batch(list_im(range),IMAGE_MEAN,batch_size); - toc, tic - fprintf('Batch %d out of %d %.2f%% Complete ETA %.2f seconds\n',... - bb,num_batches,bb/num_batches*100,toc(initic)/bb*(num_batches-bb)); - output_data = caffe('forward', {input_data}); - toc - output_data = squeeze(output_data{1}); - scores(:,range) = output_data(:,mod(range-1,batch_size)+1); - toc(batchtic) -end -toc(initic); - -if exist('filename', 'var') - save([filename '.probs.mat'],'list_im','scores','-v7.3'); -end - - - diff --git a/matlab/caffe/matcaffe_demo_vgg.m b/matlab/caffe/matcaffe_demo_vgg.m deleted file mode 100644 index 4e5a98eb5f4..00000000000 --- a/matlab/caffe/matcaffe_demo_vgg.m +++ /dev/null @@ -1,96 +0,0 @@ -function scores = matcaffe_demo_vgg(im, use_gpu, model_def_file, model_file, mean_file) -% scores = matcaffe_demo_vgg(im, use_gpu, model_def_file, model_file, mean_file) -% -% Demo of the matlab wrapper using the networks described in the BMVC-2014 paper "Return of the Devil in the Details: Delving Deep into Convolutional Nets" -% -% INPUT -% im - color image as uint8 HxWx3 -% use_gpu - 1 to use the GPU, 0 to use the CPU -% model_def_file - network configuration (.prototxt file) -% model_file - network weights (.caffemodel file) -% mean_file - mean BGR image as uint8 HxWx3 (.mat file) -% -% OUTPUT -% scores 1000-dimensional ILSVRC score vector -% -% EXAMPLE USAGE -% model_def_file = 'zoo/VGG_CNN_F_deploy.prototxt'; -% model_file = 'zoo/VGG_CNN_F.caffemodel'; -% mean_file = 'zoo/VGG_mean.mat'; -% use_gpu = true; -% im = imread('../../examples/images/cat.jpg'); -% scores = matcaffe_demo_vgg(im, use_gpu, model_def_file, model_file, mean_file); -% -% NOTES -% the image crops are prepared as described in the paper (the aspect ratio is preserved) -% -% PREREQUISITES -% You may need to do the following before you start matlab: -% $ export LD_LIBRARY_PATH=/opt/intel/mkl/lib/intel64:/usr/local/cuda/lib64 -% $ export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libstdc++.so.6 -% Or the equivalent based on where things are installed on your system - -% init caffe network (spews logging info) -matcaffe_init(use_gpu, model_def_file, model_file); - -% prepare oversampled input -% input_data is Height x Width x Channel x Num -tic; -input_data = {prepare_image(im, mean_file)}; -toc; - -% do forward pass to get scores -% scores are now Width x Height x Channels x Num -tic; -scores = caffe('forward', input_data); -toc; - -scores = scores{1}; -% size(scores) -scores = squeeze(scores); -% scores = mean(scores,2); - -% [~,maxlabel] = max(scores); - -% ------------------------------------------------------------------------ -function images = prepare_image(im, mean_file) -% ------------------------------------------------------------------------ -IMAGE_DIM = 256; -CROPPED_DIM = 224; - -d = load(mean_file); -IMAGE_MEAN = d.image_mean; - -% resize to fixed input size -im = single(im); - -if size(im, 1) < size(im, 2) - im = imresize(im, [IMAGE_DIM NaN]); -else - im = imresize(im, [NaN IMAGE_DIM]); -end - -% RGB -> BGR -im = im(:, :, [3 2 1]); - -% oversample (4 corners, center, and their x-axis flips) -images = zeros(CROPPED_DIM, CROPPED_DIM, 3, 10, 'single'); - -indices_y = [0 size(im,1)-CROPPED_DIM] + 1; -indices_x = [0 size(im,2)-CROPPED_DIM] + 1; -center_y = floor(indices_y(2) / 2)+1; -center_x = floor(indices_x(2) / 2)+1; - -curr = 1; -for i = indices_y - for j = indices_x - images(:, :, :, curr) = ... - permute(im(i:i+CROPPED_DIM-1, j:j+CROPPED_DIM-1, :)-IMAGE_MEAN, [2 1 3]); - images(:, :, :, curr+5) = images(end:-1:1, :, :, curr); - curr = curr + 1; - end -end -images(:,:,:,5) = ... - permute(im(center_y:center_y+CROPPED_DIM-1,center_x:center_x+CROPPED_DIM-1,:)-IMAGE_MEAN, ... - [2 1 3]); -images(:,:,:,10) = images(end:-1:1, :, :, curr); diff --git a/matlab/caffe/matcaffe_demo_vgg_mean_pix.m b/matlab/caffe/matcaffe_demo_vgg_mean_pix.m deleted file mode 100644 index 5f7898a7029..00000000000 --- a/matlab/caffe/matcaffe_demo_vgg_mean_pix.m +++ /dev/null @@ -1,102 +0,0 @@ -function scores = matcaffe_demo_vgg_mean_pix(im, use_gpu, model_def_file, model_file) -% scores = matcaffe_demo_vgg(im, use_gpu, model_def_file, model_file) -% -% Demo of the matlab wrapper based on the networks used for the "VGG" entry -% in the ILSVRC-2014 competition and described in the tech. report -% "Very Deep Convolutional Networks for Large-Scale Image Recognition" -% http://arxiv.org/abs/1409.1556/ -% -% INPUT -% im - color image as uint8 HxWx3 -% use_gpu - 1 to use the GPU, 0 to use the CPU -% model_def_file - network configuration (.prototxt file) -% model_file - network weights (.caffemodel file) -% -% OUTPUT -% scores 1000-dimensional ILSVRC score vector -% -% EXAMPLE USAGE -% model_def_file = 'zoo/deploy.prototxt'; -% model_file = 'zoo/model.caffemodel'; -% use_gpu = true; -% im = imread('../../examples/images/cat.jpg'); -% scores = matcaffe_demo_vgg(im, use_gpu, model_def_file, model_file); -% -% NOTES -% mean pixel subtraction is used instead of the mean image subtraction -% -% PREREQUISITES -% You may need to do the following before you start matlab: -% $ export LD_LIBRARY_PATH=/opt/intel/mkl/lib/intel64:/usr/local/cuda/lib64 -% $ export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libstdc++.so.6 -% Or the equivalent based on where things are installed on your system - -% init caffe network (spews logging info) -matcaffe_init(use_gpu, model_def_file, model_file); - -% mean BGR pixel -mean_pix = [103.939, 116.779, 123.68]; - -% prepare oversampled input -% input_data is Height x Width x Channel x Num -tic; -input_data = {prepare_image(im, mean_pix)}; -toc; - -% do forward pass to get scores -% scores are now Width x Height x Channels x Num -tic; -scores = caffe('forward', input_data); -toc; - -scores = scores{1}; -% size(scores) -scores = squeeze(scores); -% scores = mean(scores,2); - -% [~,maxlabel] = max(scores); - -% ------------------------------------------------------------------------ -function images = prepare_image(im, mean_pix) -% ------------------------------------------------------------------------ -IMAGE_DIM = 256; -CROPPED_DIM = 224; - -% resize to fixed input size -im = single(im); - -if size(im, 1) < size(im, 2) - im = imresize(im, [IMAGE_DIM NaN]); -else - im = imresize(im, [NaN IMAGE_DIM]); -end - -% RGB -> BGR -im = im(:, :, [3 2 1]); - -% oversample (4 corners, center, and their x-axis flips) -images = zeros(CROPPED_DIM, CROPPED_DIM, 3, 10, 'single'); - -indices_y = [0 size(im,1)-CROPPED_DIM] + 1; -indices_x = [0 size(im,2)-CROPPED_DIM] + 1; -center_y = floor(indices_y(2) / 2)+1; -center_x = floor(indices_x(2) / 2)+1; - -curr = 1; -for i = indices_y - for j = indices_x - images(:, :, :, curr) = ... - permute(im(i:i+CROPPED_DIM-1, j:j+CROPPED_DIM-1, :), [2 1 3]); - images(:, :, :, curr+5) = images(end:-1:1, :, :, curr); - curr = curr + 1; - end -end -images(:,:,:,5) = ... - permute(im(center_y:center_y+CROPPED_DIM-1,center_x:center_x+CROPPED_DIM-1,:), ... - [2 1 3]); -images(:,:,:,10) = images(end:-1:1, :, :, curr); - -% mean BGR pixel subtraction -for c = 1:3 - images(:, :, c, :) = images(:, :, c, :) - mean_pix(c); -end diff --git a/matlab/caffe/matcaffe_init.m b/matlab/caffe/matcaffe_init.m deleted file mode 100644 index 5d0a0a70bde..00000000000 --- a/matlab/caffe/matcaffe_init.m +++ /dev/null @@ -1,41 +0,0 @@ -function matcaffe_init(use_gpu, model_def_file, model_file) -% matcaffe_init(model_def_file, model_file, use_gpu) -% Initilize matcaffe wrapper - -if nargin < 1 - % By default use CPU - use_gpu = 0; -end -if nargin < 2 || isempty(model_def_file) - % By default use imagenet_deploy - model_def_file = '../../models/bvlc_reference_caffenet/deploy.prototxt'; -end -if nargin < 3 || isempty(model_file) - % By default use caffe reference model - model_file = '../../models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel'; -end - - -if caffe('is_initialized') == 0 - if exist(model_file, 'file') == 0 - % NOTE: you'll have to get the pre-trained ILSVRC network - error('You need a network model file'); - end - if ~exist(model_def_file,'file') - % NOTE: you'll have to get network definition - error('You need the network prototxt definition'); - end - % load network in TEST phase - caffe('init', model_def_file, model_file, 'test') -end -fprintf('Done with init\n'); - -% set to use GPU or CPU -if use_gpu - fprintf('Using GPU Mode\n'); - caffe('set_mode_gpu'); -else - fprintf('Using CPU Mode\n'); - caffe('set_mode_cpu'); -end -fprintf('Done with set_mode\n'); diff --git a/matlab/caffe/prepare_batch.m b/matlab/caffe/prepare_batch.m deleted file mode 100644 index 345c8eb5f0b..00000000000 --- a/matlab/caffe/prepare_batch.m +++ /dev/null @@ -1,41 +0,0 @@ -% ------------------------------------------------------------------------ -function images = prepare_batch(image_files,IMAGE_MEAN,batch_size) -% ------------------------------------------------------------------------ -if nargin < 2 - d = load('ilsvrc_2012_mean'); - IMAGE_MEAN = d.image_mean; -end -num_images = length(image_files); -if nargin < 3 - batch_size = num_images; -end - -IMAGE_DIM = 256; -CROPPED_DIM = 227; -indices = [0 IMAGE_DIM-CROPPED_DIM] + 1; -center = floor(indices(2) / 2)+1; - -num_images = length(image_files); -images = zeros(CROPPED_DIM,CROPPED_DIM,3,batch_size,'single'); - -parfor i=1:num_images - % read file - fprintf('%c Preparing %s\n',13,image_files{i}); - try - im = imread(image_files{i}); - % resize to fixed input size - im = single(im); - im = imresize(im, [IMAGE_DIM IMAGE_DIM], 'bilinear'); - % Transform GRAY to RGB - if size(im,3) == 1 - im = cat(3,im,im,im); - end - % permute from RGB to BGR (IMAGE_MEAN is already BGR) - im = im(:,:,[3 2 1]) - IMAGE_MEAN; - % Crop the center of the image - images(:,:,:,i) = permute(im(center:center+CROPPED_DIM-1,... - center:center+CROPPED_DIM-1,:),[2 1 3]); - catch - warning('Problems with file',image_files{i}); - end -end \ No newline at end of file diff --git a/matlab/caffe/print_cell.m b/matlab/caffe/print_cell.m deleted file mode 100644 index 864340d4be9..00000000000 --- a/matlab/caffe/print_cell.m +++ /dev/null @@ -1,42 +0,0 @@ -function res=print_cell(input,file,linesep,cellsep) -assert(iscell(input),'The input should be a cell') -if nargin < 4 - cellsep = '\t'; -end -if nargin < 3 - linesep = '\n'; -end -if exist('file','var') && ~isempty(file) - %% - fid = fopen(file,'w'); - for l=1:length(input) - if iscell(input{l}) - for i=1:length(input{l}) - fprintf(fid,['%s' cellsep],input{l}{i}); - end - fprintf(fid,linesep); - else - if size(input,2) > 1 - for i=1:size(input,2) - fprintf(fid,'%s ',input{l,i}); - end - fprintf(fid,linesep); - else - fprintf(fid,['%s' linesep],input{l}); - end - end - end - fclose(fid); -else - res = ''; - for l=1:length(input) - if iscell(input{l}) - for i=1:length(input{l}) - res = [res sprintf([cellsep{1} '%s' cellsep{2}],input{l}{i})]; - end - res = [res sprintf(linesep)]; - else - res = [res sprintf(['%s' linesep],input{l}(:))]; - end - end -end \ No newline at end of file diff --git a/matlab/caffe/read_cell.m b/matlab/caffe/read_cell.m deleted file mode 100644 index 19831167106..00000000000 --- a/matlab/caffe/read_cell.m +++ /dev/null @@ -1,21 +0,0 @@ -function res=read_cell(filename,linesep,cellsep) -if nargin < 2, linesep='\n'; end -if nargin < 3, cellsep = '\t'; end -if exist(filename,'file') - fid = fopen(filename); -else - % Assume that filename is either a file ide or a string - fid = filename; -end - -fileLines = textscan(fid,'%s','delimiter',linesep,'BufSize',100000); - -fileLines = fileLines{1}; - -if regexp(fileLines{1},cellsep,'once') - fileLines = regexprep(fileLines,['^' cellsep '|' cellsep '$'],''); - res = regexp(fileLines,cellsep,'split'); - res = cell2matcell(res); -else - res = fileLines; -end diff --git a/matlab/caffe/matcaffe_demo.m b/matlab/classification_demo.m similarity index 56% rename from matlab/caffe/matcaffe_demo.m rename to matlab/classification_demo.m index a931f910cbf..43a7bf62fdf 100644 --- a/matlab/caffe/matcaffe_demo.m +++ b/matlab/classification_demo.m @@ -1,7 +1,16 @@ -function [scores, maxlabel] = matcaffe_demo(im, use_gpu) -% scores = matcaffe_demo(im, use_gpu) +function [scores, maxlabel] = classification_demo(im, use_gpu) +% scores = classification_demo(im, use_gpu) % -% Demo of the matlab wrapper using the ILSVRC network. +% Image classification demo using BVLC CaffeNet. +% +% IMPORTANT: before you run this demo, you should download BVLC CaffeNet +% from Model Zoo (http://caffe.berkeleyvision.org/model_zoo.html) +% +% **************************************************************************** +% For detailed documentation and usage on Caffe's Matlab interface, please +% refer to Caffe Interface Tutorial at +% http://caffe.berkeleyvision.org/tutorial/interfaces.html#matlab +% **************************************************************************** % % input % im color image as uint8 HxWx3 @@ -16,8 +25,8 @@ % Or the equivalent based on where things are installed on your system % % Usage: -% im = imread('../../examples/images/cat.jpg'); -% scores = matcaffe_demo(im, 1); +% im = imread('../examples/images/cat.jpg'); +% scores = classification_demo(im, 1); % [score, class] = max(scores); % Five things to be aware of: % caffe uses row-major order @@ -26,7 +35,7 @@ % 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 +% Data coming in from matlab needs to be in the order % [width, height, channels, images] % where width is the fastest dimension. % Here is the rough matlab for putting image data into the correct @@ -42,20 +51,27 @@ % 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. - - -% init caffe network (spews logging info) -if exist('use_gpu', 'var') - matcaffe_init(use_gpu); +% Set caffe mode +if exist('use_gpu', 'var') && use_gpu + caffe.set_mode_gpu(); + gpu_id = 0; % we will use the first gpu in this demo + caffe.set_device(gpu_id); else - matcaffe_init(); + caffe.set_mode_cpu(); end +% Initialize the network using BVLC CaffeNet for image classification +% Weights (parameter) file needs to be downloaded from Model Zoo. +model_dir = '../models/bvlc_reference_caffenet/'; +net_model = [model_dir 'deploy.prototxt']; +net_weights = [model_dir 'bvlc_reference_caffenet.caffemodel']; +phase = 'test'; +net = caffe.Net(net_model, net_weights, phase); + if nargin < 1 - % For demo purposes we will use the peppers image - im = imread('peppers.png'); + % For demo purposes we will use the cat image + fprintf('using ../examples/images/cat.jpg as input image\n'); + im = imread('../examples/images/cat.jpg'); end % prepare oversampled input @@ -67,7 +83,10 @@ % do forward pass to get scores % scores are now Width x Height x Channels x Num tic; -scores = caffe('forward', input_data); +% The net forward function. It takes in a cell array of N-D arrays +% (where N == 4 here) containing data of input blob(s) and outputs a cell +% array containing data from output blob(s) +scores = net.forward(input_data); toc; scores = scores{1}; @@ -77,10 +96,13 @@ [~,maxlabel] = max(scores); +% call caffe.reset_all() to reset caffe +caffe.reset_all(); + % ------------------------------------------------------------------------ function images = prepare_image(im) % ------------------------------------------------------------------------ -d = load('ilsvrc_2012_mean'); +d = load('+caffe/imagenet/ilsvrc_2012_mean.mat'); IMAGE_MEAN = d.image_mean; IMAGE_DIM = 256; CROPPED_DIM = 227; @@ -98,13 +120,13 @@ for i = indices for j = indices images(:, :, :, curr) = ... - permute(im(i:i+CROPPED_DIM-1, j:j+CROPPED_DIM-1, :), [2 1 3]); + permute(im(i:i+CROPPED_DIM-1, j:j+CROPPED_DIM-1, :), [2 1 3]); images(:, :, :, curr+5) = images(end:-1:1, :, :, curr); curr = curr + 1; end end center = floor(indices(2) / 2)+1; images(:,:,:,5) = ... - permute(im(center:center+CROPPED_DIM-1,center:center+CROPPED_DIM-1,:), ... - [2 1 3]); + permute(im(center:center+CROPPED_DIM-1,center:center+CROPPED_DIM-1,:), ... + [2 1 3]); images(:,:,:,10) = images(end:-1:1, :, :, curr); diff --git a/matlab/caffe/hdf5creation/.gitignore b/matlab/hdf5creation/.gitignore similarity index 100% rename from matlab/caffe/hdf5creation/.gitignore rename to matlab/hdf5creation/.gitignore diff --git a/matlab/caffe/hdf5creation/demo.m b/matlab/hdf5creation/demo.m similarity index 100% rename from matlab/caffe/hdf5creation/demo.m rename to matlab/hdf5creation/demo.m diff --git a/matlab/caffe/hdf5creation/store2hdf5.m b/matlab/hdf5creation/store2hdf5.m similarity index 100% rename from matlab/caffe/hdf5creation/store2hdf5.m rename to matlab/hdf5creation/store2hdf5.m