From 99f27fc082612745c8d8cc932be42fdfd035e789 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Mon, 28 Jul 2014 14:55:13 -0700 Subject: [PATCH] define caffe.Net input preprocessing members by boost::python define `Net.{mean, input_scale, channel_swap}` on the boost::python side so that the members always exist. drop ugly initialization logic. --- python/caffe/_caffe.cpp | 34 +++++++++++++++++++++------------- python/caffe/pycaffe.py | 16 ++++++---------- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/python/caffe/_caffe.cpp b/python/caffe/_caffe.cpp index 10fc23b7..30c86aeb 100644 --- a/python/caffe/_caffe.cpp +++ b/python/caffe/_caffe.cpp @@ -25,6 +25,7 @@ using namespace caffe; // NOLINT(build/namespaces) +using boost::python::dict; using boost::python::extract; using boost::python::len; using boost::python::list; @@ -274,6 +275,10 @@ struct CaffeNet { // The pointer to the internal caffe::Net instant. shared_ptr > net_; + // Input preprocessing configuration attributes. + dict mean_; + dict input_scale_; + dict channel_swap_; // if taking input from an ndarray, we need to hold references object input_data_; object input_labels_; @@ -311,19 +316,22 @@ BOOST_PYTHON_MODULE(_caffe) { boost::python::class_ >( "Net", boost::python::init()) .def(boost::python::init()) - .def("_forward", &CaffeNet::Forward) - .def("_backward", &CaffeNet::Backward) - .def("set_mode_cpu", &CaffeNet::set_mode_cpu) - .def("set_mode_gpu", &CaffeNet::set_mode_gpu) - .def("set_phase_train", &CaffeNet::set_phase_train) - .def("set_phase_test", &CaffeNet::set_phase_test) - .def("set_device", &CaffeNet::set_device) - .add_property("_blobs", &CaffeNet::blobs) - .add_property("layers", &CaffeNet::layers) - .add_property("inputs", &CaffeNet::inputs) - .add_property("outputs", &CaffeNet::outputs) - .def("_set_input_arrays", &CaffeNet::set_input_arrays) - .def("save", &CaffeNet::save); + .def("_forward", &CaffeNet::Forward) + .def("_backward", &CaffeNet::Backward) + .def("set_mode_cpu", &CaffeNet::set_mode_cpu) + .def("set_mode_gpu", &CaffeNet::set_mode_gpu) + .def("set_phase_train", &CaffeNet::set_phase_train) + .def("set_phase_test", &CaffeNet::set_phase_test) + .def("set_device", &CaffeNet::set_device) + .add_property("_blobs", &CaffeNet::blobs) + .add_property("layers", &CaffeNet::layers) + .add_property("inputs", &CaffeNet::inputs) + .add_property("outputs", &CaffeNet::outputs) + .add_property("mean", &CaffeNet::mean_) + .add_property("input_scale", &CaffeNet::input_scale_) + .add_property("channel_swap", &CaffeNet::channel_swap_) + .def("_set_input_arrays", &CaffeNet::set_input_arrays) + .def("save", &CaffeNet::save); boost::python::class_( "Blob", boost::python::no_init) diff --git a/python/caffe/pycaffe.py b/python/caffe/pycaffe.py index 870dec4f..64747f30 100644 --- a/python/caffe/pycaffe.py +++ b/python/caffe/pycaffe.py @@ -211,8 +211,6 @@ def _Net_set_mean(self, input_, mean_f, mode='elementwise'): mode: elementwise = use the whole mean (and check dimensions) channel = channel constant (e.g. mean pixel instead of mean image) """ - if not hasattr(self, 'mean'): - self.mean = {} if input_ not in self.inputs: raise Exception('Input not in {}'.format(self.inputs)) in_shape = self.blobs[input_].data.shape @@ -240,8 +238,6 @@ def _Net_set_input_scale(self, input_, scale): input_: which input to assign this scale factor scale: scale coefficient """ - if not hasattr(self, 'input_scale'): - self.input_scale = {} if input_ not in self.inputs: raise Exception('Input not in {}'.format(self.inputs)) self.input_scale[input_] = scale @@ -257,8 +253,6 @@ def _Net_set_channel_swap(self, input_, order): order: the order to take the channels. (2,1,0) maps RGB to BGR for example. """ - if not hasattr(self, 'channel_swap'): - self.channel_swap = {} if input_ not in self.inputs: raise Exception('Input not in {}'.format(self.inputs)) self.channel_swap[input_] = order @@ -282,6 +276,7 @@ def _Net_preprocess(self, input_name, input_): caffe_inputs: (K x H x W) ndarray """ caffe_in = input_.astype(np.float32) + mean = self.mean.get(input_name) input_scale = self.input_scale.get(input_name) channel_order = self.channel_swap.get(input_name) in_size = self.blobs[input_name].data.shape[2:] @@ -292,8 +287,8 @@ def _Net_preprocess(self, input_name, input_): if channel_order is not None: caffe_in = caffe_in[:, :, channel_order] caffe_in = caffe_in.transpose((2, 0, 1)) - if hasattr(self, 'mean'): - caffe_in -= self.mean.get(input_name, 0) + if mean is not None: + caffe_in -= mean return caffe_in @@ -302,10 +297,11 @@ def _Net_deprocess(self, input_name, input_): Invert Caffe formatting; see Net.preprocess(). """ decaf_in = input_.copy().squeeze() + mean = self.mean.get(input_name) input_scale = self.input_scale.get(input_name) channel_order = self.channel_swap.get(input_name) - if hasattr(self, 'mean'): - decaf_in += self.mean.get(input_name, 0) + if mean is not None: + decaf_in += mean decaf_in = decaf_in.transpose((1,2,0)) if channel_order is not None: channel_order_inverse = [channel_order.index(i)