mexopencv  3.4.1
MEX interface for OpenCV library
mexopencv_aruco.cpp
Go to the documentation of this file.
1 
8 #include "mexopencv_aruco.hpp"
9 #include <cstdlib>
10 using std::vector;
11 using std::string;
12 using namespace cv;
13 using namespace cv::aruco;
14 
15 
16 // ==================== XXX ====================
17 
19 {
21  if (s.isField("adaptiveThreshWinSizeMin"))
22  params->adaptiveThreshWinSizeMin = s.at("adaptiveThreshWinSizeMin").toInt();
23  if (s.isField("adaptiveThreshWinSizeMax"))
24  params->adaptiveThreshWinSizeMax = s.at("adaptiveThreshWinSizeMax").toInt();
25  if (s.isField("adaptiveThreshWinSizeStep"))
26  params->adaptiveThreshWinSizeStep = s.at("adaptiveThreshWinSizeStep").toInt();
27  if (s.isField("adaptiveThreshConstant"))
28  params->adaptiveThreshConstant = s.at("adaptiveThreshConstant").toDouble();
29  if (s.isField("minMarkerPerimeterRate"))
30  params->minMarkerPerimeterRate = s.at("minMarkerPerimeterRate").toDouble();
31  if (s.isField("maxMarkerPerimeterRate"))
32  params->maxMarkerPerimeterRate = s.at("maxMarkerPerimeterRate").toDouble();
33  if (s.isField("polygonalApproxAccuracyRate"))
35  s.at("polygonalApproxAccuracyRate").toDouble();
36  if (s.isField("minCornerDistanceRate"))
37  params->minCornerDistanceRate = s.at("minCornerDistanceRate").toDouble();
38  if (s.isField("minDistanceToBorder"))
39  params->minDistanceToBorder = s.at("minDistanceToBorder").toInt();
40  if (s.isField("minMarkerDistanceRate"))
41  params->minMarkerDistanceRate = s.at("minMarkerDistanceRate").toDouble();
42  if (s.isField("cornerRefinementMethod"))
43  params->cornerRefinementMethod =
44  CornerRefineMethodMap[s.at("cornerRefinementMethod").toString()];
45  if (s.isField("cornerRefinementWinSize"))
46  params->cornerRefinementWinSize = s.at("cornerRefinementWinSize").toInt();
47  if (s.isField("cornerRefinementMaxIterations"))
49  s.at("cornerRefinementMaxIterations").toInt();
50  if (s.isField("cornerRefinementMinAccuracy"))
52  s.at("cornerRefinementMinAccuracy").toDouble();
53  if (s.isField("markerBorderBits"))
54  params->markerBorderBits = s.at("markerBorderBits").toInt();
55  if (s.isField("perspectiveRemovePixelPerCell"))
57  s.at("perspectiveRemovePixelPerCell").toInt();
58  if (s.isField("perspectiveRemoveIgnoredMarginPerCell"))
60  s.at("perspectiveRemoveIgnoredMarginPerCell").toDouble();
61  if (s.isField("maxErroneousBitsInBorderRate"))
63  s.at("maxErroneousBitsInBorderRate").toDouble();
64  if (s.isField("minOtsuStdDev"))
65  params->minOtsuStdDev = s.at("minOtsuStdDev").toDouble();
66  if (s.isField("errorCorrectionRate"))
67  params->errorCorrectionRate = s.at("errorCorrectionRate").toDouble();
68  return params;
69 }
70 
72 {
73  Ptr<Dictionary> dictionary;
74  if (arr.isChar()) {
75  string name(arr.toString());
77  }
78  else if (arr.isStruct()) {
79  dictionary = makePtr<Dictionary>(
80  arr.at("bytesList").toMat(CV_8U),
81  arr.at("markerSize").toInt(),
82  arr.at("maxCorrectionBits").toInt());
83  }
84  else {
85  vector<MxArray> args(arr.toVector<MxArray>());
86  size_t len = args.size();
87  nargchk(len>=1);
88  string type(args[0].toString());
89  if (type == "Predefined") {
90  nargchk(len==2);
91  string name(args[1].toString());
93  }
94  else if (type == "Custom") {
95  nargchk(len>=3 && (len%2)==1);
96  int nMarkers = args[1].toInt();
97  int markerSize = args[2].toInt();
98  Ptr<Dictionary> baseDictionary;
99  for (int i=3; i<len; i+=2) {
100  string key(args[i].toString());
101  if (key == "BaseDictionary")
102  baseDictionary = MxArrayToDictionary(args[i+1]);
103  else if (key == "Seed") {
104  //HACK: In order to get deterministic results, we allow to
105  // seed the rand() PRNG used in generateCustomDictionary().
106  // This is fragile because RNG state is tied to C runtime
107  // and how its library is linked.
108  srand(args[i+1].toInt());
109  }
110  else
111  mexErrMsgIdAndTxt("mexopencv:error",
112  "Unrecognized option %s", key.c_str());
113  }
114  if (baseDictionary.empty())
115  baseDictionary = makePtr<Dictionary>();
116  dictionary = generateCustomDictionary(nMarkers, markerSize,
117  baseDictionary);
118  }
119  else if (type == "Manual") {
120  nargchk(len==4);
121  Mat bytesList;
122  {
123  // bytesList(i,:) = getByteListFromBits(bits{i})
124  vector<MxArray> bits(args[1].toVector<MxArray>());
125  for (vector<MxArray>::const_iterator it = bits.begin(); it != bits.end(); ++it)
126  bytesList.push_back(Dictionary::getByteListFromBits(it->toMat(CV_8U)));
127  }
128  int markerSize = args[2].toInt();
129  int maxcorr = args[3].toInt();
130  dictionary = makePtr<Dictionary>(bytesList, markerSize, maxcorr);
131  }
132  else
133  mexErrMsgIdAndTxt("mexopencv:error",
134  "Unrecognized dictionary type %s", type.c_str());
135  }
136  if (dictionary.empty())
137  mexErrMsgIdAndTxt("mexopencv:error", "Failed to create Dictionary");
138  return dictionary;
139 }
140 
142 {
143  Ptr<Board> board;
144  if (arr.isStruct()) {
145  board = makePtr<Board>();
146  board->objPoints = MxArrayToVectorVectorPoint3<float>(arr.at("objPoints"));
147  board->dictionary = MxArrayToDictionary(arr.at("dictionary"));
148  board->ids = arr.at("ids").toVector<int>();
149  }
150  else {
151  vector<MxArray> args(arr.toVector<MxArray>());
152  nargchk(args.size() >= 1);
153  string type(args[0].toString());
154  if (type == "Board")
155  board = create_Board(args.begin() + 1, args.end());
156  else if (type == "GridBoard")
157  board = create_GridBoard(args.begin() + 1, args.end());
158  else if (type == "CharucoBoard")
159  board = create_CharucoBoard(args.begin() + 1, args.end());
160  else
161  mexErrMsgIdAndTxt("mexopencv:error",
162  "Unrecognized board type %s", type.c_str());
163  }
164  if (board.empty())
165  mexErrMsgIdAndTxt("mexopencv:error", "Failed to create Board");
166  return board;
167 }
168 
170 {
171  const char *fields[] = {"adaptiveThreshWinSizeMin",
172  "adaptiveThreshWinSizeMax", "adaptiveThreshWinSizeStep",
173  "adaptiveThreshConstant", "minMarkerPerimeterRate",
174  "maxMarkerPerimeterRate", "polygonalApproxAccuracyRate",
175  "minCornerDistanceRate", "minDistanceToBorder",
176  "minMarkerDistanceRate", "cornerRefinementMethod",
177  "cornerRefinementWinSize", "cornerRefinementMaxIterations",
178  "cornerRefinementMinAccuracy", "markerBorderBits",
179  "perspectiveRemovePixelPerCell",
180  "perspectiveRemoveIgnoredMarginPerCell",
181  "maxErroneousBitsInBorderRate", "minOtsuStdDev",
182  "errorCorrectionRate"};
183  MxArray s = MxArray::Struct(fields, 20);
184  s.set("adaptiveThreshWinSizeMin", params->adaptiveThreshWinSizeMin);
185  s.set("adaptiveThreshWinSizeMax", params->adaptiveThreshWinSizeMax);
186  s.set("adaptiveThreshWinSizeStep", params->adaptiveThreshWinSizeStep);
187  s.set("adaptiveThreshConstant", params->adaptiveThreshConstant);
188  s.set("minMarkerPerimeterRate", params->minMarkerPerimeterRate);
189  s.set("maxMarkerPerimeterRate", params->maxMarkerPerimeterRate);
190  s.set("polygonalApproxAccuracyRate", params->polygonalApproxAccuracyRate);
191  s.set("minCornerDistanceRate", params->minCornerDistanceRate);
192  s.set("minDistanceToBorder", params->minDistanceToBorder);
193  s.set("minMarkerDistanceRate", params->minMarkerDistanceRate);
194  s.set("cornerRefinementMethod",
196  s.set("cornerRefinementWinSize", params->cornerRefinementWinSize);
197  s.set("cornerRefinementMaxIterations", params->cornerRefinementMaxIterations);
198  s.set("cornerRefinementMinAccuracy", params->cornerRefinementMinAccuracy);
199  s.set("markerBorderBits", params->markerBorderBits);
200  s.set("perspectiveRemovePixelPerCell", params->perspectiveRemovePixelPerCell);
201  s.set("perspectiveRemoveIgnoredMarginPerCell",
203  s.set("maxErroneousBitsInBorderRate", params->maxErroneousBitsInBorderRate);
204  s.set("minOtsuStdDev", params->minOtsuStdDev);
205  s.set("errorCorrectionRate", params->errorCorrectionRate);
206  return s;
207 }
208 
209 MxArray toStruct(const Ptr<Dictionary> &dictionary)
210 {
211  const char *fields[] = {"bytesList", "markerSize", "maxCorrectionBits", "bits"};
212  MxArray s = MxArray::Struct(fields, 4);
213  s.set("bytesList", dictionary->bytesList);
214  s.set("markerSize", dictionary->markerSize);
215  s.set("maxCorrectionBits", dictionary->maxCorrectionBits);
216  if (true) {
217  vector<Mat> bits;
218  for (int i=0; i<dictionary->bytesList.rows; ++i) {
219  // bits{i} = getBitsFromByteList(bytesList(i,:))
220  // bits{i} is a markerSize-by-markerSize matrix
222  dictionary->bytesList.row(i), dictionary->markerSize));
223  }
224  s.set("bits", bits);
225  }
226  return s;
227 }
228 
230 {
231  const char *fields[] = {"objPoints", "dictionary", "ids"};
232  MxArray s = MxArray::Struct(fields, 3);
233  s.set("objPoints", board->objPoints);
234  s.set("dictionary", toStruct(board->dictionary));
235  s.set("ids", board->ids);
236  return s;
237 }
238 
240 {
241  const char *fields[] = {"objPoints", "dictionary", "ids",
242  "gridSize", "markerLength", "markerSeparation"};
243  MxArray s = MxArray::Struct(fields, 6);
244  s.set("objPoints", board->objPoints);
245  s.set("dictionary", toStruct(board->dictionary));
246  s.set("ids", board->ids);
247  s.set("gridSize", board->getGridSize());
248  s.set("markerLength", board->getMarkerLength());
249  s.set("markerSeparation", board->getMarkerSeparation());
250  return s;
251 }
252 
254 {
255  const char *fields[] = {"objPoints", "dictionary", "ids",
256  "chessboardSize", "squareLength", "markerLength",
257  "chessboardCorners", "nearestMarkerIdx", "nearestMarkerCorners"};
258  MxArray s = MxArray::Struct(fields, 9);
259  s.set("objPoints", board->objPoints);
260  s.set("dictionary", toStruct(board->dictionary));
261  s.set("ids", board->ids);
262  s.set("chessboardSize", board->getChessboardSize());
263  s.set("squareLength", board->getSquareLength());
264  s.set("markerLength", board->getMarkerLength());
265  s.set("chessboardCorners", board->chessboardCorners);
266  s.set("nearestMarkerIdx", board->nearestMarkerIdx);
267  s.set("nearestMarkerCorners", board->nearestMarkerCorners);
268  return s;
269 }
270 
271 
272 // ==================== XXX ====================
273 
277 {
278  ptrdiff_t len = std::distance(first, last);
279  nargchk(len==3);
280  vector<vector<Point3f> > objPoints(
281  MxArrayToVectorVectorPoint3<float>(*first)); ++first;
282  Ptr<Dictionary> dictionary = MxArrayToDictionary(*first); ++first;
283  vector<int> ids(first->toVector<int>()); ++first;
284  return Board::create(objPoints, dictionary, ids);
285 }
286 
290 {
291  ptrdiff_t len = std::distance(first, last);
292  nargchk(len>=5 && (len%2)==1);
293  int markersX = first->toInt(); ++first;
294  int markersY = first->toInt(); ++first;
295  float markerLength = first->toFloat(); ++first;
296  float markerSeparation = first->toFloat(); ++first;
297  Ptr<Dictionary> dictionary = MxArrayToDictionary(*first); ++first;
298  int firstMarker = 0;
299  for (; first != last; first += 2) {
300  string key(first->toString());
301  const MxArray& val = *(first + 1);
302  if (key == "FirstMarker")
303  firstMarker = val.toInt();
304  else
305  mexErrMsgIdAndTxt("mexopencv:error",
306  "Unrecognized option %s", key.c_str());
307  }
308  return GridBoard::create(markersX, markersY,
309  markerLength, markerSeparation, dictionary, firstMarker);
310 }
311 
315 {
316  ptrdiff_t len = std::distance(first, last);
317  nargchk(len==5);
318  int squaresX = first->toInt(); ++first;
319  int squaresY = first->toInt(); ++first;
320  float squareLength = first->toFloat(); ++first;
321  float markerLength = first->toFloat(); ++first;
322  Ptr<Dictionary> dictionary = MxArrayToDictionary(*first); ++first;
323  return CharucoBoard::create(squaresX, squaresY,
324  squareLength, markerLength, dictionary);
325 }
Ptr< Dictionary > MxArrayToDictionary(const MxArray &arr)
Convert MxArray to cv::Ptr<cv::aruco::Dictionary>
int toInt() const
Convert MxArray to int.
Definition: MxArray.cpp:489
T distance(T... args)
T at(mwIndex index) const
Template for numeric array element accessor.
Definition: MxArray.hpp:1250
void push_back(const _Tp &elem)
std::vector< std::vector< int > > nearestMarkerIdx
std::string toString() const
Convert MxArray to std::string.
Definition: MxArray.cpp:517
Size getChessboardSize() const
#define CV_8U
float getMarkerLength() const
bool isChar() const
Determine whether input is string array.
Definition: MxArray.hpp:614
std::vector< std::vector< int > > nearestMarkerCorners
float getMarkerLength() const
T end(T... args)
const ConstMap< int, std::string > CornerRefineMethodInvMap
Inverse corner refinement methods map.
void set(mwIndex index, const T &value)
Template for numeric array element write accessor.
Definition: MxArray.hpp:1310
Ptr< Board > create_Board(vector< MxArray >::const_iterator first, vector< MxArray >::const_iterator last)
Create an instance of Board using options in arguments.
float getMarkerSeparation() const
STL class.
std::vector< Point3f > chessboardCorners
MxArray toStruct(const Ptr< DetectorParameters > &params)
Convert detector parameters to scalar struct.
std::vector< int > ids
T push_back(T... args)
Common definitions for the aruco module.
static Mat getBitsFromByteList(const Mat &byteList, int markerSize)
float getSquareLength() const
static Ptr< GridBoard > create(int markersX, int markersY, float markerLength, float markerSeparation, const Ptr< Dictionary > &dictionary, int firstMarker=0)
const ConstMap< std::string, int > CornerRefineMethodMap
Corner refinement methods map.
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...
static Mat getByteListFromBits(const Mat &bits)
Size getGridSize() const
Ptr< Dictionary > dictionary
bool isField(const std::string &fieldName) const
Determine whether a struct array has a specified field.
Definition: MxArray.hpp:743
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
bool isStruct() const
Determine whether input is structure array.
Definition: MxArray.hpp:708
Ptr< CharucoBoard > create_CharucoBoard(vector< MxArray >::const_iterator first, vector< MxArray >::const_iterator last)
Create an instance of CharucoBoard using options in arguments.
Ptr< GridBoard > create_GridBoard(vector< MxArray >::const_iterator first, vector< MxArray >::const_iterator last)
Create an instance of GridBoard using options in arguments.
T size(T... args)
std::vector< T > toVector() const
Convert MxArray to std::vector<T> of primitive types.
Definition: MxArray.hpp:1151
STL class.
bool empty() const
T begin(T... args)
static Ptr< DetectorParameters > create()
const ConstMap< std::string, cv::aruco::PREDEFINED_DICTIONARY_NAME > PredefinedDictionaryMap
Predefined dictionary types.
Ptr< Dictionary > getPredefinedDictionary(PREDEFINED_DICTIONARY_NAME name)
T c_str(T... args)
Mat row(int y) const
static Ptr< Board > create(InputArrayOfArrays objPoints, const Ptr< Dictionary > &dictionary, InputArray ids)
std::vector< std::vector< Point3f > > objPoints
static Ptr< CharucoBoard > create(int squaresX, int squaresY, float squareLength, float markerLength, const Ptr< Dictionary > &dictionary)
int type() const
Ptr< DetectorParameters > MxArrayToDetectorParameters(const MxArray &s)
Convert MxArray to cv::Ptr<cv::aruco::DetectorParameters>
Ptr< Board > MxArrayToBoard(const MxArray &arr)
Convert MxArray to cv::Ptr<cv::aruco::Board>
Ptr< Dictionary > generateCustomDictionary(int nMarkers, int markerSize)