-
Notifications
You must be signed in to change notification settings - Fork 10
/
MxArray.hpp
1796 lines (1728 loc) · 61 KB
/
MxArray.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/** MxArray and ConstMap declaration.
* @file MxArray.hpp
* @author Kota Yamaguchi
* @date 2012
*/
#ifndef __MXARRAY_HPP__
#define __MXARRAY_HPP__
#include <functional>
#include <map>
#include <stdint.h>
#include <string>
#include "mex.h"
#include "opencv2/opencv.hpp"
/** Type traits for mxArray.
*/
template <typename T>
struct MxTypes {
/// maps general template parameter to unkown MATLAB type.
static const mxClassID type = mxUNKNOWN_CLASS;
};
/** int8_t traits.
*/
template<> struct MxTypes<int8_t> {
/// maps \c int8_t to \c int8 MATLAB type.
static const mxClassID type = mxINT8_CLASS;
};
/** uint8_t traits.
*/
template<> struct MxTypes<uint8_t> {
/// maps \c uint8_t to \c uint8 MATLAB type.
static const mxClassID type = mxUINT8_CLASS;
};
/** int16_t traits.
*/
template<> struct MxTypes<int16_t> {
/// maps \c int16_t to \c int16 MATLAB type.
static const mxClassID type = mxINT16_CLASS;
};
/** uint16_t traits.
*/
template<> struct MxTypes<uint16_t> {
/// maps \c uint16_t to \c uint16 MATLAB type.
static const mxClassID type = mxUINT16_CLASS;
};
/** int32_t traits.
*/
template<> struct MxTypes<int32_t> {
/// maps \c int32_t to \c int32 MATLAB type.
static const mxClassID type = mxINT32_CLASS;
};
/** uint32_t traits.
*/
template<> struct MxTypes<uint32_t> {
/// maps \c uint32_t to \c uint32 MATLAB type.
static const mxClassID type = mxUINT32_CLASS;
};
/** int64_t traits.
*/
template<> struct MxTypes<int64_t> {
/// maps \c int64_t to \c int64 MATLAB type.
static const mxClassID type = mxINT64_CLASS;
};
/** uint64_t traits.
*/
template<> struct MxTypes<uint64_t> {
/// maps \c uint64_t to \c uint64 MATLAB type.
static const mxClassID type = mxUINT64_CLASS;
};
/** float traits.
*/
template<> struct MxTypes<float> {
/// maps \c float to \c single MATLAB type.
static const mxClassID type = mxSINGLE_CLASS;
};
/** double traits.
*/
template<> struct MxTypes<double> {
/// maps \c double to \c double MATLAB type.
static const mxClassID type = mxDOUBLE_CLASS;
};
/** char traits.
*/
template<> struct MxTypes<char> {
/// maps \c char to \c mxChar MATLAB type.
static const mxClassID type = mxCHAR_CLASS;
};
/** bool traits.
*/
template<> struct MxTypes<bool> {
/// maps \c bool to \c mxLogical MATLAB type.
static const mxClassID type = mxLOGICAL_CLASS;
};
/** mxArray object wrapper for data conversion and manipulation.
*/
class MxArray
{
public:
/** MxArray constructor from mxArray*.
* @param arr mxArray pointer given by mexFunction.
*/
MxArray(const mxArray *arr) : p_(arr) {}
/** Copy constructor.
* @param arr Another MxArray.
*/
MxArray(const MxArray& arr) : p_(arr.p_) {}
/** Assignment operator.
* @param rhs Reference to another MxArray.
* @return reference to current MxArray object (for chained calls).
*/
MxArray& operator=(const MxArray& rhs);
/** MxArray constructor from int.
* @param i int value.
* @return MxArray object, a scalar double array.
*/
explicit MxArray(const int i);
/** MxArray constructor from double.
* @param d double value.
* @return MxArray object, a scalar double array.
*/
explicit MxArray(const double d);
/** MxArray constructor from bool.
* @param b bool value.
* @return MxArray object, a scalar logical array.
*/
explicit MxArray(const bool b);
/** MxArray constructor from std::string.
* @param s reference to a string value.
* @return MxArray object.
*/
explicit MxArray(const std::string& s);
/** Convert cv::Mat to MxArray.
* @param mat cv::Mat object.
* @param classid classid of mxArray. e.g., \c mxDOUBLE_CLASS. When
* \c mxUNKNOWN_CLASS is specified, classid will be automatically
* determined from the type of cv::Mat. default: \c mxUNKNOWN_CLASS.
* @param transpose Optional transposition to the return value so that
* rows and columns of the 2D Mat are mapped to the 2nd and 1st
* dimensions in MxArray, respectively. This does not apply the N-D
* array conversion. default true.
* @return MxArray object.
*
* Convert cv::Mat object to an MxArray. When the cv::Mat object is 2D, the
* width, height, and channels are mapped to the first, second, and third
* dimensions of the MxArray unless \p transpose flag is set to false. When
* the cv::Mat object is N-D, <tt>(dim 1, dim 2,...dim N, channels)</tt>
* are mapped to <tt>(dim 2, dim 1, ..., dim N, dim N+1)</tt>,
* respectively.
*
* Example:
* @code
* cv::Mat x(120, 90, CV_8UC3, Scalar(0));
* mxArray* plhs[0] = MxArray(x);
* @endcode
*/
explicit MxArray(const cv::Mat& mat,
mxClassID classid = mxUNKNOWN_CLASS, bool transpose = true);
/** Convert float cv::SparseMat to MxArray.
* @param mat cv::SparseMat object.
* @return MxArray object, a 2D sparse array.
*/
explicit MxArray(const cv::SparseMat& mat);
/** Convert cv::Moments to MxArray.
* @param m cv::Moments object.
* @return MxArray object, a scalar struct array.
*/
explicit MxArray(const cv::Moments& m);
/** Convert cv::KeyPoint to MxArray.
* @param p cv::KeyPoint object.
* @return MxArray object, a scalar struct array.
*/
explicit MxArray(const cv::KeyPoint& p);
/** Convert cv::DMatch to MxArray.
* @param m cv::DMatch object.
* @return MxArray object, a scalar struct array.
*/
explicit MxArray(const cv::DMatch& m);
/** Convert cv::RotatedRect to MxArray.
* @param r cv::RotatedRect object.
* @return MxArray object, a scalar struct array.
*/
explicit MxArray(const cv::RotatedRect& r);
/** Convert cv::TermCriteria to MxArray.
* @param t cv::TermCriteria object.
* @return MxArray object, a scalar struct array.
*/
explicit MxArray(const cv::TermCriteria& t);
/** MxArray constructor from vector<T>.
* @param v vector of type T.
* @return MxArray object, a numeric or a cell array.
*
* The constructor forwards the call to an appropriate overloaded method
* according to the paramter type (tag dispatching by instance).
* In the general case, vectors of primitive types are converted to
* numeric arrays of the equivalent MATLAB type, while other types are
* converted to cell arrays.
*
* Example:
* @code
* std::vector<double> v(10, 1.0);
* mxArray* plhs[0] = MxArray(v);
* @endcode
*/
template <typename T> explicit MxArray(const std::vector<T>& v)
{
// we do this: fromVector(v) as opposed to: fromVector<T>(v),
// that way the call gets resolved to overloaded or
// template-specialized version appropriately.
// (although we dont currently have an overloaded version)
fromVector(v);
}
/** MxArray constructor from cv::Point_<T>.
* @param p cv::Point_<T> object.
* @return two-element numeric MxArray <tt>[x, y]</tt>.
*/
template <typename T> explicit MxArray(const cv::Point_<T>& p);
/** MxArray constructor from cv::Point3_<T>.
* @param p cv::Point3_<T> object.
* @return three-element numeric MxArray <tt>[x, y, z]</tt>.
*/
template <typename T> explicit MxArray(const cv::Point3_<T>& p);
/** MxArray constructor from cv::Size_<T>.
* @param s cv::Size_<T> object.
* @return two-element numeric MxArray.
*/
template <typename T> explicit MxArray(const cv::Size_<T>& s);
/** MxArray constructor from cv::Rect_<T>.
* @param r cv::Rect_<T> object.
* @return four-element numeric MxArray <tt>[x, y, width, height]</tt>.
*/
template <typename T> explicit MxArray(const cv::Rect_<T>& r);
/** MxArray constructor from cv::Scalar_<T>.
* @param s cv::Scalar_<T> object.
* @return four-element numeric MxArray <tt>[v0, v1, v2, v3]</tt>.
*/
template <typename T> explicit MxArray(const cv::Scalar_<T>& s);
/** MxArray constructor from cv::Vec<T,cn>.
* @param vec cv::Vec<T,cn> object.
* @return \c cn -element numeric MxArray <tt>[v0, v1, ...]</tt>.
*/
template <typename T, int cn> explicit MxArray(const cv::Vec<T,cn>& vec);
/** MxArray constructor from cv::Matx<T,m,n>.
* @param mat cv::Mat<T,m,n> object.
* @return \c m-by-n numeric MxArray matrix
* <tt>[mat_11, ..., mat_1n; ....; mat_m1, ..., mat_mn]</tt>.
*/
template <typename T, int m, int n> explicit MxArray(const cv::Matx<T,m,n>& mat);
/** Destructor. This does not free the underlying mxArray*.
*/
virtual ~MxArray() {}
/** Create a new cell array.
* @param m Number of rows.
* @param n Number of cols.
* @return MxArray object, a 2D cell array with uninitialized cells.
*
* Example:
* @code
* MxArray c = MxArray::Cell(2,1);
* c.set(0, MxArray(1));
* c.set(1, MxArray(std::string("some value")));
* @endcode
*/
static inline MxArray Cell(mwSize m = 1, mwSize n = 1)
{
mxArray *pm = mxCreateCellMatrix(m,n);
if (!pm)
mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
return MxArray(pm);
}
/** Create a new struct array.
* @param fields Field names.
* @param nfields Number of fields.
* @param m Number of rows (size of the first dimension).
* @param n Number of cols (size of the second dimension).
* @return MxArray object, a 2D struct array with uninitialized fields.
*
* Example:
* @code
* const char* fields[] = {"field1", "field2"};
* MxArray s = MxArray::Struct(fields, 2);
* s.set("field1", 1);
* s.set("field2", "field2 value");
* @endcode
*/
static inline MxArray Struct(const char** fields = NULL,
int nfields = 0, mwSize m = 1, mwSize n = 1)
{
mxArray *pm = mxCreateStructMatrix(m, n, nfields, fields);
if (!pm)
mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
return MxArray(pm);
}
/** Clone mxArray. This allocates new mxArray*.
* @return MxArray object, a deep-copy clone.
*/
MxArray clone() const;
/** Deallocate memory occupied by mxArray.
*
* Use this to destroy a temporary mxArray. Do not call this on arrays
* you are returning to MATLAB as left-hand side.
*/
void destroy() { mxDestroyArray(const_cast<mxArray*>(p_)); }
/** Implicit conversion to const mxArray*.
* @return const mxArray* pointer.
*/
operator const mxArray*() const { return p_; };
/** Implicit conversion to mxArray*.
* @return mxArray* pointer.
*
* Be careful that this internally casts away mxArray* constness.
*/
operator mxArray*() const { return const_cast<mxArray*>(p_); };
/** Convert MxArray to int.
* @return int value.
*/
int toInt() const;
/** Convert MxArray to double.
* @return double value.
*/
double toDouble() const;
/** Convert MxArray to float.
* @return float value.
*/
float toFloat() const;
/** Convert MxArray to bool.
* @return bool value.
*/
bool toBool() const;
/** Convert MxArray to std::string.
* @return std::string value.
*/
std::string toString() const;
/** Convert MxArray to cv::Mat.
* @param depth depth of cv::Mat. e.g., \c CV_8U, \c CV_32F. When
* \c CV_USERTYPE1 is specified, depth will be automatically determined
* from the classid of the MxArray. default: \c CV_USERTYPE1.
* @param transpose Optional transposition to the return value so that
* rows and columns of the 2D Mat are mapped to the 2nd and 1st
* dimensions in MxArray, respectively. This does not apply the N-D
* array conversion. default true.
* @return cv::Mat object.
*
* Convert a MxArray object to a cv::Mat object. When the dimensionality
* of the MxArray is more than 2, the last dimension will be mapped to the
* channels of the cv::Mat. Also, if the resulting cv::Mat is 2D, the 1st
* and 2nd dimensions of the MxArray are mapped to rows and columns of the
* cv::Mat unless \p transpose flag is false. That is, when MxArray is 3D,
* <tt>(dim 1, dim 2, dim 3)</tt> are mapped to
* <tt>(cols, rows, channels)</tt> of the cv::Mat by default, whereas if
* MxArray is more than 4D, <tt>(dim 1, dim 2, ..., dim N-1, dim N)</tt>
* are mapped to <tt>(dim 2, dim 1, ..., dim N-1, channels)</tt> of the
* cv::Mat, respectively.
*
* Example:
* @code
* cv::Mat x(MxArray(prhs[0]).toMat());
* @endcode
*/
cv::Mat toMat(int depth = CV_USRTYPE1, bool transpose = true) const;
/** Convert MxArray to a single-channel cv::Mat.
* @param depth depth of cv::Mat. e.g., \c CV_8U, \c CV_32F. When
* \c CV_USERTYPE1 is specified, depth will be automatically determined
* from the the classid of the MxArray. default: \c CV_USERTYPE1.
* @param transpose Optional transposition to the return value so that
* rows and columns of the 2D Mat are mapped to the 2nd and 1st
* dimensions in MxArray, respectively. This does not apply the N-D
* array conversion. default true.
* @return const cv::Mat object.
*
* Convert a MxArray object to a single-channel cv::Mat object. If the
* MxArray is 2D, the 1st and 2nd dimensions of the MxArray are mapped to
* rows and columns of the cv::Mat unless \p transpose flag is false. If
* the MxArray is more than 3D, the 1st and 2nd dimensions of the MxArray
* are mapped to 2nd and 1st dimensions of the cv::Mat. That is, when
* MxArray is 2D, <tt>(dim 1, dim 2)</tt> are mapped to
* <tt>(cols, rows)</tt> of the cv::Mat by default, whereas if MxArray is
* more than 3D, <tt>(dim 1, dim 2, dim 3, ..., dim N)</tt> are mapped to
* <tt>(dim 2, dim 1, dim 3, ..., dim N)</tt> of the cv::Mat,
* respectively.
*
* Example:
* @code
* cv::Mat x(MxArray(prhs[0]).toMatND());
* @endcode
*/
cv::MatND toMatND(int depth = CV_USRTYPE1, bool transpose = true) const;
/** Convert double sparse MxArray to float cv::SparseMat.
* @return cv::SparseMat object.
*/
cv::SparseMat toSparseMat() const;
/** Convert MxArray to cv::Moments.
* @param index linear index of the struct array element.
* @return cv::Moments object.
*/
cv::Moments toMoments(mwIndex index = 0) const;
/** Convert MxArray to cv::KeyPoint.
* @param index linear index of the struct array element.
* @return cv::KeyPoint object.
*/
cv::KeyPoint toKeyPoint(mwIndex index = 0) const;
/** Convert MxArray to cv::DMatch.
* @param index linear index of the struct array element.
* @return cv::DMatch object.
*/
cv::DMatch toDMatch(mwIndex index = 0) const;
/** Convert MxArray to cv::Range.
* @return cv::Range object.
*/
cv::Range toRange() const;
/** Convert MxArray to cv::RotatedRect.
* @param index linear index of the struct array element.
* @return cv::RotatedRect object.
*/
cv::RotatedRect toRotatedRect(mwIndex index = 0) const;
/** Convert MxArray to cv::TermCriteria.
* @param index linear index of the struct array element.
* @return cv::TermCriteria object.
*/
cv::TermCriteria toTermCriteria(mwIndex index = 0) const;
/** Convert MxArray to Point_<T>.
* @return cv::Point_<T> value.
*/
template <typename T> cv::Point_<T> toPoint_() const;
/** Convert MxArray to Point3_<T>.
* @return cv::Poin3_<T> value.
*/
template <typename T> cv::Point3_<T> toPoint3_() const;
/** Convert MxArray to Size_<T>.
* @return cv::Size_<T> value.
*/
template <typename T> cv::Size_<T> toSize_() const;
/** Convert MxArray to Rect_<T>.
* @return cv::Rect_<T> value.
*/
template <typename T> cv::Rect_<T> toRect_() const;
/** Convert MxArray to Scalar_<T>.
* @return cv::Scalar_<T> value.
*/
template <typename T> cv::Scalar_<T> toScalar_() const;
/** Convert MxArray to Vec<T,cn>.
* @return cv::Vec<T,cn> value.
*/
template <typename T, int cn> cv::Vec<T,cn> toVec() const;
/** Convert MxArray to Matx<T,m,n>.
* @return cv::Matx<T,m,n> value.
*/
template <typename T, int m, int n> cv::Matx<T,m,n> toMatx() const;
/** Convert MxArray to std::vector<T> of primitive types.
* @return std::vector<T> value.
*
* The method is intended for conversion to a raw numeric vector such
* as std::vector<int> or std::vector<double>. Example:
*
* @code
* MxArray numArray(prhs[0]);
* vector<double> vd = numArray.toVector<double>();
* @endcode
*/
template <typename T> std::vector<T> toVector() const;
/** Convert MxArray to std::vector<T> by a specified conversion method.
* @param f member function of MxArray (e.g., &MxArray::toMat,
* &MxArray::toInt).
* @return std::vector<T> value.
*
* The method constructs std::vector<T> by applying conversion method \p f
* to each cell array element. This is similar to std::transform function.
* An example usage is shown below:
*
* @code
* MxArray cellArray(prhs[0]);
* const_mem_fun_ref_t<Point3i,MxArray> convert(&MxArray::toPoint3_<int>);
* vector<Point3i> v = cellArray.toVector(convert);
* @endcode
*/
template <typename T>
std::vector<T> toVector(std::const_mem_fun_ref_t<T, MxArray> f) const;
/** Alias to toPoint_<int>.
* @return cv::Point object.
*/
inline cv::Point toPoint() const { return toPoint_<int>(); }
/** Alias to toPoint_<float>.
* @return cv::Point2f object.
*/
inline cv::Point2f toPoint2f() const { return toPoint_<float>(); }
/** Alias to toPoint3_<float>.
* @return cv::Point3f object.
*/
inline cv::Point3f toPoint3f() const { return toPoint3_<float>(); }
/** Alias to toSize_<int>.
* @return cv::Size object.
*/
inline cv::Size toSize() const { return toSize_<int>(); }
/** Alias to toRect_<int>.
* @return cv::Rect object.
*/
inline cv::Rect toRect() const { return toRect_<int>(); }
/** Alias to toScalar_<double>
* @return cv::Scalar object.
*/
inline cv::Scalar toScalar() const { return toScalar_<double>(); }
/** Class ID of mxArray.
* @return identifier of the array class, enum value of type mxClassID.
*/
inline mxClassID classID() const { return mxGetClassID(p_); }
/** Class name of mxArray.
* @return class name of the array, as a string.
*/
inline const std::string className() const
{
return std::string(mxGetClassName(p_));
}
/** Number of elements in an array.
* @return number of elements in the array
*/
inline mwSize numel() const { return mxGetNumberOfElements(p_); }
/** Number of dimensions.
* @return number of dimension in the array, always >= 2.
*/
inline mwSize ndims() const { return mxGetNumberOfDimensions(p_); }
/** Array of each dimension.
* @return array of dimensions, number of elements in each dimension.
*/
inline const mwSize* dims() const { return mxGetDimensions(p_); };
/** Number of rows in an array.
* @return number of rows in the array (first dimension).
*/
inline mwSize rows() const { return mxGetM(p_); }
/** Number of columns in an array.
* @return number of cols in the array.
*
* If the array is N-dimensional, this returns the product of dimensions
* 2 through N.
*/
inline mwSize cols() const { return mxGetN(p_); }
/** Number of fields in a struct array.
* @return number of fields in the structure array.
*/
inline int nfields() const { return mxGetNumberOfFields(p_); }
/** Get specified field name from a struct array.
* @param fieldnumber position of the desired field.
* @return std::string name of n-th field.
*/
std::string fieldname(int fieldnumber) const;
/** Get field names of a struct array.
* @return std::vector<std::string> vector of all field names.
*/
std::vector<std::string> fieldnames() const;
/** Number of elements in \c IR, \c PR, and \c PI arrays.
* @return number of elements allocated to hold nonzero entries
* in the sparse array.
*/
inline mwSize nzmax() const { return mxGetNzmax(p_); }
/** Offset from first element to desired element.
* @param i index of the first dimension of the array.
* @param j index of the second dimension of the array.
* @return linear offset of the specified subscript index.
*
* Return the offset (in number of elements) from the beginning of
* the array to the specified <tt>(i,j)</tt> subscript.
*/
mwIndex subs(mwIndex i, mwIndex j = 0) const;
/** Offset from first element to desired element.
* @param si vector of subscripts for each dimension of the array.
* @return linear offset of the specified subscripts.
*
* Return the offset (in number of elements) from the beginning of
* the array to the specified subscript
* <tt>(si[0], si[1], ..., si[n])</tt>.
*/
mwIndex subs(const std::vector<mwIndex>& si) const;
/** Determine whether the array is initialized or not.
* @return true if the internal mxArray pointer is \c NULL, false
* otherwise.
*/
inline bool isNull() const { return (p_ == NULL); }
/** Determine whether input is cell array.
* @return true if array is of type \c mxCELL_CLASS, false otherwise.
*/
inline bool isCell() const { return mxIsCell(p_); }
/** Determine whether input is string array.
* @return true if array is of type \c mxCHAR_CLASS, false otherwise.
*/
inline bool isChar() const { return mxIsChar(p_); }
/** Determine whether array is member of specified class.
* @param s class name as a string
* @return true if array is of specified class, false otherwise.
*
* Example:
* @code
* bool b = MxArray(prhs[0]).isClass("uint8");
* @endcode
*/
inline bool isClass(std::string s) const
{
return mxIsClass(p_, s.c_str());
}
/** Determine whether data is complex.
* @return true if array is numeric containing complex data,
* false otherwise
*/
inline bool isComplex() const { return mxIsComplex(p_); }
/** Determine whether mxArray represents data as double-precision,
* floating-point numbers.
* @return true if array is of type \c mxDOUBLE_CLASS, false otherwise.
*/
inline bool isDouble() const { return mxIsDouble(p_); }
/** Determine whether array is empty.
* @return true if array is empty, false otherwise.
*
* An array is empty if the size of any of its dimensions is 0.
*/
inline bool isEmpty() const { return mxIsEmpty(p_); }
/** Determine whether input is finite.
* @param d double-precision floating-point number
* @return true if value is finite, false otherwise.
*/
static inline bool isFinite(double d) { return mxIsFinite(d); }
/** Determine whether array was copied from MATLAB global workspace.
* @return true if the array was copied out of the global workspace,
* false otherwise.
*/
inline bool isFromGlobalWS() const { return mxIsFromGlobalWS(p_); };
/** Determine whether input is infinite.
* @param d double-precision floating-point number
* @return true if value is infinity, false otherwise.
*/
static inline bool isInf(double d) { return mxIsInf(d); }
/** Determine whether array represents data as signed 8-bit integers.
* @return true if array is of type \c mxINT8_CLASS, false otherwise.
*/
inline bool isInt8() const { return mxIsInt8(p_); }
/** Determine whether array represents data as signed 16-bit integers.
* @return true if array is of type \c mxINT16_CLASS, false otherwise.
*/
inline bool isInt16() const { return mxIsInt16(p_); }
/** Determine whether array represents data as signed 32-bit integers.
* @return true if array is of type \c mxINT32_CLASS, false otherwise.
*/
inline bool isInt32() const { return mxIsInt32(p_); }
/** Determine whether array represents data as signed 64-bit integers.
* @return true if array is of type \c mxINT64_CLASS, false otherwise.
*/
inline bool isInt64() const { return mxIsInt64(p_); }
/** Determine whether array is of type mxLogical.
* @return true if array is of type \c mxLOGICAL_CLASS, false otherwise.
*/
inline bool isLogical() const { return mxIsLogical(p_); }
/** Determine whether scalar array is of type mxLogical.
* @return true if array is 1-by-1 of type \c mxLOGICAL_CLASS,
* false otherwise.
*/
inline bool isLogicalScalar() const { return mxIsLogicalScalar(p_); }
/** Determine whether scalar array of type \c mxLogical is true.
* @return true if array is 1-by-1 of type \c mxLOGICAL_CLASS
* containing a value of true, returns false otherwise.
*/
inline bool isLogicalScalarTrue() const
{
return mxIsLogicalScalarTrue(p_);
}
/** Determine whether array is numeric.
* @return true if array is numeric, false otherwise.
*/
inline bool isNumeric() const { return mxIsNumeric(p_); }
/** Determine whether array represents data as single-precision,
* floating-point numbers.
* @return true if array is of type \c mxSINGLE_CLASS, false otherwise.
*/
inline bool isSingle() const { return mxIsSingle(p_); }
/** Determine whether input is sparse array.
* @return true if array is numeric sparse array, false otherwise.
*/
inline bool isSparse() const { return mxIsSparse(p_); }
/** Determine whether input is structure array.
* @return true if array is of type \c mxSTRUCT_CLASS, false otherwise.
*/
inline bool isStruct() const { return mxIsStruct(p_); }
/** Determine whether array represents data as unsigned 8-bit integers.
* @return true if array is of type \c mxUINT8_CLASS, false otherwise.
*/
inline bool isUint8() const { return mxIsUint8(p_); }
/** Determine whether array represents data as unsigned 16-bit integers.
* @return true if array is of type \c mxUINT16_CLASS, false otherwise.
*/
inline bool isUint16() const { return mxIsUint16(p_); }
/** Determine whether array represents data as unsigned 32-bit integers.
* @return true if array is of type \c mxUINT32_CLASS, false otherwise.
*/
inline bool isUint32() const { return mxIsUint32(p_); }
/** Determine whether array represents data as unsigned 64-bit integers.
* @return true if array is of type \c mxUINT64_CLASS, false otherwise.
*/
inline bool isUint64() const { return mxIsUint64(p_); }
/** Determine whether a struct array has a specified field.
* @param fieldName name of field to check
* @return true if struct array has specified field, false otherwise.
*/
inline bool isField(const std::string& fieldName) const
{
return isStruct() && mxGetFieldNumber(p_, fieldName.c_str()) != -1;
}
/** Template for numeric array element accessor.
* @param index linear index of the array element.
* @return value of the element at specified index.
*
* This getter method is intended for accessing elements of primitive
* types of a numeric array. Use an appropriate specialized/overloaded
* method version for accessing elements of struct or cell arrays.
*
* In MATLAB, this is equivalent to getting:
* @code
* value = arr(index)
* @endcode
*
* Example:
* @code
* MxArray m(prhs[0]);
* double d = m.at<double>(0);
* @endcode
*/
template <typename T> T at(mwIndex index) const;
/** Template for numeric array element accessor.
* @param i index of the first dimension.
* @param j index of the second dimension.
* @return value of the element at (i,j) subscript.
*
* This getter method is intended for accessing elements of primitive
* types of a numeric array.
*
* In MATLAB, this is equivalent to getting:
* @code
* value = arr(i,j)
* @endcode
*/
template <typename T> T at(mwIndex i, mwIndex j) const;
/** Template for numeric array element accessor.
* @param si vector of subscripts for each dimension of the array.
* @return value of the element at subscript index.
*
* This getter method is intended for accessing elements of primitive
* types of a numeric array.
*
* In MATLAB, this is equivalent to getting:
* @code
* value = arr(dim1Sub, dim2Sub, ,dim3Sub, ...)
* @endcode
*/
template <typename T> T at(const std::vector<mwIndex>& si) const;
/** Struct array element accessor.
* @param fieldName name of field in the structure.
* @param index linear index of the struct array element.
* @return MxArray of the field at the specified index.
*
* In MATLAB, this is equivalent to getting:
* @code
* value = st(index).fieldname
* @endcode
*
* Example:
* @code
* MxArray structArray(prhs[0]);
* MxArray x = structArray.at<MxArray>("some_field");
* @endcode
*/
MxArray at(const std::string& fieldName, mwIndex index = 0) const;
/** Template for numeric array element write accessor.
* @param index linear index of the array element.
* @param value value to assign to the element at the specified index.
*
* (If the array is a cell array, \p value type must be convertible to
* MxArray using an existing constructor.)
*
* In MATLAB, this is equivalent to setting:
* @code
* arr(index) = value
* @endcode
*
* Example:
* @code
* MxArray arr(prhs[0]);
* arr.set<double>(0, 3.14);
* @endcode
*/
template <typename T> void set(mwIndex index, const T& value);
/** Template for numeric array element write accessor.
* @param i index of the first dimension of the array element.
* @param j index of the first dimension of the array element.
* @param value value to assign to the element at the specified index.
*
* In MATLAB, this is equivalent to setting:
* @code
* arr(i,j) = value
* @endcode
*/
template <typename T> void set(mwIndex i, mwIndex j, const T& value);
/** Template for numeric array element write accessor.
* @param si vector of subscripts for each dimension of the array.
* @param value value to assign to the element at the specified subscript.
*
* In MATLAB, this is equivalent to setting:
* @code
* arr(dim1Sub, dim2Sub, ,dim3Sub, ...) = value
* @endcode
*/
template <typename T> void set(const std::vector<mwIndex>& si,
const T& value);
/** Template for struct array element write accessor.
* @param fieldName name of field in the structure.
* @param value value to assign to the field.
* @param index linear index of the struct array element.
*
* The value type must be convertible to MxArray using an existing
* constructor.
*
* In MATLAB, this is equivalent to setting:
* @code
* st(index).fieldname = value
* @endcode
*
* Example:
* @code
* MxArray structArray = MxArray::Struct();
* structArray.set<double>("some_field", 3.14);
* @endcode
*/
template <typename T> void set(const std::string& fieldName,
const T& value, mwIndex index = 0);
/** Determine whether input is NaN (Not-a-Number).
* @param d double-precision floating-point number
* @return true if value is \c NaN, false otherwise.
*/
static inline bool isNaN(double d) { return mxIsNaN(d); }
/** Value of infinity.
* @return double-precision value representing infinity.
*/
static inline double Inf() { return mxGetInf(); }
/** Value of \c NaN (Not-a-Number).
* @return double-precision value representing \c NaN.
*/
static inline double NaN() { return mxGetNaN(); }
/** Value of \c EPS.
* @return double-precision value representing MATLAB \c eps.
*
* This variable holds the distance from 1.0 to the next largest
* floating-point number. As such, it is a measure of floating-point
* accuracy.
*/
static inline double Eps() { return mxGetEps(); }
private:
/** Internal converter from std::vector to MxArray.
* @param v vector of type \c T.
* @return MxArray object, representing a numeric or a cell array.
*
* Vectors of primitive types are converted to numeric arrays of the
* equivalent MATLAB type, while other types are converted to cell arrays
* (assuming an appropriate constructor exists that converts each element
* of type \c T to MxArray).
*/
template <typename T> void fromVector(const std::vector<T>& v);
/** const pointer to the mxArray opaque object.
*/
const mxArray* p_;
};
/** std::map wrapper with one-line initialization and lookup method.
*
* Initialization:
* @code
* const ConstMap<std::string,int> BorderType = ConstMap<std::string,int>
* ("Replicate", cv::BORDER_REPLICATE)
* ("Constant", cv::BORDER_CONSTANT)
* ("Reflect", cv::BORDER_REFLECT);
* @endcode
*
* Lookup:
* @code
* BorderType["Constant"] // => cv::BORDER_CONSTANT
* @endcode
*/
template <typename T, typename U>
class ConstMap
{
public:
/// Constructor with a single key-value pair
ConstMap(const T& key, const U& val)
{
m_[key] = val;
}
/// Consecutive insertion operator
ConstMap<T,U>& operator() (const T& key, const U& val)
{
m_[key] = val;
return *this;
}
/// Implicit converter to std::map
operator std::map<T,U>() const { return m_; }
/// Lookup operator; fail if not found
const U& operator[] (const T& key) const
{
typename std::map<T,U>::const_iterator it = m_.find(key);
if (it==m_.end())
mexErrMsgIdAndTxt("mexopencv:error", "ConstMap: Value not found");
return (*it).second;
}
private:
//// private map object
std::map<T,U> m_;
};
template <typename T>
void MxArray::fromVector(const std::vector<T>& v)
{
if (MxTypes<T>::type == mxUNKNOWN_CLASS) {
p_ = mxCreateCellMatrix(1, v.size());
if (!p_)
mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
for (mwIndex i = 0; i < v.size(); ++i)
mxSetCell(const_cast<mxArray*>(p_), i, MxArray(v[i]));
} else {
p_ = mxCreateNumericMatrix(1, v.size(), MxTypes<T>::type, mxREAL);
if (!p_)
mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
std::copy(v.begin(), v.end(), reinterpret_cast<T*>(mxGetData(p_)));
}
}
template <typename T>
MxArray::MxArray(const cv::Point_<T>& p)
: p_(mxCreateNumericMatrix(1, 2, mxDOUBLE_CLASS, mxREAL))
{
if (!p_)
mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
double *x = mxGetPr(p_);
x[0] = static_cast<double>(p.x);
x[1] = static_cast<double>(p.y);
}
template <typename T>
MxArray::MxArray(const cv::Point3_<T>& p)
: p_(mxCreateNumericMatrix(1, 3, mxDOUBLE_CLASS, mxREAL))
{
if (!p_)
mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
double *x = mxGetPr(p_);
x[0] = static_cast<double>(p.x);
x[1] = static_cast<double>(p.y);
x[2] = static_cast<double>(p.z);
}
template <typename T>
MxArray::MxArray(const cv::Size_<T>& s)
: p_(mxCreateNumericMatrix(1, 2, mxDOUBLE_CLASS, mxREAL))
{
if (!p_)
mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
double *x = mxGetPr(p_);
x[0] = static_cast<double>(s.width);
x[1] = static_cast<double>(s.height);
}
template <typename T>
MxArray::MxArray(const cv::Rect_<T>& r)
: p_(mxCreateNumericMatrix(1, 4, mxDOUBLE_CLASS, mxREAL))
{
if (!p_)
mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
double *x = mxGetPr(p_);
x[0] = static_cast<double>(r.x);
x[1] = static_cast<double>(r.y);
x[2] = static_cast<double>(r.width);
x[3] = static_cast<double>(r.height);
}
template <typename T>
MxArray::MxArray(const cv::Scalar_<T>& s)
: p_(mxCreateNumericMatrix(1, 4, mxDOUBLE_CLASS, mxREAL))
{
if (!p_)
mexErrMsgIdAndTxt("mexopencv:error", "Allocation error");
double *x = mxGetPr(p_);
x[0] = static_cast<double>(s[0]);
x[1] = static_cast<double>(s[1]);
x[2] = static_cast<double>(s[2]);
x[3] = static_cast<double>(s[3]);
}