mexopencv  0.1
mex interface for opencv library
MxArray.cpp
Go to the documentation of this file.
1 
6 #include "MxArray.hpp"
7 
8 namespace {
9 
11 const char *cv_moments_fields[24] = {
12  "m00", "m10", "m01", "m20", "m11", "m02","m30", "m21", "m12", "m03",
13  "mu20", "mu11", "mu02", "mu30", "mu21", "mu12", "mu03",
14  "nu20", "nu11", "nu02", "nu30", "nu21", "nu12", "nu03"};
16 const char *cv_rotated_rect_fields[3] = {"center", "size", "angle"};
18 const char *cv_term_criteria_fields[3] = {"type", "maxCount", "epsilon"};
20 const char *cv_keypoint_fields[6] = {"pt", "size", "angle", "response",
21  "octave", "class_id"};
23 const char *cv_dmatch_fields[4] = {"queryIdx", "trainIdx", "imgIdx",
24  "distance"};
25 
31  (mxDOUBLE_CLASS, CV_64F)
32  (mxSINGLE_CLASS, CV_32F)
33  (mxINT8_CLASS, CV_8S)
34  (mxUINT8_CLASS, CV_8U)
35  (mxINT16_CLASS, CV_16S)
36  (mxUINT16_CLASS, CV_16U)
37  (mxINT32_CLASS, CV_32S)
38  (mxUINT32_CLASS, CV_32S)
39  (mxLOGICAL_CLASS, CV_8U);
40 
46  (CV_64F, mxDOUBLE_CLASS)
47  (CV_32F, mxSINGLE_CLASS)
48  (CV_8S, mxINT8_CLASS)
49  (CV_8U, mxUINT8_CLASS)
50  (CV_16S, mxINT16_CLASS)
51  (CV_16U, mxUINT16_CLASS)
52  (CV_32S, mxINT32_CLASS);
53 
58 struct CompareSparseMatNode {
60  bool operator () (const cv::SparseMat::Node* rhs,
61  const cv::SparseMat::Node* lhs) const
62  {
63  // sort by column, then by row
64  if (rhs->idx[1] < lhs->idx[1])
65  return true;
66  if (rhs->idx[1] == lhs->idx[1] && rhs->idx[0] < lhs->idx[0])
67  return true;
68  return false;
69  }
70 };
71 
74  (cv::TermCriteria::COUNT, "Count")
75  (cv::TermCriteria::EPS, "EPS")
76  (cv::TermCriteria::COUNT+cv::TermCriteria::EPS, "Count+EPS");
77 
80  ("Count", cv::TermCriteria::COUNT)
81  ("EPS", cv::TermCriteria::EPS)
82  ("Count+EPS", cv::TermCriteria::COUNT+cv::TermCriteria::EPS);
83 
84 } // anonymous namespace
85 
86 int MexErrorHandler(int status, const char *func_name, const char *err_msg,
87  const char *file_name, int line, void * /*userdata*/)
88 {
89  mexErrMsgIdAndTxt("mexopencv:error",
90  "OpenCV Error:\n"
91  " Status : %s (%d)\n"
92  " Message : %s\n"
93  " Function: %s\n"
94  " File : <a href=\"matlab:opentoline('%s',%d)\">%s</a>\n"
95  " Line : %d\n",
96  cvErrorStr(status), status, err_msg,
97  (func_name ? func_name : "(unknown)"),
98  file_name, line, file_name, line);
99  return 0;
100 }
101 
103 {
104  if (this != &rhs)
105  this->p_ = rhs.p_;
106  return *this;
107 }
108 
109 MxArray::MxArray(const int i)
110  : p_(mxCreateDoubleScalar(static_cast<double>(i)))
111 {
112  if (!p_)
113  mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
114 }
115 
116 MxArray::MxArray(const double d)
117  : p_(mxCreateDoubleScalar(d))
118 {
119  if (!p_)
120  mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
121 }
122 
123 MxArray::MxArray(const bool b)
124  : p_(mxCreateLogicalScalar(b))
125 {
126  if (!p_)
127  mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
128 }
129 
130 MxArray::MxArray(const std::string& s)
131  : p_(mxCreateString(s.c_str()))
132 {
133  if (!p_)
134  mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
135 }
136 
137 #if 0
138 // - works for multi-channel arrays, but doesnt work for ND-arrays because
139 // the order of dimensions is not right (row to column major order)
140 // (the std::swap below only gets it right for 2D arrays).
141 // - There's another bug regarding multi-channel arrays where mat.channels()
142 // is limited because of cv::transpose, which is only implemented for a number
143 // of cases, and asserts that mat.elementSize() <= 32
144 // (elementSize = sizeof(depth)*nchannels), so for mat.depth()==CV_8U we can
145 // go up to 32 channels, but for mat.depth()==CV_64F we can only go up to a
146 // maximum of 4 channels (8*4 == 32)
147 MxArray::MxArray(const cv::Mat& mat, mxClassID classid, bool transpose)
148 {
149  // handle special case of empty input Mat by creating an empty array
150  classid = (classid == mxUNKNOWN_CLASS) ? ClassIDOf[mat.depth()] : classid;
151  if (mat.empty()) {
152  p_ = mxCreateNumericMatrix(0, 0, classid, mxREAL);
153  if (!p_)
154  mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
155  return;
156  }
157  // transpose cv::Mat if needed
158  cv::Mat input(mat);
159  if (input.dims == 2 && transpose)
160  input = input.t();
161  // Create a new mxArray (of the specified classID) equivalent to cv::Mat
162  const mwSize nchannels = input.channels();
163  const int* dims_ = input.size;
164  std::vector<mwSize> d(dims_, dims_ + input.dims);
165  d.push_back(nchannels); // mxCreate* ignores trailing singleton dimensions
166  std::swap(d[0], d[1]);
167  if (classid == mxLOGICAL_CLASS) {
168  // OpenCV's logical true is any nonzero, while MATLAB's true is 1.
169  cv::compare(input, 0, input, cv::CMP_NE);
170  input.setTo(1, input);
171  p_ = mxCreateLogicalArray(d.size(), &d[0]);
172  }
173  else
174  p_ = mxCreateNumericArray(d.size(), &d[0], classid, mxREAL);
175  if (!p_)
176  mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
177  // split input cv::Mat into several single-channel arrays
178  std::vector<cv::Mat> channels;
179  channels.reserve(nchannels);
180  cv::split(input, channels);
181  // Copy each channel from Mat to mxArray (converting to specified classid),
182  // as in: p_(:,:,i) <- cast_to_classid_type(channels[i])
183  std::vector<mwSize> si(d.size(), 0); // subscript index
184  const int type = CV_MAKETYPE(DepthOf[classid], 1); // destination type
185  for (mwIndex i = 0; i < nchannels; ++i) {
186  si[si.size() - 1] = i; // last dim is a channel index
187  void *ptr = reinterpret_cast<void*>(
188  reinterpret_cast<size_t>(mxGetData(p_)) +
189  mxGetElementSize(p_) * subs(si)); // ptr to i-th channel data
190  cv::Mat m(input.dims, dims_, type, ptr); // only creates Mat header
191  channels[i].convertTo(m, type); // Write to mxArray through m
192  }
193 }
194 #else
195 // works for any cv::Mat/cv::MatND (any combination of channels and dimensions)
196 MxArray::MxArray(const cv::Mat& mat, mxClassID classid, bool)
197 {
198  // determine classID of output array
199  classid = (classid == mxUNKNOWN_CLASS) ? ClassIDOf[mat.depth()] : classid;
200 
201  // handle special case of empty input Mat by returning 0x0 array
202  if (mat.empty()) {
203  // TODO: maybe return empty array of same dimensions 0x1, 1x0x2, ...
204  p_ = mxCreateNumericMatrix(0, 0, classid, mxREAL);
205  if (!p_)
206  mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
207  return;
208  }
209 
210  // Create output mxArray (of specified type), equivalent to the input Mat
211  const mwSize cn = mat.channels();
212  const mwSize len = mat.total() * cn;
213  std::vector<mwSize> sz(mat.size.p, mat.size.p + mat.dims);
214  if (cn > 1)
215  sz.push_back(cn); // channels is treated as another dimension
216  std::reverse(sz.begin(), sz.end()); // row vs. column major order
217  if (classid == mxLOGICAL_CLASS)
218  p_ = mxCreateLogicalArray(sz.size(), &sz[0]);
219  else
220  p_ = mxCreateNumericArray(sz.size(), &sz[0], classid, mxREAL);
221  if (!p_)
222  mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
223 
224  // fill output with values from input Mat
225  // (linearized as a 1D-vector, both dimensions and channels)
226  {
227  // wrap destination data using a cv::Mat
228  const int type = CV_MAKETYPE(DepthOf[classid], 1); // destination type
229  cv::Mat m(len, 1, type, mxGetData(p_)); // only creates Mat header
230 
231  // copy flattened input to output array (converting to specified type)
232  const cv::Mat mat0(len, 1, mat.depth(), mat.data); // no data copying
233  if (classid == mxLOGICAL_CLASS) {
234  // OpenCV's logical true is any nonzero, while MATLAB's true is 1
235  cv::compare(mat0, 0, m, cv::CMP_NE); // values either 0 or 255
236  m.setTo(1, m); // values either 0 or 1 (CV_8U)
237  }
238  else
239  mat0.convertTo(m, type);
240  }
241 
242  // rearrange dimensions of mxArray by calling PERMUTE from MATLAB. We want
243  // to convert from row-major order (C-style, last dim changes fastest) to a
244  // column-major order (MATLAB-style, first dim changes fastest). This will
245  // handle all cases of cv::Mat as multi-channels and/or multi-dimensions.
246  std::vector<double> order;
247  order.reserve(sz.size());
248  for (int i=sz.size(); i>0; i--)
249  order.push_back(i);
250 
251  // CALL: out = permute(in, ndims(in):-1:1)
252  mxArray *lhs, *rhs[2];
253  rhs[0] = const_cast<mxArray*>(p_);
254  rhs[1] = MxArray(order);
255  lhs = NULL; // new data copy will be returned
256  if (mexCallMATLAB(1, &lhs, 2, rhs, "permute") != 0)
257  mexErrMsgIdAndTxt("mexopencv:error", "Error calling permute");
258  p_ = lhs;
259  mxDestroyArray(rhs[0]); // discard old copy
260  mxDestroyArray(rhs[1]);
261  CV_DbgAssert(!isNull() && classID()==classid && numel()==len);
262 }
263 #endif
264 
265 MxArray::MxArray(const cv::SparseMat& mat)
266 {
267  // MATLAB only supports 2D sparse arrays of class double
268  if (mat.dims() != 2 || mat.channels() != 1)
269  mexErrMsgIdAndTxt("mexopencv:error",
270  "Not a 2D 1-channel sparse matrix");
271  /*
272  else {
273  //TODO: convert cv::SparseMat to dense cv::Mat to dense mxArray
274  Mat m;
275  mat.copyTo(m); // mat.convertTo(m);
276  *this = MxArray(m);
277  return;
278  }
279  */
280 
281  // create sparse array of same dimensions and capacity
282  const mwSize m = mat.size(0), n = mat.size(1), nnz = mat.nzcount();
283  p_ = mxCreateSparse(m, n, nnz, mxREAL);
284  if (!p_)
285  mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
286 
287  // get pointers to data (PR, IR, JC)
288  mwIndex *ir = mxGetIr(p_); // array of length nzmax
289  mwIndex *jc = mxGetJc(p_); // array of length n+1
290  double *pr = mxGetPr(p_); // array of length nzmax
291  if (!ir || !jc || !pr)
292  mexErrMsgIdAndTxt("mexopencv:error", "Null pointer error");
293 
294  // collect SparseMat nodes. They are enumerated semi-randomly
295  // (iterator returns them in an order based on their hash value)
296  std::vector<const cv::SparseMat::Node*> nodes;
297  nodes.reserve(nnz);
298  for (cv::SparseMat::const_iterator it = mat.begin(); it != mat.end(); ++it)
299  nodes.push_back(it.node());
300  // sort the nodes in a column-major order before we put elems into mxArray
301  std::sort(nodes.begin(), nodes.end(), CompareSparseMatNode());
302 
303  // Copy data by converting from (row,col,val) triplets to CSC format
304  jc[0] = 0;
305  for (mwIndex i = 0; i < nodes.size(); ++i) {
306  const mwIndex row = nodes[i]->idx[0], col = nodes[i]->idx[1];
307  ir[i] = row;
308  jc[col+1] = i+1;
309  // val = mat(row,col), up-casting value to double
310  switch (mat.depth()) {
311  case CV_8U:
312  pr[i] = static_cast<double>(mat.value<uchar>(nodes[i]));
313  break;
314  case CV_8S:
315  pr[i] = static_cast<double>(mat.value<schar>(nodes[i]));
316  break;
317  case CV_16U:
318  pr[i] = static_cast<double>(mat.value<ushort>(nodes[i]));
319  break;
320  case CV_16S:
321  pr[i] = static_cast<double>(mat.value<short>(nodes[i]));
322  break;
323  case CV_32S:
324  pr[i] = static_cast<double>(mat.value<int>(nodes[i]));
325  break;
326  case CV_32F:
327  pr[i] = static_cast<double>(mat.value<float>(nodes[i]));
328  break;
329  case CV_64F:
330  pr[i] = mat.value<double>(nodes[i]);
331  break;
332  default:
333  break; // should never reach this case
334  }
335  }
336  // fill indices in JC array where columns were empty and had no values
337  for (mwIndex i = 1; i < n+1; ++i) {
338  if (jc[i] == 0)
339  jc[i] = jc[i-1];
340  }
341  //CV_DbgAssert(jc[0] == 0 && jc[n] == nnz); // sanity check
342 }
343 
344 MxArray::MxArray(const cv::Moments& m)
345  : p_(mxCreateStructMatrix(1, 1, 24, cv_moments_fields))
346 {
347  if (!p_)
348  mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
349  set("m00", m.m00);
350  set("m10", m.m10);
351  set("m01", m.m01);
352  set("m20", m.m20);
353  set("m11", m.m11);
354  set("m02", m.m02);
355  set("m30", m.m30);
356  set("m12", m.m12);
357  set("m21", m.m21);
358  set("m03", m.m03);
359  set("mu20", m.mu20);
360  set("mu11", m.mu11);
361  set("mu02", m.mu02);
362  set("mu30", m.mu30);
363  set("mu21", m.mu21);
364  set("mu12", m.mu12);
365  set("mu03", m.mu03);
366  set("nu20", m.nu20);
367  set("nu11", m.nu11);
368  set("nu02", m.nu02);
369  set("nu30", m.nu30);
370  set("nu21", m.nu21);
371  set("nu12", m.nu12);
372  set("nu03", m.nu03);
373 }
374 
375 MxArray::MxArray(const cv::KeyPoint& p)
376  : p_(mxCreateStructMatrix(1, 1, 6, cv_keypoint_fields))
377 {
378  if (!p_)
379  mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
380  set("pt", p.pt);
381  set("size", p.size);
382  set("angle", p.angle);
383  set("response", p.response);
384  set("octave", p.octave);
385  set("class_id", p.class_id);
386 }
387 
388 template<>
389 void MxArray::fromVector(const std::vector<char>& v)
390 {
391  const mwSize size[] = {1, v.size()};
392  p_ = mxCreateCharArray(2, size);
393  if (!p_)
394  mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
395  std::copy(v.begin(), v.end(), mxGetChars(p_));
396 }
397 
398 template<>
399 void MxArray::fromVector(const std::vector<bool>& v)
400 {
401  p_ = mxCreateLogicalMatrix(1, v.size());
402  if (!p_)
403  mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
404  std::copy(v.begin(), v.end(), mxGetLogicals(p_));
405 }
406 
407 template <>
408 MxArray::MxArray(const std::vector<cv::KeyPoint>& v)
409  : p_(mxCreateStructMatrix(1, v.size(), 6, cv_keypoint_fields))
410 {
411  if (!p_)
412  mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
413  for (mwIndex i = 0; i < v.size(); ++i) {
414  set("pt", v[i].pt, i);
415  set("size", v[i].size, i);
416  set("angle", v[i].angle, i);
417  set("response", v[i].response, i);
418  set("octave", v[i].octave, i);
419  set("class_id", v[i].class_id, i);
420  }
421 }
422 
423 MxArray::MxArray(const cv::DMatch& m)
424  : p_(mxCreateStructMatrix(1, 1, 4, cv_keypoint_fields))
425 {
426  if (!p_)
427  mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
428  set("queryIdx", m.queryIdx);
429  set("trainIdx", m.trainIdx);
430  set("imgIdx", m.imgIdx);
431  set("distance", m.distance);
432 }
433 
434 template <>
435 MxArray::MxArray(const std::vector<cv::DMatch>& v)
436  : p_(mxCreateStructMatrix(1, v.size(), 4, cv_dmatch_fields))
437 {
438  if (!p_)
439  mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
440  for (mwIndex i = 0; i < v.size(); ++i) {
441  set("queryIdx", v[i].queryIdx, i);
442  set("trainIdx", v[i].trainIdx, i);
443  set("imgIdx", v[i].imgIdx, i);
444  set("distance", v[i].distance, i);
445  }
446 }
447 
448 MxArray::MxArray(const cv::RotatedRect& r)
449  : p_(mxCreateStructMatrix(1, 1, 3, cv_rotated_rect_fields))
450 {
451  if (!p_)
452  mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
453  set("center", r.center);
454  set("size", r.size);
455  set("angle", r.angle);
456 }
457 
458 template <>
459 MxArray::MxArray(const std::vector<cv::RotatedRect>& v)
460  : p_(mxCreateStructMatrix(1, v.size(), 3, cv_rotated_rect_fields))
461 {
462  if (!p_)
463  mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
464  for (mwIndex i = 0; i < v.size(); ++i) {
465  set("center", v[i].center, i);
466  set("size", v[i].size, i);
467  set("angle", v[i].angle, i);
468  }
469 }
470 
471 MxArray::MxArray(const cv::TermCriteria& t)
472  : p_(mxCreateStructMatrix(1, 1, 3, cv_term_criteria_fields))
473 {
474  if (!p_)
475  mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
476  set("type", InvTermCritType[t.type]);
477  set("maxCount", t.maxCount);
478  set("epsilon", t.epsilon);
479 }
480 
482 {
483  mxArray *pm = mxDuplicateArray(p_);
484  if (!pm)
485  mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
486  return MxArray(pm);
487 }
488 
489 int MxArray::toInt() const
490 {
491  if (numel() != 1)
492  mexErrMsgIdAndTxt("mexopencv:error", "MxArray is not a scalar");
493  return at<int>(0);
494 }
495 
496 double MxArray::toDouble() const
497 {
498  if (numel() != 1)
499  mexErrMsgIdAndTxt("mexopencv:error", "MxArray is not a scalar");
500  return at<double>(0);
501 }
502 
503 float MxArray::toFloat() const
504 {
505  if (numel() != 1)
506  mexErrMsgIdAndTxt("mexopencv:error", "MxArray is not a scalar");
507  return at<float>(0);
508 }
509 
510 bool MxArray::toBool() const
511 {
512  if (numel() != 1)
513  mexErrMsgIdAndTxt("mexopencv:error", "MxArray is not a scalar");
514  return at<bool>(0);
515 }
516 
517 std::string MxArray::toString() const
518 {
519  if (!isChar())
520  mexErrMsgIdAndTxt("mexopencv:error", "MxArray not of type char");
521  char *pc = mxArrayToString(p_);
522  if (!pc)
523  mexErrMsgIdAndTxt("mexopencv:error", "Null pointer error");
524  std::string s(pc);
525  mxFree(pc);
526  return s;
527 }
528 
529 cv::Mat MxArray::toMat(int depth, bool transpose) const
530 {
531  CV_Assert(isNumeric() || isLogical() || isChar());
532 
533  // the rest of this function works fine for 2D and 3D arrays, but for
534  // higher ND-arrays the order of dimensions is not right (the std::swap
535  // below is only intended for 2d array).
536  // So instead we use MxArray::toMatND on the input ND-array and then
537  // convert the last dimension of the MatND into channels.
538  if (ndims() > 3) {
539  cv::Mat matnd(toMatND(depth, transpose)); // ND-array, 1-channel
540  CV_DbgAssert(matnd.isContinuous() && matnd.dims == ndims() && matnd.channels() == 1);
541  std::vector<int> d(matnd.size.p, matnd.size.p + matnd.dims);
542  const int cn = d.back();
543  const int type = CV_MAKETYPE(matnd.depth(), cn);
544  CV_Assert(cn <= CV_CN_MAX);
545  return matnd.reshape(cn, d.size()-1, &d[0]);
546  }
547 
548  // Create cv::Mat object (of the specified depth), equivalent to mxArray.
549  // At this point we create either a 2-dim with 1-channel mat, or a 2-dim
550  // with multi-channels mat. Multi-dims case is handled above.
551  std::vector<int> d(dims(), dims()+ndims());
552  const mwSize ndims = (d.size()>2) ? d.size()-1 : d.size();
553  const mwSize nchannels = (d.size()>2) ? d.back() : 1;
554  depth = (depth == CV_USRTYPE1) ? DepthOf[classID()] : depth;
555  std::swap(d[0], d[1]);
556  cv::Mat mat(ndims, &d[0], CV_MAKETYPE(depth, nchannels));
557  // Copy each channel from mxArray to Mat (converting to specified depth),
558  // as in: channels[i] <- cast_to_mat_depth(p_(:,:,i))
559  std::vector<cv::Mat> channels(nchannels);
560  std::vector<mwSize> si(d.size(), 0); // subscript index
561  const int type = CV_MAKETYPE(DepthOf[classID()], 1); // Source type
562  for (mwIndex i = 0; i<nchannels; ++i) {
563  si[si.size() - 1] = i; // last dim is a channel idx
564  void *pd = reinterpret_cast<void*>(
565  reinterpret_cast<size_t>(mxGetData(p_)) +
566  mxGetElementSize(p_)*subs(si)); // ptr to i-th channel data
567  const cv::Mat m(ndims, &d[0], type, pd); // only creates Mat headers
568  // Read from mxArray through m, writing into channels[i]
569  m.convertTo(channels[i], CV_MAKETYPE(depth, 1));
570  // transpose cv::Mat if needed. We do this inside the loop on each 2d
571  // 1-cn slice to avoid cv::transpose limitation on number of channels
572  if (transpose)
573  cv::transpose(channels[i], channels[i]); // in-place transpose
574  }
575  // Merge channels back into one cv::Mat array
576  cv::merge(channels, mat);
577  return mat;
578 }
579 
580 #if 0
581 // works for 2D, but for ND-arrays the dimensions are not arranged correctly
582 cv::MatND MxArray::toMatND(int depth, bool transpose) const
583 {
584  // Create cv::MatND object (of the specified depth), equivalent to mxArray
585  std::vector<int> d(dims(), dims()+ndims());
586  std::swap(d[0], d[1]);
587  depth = (depth == CV_USRTYPE1) ? DepthOf[classID()] : depth;
588  cv::MatND mat(d.size(), &d[0], CV_MAKETYPE(depth, 1));
589  // Copy from mxArray to cv::MatND (converting to specified depth)
590  const int type = CV_MAKETYPE(DepthOf[classID()], 1); // source type
591  const cv::MatND m(d.size(), &d[0], type, mxGetData(p_)); // only Mat header
592  // Read from mxArray through m, writing into mat
593  m.convertTo(mat, CV_MAKETYPE(depth, 1));
594  // transpose cv::MatND if needed
595  if (mat.dims==2 && transpose)
596  cv::transpose(mat, mat); // in-place transpose
597  return mat;
598 }
599 #else
600 // works for any number of dimensions
601 cv::MatND MxArray::toMatND(int depth, bool) const
602 {
603  CV_Assert(isNumeric() || isLogical() || isChar());
604  CV_Assert(ndims() <= CV_MAX_DIM);
605 
606  // rearrange ND-array from MATLAB-style (column-major order, first dim
607  // changes fastest) to C-style (row-major order, last dim changes fastest)
608  // by calling PERMUTE from MATLAB.
609  std::vector<double> order;
610  order.reserve(ndims());
611  for (int i=ndims(); i>0; i--)
612  order.push_back(i);
613 
614  // CALL: out = permute(in, ndims(in):-1:1)
615  mxArray *lhs, *rhs[2];
616  rhs[0] = const_cast<mxArray*>(p_);
617  rhs[1] = MxArray(order);
618  lhs = NULL; // new data copy will be returned
619  if (mexCallMATLAB(1, &lhs, 2, rhs, "permute") != 0)
620  mexErrMsgIdAndTxt("mexopencv:error", "Error calling permute");
621  mxDestroyArray(rhs[1]);
622  CV_DbgAssert(lhs!=NULL && mxGetClassID(lhs)==classID() &&
623  mxGetNumberOfElements(lhs)==numel());
624 
625  // Create output cv::MatND object of the specified depth, and of same size
626  // as mxArray. This is a single-channel multi-dimensional array.
627  std::vector<int> d(dims(), dims() + ndims());
628  depth = (depth == CV_USRTYPE1) ? DepthOf[classID()] : depth;
629  cv::MatND mat(d.size(), &d[0], CV_MAKETYPE(depth, 1));
630 
631  // Copy data from mxArray to cv::MatND (converting to specified depth)
632  {
633  // wrap source data using a cv::Mat (only creates header, data shared)
634  const int type = CV_MAKETYPE(DepthOf[classID()], 1); // source type
635  const cv::MatND m(d.size(), &d[0], type, mxGetData(lhs));
636 
637  // Read from mxArray through m, writing into mat
638  m.convertTo(mat, CV_MAKETYPE(depth, 1));
639  }
640 
641  // clean temporary copy, and return result
642  mxDestroyArray(lhs);
643  return mat;
644 }
645 #endif
646 
647 cv::SparseMat MxArray::toSparseMat(int depth) const
648 {
649  // check if it's sparse. MATLAB only has 2D double sparse arrays.
650  if (!isSparse() || !isDouble() || isComplex() || ndims() != 2)
651  mexErrMsgIdAndTxt("mexopencv:error",
652  "MxArray is not real 2D double sparse");
653 
654  // create cv::SparseMat of same size and requested depth
655  depth = (depth == CV_USRTYPE1) ? DepthOf[classID()] : depth;
656  const mwSize m = rows(), n = cols();
657  const int dims[] = {static_cast<int>(m), static_cast<int>(n)};
658  cv::SparseMat mat(2, dims, depth);
659 
660  // get pointers to data (PR, IR, JC)
661  const mwIndex *ir = mxGetIr(p_); // array of length nzmax
662  const mwIndex *jc = mxGetJc(p_); // array of length n+1
663  const double *pr = mxGetPr(p_); // array of length nzmax
664  if (!ir || !jc || !pr)
665  mexErrMsgIdAndTxt("mexopencv:error", "Null pointer error");
666 
667  // copy data by converting from CSC format to (row,col,val) triplets
668  for (mwIndex j = 0; j < n; ++j) {
669  // JC contains indices into PR and IR of the first non-zero value in a column
670  const mwIndex start = jc[j], end = jc[j+1];
671  for (mwIndex i = start; i < end; ++i) {
672  // mat(row,col) = val, casting double value to depth
673  //TODO: consider using cv::saturate_cast instead of static_cast
674  switch (mat.depth()) {
675  case CV_8U:
676  mat.ref<uchar>(ir[i], j) = static_cast<uchar>(pr[i]);
677  break;
678  case CV_8S:
679  mat.ref<schar>(ir[i], j) = static_cast<schar>(pr[i]);
680  break;
681  case CV_16U:
682  mat.ref<ushort>(ir[i], j) = static_cast<ushort>(pr[i]);
683  break;
684  case CV_16S:
685  mat.ref<short>(ir[i], j) = static_cast<short>(pr[i]);
686  break;
687  case CV_32S:
688  mat.ref<int>(ir[i], j) = static_cast<int>(pr[i]);
689  break;
690  case CV_32F:
691  mat.ref<float>(ir[i], j) = static_cast<float>(pr[i]);
692  break;
693  case CV_64F:
694  mat.ref<double>(ir[i], j) = pr[i];
695  break;
696  default:
697  break; // should never reach this case
698  }
699  }
700  }
701  //CV_DbgAssert(mat.nzcount() == nzmax()); // sanity check
702  return mat;
703 }
704 
705 cv::Moments MxArray::toMoments(mwIndex index) const
706 {
707  // the muXX and nuXX are computed from mXX
708  return cv::Moments(
709  (isField("m00")) ? at("m00", index).toDouble() : 0,
710  (isField("m10")) ? at("m10", index).toDouble() : 0,
711  (isField("m01")) ? at("m01", index).toDouble() : 0,
712  (isField("m20")) ? at("m20", index).toDouble() : 0,
713  (isField("m11")) ? at("m11", index).toDouble() : 0,
714  (isField("m02")) ? at("m02", index).toDouble() : 0,
715  (isField("m30")) ? at("m30", index).toDouble() : 0,
716  (isField("m12")) ? at("m12", index).toDouble() : 0,
717  (isField("m21")) ? at("m21", index).toDouble() : 0,
718  (isField("m03")) ? at("m03", index).toDouble() : 0
719  );
720 }
721 
722 cv::KeyPoint MxArray::toKeyPoint(mwIndex index) const
723 {
724  return cv::KeyPoint(
725  at("pt", index).toPoint2f(),
726  at("size", index).toFloat(),
727  (isField("angle")) ? at("angle", index).toFloat() : -1,
728  (isField("response")) ? at("response", index).toFloat() : 0,
729  (isField("octave")) ? at("octave", index).toInt() : 0,
730  (isField("class_id")) ? at("class_id", index).toInt() : -1
731  );
732 }
733 
734 cv::DMatch MxArray::toDMatch(mwIndex index) const
735 {
736  return cv::DMatch(
737  (isField("queryIdx")) ? at("queryIdx", index).toInt() : 0,
738  (isField("trainIdx")) ? at("trainIdx", index).toInt() : 0,
739  (isField("imgIdx")) ? at("imgIdx", index).toInt() : 0,
740  (isField("distance")) ? at("distance", index).toFloat() : 0
741  );
742 }
743 
744 cv::Range MxArray::toRange() const
745 {
746  cv::Range r;
747  if (isNumeric() && numel()==2)
748  r = cv::Range(at<int>(0), at<int>(1));
749  else if (isChar() && toString()==":")
750  r = cv::Range::all();
751  else
752  mexErrMsgIdAndTxt("mexopencv:error", "Invalid range value");
753  return r;
754 }
755 
756 cv::RotatedRect MxArray::toRotatedRect(mwIndex index) const
757 {
758  cv::RotatedRect rr;
759  if (isField("center")) rr.center = at("center", index).toPoint_<float>();
760  if (isField("size")) rr.size = at("size", index).toSize_<float>();
761  if (isField("angle")) rr.angle = at("angle", index).toFloat();
762  return rr;
763 }
764 
765 cv::TermCriteria MxArray::toTermCriteria(mwIndex index) const
766 {
767  const MxArray _type(at("type", index));
768  return cv::TermCriteria(
769  (_type.isChar()) ? TermCritType[_type.toString()] : _type.toInt(),
770  at("maxCount", index).toInt(),
771  at("epsilon", index).toDouble()
772  );
773 }
774 
775 std::string MxArray::fieldname(int fieldnumber) const
776 {
777  if (!isStruct())
778  mexErrMsgIdAndTxt("mexopencv:error", "MxArray is not struct");
779  const char *fname = mxGetFieldNameByNumber(p_, fieldnumber);
780  if (!fname)
781  mexErrMsgIdAndTxt("mexopencv:error",
782  "Failed to get field name at %d\n", fieldnumber);
783  return std::string(fname);
784 }
785 
786 std::vector<std::string> MxArray::fieldnames() const
787 {
788  if (!isStruct())
789  mexErrMsgIdAndTxt("mexopencv:error", "MxArray is not a struct array");
790  const mwSize n = nfields();
791  std::vector<std::string> v;
792  v.reserve(n);
793  for (mwIndex i = 0; i < n; ++i)
794  v.push_back(fieldname(i));
795  return v;
796 }
797 
798 mwIndex MxArray::subs(mwIndex i, mwIndex j) const
799 {
800  if (i >= rows() || j >= cols())
801  mexErrMsgIdAndTxt("mexopencv:error", "Subscript out of range");
802  mwIndex si[] = {i, j};
803  return mxCalcSingleSubscript(p_, 2, si);
804 }
805 
806 mwIndex MxArray::subs(const std::vector<mwIndex>& si) const
807 {
808  std::vector<mwIndex> v(si);
809  return mxCalcSingleSubscript(p_, si.size(), (!v.empty() ? &v[0] : NULL));
810 }
811 
812 MxArray MxArray::at(const std::string& fieldName, mwIndex index) const
813 {
814  if (!isStruct())
815  mexErrMsgIdAndTxt("mexopencv:error", "MxArray is not struct");
816  if (numel() <= index)
817  mexErrMsgIdAndTxt("mexopencv:error", "Index out of range");
818  const mxArray* pm = mxGetField(p_, index, fieldName.c_str());
819  if (!pm)
820  mexErrMsgIdAndTxt("mexopencv:error",
821  "Field '%s' doesn't exist", fieldName.c_str());
822  return MxArray(pm);
823 }
824 
825 template <>
826 MxArray MxArray::at(mwIndex index) const
827 {
828  if (!isCell())
829  mexErrMsgIdAndTxt("mexopencv:error", "MxArray is not cell");
830  if (numel() <= index)
831  mexErrMsgIdAndTxt("mexopencv:error", "Index out of range");
832  return MxArray(mxGetCell(p_, index));
833 }
834 
835 template <>
836 void MxArray::set(mwIndex index, const MxArray& value)
837 {
838  if (!isCell())
839  mexErrMsgIdAndTxt("mexopencv:error", "MxArray is not cell");
840  if (numel() <= index)
841  mexErrMsgIdAndTxt("mexopencv:error", "Index out of range");
842  mxSetCell(const_cast<mxArray*>(p_), index, static_cast<mxArray*>(value));
843 }
844 
845 template <>
846 std::vector<MxArray> MxArray::toVector() const
847 {
848  std::vector<MxArray> v;
849  if (isCell()) {
850  const mwSize n = numel();
851  v.reserve(n);
852  for (mwIndex i = 0; i < n; ++i)
853  //v.push_back(at<MxArray>(i));
854  v.push_back(MxArray(mxGetCell(p_, i)));
855  }
856  else
857  v.push_back(*this);
858  return v;
859 }
860 
861 template <>
862 std::vector<std::string> MxArray::toVector() const
863 {
864  return toVector(
865  std::const_mem_fun_ref_t<std::string,MxArray>(&MxArray::toString));
866 }
867 
868 template <>
869 std::vector<cv::Mat> MxArray::toVector() const
870 {
871  const std::vector<MxArray> v(toVector<MxArray>());
872  std::vector<cv::Mat> vm;
873  vm.reserve(v.size());
874  for (std::vector<MxArray>::const_iterator it = v.begin(); it != v.end(); ++it)
875  vm.push_back((*it).toMat());
876  return vm;
877 }
878 
879 template <>
880 std::vector<cv::Point> MxArray::toVector() const
881 {
882  if (isNumeric()) {
883  std::vector<cv::Point> vp;
884  if (numel() == 2)
885  vp.push_back(toPoint());
886  else
887  toMat(CV_32S).reshape(2, 0).copyTo(vp);
888  return vp;
889  }
890  else {
891  return toVector(
892  std::const_mem_fun_ref_t<cv::Point, MxArray>(
893  &MxArray::toPoint_<int>));
894  }
895 }
896 
897 template <>
898 std::vector<cv::Point2f> MxArray::toVector() const
899 {
900  if (isNumeric()) {
901  std::vector<cv::Point2f> vp;
902  if (numel() == 2)
903  vp.push_back(toPoint2f());
904  else
905  toMat(CV_32F).reshape(2, 0).copyTo(vp);
906  return vp;
907  }
908  else {
909  return toVector(
910  std::const_mem_fun_ref_t<cv::Point2f, MxArray>(
911  &MxArray::toPoint_<float>));
912  }
913 }
914 
915 template <>
916 std::vector<cv::Point2d> MxArray::toVector() const
917 {
918  if (isNumeric()) {
919  std::vector<cv::Point2d> vp;
920  if (numel() == 2)
921  vp.push_back(toPoint_<double>());
922  else
923  toMat(CV_64F).reshape(2, 0).copyTo(vp);
924  return vp;
925  }
926  else {
927  return toVector(
928  std::const_mem_fun_ref_t<cv::Point2d, MxArray>(
929  &MxArray::toPoint_<double>));
930  }
931 }
932 
933 template <>
934 std::vector<cv::Point3i> MxArray::toVector() const
935 {
936  if (isNumeric()) {
937  std::vector<cv::Point3i> vp;
938  if (numel() == 3)
939  vp.push_back(toPoint3_<int>());
940  else
941  toMat(CV_32S).reshape(3, 0).copyTo(vp);
942  return vp;
943  }
944  else {
945  return toVector(
946  std::const_mem_fun_ref_t<cv::Point3i, MxArray>(
947  &MxArray::toPoint3_<int>));
948  }
949 }
950 
951 template <>
952 std::vector<cv::Point3f> MxArray::toVector() const
953 {
954  if (isNumeric()) {
955  std::vector<cv::Point3f> vp;
956  if (numel() == 3)
957  vp.push_back(toPoint3f());
958  else
959  toMat(CV_32F).reshape(3, 0).copyTo(vp);
960  return vp;
961  }
962  else {
963  return toVector(
964  std::const_mem_fun_ref_t<cv::Point3f, MxArray>(
965  &MxArray::toPoint3_<float>));
966  }
967 }
968 
969 template <>
970 std::vector<cv::Point3d> MxArray::toVector() const
971 {
972  if (isNumeric()) {
973  std::vector<cv::Point3d> vp;
974  if (numel() == 3)
975  vp.push_back(toPoint3_<double>());
976  else
977  toMat(CV_64F).reshape(3, 0).copyTo(vp);
978  return vp;
979  }
980  else {
981  return toVector(
982  std::const_mem_fun_ref_t<cv::Point3d, MxArray>(
983  &MxArray::toPoint3_<double>));
984  }
985 }
986 
987 template <>
988 std::vector<cv::Size> MxArray::toVector() const
989 {
990  if (isNumeric()) {
991  std::vector<cv::Size> vs;
992  if (numel() == 2)
993  vs.push_back(toSize());
994  else
995  toMat(CV_32S).reshape(2, 0).copyTo(vs);
996  return vs;
997  }
998  else {
999  return toVector(
1000  std::const_mem_fun_ref_t<cv::Size, MxArray>(&MxArray::toSize));
1001  }
1002 }
1003 
1004 template <>
1005 std::vector<cv::Rect> MxArray::toVector() const
1006 {
1007  if (isNumeric()) {
1008  std::vector<cv::Rect> vr;
1009  if (numel() == 4)
1010  vr.push_back(toRect());
1011  else
1012  toMat(CV_32S).reshape(4, 0).copyTo(vr);
1013  return vr;
1014  }
1015  else {
1016  return toVector(
1017  std::const_mem_fun_ref_t<cv::Rect, MxArray>(&MxArray::toRect));
1018  }
1019 }
1020 
1021 template <>
1022 std::vector<cv::Vec2i> MxArray::toVector() const
1023 {
1024  if (isNumeric()) {
1025  std::vector<cv::Vec2i> vv;
1026  if (numel() == 2)
1027  vv.push_back(toVec<int,2>());
1028  else
1029  toMat(CV_32S).reshape(2, 0).copyTo(vv);
1030  return vv;
1031  }
1032  else {
1033  return toVector(
1034  std::const_mem_fun_ref_t<cv::Vec2i, MxArray>(
1035  &MxArray::toVec<int,2>));
1036  }
1037 }
1038 
1039 template <>
1040 std::vector<cv::Vec2f> MxArray::toVector() const
1041 {
1042  if (isNumeric()) {
1043  std::vector<cv::Vec2f> vv;
1044  if (numel() == 2)
1045  vv.push_back(toVec<float,2>());
1046  else
1047  toMat(CV_32F).reshape(2, 0).copyTo(vv);
1048  return vv;
1049  }
1050  else {
1051  return toVector(
1052  std::const_mem_fun_ref_t<cv::Vec2f, MxArray>(
1053  &MxArray::toVec<float,2>));
1054  }
1055 }
1056 
1057 template <>
1058 std::vector<cv::Vec3i> MxArray::toVector() const
1059 {
1060  if (isNumeric()) {
1061  std::vector<cv::Vec3i> vv;
1062  if (numel() == 3)
1063  vv.push_back(toVec<int,3>());
1064  else
1065  toMat(CV_32S).reshape(3, 0).copyTo(vv);
1066  return vv;
1067  }
1068  else {
1069  return toVector(
1070  std::const_mem_fun_ref_t<cv::Vec3i, MxArray>(
1071  &MxArray::toVec<int,3>));
1072  }
1073 }
1074 
1075 template <>
1076 std::vector<cv::Vec3f> MxArray::toVector() const
1077 {
1078  if (isNumeric()) {
1079  std::vector<cv::Vec3f> vv;
1080  if (numel() == 3)
1081  vv.push_back(toVec<float,3>());
1082  else
1083  toMat(CV_32F).reshape(3, 0).copyTo(vv);
1084  return vv;
1085  }
1086  else {
1087  return toVector(
1088  std::const_mem_fun_ref_t<cv::Vec3f, MxArray>(
1089  &MxArray::toVec<float,3>));
1090  }
1091 }
1092 
1093 template <>
1094 std::vector<cv::Vec4i> MxArray::toVector() const
1095 {
1096  if (isNumeric()) {
1097  std::vector<cv::Vec4i> vv;
1098  if (numel() == 4)
1099  vv.push_back(toVec<int,4>());
1100  else
1101  toMat(CV_32S).reshape(4, 0).copyTo(vv);
1102  return vv;
1103  }
1104  else {
1105  return toVector(
1106  std::const_mem_fun_ref_t<cv::Vec4i, MxArray>(
1107  &MxArray::toVec<int,4>));
1108  }
1109 }
1110 
1111 template <>
1112 std::vector<cv::Vec4f> MxArray::toVector() const
1113 {
1114  if (isNumeric()) {
1115  std::vector<cv::Vec4f> vv;
1116  if (numel() == 4)
1117  vv.push_back(toVec<float,4>());
1118  else
1119  toMat(CV_32F).reshape(4, 0).copyTo(vv);
1120  return vv;
1121  }
1122  else {
1123  return toVector(
1124  std::const_mem_fun_ref_t<cv::Vec4f, MxArray>(
1125  &MxArray::toVec<float,4>));
1126  }
1127 }
1128 
1129 template <>
1130 std::vector<cv::RotatedRect> MxArray::toVector() const
1131 {
1132  const mwSize n = numel();
1133  std::vector<cv::RotatedRect> v;
1134  v.reserve(n);
1135  if (isCell())
1136  for (mwIndex i = 0; i < n; ++i)
1137  v.push_back(at<MxArray>(i).toRotatedRect());
1138  else if (isStruct())
1139  for (mwIndex i = 0; i < n; ++i)
1140  v.push_back(toRotatedRect(i));
1141  else
1142  mexErrMsgIdAndTxt("mexopencv:error",
1143  "MxArray unable to convert to std::vector<cv::RotatedRect>");
1144  return v;
1145 }
1146 
1147 template <>
1148 std::vector<cv::KeyPoint> MxArray::toVector() const
1149 {
1150  const mwSize n = numel();
1151  std::vector<cv::KeyPoint> v;
1152  v.reserve(n);
1153  if (isCell())
1154  for (mwIndex i = 0; i < n; ++i)
1155  v.push_back(at<MxArray>(i).toKeyPoint());
1156  else if (isStruct())
1157  for (mwIndex i = 0; i < n; ++i)
1158  v.push_back(toKeyPoint(i));
1159  else
1160  mexErrMsgIdAndTxt("mexopencv:error",
1161  "MxArray unable to convert to std::vector<cv::KeyPoint>");
1162  return v;
1163 }
1164 
1165 template <>
1166 std::vector<cv::DMatch> MxArray::toVector() const
1167 {
1168  const mwSize n = numel();
1169  std::vector<cv::DMatch> v;
1170  v.reserve(n);
1171  if (isCell())
1172  for (mwIndex i = 0; i < n; ++i)
1173  v.push_back(at<MxArray>(i).toDMatch());
1174  else if (isStruct())
1175  for (mwIndex i = 0; i < n; ++i)
1176  v.push_back(toDMatch(i));
1177  else
1178  mexErrMsgIdAndTxt("mexopencv:error",
1179  "MxArray unable to convert to std::vector<cv::DMatch>");
1180  return v;
1181 }
bool isSparse() const
Determine whether input is sparse array.
Definition: MxArray.hpp:704
bool isStruct() const
Determine whether input is structure array.
Definition: MxArray.hpp:708
cv::MatND toMatND(int depth=CV_USRTYPE1, bool transpose=true) const
Convert MxArray to a single-channel cv::Mat.
Definition: MxArray.cpp:601
cv::Point2f toPoint2f() const
Alias to toPoint_<float>.
Definition: MxArray.hpp:515
cv::Size toSize() const
Alias to toSize_<int>.
Definition: MxArray.hpp:523
mwIndex subs(mwIndex i, mwIndex j=0) const
Offset from first element to desired element.
Definition: MxArray.cpp:798
std::vector< std::string > fieldnames() const
Get field names of a struct array.
Definition: MxArray.cpp:786
void set(mwIndex index, const T &value)
Template for numeric array element write accessor.
Definition: MxArray.hpp:1310
bool isChar() const
Determine whether input is string array.
Definition: MxArray.hpp:614
cv::RotatedRect toRotatedRect(mwIndex index=0) const
Convert MxArray to cv::RotatedRect.
Definition: MxArray.cpp:756
int MexErrorHandler(int status, const char *func_name, const char *err_msg, const char *file_name, int line, void *)
Cutom error callback to be invoked by cv::error(), CV_Assert, etc...
Definition: MxArray.cpp:86
double toDouble() const
Convert MxArray to double.
Definition: MxArray.cpp:496
int toInt() const
Convert MxArray to int.
Definition: MxArray.cpp:489
mxClassID classID() const
Class ID of mxArray.
Definition: MxArray.hpp:535
cv::Range toRange() const
Convert MxArray to cv::Range.
Definition: MxArray.cpp:744
cv::Point toPoint() const
Alias to toPoint_<int>.
Definition: MxArray.hpp:511
float toFloat() const
Convert MxArray to float.
Definition: MxArray.cpp:503
std::vector< T > toVector() const
Convert MxArray to std::vector<T> of primitive types.
Definition: MxArray.hpp:1151
cv::DMatch toDMatch(mwIndex index=0) const
Convert MxArray to cv::DMatch.
Definition: MxArray.cpp:734
MxArray and ConstMap declaration.
bool isComplex() const
Determine whether data is complex.
Definition: MxArray.hpp:632
mxArray object wrapper for data conversion and manipulation.
Definition: MxArray.hpp:123
cv::Point3f toPoint3f() const
Alias to toPoint3_<float>.
Definition: MxArray.hpp:519
bool toBool() const
Convert MxArray to bool.
Definition: MxArray.cpp:510
cv::TermCriteria toTermCriteria(mwIndex index=0) const
Convert MxArray to cv::TermCriteria.
Definition: MxArray.cpp:765
bool isNull() const
Determine whether the array is initialized or not.
Definition: MxArray.hpp:606
cv::Moments toMoments(mwIndex index=0) const
Convert MxArray to cv::Moments.
Definition: MxArray.cpp:705
bool isField(const std::string &fieldName) const
Determine whether a struct array has a specified field.
Definition: MxArray.hpp:743
std::string fieldname(int fieldnumber) const
Get specified field name from a struct array.
Definition: MxArray.cpp:775
bool isLogical() const
Determine whether array is of type mxLogical.
Definition: MxArray.hpp:678
cv::KeyPoint toKeyPoint(mwIndex index=0) const
Convert MxArray to cv::KeyPoint.
Definition: MxArray.cpp:722
mwSize numel() const
Number of elements in an array.
Definition: MxArray.hpp:546
int nfields() const
Number of fields in a struct array.
Definition: MxArray.hpp:569
MxArray(const mxArray *arr)
MxArray constructor from mxArray*.
Definition: MxArray.hpp:129
mwSize ndims() const
Number of dimensions.
Definition: MxArray.hpp:550
bool isDouble() const
Determine whether mxArray represents data as double-precision, floating-point numbers.
Definition: MxArray.hpp:637
cv::Rect toRect() const
Alias to toRect_<int>.
Definition: MxArray.hpp:527
T at(mwIndex index) const
Template for numeric array element accessor.
Definition: MxArray.hpp:1250
std::map wrapper with one-line initialization and lookup method.
Definition: MxArray.hpp:927
MxArray clone() const
Clone mxArray.
Definition: MxArray.cpp:481
const mwSize * dims() const
Array of each dimension.
Definition: MxArray.hpp:554
std::string toString() const
Convert MxArray to std::string.
Definition: MxArray.cpp:517
cv::SparseMat toSparseMat(int depth=CV_USRTYPE1) const
Convert double sparse MxArray to 2D single-channel cv::SparseMat.
Definition: MxArray.cpp:647
cv::Mat toMat(int depth=CV_USRTYPE1, bool transpose=true) const
Convert MxArray to cv::Mat.
Definition: MxArray.cpp:529
bool isNumeric() const
Determine whether array is numeric.
Definition: MxArray.hpp:695
mwSize rows() const
Number of rows in an array.
Definition: MxArray.hpp:558
MxArray & operator=(const MxArray &rhs)
Assignment operator.
Definition: MxArray.cpp:102
mwSize cols() const
Number of columns in an array.
Definition: MxArray.hpp:565
bool isCell() const
Determine whether input is cell array.
Definition: MxArray.hpp:610