mexopencv  3.4.1
MEX interface for OpenCV library
AffineFeature2D_.cpp
Go to the documentation of this file.
1 
8 #include "mexopencv.hpp"
10 #include "opencv2/xfeatures2d.hpp"
11 #include <typeinfo>
12 using namespace std;
13 using namespace cv;
14 using namespace cv::xfeatures2d;
15 
16 // Persistent objects
17 namespace {
19 int last_id = 0;
22 
24 const char *cv_elliptic_keypoint_fields[9] = {"pt", "size", "angle",
25  "response", "octave", "class_id", "axes", "si", "transf"};
26 
28 {
30  s.set("pt", kpt.pt);
31  s.set("size", kpt.size);
32  s.set("angle", kpt.angle);
33  s.set("response", kpt.response);
34  s.set("octave", kpt.octave);
35  s.set("class_id", kpt.class_id);
36  s.set("axes", kpt.axes);
37  s.set("si", kpt.si);
38  s.set("transf", kpt.transf);
39  return s;
40 }
41 
43 {
45  for (mwIndex i = 0; i < kpts.size(); ++i) {
46  s.set("pt", kpts[i].pt, i);
47  s.set("size", kpts[i].size, i);
48  s.set("angle", kpts[i].angle, i);
49  s.set("response", kpts[i].response, i);
50  s.set("octave", kpts[i].octave, i);
51  s.set("class_id", kpts[i].class_id, i);
52  s.set("axes", kpts[i].axes, i);
53  s.set("si", kpts[i].si, i);
54  s.set("transf", kpts[i].transf, i);
55  }
56  return s;
57 }
58 
60 {
62  kpt.pt = arr.at("pt", idx).toPoint2f();
63  kpt.size = arr.at("size", idx).toFloat();
64  kpt.angle = arr.isField("angle") ? arr.at("angle", idx).toFloat() : -1;
65  kpt.response = arr.isField("response") ? arr.at("response", idx).toFloat() : 0;
66  kpt.octave = arr.isField("octave") ? arr.at("octave", idx).toInt() : 0;
67  kpt.class_id = arr.isField("class_id") ? arr.at("class_id", idx).toInt() : -1;
68  kpt.axes = arr.at("axes", idx).toSize_<float>();
69  kpt.si = arr.at("si", idx).toFloat();
70  kpt.transf = arr.at("transf", idx).toMatx<float,2,3>();
71  return kpt;
72 }
73 
75 {
76  const mwSize n = arr.numel();
78  v.reserve(n);
79  if (arr.isCell())
80  for (mwIndex i = 0; i < n; ++i)
81  v.push_back(MxArrayToEllipticKeyPoint(arr.at<MxArray>(i), 0));
82  else if (arr.isStruct())
83  for (mwIndex i = 0; i < n; ++i)
84  v.push_back(MxArrayToEllipticKeyPoint(arr, i));
85  else
86  mexErrMsgIdAndTxt("mexopencv:error",
87  "MxArray unable to convert to vector<Elliptic_KeyPoint>");
88  return v;
89 }
90 }
91 
99 void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
100 {
101  // Check the number of arguments
102  nargchk(nrhs>=2 && nlhs<=2);
103 
104  // Argument vector
105  vector<MxArray> rhs(prhs, prhs+nrhs);
106  int id = rhs[0].toInt();
107  string method(rhs[1].toString());
108 
109  // Constructor is called. Create a new object from argument
110  if (method == "new") {
111  nargchk((nrhs==3 || nrhs==4) && nlhs<=1);
112  // detector
113  Ptr<FeatureDetector> detector;
114  if (rhs[2].isChar())
115  detector = createFeatureDetector(
116  rhs[2].toString(), rhs.end(), rhs.end());
117  else if (rhs[2].isCell() && rhs[2].numel() >= 1) {
118  vector<MxArray> args(rhs[2].toVector<MxArray>());
119  detector = createFeatureDetector(
120  args[0].toString(), args.begin() + 1, args.end());
121  }
122  else
123  mexErrMsgIdAndTxt("mexopencv:error",
124  "Invalid detector arguments");
125  // extractor
126  Ptr<DescriptorExtractor> extractor;
127  if (nrhs == 4) {
128  if (rhs[3].isChar())
129  extractor = createDescriptorExtractor(
130  rhs[3].toString(), rhs.end(), rhs.end());
131  else if (rhs[3].isCell() && rhs[3].numel() >= 1) {
132  vector<MxArray> args(rhs[3].toVector<MxArray>());
133  extractor = createDescriptorExtractor(
134  args[0].toString(), args.begin() + 1, args.end());
135  }
136  else
137  mexErrMsgIdAndTxt("mexopencv:error",
138  "Invalid extractor arguments");
139  }
140  obj_[++last_id] = (nrhs == 3) ? AffineFeature2D::create(detector) :
141  AffineFeature2D::create(detector, extractor);
142  plhs[0] = MxArray(last_id);
143  mexLock();
144  return;
145  }
146 
147  // Big operation switch
148  Ptr<AffineFeature2D> obj = obj_[id];
149  if (obj.empty())
150  mexErrMsgIdAndTxt("mexopencv:error", "Object not found id=%d", id);
151  if (method == "delete") {
152  nargchk(nrhs==2 && nlhs==0);
153  obj_.erase(id);
154  mexUnlock();
155  }
156  else if (method == "typeid") {
157  nargchk(nrhs==2 && nlhs<=1);
158  plhs[0] = MxArray(string(typeid(*obj).name()));
159  }
160  else if (method == "clear") {
161  nargchk(nrhs==2 && nlhs==0);
162  obj->clear();
163  }
164  else if (method == "load") {
165  nargchk(nrhs>=3 && (nrhs%2)==1 && nlhs==0);
166  string objname;
167  bool loadFromString = false;
168  for (int i=3; i<nrhs; i+=2) {
169  string key(rhs[i].toString());
170  if (key == "ObjName")
171  objname = rhs[i+1].toString();
172  else if (key == "FromString")
173  loadFromString = rhs[i+1].toBool();
174  else
175  mexErrMsgIdAndTxt("mexopencv:error",
176  "Unrecognized option %s", key.c_str());
177  }
178  /*
179  obj_[id] = (loadFromString ?
180  Algorithm::loadFromString<AffineFeature2D>(rhs[2].toString(), objname) :
181  Algorithm::load<AffineFeature2D>(rhs[2].toString(), objname));
182  */
184  // HACK: workaround for missing AffineFeature2D::create()
185  FileStorage fs(rhs[2].toString(), FileStorage::READ +
186  (loadFromString ? FileStorage::MEMORY : 0));
187  if (!fs.isOpened())
188  mexErrMsgIdAndTxt("mexopencv:error", "Failed to open file");
189  FileNode fn(objname.empty() ? fs.getFirstTopLevelNode() : fs[objname]);
190  if (fn.empty())
191  mexErrMsgIdAndTxt("mexopencv:error", "Failed to get node");
192  obj->read(fn);
193  //*/
194  }
195  else if (method == "save") {
196  nargchk(nrhs==3 && nlhs==0);
197  obj->save(rhs[2].toString());
198  }
199  else if (method == "empty") {
200  nargchk(nrhs==2 && nlhs<=1);
201  plhs[0] = MxArray(obj->empty());
202  }
203  else if (method == "getDefaultName") {
204  nargchk(nrhs==2 && nlhs<=1);
205  plhs[0] = MxArray(obj->getDefaultName());
206  }
207  else if (method == "defaultNorm") {
208  nargchk(nrhs==2 && nlhs<=1);
209  plhs[0] = MxArray(NormTypeInv[obj->defaultNorm()]);
210  }
211  else if (method == "descriptorSize") {
212  nargchk(nrhs==2 && nlhs<=1);
213  plhs[0] = MxArray(obj->descriptorSize());
214  }
215  else if (method == "descriptorType") {
216  nargchk(nrhs==2 && nlhs<=1);
217  plhs[0] = MxArray(ClassNameInvMap[obj->descriptorType()]);
218  }
219  else if (method == "detect") {
220  nargchk(nrhs>=3 && (nrhs%2)==1 && nlhs<=1);
221  if (rhs[2].isNumeric()) { // first variant that accepts an image
222  Mat mask;
223  for (int i=3; i<nrhs; i+=2) {
224  string key(rhs[i].toString());
225  if (key == "Mask")
226  mask = rhs[i+1].toMat(CV_8U);
227  else
228  mexErrMsgIdAndTxt("mexopencv:error",
229  "Unrecognized option %s", key.c_str());
230  }
231  Mat image(rhs[2].toMat(CV_8U));
232  vector<KeyPoint> keypoints;
233  obj->detect(image, keypoints, mask);
234  plhs[0] = MxArray(keypoints);
235  }
236  else if (rhs[2].isCell()) { // second variant that accepts an image set
237  vector<Mat> masks;
238  for (int i=3; i<nrhs; i+=2) {
239  string key(rhs[i].toString());
240  if (key == "Mask") {
241  //masks = rhs[i+1].toVector<Mat>();
242  vector<MxArray> arr(rhs[i+1].toVector<MxArray>());
243  masks.clear();
244  masks.reserve(arr.size());
245  for (vector<MxArray>::const_iterator it = arr.begin(); it != arr.end(); ++it)
246  masks.push_back(it->toMat(CV_8U));
247  }
248  else
249  mexErrMsgIdAndTxt("mexopencv:error",
250  "Unrecognized option %s", key.c_str());
251  }
252  //vector<Mat> images(rhs[2].toVector<Mat>());
253  vector<Mat> images;
254  {
255  vector<MxArray> arr(rhs[2].toVector<MxArray>());
256  images.reserve(arr.size());
257  for (vector<MxArray>::const_iterator it = arr.begin(); it != arr.end(); ++it)
258  images.push_back(it->toMat(CV_8U));
259  }
260  vector<vector<KeyPoint> > keypoints;
261  obj->detect(images, keypoints, masks);
262  plhs[0] = MxArray(keypoints);
263  }
264  else
265  mexErrMsgIdAndTxt("mexopencv:error", "Invalid arguments");
266  }
267  else if (method == "compute") {
268  nargchk(nrhs==4 && nlhs<=2);
269  if (rhs[2].isNumeric()) { // first variant that accepts an image
270  Mat image(rhs[2].toMat(CV_8U)), descriptors;
271  vector<KeyPoint> keypoints(rhs[3].toVector<KeyPoint>());
272  obj->compute(image, keypoints, descriptors);
273  plhs[0] = MxArray(descriptors);
274  if (nlhs > 1)
275  plhs[1] = MxArray(keypoints);
276  }
277  else if (rhs[2].isCell()) { // second variant that accepts an image set
278  //vector<Mat> images(rhs[2].toVector<Mat>());
279  vector<Mat> images, descriptors;
280  {
281  vector<MxArray> arr(rhs[2].toVector<MxArray>());
282  images.reserve(arr.size());
283  for (vector<MxArray>::const_iterator it = arr.begin(); it != arr.end(); ++it)
284  images.push_back(it->toMat(CV_8U));
285  }
286  vector<vector<KeyPoint> > keypoints(rhs[3].toVector(
287  const_mem_fun_ref_t<vector<KeyPoint>, MxArray>(
288  &MxArray::toVector<KeyPoint>)));
289  obj->compute(images, keypoints, descriptors);
290  plhs[0] = MxArray(descriptors);
291  if (nlhs > 1)
292  plhs[1] = MxArray(keypoints);
293  }
294  else
295  mexErrMsgIdAndTxt("mexopencv:error", "Invalid arguments");
296  }
297  else if (method == "detectAndCompute") {
298  nargchk(nrhs>=3 && (nrhs%2)==1 && nlhs<=2);
299  Mat mask;
300  vector<KeyPoint> keypoints;
301  bool useProvidedKeypoints = false;
302  for (int i=3; i<nrhs; i+=2) {
303  string key(rhs[i].toString());
304  if (key == "Mask")
305  mask = rhs[i+1].toMat(CV_8U);
306  else if (key == "Keypoints") {
307  keypoints = rhs[i+1].toVector<KeyPoint>();
308  useProvidedKeypoints = true;
309  }
310  else
311  mexErrMsgIdAndTxt("mexopencv:error",
312  "Unrecognized option %s", key.c_str());
313  }
314  Mat image(rhs[2].toMat(CV_8U)), descriptors;
315  obj->detectAndCompute(image, mask, keypoints, descriptors,
316  useProvidedKeypoints);
317  plhs[0] = MxArray(keypoints);
318  if (nlhs > 1)
319  plhs[1] = MxArray(descriptors);
320  }
321  else if (method == "detect_elliptic") {
322  nargchk(nrhs>=3 && (nrhs%2)==1 && nlhs<=1);
323  Mat mask;
324  for (int i=3; i<nrhs; i+=2) {
325  string key(rhs[i].toString());
326  if (key == "Mask")
327  mask = rhs[i+1].toMat(CV_8U);
328  else
329  mexErrMsgIdAndTxt("mexopencv:error",
330  "Unrecognized option %s", key.c_str());
331  }
332  Mat image(rhs[2].toMat(CV_8U));
333  vector<Elliptic_KeyPoint> keypoints;
334  obj->detect(image, keypoints, mask);
335  plhs[0] = toStruct(keypoints);
336  }
337  else if (method == "detectAndCompute_elliptic") {
338  nargchk(nrhs>=3 && (nrhs%2)==1 && nlhs<=2);
339  Mat mask;
340  vector<Elliptic_KeyPoint> keypoints;
341  bool useProvidedKeypoints = false;
342  for (int i=3; i<nrhs; i+=2) {
343  string key(rhs[i].toString());
344  if (key == "Mask")
345  mask = rhs[i+1].toMat(CV_8U);
346  else if (key == "Keypoints") {
347  keypoints = MxArrayToVectorEllipticKeyPoint(rhs[i+1]);
348  useProvidedKeypoints = true;
349  }
350  else
351  mexErrMsgIdAndTxt("mexopencv:error",
352  "Unrecognized option %s", key.c_str());
353  }
354  Mat image(rhs[2].toMat(CV_8U)), descriptors;
355  obj->detectAndCompute(image, mask, keypoints, descriptors,
356  useProvidedKeypoints);
357  plhs[0] = toStruct(keypoints);
358  if (nlhs > 1)
359  plhs[1] = MxArray(descriptors);
360  }
361  else
362  mexErrMsgIdAndTxt("mexopencv:error",
363  "Unrecognized operation %s",method.c_str());
364 }
virtual int descriptorType() const
T empty(T... args)
mwSize numel() const
Number of elements in an array.
Definition: MxArray.hpp:546
T at(mwIndex index) const
Template for numeric array element accessor.
Definition: MxArray.hpp:1250
LIBMWMEX_API_EXTERN_C void mexLock(void)
Lock a MEX-function so that it cannot be cleared from memory.
int last_id
Last object id to allocate.
MxArray toStruct(const vector< Elliptic_KeyPoint > &kpts)
#define CV_8U
vector< Elliptic_KeyPoint > MxArrayToVectorEllipticKeyPoint(const MxArray &arr)
cv::Ptr< cv::DescriptorExtractor > createDescriptorExtractor(const std::string &type, std::vector< MxArray >::const_iterator first, std::vector< MxArray >::const_iterator last)
Factory function for DescriptorExtractor creation.
STL namespace.
const ConstMap< int, std::string > NormTypeInv
Inverse norm type map for option processing.
Definition: mexopencv.hpp:160
void read(const String &fileName)
T end(T... args)
virtual bool isOpened() const
struct mxArray_tag mxArray
Forward declaration for mxArray.
Definition: matrix.h:259
void set(mwIndex index, const T &value)
Template for numeric array element write accessor.
Definition: MxArray.hpp:1310
STL class.
Elliptic_KeyPoint MxArrayToEllipticKeyPoint(const MxArray &arr, mwIndex idx)
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
Main entry called from Matlab.
T push_back(T... args)
virtual int defaultNorm() const
virtual void clear()
uint32_t v
cv::Ptr< cv::FeatureDetector > createFeatureDetector(const std::string &type, std::vector< MxArray >::const_iterator first, std::vector< MxArray >::const_iterator last)
Factory function for FeatureDetector creation.
LIBMWMEX_API_EXTERN_C void mexErrMsgIdAndTxt(const char *identifier, const char *err_msg,...)
Issue formatted error message with corresponding error identifier and return to MATLAB prompt...
bool isCell() const
Determine whether input is cell array.
Definition: MxArray.hpp:610
LIBMWMEX_API_EXTERN_C void mexUnlock(void)
Unlock a locked MEX-function so that it can be cleared from memory.
T clear(T... args)
virtual int descriptorSize() const
bool isField(const std::string &fieldName) const
Determine whether a struct array has a specified field.
Definition: MxArray.hpp:743
virtual void detect(InputArray image, std::vector< Elliptic_KeyPoint > &keypoints, InputArray mask=noArray())=0
mxArray object wrapper for data conversion and manipulation.
Definition: MxArray.hpp:123
void nargchk(bool cond)
Alias for input/output arguments number check.
Definition: mexopencv.hpp:181
Common definitions for the features2d and xfeatures2d modules.
static MxArray Struct(const char **fields=NULL, int nfields=0, mwSize m=1, mwSize n=1)
Create a new struct array.
Definition: MxArray.hpp:312
const char * cv_elliptic_keypoint_fields[9]
Field names for cv::xfeatures2d::Elliptic_KeyPoint.
virtual String getDefaultName() const
FileNode getFirstTopLevelNode() const
bool isStruct() const
Determine whether input is structure array.
Definition: MxArray.hpp:708
T size(T... args)
virtual void detectAndCompute(InputArray image, InputArray mask, std::vector< Elliptic_KeyPoint > &keypoints, OutputArray descriptors, bool useProvidedKeypoints=false)=0
const ConstMap< int, std::string > ClassNameInvMap
Translates data type definition used in OpenCV to that of MATLAB.
Definition: mexopencv.hpp:42
STL class.
bool empty() const
Global constant definitions.
T begin(T... args)
T c_str(T... args)
virtual void compute(InputArray image, std::vector< KeyPoint > &keypoints, OutputArray descriptors)
virtual bool empty() const
map< int, Ptr< AffineFeature2D > > obj_
Object container.
virtual void save(const String &filename) const
void create(int arows, int acols, int atype, Target target=ARRAY_BUFFER, bool autoRelease=false)
cv::Mat toMat() const
size_t size() const
T reserve(T... args)