mexopencv  3.4.1
MEX interface for OpenCV library
ConjGradSolver_.cpp
Go to the documentation of this file.
1 
8 #include "mexopencv.hpp"
9 using namespace std;
10 using namespace cv;
11 
12 // Persistent objects
13 namespace {
15 int last_id = 0;
18 
21 {
22 public:
30  MatlabFunction(int num_dims, const string &func, const string &grad_func = "", double h = 1e-3)
31  : dims(num_dims), fun_name(func), grad_fun_name(grad_func), gradeps(h)
32  {}
33 
50  double calc(const double *x) const
51  {
52  // create input to evaluate objective function
53  mxArray *lhs, *rhs[2];
54  rhs[0] = MxArray(fun_name);
55  rhs[1] = MxArray(vector<double>(x, x + dims));
56 
57  // evaluate specified function in MATLAB as:
58  // val = feval("fun_name", x)
59  double val;
60  if (mexCallMATLAB(1, &lhs, 2, rhs, "feval") == 0) {
61  MxArray res(lhs);
62  CV_Assert(res.isDouble() && !res.isComplex() && res.numel() == 1);
63  val = res.at<double>(0);
64  }
65  else {
66  //TODO: error
67  val = 0;
68  }
69 
70  // cleanup
71  mxDestroyArray(lhs);
72  mxDestroyArray(rhs[0]);
73  mxDestroyArray(rhs[1]);
74 
75  // return scalar value of objective function evaluated at x
76  return val;
77  }
78 
95  void getGradient(const double* x, double* grad) /*const*/
96  {
97  // if no function is specified, approximate the gradient using
98  // finite difference method: F'(x) = (F(x+h) - F(x-h)) / 2*h
99  if (grad_fun_name.empty()) {
101  return;
102  }
103 
104  // create input to evaluate gradient function
105  mxArray *lhs, *rhs[2];
106  rhs[0] = MxArray(grad_fun_name);
107  rhs[1] = MxArray(vector<double>(x, x + dims));
108 
109  // evaluate specified function in MATLAB as:
110  // grad = feval("grad_fun_name", x)
111  if (mexCallMATLAB(1, &lhs, 2, rhs, "feval") == 0) {
112  MxArray res(lhs);
113  CV_Assert(res.isDouble() && !res.isComplex() && res.ndims() == 2);
114  vector<double> v(res.toVector<double>());
115  CV_Assert(v.size() == dims);
116  std::copy(v.begin(), v.end(), grad);
117  }
118  else {
119  //TODO: error
120  std::fill(grad, grad + dims, 0.0);
121  }
122 
123  // cleanup
124  mxDestroyArray(lhs);
125  mxDestroyArray(rhs[0]);
126  mxDestroyArray(rhs[1]);
127  }
128 
132  double getGradientEps() const
133  {
134  return gradeps;
135  }
136 
140  int getDims() const
141  {
142  return dims;
143  }
144 
149  {
151  s.set("dims", dims);
152  s.set("fun", fun_name);
153  s.set("gradfun", grad_fun_name);
154  s.set("gradeps", gradeps);
155  return s;
156  }
157 
167  {
168  if (!s.isStruct() || s.numel()!=1)
169  mexErrMsgIdAndTxt("mexopencv:error", "Invalid objective function");
170  return makePtr<MatlabFunction>(
171  s.at("dims").toInt(),
172  s.at("fun").toString(),
173  s.isField("gradfun") ? s.at("gradfun").toString() : "",
174  s.isField("gradeps") ? s.at("gradeps").toDouble() : 1e-3);
175  }
176 
177 private:
178  int dims;
179  string fun_name;
180  string grad_fun_name;
181  double gradeps;
182 };
183 }
184 
192 void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
193 {
194  // Check the number of arguments
195  nargchk(nrhs>=2 && nlhs<=2);
196 
197  // Arguments vector
198  vector<MxArray> rhs(prhs, prhs+nrhs);
199  int id = rhs[0].toInt();
200  string method(rhs[1].toString());
201 
202  // Constructor is called. Create a new object from argument
203  if (method == "new") {
204  nargchk(nrhs>=2 && (nrhs%2)==0 && nlhs<=1);
206  TermCriteria termcrit(TermCriteria::MAX_ITER+TermCriteria::EPS, 5000, 1e-6);
207  for (int i=2; i<nrhs; i+=2) {
208  string key(rhs[i].toString());
209  if (key == "Function")
210  f = MatlabFunction::create(rhs[i+1]);
211  else if (key == "TermCriteria")
212  termcrit = rhs[i+1].toTermCriteria();
213  else
214  mexErrMsgIdAndTxt("mexopencv:error",
215  "Unrecognized option %s", key.c_str());
216  }
217  obj_[++last_id] = ConjGradSolver::create(f, termcrit);
218  plhs[0] = MxArray(last_id);
219  mexLock();
220  return;
221  }
222 
223  // Big operation switch
224  Ptr<ConjGradSolver> obj = obj_[id];
225  if (obj.empty())
226  mexErrMsgIdAndTxt("mexopencv:error", "Object not found id=%d", id);
227  if (method == "delete") {
228  nargchk(nrhs==2 && nlhs==0);
229  obj_.erase(id);
230  mexUnlock();
231  }
232  else if (method == "clear") {
233  nargchk(nrhs==2 && nlhs==0);
234  obj->clear();
235  }
236  else if (method == "load") {
237  nargchk(nrhs>=3 && (nrhs%2)==1 && nlhs==0);
238  string objname;
239  bool loadFromString = false;
240  for (int i=3; i<nrhs; i+=2) {
241  string key(rhs[i].toString());
242  if (key == "ObjName")
243  objname = rhs[i+1].toString();
244  else if (key == "FromString")
245  loadFromString = rhs[i+1].toBool();
246  else
247  mexErrMsgIdAndTxt("mexopencv:error",
248  "Unrecognized option %s", key.c_str());
249  }
250  obj_[id] = (loadFromString ?
251  Algorithm::loadFromString<ConjGradSolver>(rhs[2].toString(), objname) :
252  Algorithm::load<ConjGradSolver>(rhs[2].toString(), objname));
253  }
254  else if (method == "save") {
255  nargchk(nrhs==3 && nlhs==0);
256  obj->save(rhs[2].toString());
257  }
258  else if (method == "empty") {
259  nargchk(nrhs==2 && nlhs<=1);
260  plhs[0] = MxArray(obj->empty());
261  }
262  else if (method == "getDefaultName") {
263  nargchk(nrhs==2 && nlhs<=1);
264  plhs[0] = MxArray(obj->getDefaultName());
265  }
266  else if (method == "minimize") {
267  nargchk(nrhs==3 && nlhs<=2);
268  Mat x(rhs[2].toMat(CV_64F));
269  double fx = obj->minimize(x);
270  plhs[0] = MxArray(x);
271  if (nlhs>1)
272  plhs[1] = MxArray(fx);
273  }
274  else if (method == "get") {
275  nargchk(nrhs==3 && nlhs<=1);
276  string prop(rhs[2].toString());
277  if (prop == "Function") {
279  plhs[0] = (f.empty()) ? MxArray::Struct() :
280  (f.dynamicCast<MatlabFunction>())->toStruct();
281  }
282  else if (prop == "TermCriteria")
283  plhs[0] = MxArray(obj->getTermCriteria());
284  else
285  mexErrMsgIdAndTxt("mexopencv:error",
286  "Unrecognized property %s", prop.c_str());
287  }
288  else if (method == "set") {
289  nargchk(nrhs==4 && nlhs==0);
290  string prop(rhs[2].toString());
291  if (prop == "Function")
292  obj->setFunction(MatlabFunction::create(rhs[3]));
293  else if (prop == "TermCriteria")
294  obj->setTermCriteria(rhs[3].toTermCriteria());
295  else
296  mexErrMsgIdAndTxt("mexopencv:error",
297  "Unrecognized property %s", prop.c_str());
298  }
299  else
300  mexErrMsgIdAndTxt("mexopencv:error",
301  "Unrecognized operation %s", method.c_str());
302 }
mwSize ndims() const
Number of dimensions.
Definition: MxArray.hpp:550
static Ptr< MatlabFunction > create(const MxArray &s)
Factory function.
T copy(T... args)
#define CV_Assert(...)
mwSize numel() const
Number of elements in an array.
Definition: MxArray.hpp:546
virtual Ptr< Function > getFunction() const=0
T at(mwIndex index) const
Template for numeric array element accessor.
Definition: MxArray.hpp:1250
virtual void setTermCriteria(const TermCriteria &termcrit)=0
LIBMWMEX_API_EXTERN_C void mexLock(void)
Lock a MEX-function so that it cannot be cleared from memory.
MxArray toStruct() const
Convert object to MxArray.
virtual double minimize(InputOutputArray x)=0
STL namespace.
LIBMMWMATRIX_PUBLISHED_API_EXTERN_C void mxDestroyArray(mxArray *pa)
mxArray destructor
bool isDouble() const
Determine whether mxArray represents data as double-precision, floating-point numbers.
Definition: MxArray.hpp:637
struct mxArray_tag mxArray
Forward declaration for mxArray.
Definition: matrix.h:259
void set(mwIndex index, const T &value)
Template for numeric array element write accessor.
Definition: MxArray.hpp:1310
STL class.
string func
name of MATLAB function to evaluate (custom face detector)
Definition: Facemark_.cpp:21
void getGradient(const double *x, double *grad)
Evaluates MATLAB gradient function.
virtual void getGradient(const double *x, double *grad)
virtual void clear()
uint32_t v
map< int, Ptr< ConjGradSolver > > obj_
Object container.
bool isComplex() const
Determine whether data is complex.
Definition: MxArray.hpp:632
virtual TermCriteria getTermCriteria() const=0
#define CV_64F
LIBMWMEX_API_EXTERN_C void mexErrMsgIdAndTxt(const char *identifier, const char *err_msg,...)
Issue formatted error message with corresponding error identifier and return to MATLAB prompt...
double calc(const double *x) const
Evaluates MATLAB objective function.
LIBMWMEX_API_EXTERN_C void mexUnlock(void)
Unlock a locked MEX-function so that it can be cleared from memory.
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
Main entry called from Matlab.
bool isField(const std::string &fieldName) const
Determine whether a struct array has a specified field.
Definition: MxArray.hpp:743
mxArray object wrapper for data conversion and manipulation.
Definition: MxArray.hpp:123
void nargchk(bool cond)
Alias for input/output arguments number check.
Definition: mexopencv.hpp:181
static MxArray Struct(const char **fields=NULL, int nfields=0, mwSize m=1, mwSize n=1)
Create a new struct array.
Definition: MxArray.hpp:312
MatlabFunction(int num_dims, const string &func, const string &grad_func="", double h=1e-3)
Constructor.
bool isStruct() const
Determine whether input is structure array.
Definition: MxArray.hpp:708
virtual void setFunction(const Ptr< Function > &f)=0
std::vector< T > toVector() const
Convert MxArray to std::vector<T> of primitive types.
Definition: MxArray.hpp:1151
bool empty() const
virtual String getDefaultName() const
Global constant definitions.
Represents objective function being optimized, implemented as a MATLAB file.
int last_id
Last object id to allocate.
T c_str(T... args)
int getDims() const
Return number of dimensions.
T fill(T... args)
virtual void save(const String &filename) const
virtual bool empty() const
LIBMWMEX_API_EXTERN_C int mexCallMATLAB(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[], const char *fcn_name)
call MATLAB function
void create(int arows, int acols, int atype, Target target=ARRAY_BUFFER, bool autoRelease=false)
cv::Mat toMat() const