mexopencv  3.4.1
MEX interface for OpenCV library
BinaryDescriptor_.cpp
Go to the documentation of this file.
1 
8 #include "mexopencv.hpp"
10 using namespace std;
11 using namespace cv;
12 using namespace cv::line_descriptor;
13 
14 // Persistent objects
15 namespace {
17 int last_id = 0;
20 
26 {
27  const char *fields[] = {"angle", "class_id", "octave", "pt", "response",
28  "size", "startPoint", "endPoint", "startPointInOctave",
29  "endPointInOctave", "lineLength", "numOfPixels"};
30  MxArray s = MxArray::Struct(fields, 12, 1, keylines.size());
31  for (mwIndex i = 0; i < keylines.size(); ++i) {
32  s.set("angle", keylines[i].angle, i);
33  s.set("class_id", keylines[i].class_id, i);
34  s.set("octave", keylines[i].octave, i);
35  s.set("pt", keylines[i].pt, i);
36  s.set("response", keylines[i].response, i);
37  s.set("size", keylines[i].size, i);
38  s.set("startPoint", keylines[i].getStartPoint(), i);
39  s.set("endPoint", keylines[i].getEndPoint(), i);
40  s.set("startPointInOctave", keylines[i].getStartPointInOctave(), i);
41  s.set("endPointInOctave", keylines[i].getEndPointInOctave(), i);
42  s.set("lineLength", keylines[i].lineLength, i);
43  s.set("numOfPixels", keylines[i].numOfPixels, i);
44  }
45  return s;
46 }
47 
53 {
54  MxArray c = MxArray::Cell(1, keylines.size());
55  for (mwIndex i = 0; i < keylines.size(); ++i)
56  c.set(i, toStruct(keylines[i]));
57  return c;
58 }
59 
66 {
67  KeyLine keyline;
68  keyline.angle = arr.at("angle", idx).toFloat();
69  keyline.class_id = arr.at("class_id", idx).toInt();
70  keyline.octave = arr.at("octave", idx).toInt();
71  keyline.pt = arr.at("pt", idx).toPoint2f();
72  keyline.response = arr.at("response", idx).toFloat();
73  keyline.size = arr.at("size", idx).toFloat();
74  keyline.startPointX = arr.at("startPoint", idx).toPoint2f().x;
75  keyline.startPointY = arr.at("startPoint", idx).toPoint2f().y;
76  keyline.endPointX = arr.at("endPoint", idx).toPoint2f().x;
77  keyline.endPointY = arr.at("endPoint", idx).toPoint2f().y;
78  keyline.sPointInOctaveX = arr.at("startPointInOctave", idx).toPoint2f().x;
79  keyline.sPointInOctaveY = arr.at("startPointInOctave", idx).toPoint2f().y;
80  keyline.ePointInOctaveX = arr.at("endPointInOctave", idx).toPoint2f().x;
81  keyline.ePointInOctaveY = arr.at("endPointInOctave", idx).toPoint2f().y;
82  keyline.lineLength = arr.at("lineLength", idx).toFloat();
83  keyline.numOfPixels = arr.at("numOfPixels", idx).toInt();
84  return keyline;
85 }
86 
92 {
93  const mwSize n = arr.numel();
94  vector<KeyLine> vk;
95  vk.reserve(n);
96  if (arr.isCell())
97  for (mwIndex i = 0; i < n; ++i)
98  vk.push_back(MxArrayToKeyLine(arr.at<MxArray>(i)));
99  else if (arr.isStruct())
100  for (mwIndex i = 0; i < n; ++i)
101  vk.push_back(MxArrayToKeyLine(arr,i));
102  else
103  mexErrMsgIdAndTxt("mexopencv:error",
104  "MxArray unable to convert to std::vector<cv::line_descriptor::KeyLine>");
105  return vk;
106 }
107 
113 {
114  vector<MxArray> va(arr.toVector<MxArray>());
116  vvk.reserve(va.size());
117  for (vector<MxArray>::const_iterator it = va.begin(); it != va.end(); ++it)
119  return vvk;
120 }
121 }
122 
130 void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
131 {
132  // Check the number of arguments
133  nargchk(nrhs>=2 && nlhs<=2);
134 
135  // Argument vector
136  vector<MxArray> rhs(prhs, prhs+nrhs);
137  int id = rhs[0].toInt();
138  string method(rhs[1].toString());
139 
140  // Constructor is called. Create a new object from argument
141  if (method == "new") {
142  nargchk(nrhs>=2 && (nrhs%2)==0 && nlhs<=1);
143  BinaryDescriptor::Params parameters;
144  for (int i=2; i<nrhs; i+=2) {
145  string key(rhs[i].toString());
146  if (key == "KSize")
147  parameters.ksize_ = rhs[i+1].toInt();
148  else if (key == "NumOfOctave")
149  parameters.numOfOctave_ = rhs[i+1].toInt();
150  else if (key == "ReductionRatio")
151  parameters.reductionRatio = rhs[i+1].toInt();
152  else if (key == "WidthOfBand")
153  parameters.widthOfBand_ = rhs[i+1].toInt();
154  else
155  mexErrMsgIdAndTxt("mexopencv:error",
156  "Unrecognized option %s", key.c_str());
157  }
158  obj_[++last_id] = BinaryDescriptor::createBinaryDescriptor(parameters);
159  plhs[0] = MxArray(last_id);
160  mexLock();
161  return;
162  }
163 
164  // Big operation switch
165  Ptr<BinaryDescriptor> obj = obj_[id];
166  if (obj.empty())
167  mexErrMsgIdAndTxt("mexopencv:error", "Object not found id=%d", id);
168  if (method == "delete") {
169  nargchk(nrhs==2 && nlhs==0);
170  obj_.erase(id);
171  mexUnlock();
172  }
173  else if (method == "clear") {
174  nargchk(nrhs==2 && nlhs==0);
175  obj->clear();
176  }
177  else if (method == "load") {
178  nargchk(nrhs>=3 && (nrhs%2)==1 && nlhs==0);
179  string objname;
180  bool loadFromString = false;
181  for (int i=3; i<nrhs; i+=2) {
182  string key(rhs[i].toString());
183  if (key == "ObjName")
184  objname = rhs[i+1].toString();
185  else if (key == "FromString")
186  loadFromString = rhs[i+1].toBool();
187  else
188  mexErrMsgIdAndTxt("mexopencv:error",
189  "Unrecognized option %s", key.c_str());
190  }
191  /*
192  obj_[id] = (loadFromString ?
193  Algorithm::loadFromString<BinaryDescriptor>(rhs[2].toString(), objname) :
194  Algorithm::load<BinaryDescriptor>(rhs[2].toString(), objname));
195  */
197  // HACK: workaround for missing BinaryDescriptor::create()
198  FileStorage fs(rhs[2].toString(), FileStorage::READ +
199  (loadFromString ? FileStorage::MEMORY : 0));
200  if (!fs.isOpened())
201  mexErrMsgIdAndTxt("mexopencv:error", "Failed to open file");
202  FileNode fn(objname.empty() ? fs.getFirstTopLevelNode() : fs[objname]);
203  if (fn.empty())
204  mexErrMsgIdAndTxt("mexopencv:error", "Failed to get node");
205  obj->read(fn);
206  //*/
207  }
208  else if (method == "save") {
209  nargchk(nrhs==3 && nlhs==0);
210  obj->save(rhs[2].toString());
211  }
212  else if (method == "empty") {
213  nargchk(nrhs==2 && nlhs<=1);
214  plhs[0] = MxArray(obj->empty());
215  }
216  else if (method == "getDefaultName") {
217  nargchk(nrhs==2 && nlhs<=1);
218  plhs[0] = MxArray(obj->getDefaultName());
219  }
220  else if (method == "defaultNorm") {
221  nargchk(nrhs==2 && nlhs<=1);
222  plhs[0] = MxArray(NormTypeInv[obj->defaultNorm()]);
223  }
224  else if (method == "descriptorSize") {
225  nargchk(nrhs==2 && nlhs<=1);
226  plhs[0] = MxArray(obj->descriptorSize());
227  }
228  else if (method == "descriptorType") {
229  nargchk(nrhs==2 && nlhs<=1);
230  plhs[0] = MxArray(ClassNameInvMap[obj->descriptorType()]);
231  }
232  else if (method == "detect") {
233  nargchk(nrhs>=3 && (nrhs%2)==1 && nlhs<=1);
234  if (rhs[2].isNumeric()) { // first variant that accepts an image
235  Mat mask;
236  for (int i=3; i<nrhs; i+=2) {
237  string key(rhs[i].toString());
238  if (key == "Mask")
239  mask = rhs[i+1].toMat(CV_8U);
240  else
241  mexErrMsgIdAndTxt("mexopencv:error",
242  "Unrecognized option %s", key.c_str());
243  }
244  Mat image(rhs[2].toMat(CV_8U));
245  vector<KeyLine> keylines;
246  obj->detect(image, keylines, mask);
247  plhs[0] = toStruct(keylines);
248  }
249  else if (rhs[2].isCell()) { // second variant that accepts an image set
250  vector<Mat> masks;
251  for (int i=3; i<nrhs; i+=2) {
252  string key(rhs[i].toString());
253  if (key == "Mask") {
254  //masks = rhs[i+1].toVector<Mat>();
255  vector<MxArray> arr(rhs[i+1].toVector<MxArray>());
256  masks.clear();
257  masks.reserve(arr.size());
258  for (vector<MxArray>::const_iterator it = arr.begin(); it != arr.end(); ++it)
259  masks.push_back(it->toMat(CV_8U));
260  }
261  else
262  mexErrMsgIdAndTxt("mexopencv:error",
263  "Unrecognized option %s", key.c_str());
264  }
265  //vector<Mat> images(rhs[2].toVector<Mat>());
266  vector<Mat> images;
267  {
268  vector<MxArray> arr(rhs[2].toVector<MxArray>());
269  images.reserve(arr.size());
270  for (vector<MxArray>::const_iterator it = arr.begin(); it != arr.end(); ++it)
271  images.push_back(it->toMat(CV_8U));
272  }
273  //HACK: detect method does not like an empty masks vector!
274  if (masks.empty())
275  masks.assign(images.size(), Mat());
276  vector<vector<KeyLine> > keylines;
277  //HACK: detect method does not take care of allocating outer vector!
278  keylines.resize(images.size());
279  obj->detect(images, keylines, masks);
280  plhs[0] = toCellOfStruct(keylines);
281  }
282  else
283  mexErrMsgIdAndTxt("mexopencv:error", "Invalid arguments");
284  }
285  else if (method == "compute") {
286  nargchk(nrhs>=4 && (nrhs%2)==0 && nlhs<=2);
287  bool returnFloatDescr = false;
288  for (int i=4; i<nrhs; i+=2) {
289  string key(rhs[i].toString());
290  if (key == "ReturnFloatDescr")
291  returnFloatDescr = rhs[i+1].toBool();
292  else
293  mexErrMsgIdAndTxt("mexopencv:error",
294  "Unrecognized option %s", key.c_str());
295  }
296  if (rhs[2].isNumeric()) { // first variant that accepts an image
297  Mat image(rhs[2].toMat(CV_8U)), descriptors;
298  vector<KeyLine> keylines(MxArrayToVectorKeyLine(rhs[3]));
299  obj->compute(image, keylines, descriptors, returnFloatDescr);
300  plhs[0] = MxArray(descriptors);
301  if (nlhs > 1)
302  plhs[1] = toStruct(keylines);
303  }
304  else if (rhs[2].isCell()) { // second variant that accepts an image set
305  //vector<Mat> images(rhs[2].toVector<Mat>());
306  vector<Mat> images, descriptors;
307  {
308  vector<MxArray> arr(rhs[2].toVector<MxArray>());
309  images.reserve(arr.size());
310  for (vector<MxArray>::const_iterator it = arr.begin(); it != arr.end(); ++it)
311  images.push_back(it->toMat(CV_8U));
312  }
314  //HACK: compute method does not check correct sizes, so we do it
315  if (keylines.size() != images.size())
316  mexErrMsgIdAndTxt("mexopencv:error", "Incorrect keylines size");
317  //HACK: compute method does not take care of allocating output vector!
318  descriptors.resize(images.size());
319  obj->compute(images, keylines, descriptors, returnFloatDescr);
320  plhs[0] = MxArray(descriptors);
321  if (nlhs > 1)
322  plhs[1] = toCellOfStruct(keylines);
323  }
324  else
325  mexErrMsgIdAndTxt("mexopencv:error", "Invalid arguments");
326  }
327  else if (method == "detectAndCompute") {
328  nargchk(nrhs>=3 && (nrhs%2)==1 && nlhs<=2);
329  Mat mask;
330  vector<KeyLine> keylines;
331  bool useProvidedKeyLines = false;
332  bool returnFloatDescr = false;
333  for (int i=3; i<nrhs; i+=2) {
334  string key(rhs[i].toString());
335  if (key == "Mask")
336  mask = rhs[i+1].toMat(CV_8U);
337  else if (key == "KeyLines") {
338  keylines = MxArrayToVectorKeyLine(rhs[i+1]);
339  useProvidedKeyLines = true;
340  }
341  else if (key == "ReturnFloatDescr")
342  returnFloatDescr = rhs[i+1].toBool();
343  else
344  mexErrMsgIdAndTxt("mexopencv:error",
345  "Unrecognized option %s", key.c_str());
346  }
347  Mat image(rhs[2].toMat(CV_8U)), descriptors;
348  obj->operator()(image, mask, keylines, descriptors,
349  useProvidedKeyLines, returnFloatDescr);
350  plhs[0] = toStruct(keylines);
351  if (nlhs > 1)
352  plhs[1] = MxArray(descriptors);
353  }
354  else if (method == "get") {
355  nargchk(nrhs==3 && nlhs<=1);
356  string prop(rhs[2].toString());
357  if (prop == "NumOfOctaves")
358  plhs[0] = MxArray(obj->getNumOfOctaves());
359  else if (prop == "ReductionRatio")
360  plhs[0] = MxArray(obj->getReductionRatio());
361  else if (prop == "WidthOfBand")
362  plhs[0] = MxArray(obj->getWidthOfBand());
363  else
364  mexErrMsgIdAndTxt("mexopencv:error",
365  "Unrecognized property %s", prop.c_str());
366  }
367  else if (method == "set") {
368  nargchk(nrhs==4 && nlhs==0);
369  string prop(rhs[2].toString());
370  if (prop == "NumOfOctaves")
371  obj->setNumOfOctaves(rhs[3].toInt());
372  else if (prop == "ReductionRatio")
373  obj->setReductionRatio(rhs[3].toInt());
374  else if (prop == "WidthOfBand")
375  obj->setWidthOfBand(rhs[3].toInt());
376  else
377  mexErrMsgIdAndTxt("mexopencv:error",
378  "Unrecognized property %s", prop.c_str());
379  }
380  else
381  mexErrMsgIdAndTxt("mexopencv:error",
382  "Unrecognized operation %s",method.c_str());
383 }
vector< KeyLine > MxArrayToVectorKeyLine(const MxArray &arr)
Convert an MxArray to std::vector<cv::line_descriptor::KeyLine>
T empty(T... args)
map< int, Ptr< BinaryDescriptor > > obj_
Object container.
MxArray toCellOfStruct(const vector< vector< KeyLine > > &keylines)
Convert set of keylines to cell-array of struct-arrays.
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
vector< vector< KeyLine > > MxArrayToVectorVectorKeyLine(const MxArray &arr)
Convert an MxArray to std::vector<std::vector<cv::line_descriptor::KeyLine>>
void compute(const Mat &image, std::vector< KeyLine > &keylines, Mat &descriptors, bool returnFloatDescr=false) const
LIBMWMEX_API_EXTERN_C void mexLock(void)
Lock a MEX-function so that it cannot be cleared from memory.
#define CV_8U
STL namespace.
const ConstMap< int, std::string > NormTypeInv
Inverse norm type map for option processing.
Definition: mexopencv.hpp:160
KeyLine MxArrayToKeyLine(const MxArray &arr, mwIndex idx=0)
Convert an MxArray to cv::line_descriptor::KeyLine.
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.
T resize(T... args)
T push_back(T... args)
virtual void read(const cv::FileNode &fn)
virtual void clear()
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...
MxArray toStruct(const vector< KeyLine > &keylines)
Convert keylines to struct array.
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)
mxArray object wrapper for data conversion and manipulation.
Definition: MxArray.hpp:123
void nargchk(bool cond)
Alias for input/output arguments number check.
Definition: mexopencv.hpp:181
static MxArray Struct(const char **fields=NULL, int nfields=0, mwSize m=1, mwSize n=1)
Create a new struct array.
Definition: MxArray.hpp:312
FileNode getFirstTopLevelNode() const
bool isStruct() const
Determine whether input is structure array.
Definition: MxArray.hpp:708
void detect(const Mat &image, std::vector< KeyLine > &keypoints, const Mat &mask=Mat())
static MxArray Cell(mwSize m=1, mwSize n=1)
Create a new cell array.
Definition: MxArray.hpp:290
T size(T... args)
T assign(T... args)
const ConstMap< int, std::string > ClassNameInvMap
Translates data type definition used in OpenCV to that of MATLAB.
Definition: mexopencv.hpp:42
std::vector< T > toVector() const
Convert MxArray to std::vector<T> of primitive types.
Definition: MxArray.hpp:1151
STL class.
bool empty() const
virtual String getDefaultName() const
Global constant definitions.
T begin(T... args)
int last_id
Last object id to allocate.
T c_str(T... args)
virtual void save(const String &filename) const
virtual bool empty() const
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
Main entry called from Matlab.
cv::Mat toMat() const
size_t size() const
T reserve(T... args)