forked from tikroeger/OF_DIS
-
Notifications
You must be signed in to change notification settings - Fork 1
/
MxArray.hpp
1118 lines (1066 loc) · 36 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 {
static const mxClassID type = mxUNKNOWN_CLASS;
};
/** int8_t traits.
*/
template<> struct MxTypes<int8_t>
{
static const mxClassID type = mxINT8_CLASS;
};
/** uint8_t traits.
*/
template<> struct MxTypes<uint8_t>
{
static const mxClassID type = mxUINT8_CLASS;
};
/** int16_t traits.
*/
template<> struct MxTypes<int16_t>
{
static const mxClassID type = mxINT16_CLASS;
};
/** uint16_t traits.
*/
template<> struct MxTypes<uint16_t>
{
static const mxClassID type = mxUINT16_CLASS;
};
/** int32_t traits.
*/
template<> struct MxTypes<int32_t>
{
static const mxClassID type = mxINT32_CLASS;
};
/** uint32_t traits.
*/
template<> struct MxTypes<uint32_t>
{
static const mxClassID type = mxUINT32_CLASS;
};
/** int64_t traits.
*/
template<> struct MxTypes<int64_t>
{
static const mxClassID type = mxINT64_CLASS;
};
/** uint64_t traits.
*/
template<> struct MxTypes<uint64_t>
{
static const mxClassID type = mxUINT64_CLASS;
};
/** float traits.
*/
template<> struct MxTypes<float>
{
static const mxClassID type = mxSINGLE_CLASS;
};
/** double traits.
*/
template<> struct MxTypes<double>
{
static const mxClassID type = mxDOUBLE_CLASS;
};
/** char traits.
*/
template<> struct MxTypes<char>
{
static const mxClassID type = mxCHAR_CLASS;
};
/** bool traits.
*/
template<> struct MxTypes<bool>
{
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.
*/
MxArray& operator=(const MxArray& rhs);
/** MxArray constructor from int.
* @param i int value.
*/
explicit MxArray(const int i);
/** MxArray constructor from double.
* @param d double value.
*/
explicit MxArray(const double d);
/** MxArray constructor from bool.
* @param b bool value.
*/
explicit MxArray(const bool b);
/** MxArray constructor from std::string.
* @param s reference to a string value.
*/
explicit MxArray(const std::string& s);
/** Convert cv::Mat to MxArray.
* @param mat cv::Mat object.
* @param classid classid of mxArray. e.g., mxDOUBLE_CLASS. When
* mxUNKNOWN_CLASS is specified, classid will be
* automatically determined from the type of cv::Mat.
* default: 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 transpose flag is set to false. When
* the cv::Mat object is N-D, (dim 1, dim 2,...dim N, channels) are mapped
* to (dim 2, dim 1, ..., dim N, dim N+1), 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.
*/
explicit MxArray(const cv::SparseMat& mat);
/** Convert cv::Moments to MxArray.
* @param m cv::Moments object.
* @return MxArray object.
*/
explicit MxArray(const cv::Moments& m);
/** Convert cv::KeyPoint to MxArray.
* @param p cv::KeyPoint object.
* @return MxArray object.
*/
explicit MxArray(const cv::KeyPoint& p);
/** Convert cv::DMatch to MxArray.
* @param m cv::DMatch object.
* @return MxArray object.
*/
explicit MxArray(const cv::DMatch& m);
/** Convert cv::RotatedRect to MxArray.
* @param m cv::RotatedRect object.
* @return MxArray object.
*/
explicit MxArray(const cv::RotatedRect& m);
/** Convert cv::TermCriteria to MxArray.
* @param t cv::TermCriteria object.
* @return MxArray object.
*/
explicit MxArray(const cv::TermCriteria& t);
/** MxArray constructor from vector<T>. Make a numeric or cell array.
* @param v vector of type T.
*/
template <typename T> explicit MxArray(const std::vector<T>& v) {
fromVector<T>(v);
}
/** MxArray constructor from cv::Point_<T>.
* @param p cv::Point_<T> object.
* @return two-element numeric MxArray.
*/
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.
*/
template <typename T> explicit MxArray(const cv::Point3_<T>& p);
/** MxArray constructor from cv::Size_<T>.
* @return two-element numeric MxArray.
*/
template <typename T> explicit MxArray(const cv::Size_<T>& s);
/** MxArray constructor from cv::Rect_<T>.
* @return four-element numeric MxArray [x, y, width, height].
*/
template <typename T> explicit MxArray(const cv::Rect_<T>& r);
/** MxArray constructor from cv::Scalar_<T>.
* @return four-element numeric MxArray.
*/
template <typename T> explicit MxArray(const cv::Scalar_<T>& s);
/** Generic constructor for a struct array.
* @param fields field names.
* @param nfields number of field names.
* @param m size of the first dimension.
* @param n size of the second dimension.
*
* Example:
* @code
* const char* fields[] = {"field1", "field2"};
* MxArray m(fields, 2);
* m.set("field1", 1);
* m.set("field2", "field2 value");
* @endcode
*/
MxArray(const char**fields, int nfields, int m=1, int n=1);
/** 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.
*/
static inline MxArray Cell(int m=1, int n=1)
{
return MxArray(mxCreateCellMatrix(m,n));
}
/** Create a new struct array.
* @param fields Field names.
* @param nfields Number of fields.
* @param m Number of rows.
* @param n Number of cols.
*/
static inline MxArray Struct(const char**fields=NULL,
int nfields=0,
int m=1,
int n=1)
{
return MxArray(mxCreateStructMatrix(m, n, nfields, fields));
}
/** Clone mxArray. This allocates new mxArray*.
* @return MxArray object.
*/
MxArray clone() { return MxArray(mxDuplicateArray(p_)); }
/** Destroy allocated mxArray. Use this to destroy a temporary mxArray not
* to be used in matlab.
* @return newly allocated MxArray object.
*/
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*. Be careful that this internally cast
* away mxArray* constness.
* @return mxArray* pointer.
*/
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 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., CV_8U, CV_32F. When CV_USERTYPE1
* is specified, depth will be automatically determined from
* the classid of the MxArray. default: 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 transpose flag is false. That is, when MxArray is 3D,
* (dim 1, dim 2, dim 3) are mapped to (cols, rows, channels) of the
* cv::Mat by default, whereas if MxArray is more than 4D, (dim 1, dim 2,
* ..., dim N-1, dim N) are mapped to (dim 2, dim 1, ..., dim N-1,
* channels) 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., CV_8U, CV_32F. When CV_USERTYPE1
* is specified, depth will be automatically determined from
* the the classid of the MxArray. default: 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 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, (dim 1, dim 2) are mapped to (cols, rows) of the cv::Mat by
* default, whereas if MxArray is more than 3D, (dim 1, dim 2, dim 3, ...,
* dim N) are mapped to (dim 2, dim 1, dim 3, ..., dim N) 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 index of the struct array.
* @return cv::Moments.
*/
cv::Moments toMoments(mwIndex index=0) const;
/** Convert MxArray to cv::KeyPoint.
* @param index index of the struct array.
* @return cv::KeyPoint.
*/
cv::KeyPoint toKeyPoint(mwIndex index=0) const;
/** Convert MxArray to cv::DMatch.
* @param index index of the struct array.
* @return cv::DMatch.
*/
cv::DMatch toDMatch(mwIndex index=0) const;
/** Convert MxArray to cv::Range.
* @return cv::Range.
*/
cv::Range toRange() const;
/** Convert MxArray to cv::TermCriteria.
* @param index index of the struct array.
* @return cv::TermCriteria.
*/
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 std::vector<T> for a primitive type.
* @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 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> converter(&MxArray::toPoint3_<int>);
* vector<Point3i> v = cellArray.toVector(converter);
* @endcode
*/
template <typename T>
std::vector<T> toVector(std::const_mem_fun_ref_t<T, MxArray> f) const;
/** Alias to toPoint_<int>.
*/
inline cv::Point toPoint() const { return toPoint_<int>(); }
/** Alias to toPoint_<float>.
*/
inline cv::Point2f toPoint2f() const { return toPoint_<float>(); }
/** Alias to toPoint3_<float>.
*/
inline cv::Point3f toPoint3f() const { return toPoint3_<float>(); }
/** Alias to toSize_<int>.
*/
inline cv::Size toSize() const { return toSize_<int>(); }
/** Alias to toRect_<int>.
*/
inline cv::Rect toRect() const { return toRect_<int>(); }
/** Alias to toScalar_<double>
*/
inline cv::Scalar toScalar() const { return toScalar_<double>(); }
/** Class ID of mxArray.
*/
inline mxClassID classID() const { return mxGetClassID(p_); }
/** Class name of mxArray.
*/
inline const std::string className() const
{
return std::string(mxGetClassName(p_));
}
/** Number of elements in an array.
*/
inline mwSize numel() const { return mxGetNumberOfElements(p_); }
/** Number of dimensions.
*/
inline mwSize ndims() const { return mxGetNumberOfDimensions(p_); }
/** Array of each dimension.
*/
inline const mwSize* dims() const { return mxGetDimensions(p_); };
/** Number of rows in an array.
*/
inline mwSize rows() const { return mxGetM(p_); }
/** Number of columns in an array.
*/
inline mwSize cols() const { return mxGetN(p_); }
/** Number of fields in a struct array.
*/
inline int nfields() const { return mxGetNumberOfFields(p_); }
/** Get field name of a struct array.
* @param index index of the struct array.
* @return std::string.
*/
std::string fieldname(int index=0) const;
/** Get field names of a struct array.
* @return std::string.
*/
std::vector<std::string> fieldnames() const;
/** Number of elements in IR, PR, and PI arrays.
*/
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.
*/
mwIndex subs(mwIndex i, mwIndex j=0) const;
/** Offset from first element to desired element.
* @param si subscript index of the array.
* @return linear offset of the specified subscript index.
*/
mwIndex subs(const std::vector<mwIndex>& si) const;
/** Determine whether input is cell array.
*/
inline bool isCell() const { return mxIsCell(p_); }
/** Determine whether input is string array.
*/
inline bool isChar() const { return mxIsChar(p_); }
/** Determine whether array is member of specified class.
*/
inline bool isClass(std::string s) const
{
return mxIsClass(p_, s.c_str());
}
/** Determine whether data is complex.
*/
inline bool isComplex() const { return mxIsComplex(p_); }
/** Determine whether mxArray represents data as double-precision,
* floating-point numbers.
*/
inline bool isDouble() const { return mxIsDouble(p_); }
/** Determine whether array is empty.
*/
inline bool isEmpty() const { return mxIsEmpty(p_); }
/** Determine whether input is finite.
*/
static inline bool isFinite(double d) { return mxIsFinite(d); }
/** Determine whether array was copied from MATLAB global workspace.
*/
inline bool isFromGlobalWS() const { return mxIsFromGlobalWS(p_); };
/** Determine whether input is infinite.
*/
static inline bool isInf(double d) { return mxIsInf(d); }
/** Determine whether array represents data as signed 8-bit integers.
*/
inline bool isInt8() const { return mxIsInt8(p_); }
/** Determine whether array represents data as signed 16-bit integers.
*/
inline bool isInt16() const { return mxIsInt16(p_); }
/** Determine whether array represents data as signed 32-bit integers.
*/
inline bool isInt32() const { return mxIsInt32(p_); }
/** Determine whether array represents data as signed 64-bit integers.
*/
inline bool isInt64() const { return mxIsInt64(p_); }
/** Determine whether array is of type mxLogical.
*/
inline bool isLogical() const { return mxIsLogical(p_); }
/** Determine whether scalar array is of type mxLogical.
*/
inline bool isLogicalScalar() const { return mxIsLogicalScalar(p_); }
/** Determine whether scalar array of type mxLogical is true.
*/
inline bool isLogicalScalarTrue() const
{
return mxIsLogicalScalarTrue(p_);
}
/** Determine whether array is numeric.
*/
inline bool isNumeric() const { return mxIsNumeric(p_); }
/** Determine whether array represents data as single-precision,
* floating-point numbers.
*/
inline bool isSingle() const { return mxIsSingle(p_); }
/** Determine whether input is sparse array.
*/
inline bool isSparse() const { return mxIsSparse(p_); }
/** Determine whether input is structure array.
*/
inline bool isStruct() const { return mxIsStruct(p_); }
/** Determine whether array represents data as unsigned 8-bit integers.
*/
inline bool isUint8() const { return mxIsUint8(p_); }
/** Determine whether array represents data as unsigned 16-bit integers.
*/
inline bool isUint16() const { return mxIsUint16(p_); }
/** Determine whether array represents data as unsigned 32-bit integers.
*/
inline bool isUint32() const { return mxIsUint32(p_); }
/** Determine whether array represents data as unsigned 64-bit integers.
*/
inline bool isUint64() const { return mxIsUint64(p_); }
/** Determine whether a struct array has a specified field.
*/
bool isField(const std::string& fieldName, mwIndex index=0) const
{
return isStruct() &&
mxGetField(p_, index, fieldName.c_str()) != NULL;
}
/** Template for element accessor.
* @param index index of the array element.
* @return value of the element at index.
*
* Example:
* @code
* MxArray m(prhs[0]);
* double d = m.at<double>(0);
* @endcode
*/
template <typename T> T at(mwIndex index) const;
/** Template for element accessor.
* @param i index of the first dimension.
* @param j index of the second dimension.
* @return value of the element at (i,j).
*/
template <typename T> T at(mwIndex i, mwIndex j) const;
/** Template for element accessor.
* @param si subscript index of the element.
* @return value of the element at subscript index.
*/
template <typename T> T at(const std::vector<mwIndex>& si) const;
/** Struct element accessor.
* @param fieldName field name of the struct array.
* @param index index of the struct array.
* @return value of the element at the specified field.
*/
MxArray at(const std::string& fieldName, mwIndex index=0) const;
/** Template for element write accessor.
* @param index offset of the array element.
* @param value value of the field.
*/
template <typename T> void set(mwIndex index, const T& value);
/** Template for 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 of the field.
*/
template <typename T> void set(mwIndex i, mwIndex j, const T& value);
/** Template for element write accessor.
* @param si subscript index of the element.
* @param value value of the field.
*/
template <typename T> void set(const std::vector<mwIndex>& si,
const T& value);
/** Template for struct element write accessor.
* @param fieldName field name of the struct array.
* @param value value of the field.
* @param index linear index of the struct array element.
*/
template <typename T> void set(const std::string& fieldName,
const T& value,
mwIndex index=0);
/** Determine whether input is NaN (Not-a-Number).
*/
static inline bool isNaN(double d) { return mxIsNaN(d); }
/** Value of infinity.
*/
static inline double Inf() { return mxGetInf(); }
/** Value of NaN (Not-a-Number).
*/
static inline double NaN() { return mxGetNaN(); }
/** Value of EPS.
*/
static inline double Eps() { return mxGetEps(); }
private:
/** Internal std::vector converter.
*/
template <typename T>
void fromVector(const std::vector<T>& v);
/** mxArray c 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>() { return m_; }
/// Lookup operator; fail if not found
U operator [](const T& key) const
{
typename std::map<T,U>::const_iterator it = m_.find(key);
if (it==m_.end())
mexErrMsgIdAndTxt("mexopencv:error", "Value not found");
return (*it).second;
}
private:
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 (int 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] = p.x;
x[1] = 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] = p.x;
x[1] = p.y;
x[2] = 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] = s.width;
x[1] = 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] = r.x;
x[1] = r.y;
x[2] = r.width;
x[3] = 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] = s[0];
x[1] = s[1];
x[2] = s[2];
x[3] = s[3];
}
template <typename T>
cv::Point_<T> MxArray::toPoint_() const
{
if (!isNumeric() || numel()!=2)
mexErrMsgIdAndTxt("mexopencv:error", "MxArray is not a Point");
return cv::Point_<T>(at<T>(0), at<T>(1));
}
template <typename T>
cv::Point3_<T> MxArray::toPoint3_() const
{
if (!isNumeric() || numel()!=3)
mexErrMsgIdAndTxt("mexopencv:error", "MxArray is not a Point");
return cv::Point3_<T>(at<T>(0), at<T>(1), at<T>(2));
}
template <typename T>
cv::Size_<T> MxArray::toSize_() const
{
if (!isNumeric() || numel()!=2)
mexErrMsgIdAndTxt("mexopencv:error",
"MxArray is incompatible to cv::Size");
return cv::Size_<T>(at<T>(0), at<T>(1));
}
template <typename T>
cv::Rect_<T> MxArray::toRect_() const
{
if (!isNumeric() || numel()!=4)
mexErrMsgIdAndTxt("mexopencv:error",
"MxArray is incompatible to cv::Rect");
return cv::Rect_<T>(at<T>(0), at<T>(1), at<T>(2), at<T>(3));
}
template <typename T>
cv::Scalar_<T> MxArray::toScalar_() const
{
int n = numel();
if (!isNumeric() || n < 1 || 4 < n)
mexErrMsgIdAndTxt("mexopencv:error",
"MxArray is incompatible to cv::Scalar");
switch (n)
{
case 1: return cv::Scalar_<T>(at<T>(0));
case 2: return cv::Scalar_<T>(at<T>(0), at<T>(1));
case 3: return cv::Scalar_<T>(at<T>(0), at<T>(1), at<T>(2));
case 4: return cv::Scalar_<T>(at<T>(0), at<T>(1), at<T>(2), at<T>(3));
}
return cv::Scalar_<T>();
}
template <typename T>
std::vector<T> MxArray::toVector() const
{
int n = numel();
std::vector<T> vt(n);
if (isNumeric())
for (int i = 0; i < n; ++i)
vt[i] = at<T>(i);
else if (isCell())
for (int i = 0; i < n; ++i)
vt[i] = MxArray(mxGetCell(p_, i)).at<T>(0);
else
mexErrMsgIdAndTxt("mexopencv:error", "Cannot convert to std::vector");
return vt;
}
template <typename T>
std::vector<T> MxArray::toVector(std::const_mem_fun_ref_t<T,MxArray> f) const
{
std::vector<MxArray> v = toVector<MxArray>();
std::vector<T> vt;
vt.reserve(v.size());
for (std::vector<MxArray>::iterator it=v.begin(); it<v.end(); ++it)
vt.push_back(f(*it));
return vt;
}
template <typename T>
T MxArray::at(mwIndex index) const
{
if (!p_ || numel() <= index)
mexErrMsgIdAndTxt("mexopencv:error", "Accessing invalid range");
switch (classID())
{
case mxCHAR_CLASS:
return static_cast<T>(*(mxGetChars(p_)+index));
case mxDOUBLE_CLASS:
return static_cast<T>(*(mxGetPr(p_)+index));
case mxINT8_CLASS:
return static_cast<T>(
*(reinterpret_cast<int8_t*>(mxGetData(p_))+index));
case mxUINT8_CLASS:
return static_cast<T>(
*(reinterpret_cast<uint8_t*>(mxGetData(p_))+index));
case mxINT16_CLASS:
return static_cast<T>(
*(reinterpret_cast<int16_t*>(mxGetData(p_))+index));
case mxUINT16_CLASS:
return static_cast<T>(
*(reinterpret_cast<uint16_t*>(mxGetData(p_))+index));
case mxINT32_CLASS:
return static_cast<T>(
*(reinterpret_cast<int32_t*>(mxGetData(p_))+index));
case mxUINT32_CLASS:
return static_cast<T>(
*(reinterpret_cast<uint32_t*>(mxGetData(p_))+index));
case mxINT64_CLASS:
return static_cast<T>(
*(reinterpret_cast<int64_t*>(mxGetData(p_))+index));
case mxUINT64_CLASS:
return static_cast<T>(
*(reinterpret_cast<uint64_t*>(mxGetData(p_))+index));
case mxSINGLE_CLASS:
return static_cast<T>(
*(reinterpret_cast<float*>(mxGetData(p_))+index));
case mxLOGICAL_CLASS:
return static_cast<T>(*(mxGetLogicals(p_)+index));
case mxCELL_CLASS:
case mxSTRUCT_CLASS:
case mxFUNCTION_CLASS:
default:
mexErrMsgIdAndTxt("mexopencv:error", "MxArray is not primitive");
return static_cast<T>(0);
}
}
template <typename T>
T MxArray::at(mwIndex i, mwIndex j) const
{
return at<T>(subs(i,j));
}
template <typename T>
T MxArray::at(const std::vector<mwIndex>& si) const
{
return at<T>(subs(si));
}
template <typename T>
void MxArray::set(mwIndex index, const T& value)
{
if (numel() <= index)
mexErrMsgIdAndTxt("mexopencv:error", "Accessing invalid range");
switch (classID())
{
case mxCHAR_CLASS:
*(mxGetChars(p_)+index) = static_cast<mxChar>(value); break;
case mxDOUBLE_CLASS:
*(mxGetPr(p_)+index) = static_cast<double>(value); break;
case mxINT8_CLASS:
*(reinterpret_cast<int8_t*>(mxGetData(p_))+index) =
static_cast<int8_t>(value); break;
case mxUINT8_CLASS:
*(reinterpret_cast<uint8_t*>(mxGetData(p_))+index) =
static_cast<uint8_t>(value); break;
case mxINT16_CLASS:
*(reinterpret_cast<int16_t*>(mxGetData(p_))+index) =
static_cast<int16_t>(value); break;
case mxUINT16_CLASS:
*(reinterpret_cast<uint16_t*>(mxGetData(p_))+index) =
static_cast<uint16_t>(value); break;
case mxINT32_CLASS:
*(reinterpret_cast<int32_t*>(mxGetData(p_))+index) =
static_cast<int32_t>(value); break;
case mxUINT32_CLASS:
*(reinterpret_cast<uint32_t*>(mxGetData(p_))+index) =
static_cast<uint32_t>(value); break;
case mxINT64_CLASS:
*(reinterpret_cast<int64_t*>(mxGetData(p_))+index) =
static_cast<int64_t>(value); break;
case mxUINT64_CLASS:
*(reinterpret_cast<uint64_t*>(mxGetData(p_))+index) =
static_cast<uint64_t>(value); break;
case mxSINGLE_CLASS:
*(reinterpret_cast<float*>(mxGetData(p_))+index) =
static_cast<float>(value); break;
case mxLOGICAL_CLASS:
*(mxGetLogicals(p_)+index) = static_cast<mxLogical>(value); break;
case mxCELL_CLASS:
mxSetCell(const_cast<mxArray*>(p_), index, MxArray(value)); break;
case mxSTRUCT_CLASS:
case mxFUNCTION_CLASS:
default:
mexErrMsgIdAndTxt("mexopencv:error", "MxArray type is not valid");
}
}
template <typename T>
void MxArray::set(mwIndex i, mwIndex j, const T& value)
{
set<T>(subs(i,j),value);
}
template <typename T>
void MxArray::set(const std::vector<mwIndex>& si, const T& value)
{
set<T>(subs(si),value);
}
template <typename T>
void MxArray::set(const std::string& fieldName, const T& value, mwIndex index)
{
if (!isStruct())
mexErrMsgIdAndTxt("mexopencv:error", "MxArray is not struct");
if (!isField(fieldName))
{
if (mxAddField(const_cast<mxArray*>(p_), fieldName.c_str())<0)
mexErrMsgIdAndTxt("mexopencv:error",
"Failed to create a field '%s'",
fieldName.c_str());
}
mxSetField(const_cast<mxArray*>(p_), index, fieldName.c_str(),
static_cast<mxArray*>(MxArray(value)));
}
/** Specialization for vector<char> construction.
*/
template<>
void MxArray::fromVector(const std::vector<char>& v);
/** Specialization for vector<bool> construction.
*/
template<>
void MxArray::fromVector(const std::vector<bool>& v);