markermap.cpp
Go to the documentation of this file.
1 
17 #include "markermap.h"
18 #include "dictionary.h"
19 
20 #include <opencv2/calib3d/calib3d.hpp>
21 #include <opencv2/imgproc/imgproc.hpp>
22 
23 #include <fstream>
24 
25 using namespace std;
26 using namespace cv;
27 
28 namespace aruco
29 {
30 Marker3DInfo::Marker3DInfo()
31 {
32 }
33 Marker3DInfo::Marker3DInfo(int _id) : id(_id)
34 {
35 }
41 {
42  mInfoType = NONE;
43 }
48 MarkerMap::MarkerMap(string filePath)
49 {
50  mInfoType = NONE;
51  readFromFile(filePath);
52 }
53 
58 void MarkerMap::saveToFile(string sfile)
59 {
60  cv::FileStorage fs(sfile, cv::FileStorage::WRITE);
61  saveToFile(fs);
62 }
65 void MarkerMap::saveToFile(cv::FileStorage& fs)
66 {
67  fs << "aruco_bc_dict" << dictionary;
68  fs << "aruco_bc_nmarkers" << (int)size();
69  fs << "aruco_bc_mInfoType" << (int)mInfoType;
70  fs << "aruco_bc_markers"
71  << "[";
72  for (size_t i = 0; i < size(); i++)
73  {
74  fs << "{:"
75  << "id" << at(i).id;
76 
77  fs << "corners"
78  << "[:";
79  for (size_t c = 0; c < at(i).size(); c++)
80  fs << at(i)[c];
81  fs << "]";
82  fs << "}";
83  }
84  fs << "]";
85 }
86 
91 void MarkerMap::readFromFile(string sfile)
92 {
93  try
94  {
95  cv::FileStorage fs(sfile, cv::FileStorage::READ);
96  if (!fs.isOpened())
97  throw cv::Exception(81818, "MarkerMap::readFromFile",
98  string(" file not opened ") + sfile, __FILE__, __LINE__);
99  readFromFile(fs);
100  }
101  catch (std::exception& ex)
102  {
103  throw cv::Exception(81818, "MarkerMap::readFromFile",
104  ex.what() + string(" file=)") + sfile, __FILE__, __LINE__);
105  }
106 }
107 
110 void MarkerMap::readFromFile(cv::FileStorage& fs)
111 {
112  int aux = 0;
113  // look for the nmarkers
114  if (fs["aruco_bc_nmarkers"].name() != "aruco_bc_nmarkers")
115  throw cv::Exception(81818, "MarkerMap::readFromFile", "invalid file type", __FILE__, __LINE__);
116  fs["aruco_bc_nmarkers"] >> aux;
117  resize(aux);
118  fs["aruco_bc_mInfoType"] >> mInfoType;
119  cv::FileNode markers = fs["aruco_bc_markers"];
120  int i = 0;
121  for (FileNodeIterator it = markers.begin(); it != markers.end(); ++it, i++)
122  {
123  at(i).id = (*it)["id"];
124  FileNode FnCorners = (*it)["corners"];
125  for (FileNodeIterator itc = FnCorners.begin(); itc != FnCorners.end(); ++itc)
126  {
127  vector<float> coordinates3d;
128  (*itc) >> coordinates3d;
129  if (coordinates3d.size() != 3)
130  throw cv::Exception(81818, "MarkerMap::readFromFile", "invalid file type 3",
131  __FILE__, __LINE__);
132  cv::Point3f point(coordinates3d[0], coordinates3d[1], coordinates3d[2]);
133  at(i).push_back(point);
134  }
135  }
136 
137  if (fs["aruco_bc_dict"].name() == "aruco_bc_dict")
138  fs["aruco_bc_dict"] >> dictionary;
139 }
140 
144 {
145  for (size_t i = 0; i < size(); i++)
146  if (at(i).id == id)
147  return static_cast<int>(i);
148  return -1;
149 }
150 
154 {
155  for (size_t i = 0; i < size(); i++)
156  if (at(i).id == id)
157  return at(i);
158  throw cv::Exception(111, "MarkerMap::getMarker3DInfo",
159  "Marker with the id given is not found", __FILE__, __LINE__);
160 }
161 
162 void __glGetModelViewMatrix(double modelview_matrix[16], const cv::Mat& Rvec, const cv::Mat& Tvec)
163 {
164  // check if paremeters are valid
165  bool invalid = false;
166  for (int i = 0; i < 3 && !invalid; i++)
167  {
168  if (Tvec.at<float>(i, 0) != -999999)
169  invalid |= false;
170  if (Rvec.at<float>(i, 0) != -999999)
171  invalid |= false;
172  }
173  if (invalid)
174  throw cv::Exception(9002, "extrinsic parameters are not set",
175  "Marker::getModelViewMatrix", __FILE__, __LINE__);
176  Mat Rot(3, 3, CV_32FC1), Jacob;
177  Rodrigues(Rvec, Rot, Jacob);
178 
179  double para[3][4];
180  for (int i = 0; i < 3; i++)
181  for (int j = 0; j < 3; j++)
182  para[i][j] = Rot.at<float>(i, j);
183  // now, add the translation
184  para[0][3] = Tvec.at<float>(0, 0);
185  para[1][3] = Tvec.at<float>(1, 0);
186  para[2][3] = Tvec.at<float>(2, 0);
187  double scale = 1;
188 
189  modelview_matrix[0 + 0 * 4] = para[0][0];
190  // R1C2
191  modelview_matrix[0 + 1 * 4] = para[0][1];
192  modelview_matrix[0 + 2 * 4] = para[0][2];
193  modelview_matrix[0 + 3 * 4] = para[0][3];
194  // R2
195  modelview_matrix[1 + 0 * 4] = para[1][0];
196  modelview_matrix[1 + 1 * 4] = para[1][1];
197  modelview_matrix[1 + 2 * 4] = para[1][2];
198  modelview_matrix[1 + 3 * 4] = para[1][3];
199  // R3
200  modelview_matrix[2 + 0 * 4] = -para[2][0];
201  modelview_matrix[2 + 1 * 4] = -para[2][1];
202  modelview_matrix[2 + 2 * 4] = -para[2][2];
203  modelview_matrix[2 + 3 * 4] = -para[2][3];
204  modelview_matrix[3 + 0 * 4] = 0.0;
205  modelview_matrix[3 + 1 * 4] = 0.0;
206  modelview_matrix[3 + 2 * 4] = 0.0;
207  modelview_matrix[3 + 3 * 4] = 1.0;
208  if (scale != 0.0)
209  {
210  modelview_matrix[12] *= scale;
211  modelview_matrix[13] *= scale;
212  modelview_matrix[14] *= scale;
213  }
214 }
215 
216 /****
217  *
218  */
219 void __OgreGetPoseParameters(double position[3], double orientation[4],
220  const cv::Mat& Rvec, const cv::Mat& Tvec)
221 {
222  // check if paremeters are valid
223  bool invalid = false;
224  for (int i = 0; i < 3 && !invalid; i++)
225  {
226  if (Tvec.at<float>(i, 0) != -999999)
227  invalid |= false;
228  if (Rvec.at<float>(i, 0) != -999999)
229  invalid |= false;
230  }
231  if (invalid)
232  throw cv::Exception(9003, "extrinsic parameters are not set",
233  "Marker::getModelViewMatrix", __FILE__, __LINE__);
234 
235  // calculate position vector
236  position[0] = -Tvec.ptr<float>(0)[0];
237  position[1] = -Tvec.ptr<float>(0)[1];
238  position[2] = +Tvec.ptr<float>(0)[2];
239 
240  // now calculare orientation quaternion
241  cv::Mat Rot(3, 3, CV_32FC1);
242  cv::Rodrigues(Rvec, Rot);
243 
244  // calculate axes for quaternion
245  double stAxes[3][3];
246  // x axis
247  stAxes[0][0] = -Rot.at<float>(0, 0);
248  stAxes[0][1] = -Rot.at<float>(1, 0);
249  stAxes[0][2] = +Rot.at<float>(2, 0);
250  // y axis
251  stAxes[1][0] = -Rot.at<float>(0, 1);
252  stAxes[1][1] = -Rot.at<float>(1, 1);
253  stAxes[1][2] = +Rot.at<float>(2, 1);
254  // for z axis, we use cross product
255  stAxes[2][0] = stAxes[0][1] * stAxes[1][2] - stAxes[0][2] * stAxes[1][1];
256  stAxes[2][1] = -stAxes[0][0] * stAxes[1][2] + stAxes[0][2] * stAxes[1][0];
257  stAxes[2][2] = stAxes[0][0] * stAxes[1][1] - stAxes[0][1] * stAxes[1][0];
258 
259  // transposed matrix
260  double axes[3][3];
261  axes[0][0] = stAxes[0][0];
262  axes[1][0] = stAxes[0][1];
263  axes[2][0] = stAxes[0][2];
264 
265  axes[0][1] = stAxes[1][0];
266  axes[1][1] = stAxes[1][1];
267  axes[2][1] = stAxes[1][2];
268 
269  axes[0][2] = stAxes[2][0];
270  axes[1][2] = stAxes[2][1];
271  axes[2][2] = stAxes[2][2];
272 
273  // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
274  // article "Quaternion Calculus and Fast Animation".
275  double fTrace = axes[0][0] + axes[1][1] + axes[2][2];
276  double fRoot;
277 
278  if (fTrace > 0.0)
279  {
280  // |w| > 1/2, may as well choose w > 1/2
281  fRoot = sqrt(fTrace + 1.0); // 2w
282  orientation[0] = 0.5 * fRoot;
283  fRoot = 0.5 / fRoot; // 1/(4w)
284  orientation[1] = (axes[2][1] - axes[1][2]) * fRoot;
285  orientation[2] = (axes[0][2] - axes[2][0]) * fRoot;
286  orientation[3] = (axes[1][0] - axes[0][1]) * fRoot;
287  }
288  else
289  {
290  // |w| <= 1/2
291  static unsigned int s_iNext[3] = { 1, 2, 0 };
292  unsigned int i = 0;
293  if (axes[1][1] > axes[0][0])
294  i = 1;
295  if (axes[2][2] > axes[i][i])
296  i = 2;
297  unsigned int j = s_iNext[i];
298  unsigned int k = s_iNext[j];
299 
300  fRoot = sqrt(axes[i][i] - axes[j][j] - axes[k][k] + 1.0);
301  double* apkQuat[3] = { &orientation[1], &orientation[2], &orientation[3] };
302  *apkQuat[i] = 0.5 * fRoot;
303  fRoot = 0.5 / fRoot;
304  orientation[0] = (axes[k][j] - axes[j][k]) * fRoot;
305  *apkQuat[j] = (axes[j][i] + axes[i][j]) * fRoot;
306  *apkQuat[k] = (axes[k][i] + axes[i][k]) * fRoot;
307  }
308 }
309 
312 void MarkerMap::getIdList(std::vector<int>& ids, bool append) const
313 {
314  if (!append)
315  ids.clear();
316  for (size_t i = 0; i < size(); i++)
317  ids.push_back(at(i).id);
318 }
319 
320 MarkerMap MarkerMap::convertToMeters(float markerSize_meters) const
321 {
322  if (!isExpressedInPixels())
323  throw cv::Exception(-1, "The board is not expressed in pixels",
324  "MarkerMap::convertToMeters", __FILE__, __LINE__);
325  // first, we are assuming all markers are equally sized. So, lets get the size in pixels
326  int markerSizePix = static_cast<int>(cv::norm(at(0)[0] - at(0)[1]));
327  MarkerMap BInfo(*this);
329  // now, get the size of a pixel, and change scale
330  float pixSize = markerSize_meters / float(markerSizePix);
331  // cout << markerSize_meters << " " << float(markerSizePix) << " " << pixSize <<
332  // endl;
333  for (size_t i = 0; i < BInfo.size(); i++)
334  for (int c = 0; c < 4; c++)
335  {
336  BInfo[i][c] *= pixSize;
337  }
338  return BInfo;
339 }
340 cv::Mat MarkerMap::getImage(float METER2PIX) const
341 {
342  if (mInfoType == NONE)
343  throw cv::Exception(-1, "The board is not valid mInfoType==NONE ",
344  "MarkerMap::getImage", __FILE__, __LINE__);
345  if (METER2PIX <= 0 && mInfoType != PIX)
346  throw cv::Exception(-1, "The board is not expressed in pixels and not METER2PIX indicated",
347  "MarkerMap::getImage", __FILE__, __LINE__);
348 
350 
351  // get image limits
352  cv::Point pmin(std::numeric_limits<int>::max(), std::numeric_limits<int>::max()),
353  pmax(std::numeric_limits<int>::lowest(), std::numeric_limits<int>::lowest());
354  for (auto b : *this)
355  {
356  for (auto p : b.points)
357  {
358  pmin.x = min(int(p.x), pmin.x);
359  pmin.y = min(int(p.y), pmin.y);
360  pmax.x = max(int(p.x + 0.5), pmax.x);
361  pmax.y = max(int(p.y + 0.5), pmax.y);
362  assert(p.z == 0);
363  }
364  }
365 
366  cv::Point psize = pmax - pmin;
367  cv::Mat image(cv::Size(psize.x, psize.y), CV_8UC1);
368  image.setTo(cv::Scalar::all(255));
369 
370  vector<Marker3DInfo> p3d = *this;
371  // the points must be moved from a real reference system to image reference sysmte (y
372  // positive is inverse)
373  for (auto& m : p3d)
374  for (auto& p : m.points)
375  {
376  p -= cv::Point3f(static_cast<float>(pmin.x), static_cast<float>(pmax.y), 0.f);
377  // now, use inverse y
378  p.y = -p.y;
379  }
380  for (auto m : p3d)
381  {
382  // get size and find size of this
383  const float size = static_cast<float>(cv::norm(m[0] - m[1]));
384  auto im1 = Dict.getMarkerImage_id(m.id, int(size / 8));
385  cv::Mat im2;
386  // now resize to fit
387  cv::resize(im1, im2, cv::Size(static_cast<int>(size), static_cast<int>(size)));
388  // copy in correct position
389  auto ry = cv::Range(int(m[0].y), int(m[2].y));
390  auto rx = cv::Range(int(m[0].x), int(m[2].x));
391  cv::Mat sub = image(ry, rx);
392  im2.copyTo(sub);
393  }
394  return image;
395 }
396 
397 std::vector<int> MarkerMap::getIndices(const vector<aruco::Marker>& markers) const
398 {
399  std::vector<int> indices;
400  for (size_t i = 0; i < markers.size(); i++)
401  {
402  bool found = false;
403  for (size_t j = 0; j < size() && !found; j++)
404  {
405  if (markers[i].id == at(j).id)
406  {
407  found = true;
408  indices.push_back(static_cast<int>(i));
409  }
410  }
411  }
412  return indices;
413 }
414 void MarkerMap::toStream(std::ostream& str)
415 {
416  str << mInfoType << " " << size() << " ";
417  for (size_t i = 0; i < size(); i++)
418  {
419  at(i).toStream(str);
420  }
421  // write dic string info
422  str << dictionary;
423 }
424 void MarkerMap::fromStream(std::istream& str)
425 {
426  int s;
427  str >> mInfoType >> s;
428  resize(s);
429  for (size_t i = 0; i < size(); i++)
430  at(i).fromStream(str);
431  str >> dictionary;
432 }
433 pair<cv::Mat, cv::Mat> MarkerMap::calculateExtrinsics(const std::vector<aruco::Marker>& markers,
434  float markerSize, cv::Mat CameraMatrix,
435  cv::Mat Distorsion)
436 {
437  vector<cv::Point2f> p2d;
438  MarkerMap m_meters;
439  if (isExpressedInPixels())
440  m_meters = convertToMeters(markerSize);
441  else
442  m_meters = *this;
443  vector<cv::Point3f> p3d;
444  for (auto marker : markers)
445  {
446  auto it = find(m_meters.begin(), m_meters.end(), marker.id);
447  if (it != m_meters.end())
448  { // is the marker part of the map?
449  for (auto p : marker)
450  p2d.push_back(p);
451  for (auto p : it->points)
452  p3d.push_back(p);
453  }
454  }
455 
456  cv::Mat rvec, tvec;
457  if (p2d.size() != 0)
458  { // no points in the vector
459  cv::solvePnPRansac(p3d, p2d, CameraMatrix, Distorsion, rvec, tvec);
460  }
461  if (rvec.type() == CV_64F)
462  rvec.convertTo(rvec, CV_64F);
463  if (tvec.type() == CV_64F)
464  tvec.convertTo(tvec, CV_64F);
465  return make_pair(rvec, tvec);
466 }
467 }; // namespace aruco
aruco::MarkerMap
This class defines a set of markers whose locations are attached to a common reference system,...
Definition: markermap.h:111
aruco::MarkerMap::METERS
@ METERS
Definition: markermap.h:185
aruco::__OgreGetPoseParameters
void __OgreGetPoseParameters(double position[3], double orientation[4], const cv::Mat &Rvec, const cv::Mat &Tvec)
Definition: markermap.cpp:219
aruco::MarkerMap::isExpressedInPixels
bool isExpressedInPixels() const
Definition: markermap.h:131
aruco::Dictionary::loadPredefined
static Dictionary loadPredefined(DICT_TYPES type)
Definition: dictionary.cpp:113
aruco::MarkerMap::calculateExtrinsics
std::pair< cv::Mat, cv::Mat > calculateExtrinsics(const std::vector< aruco::Marker > &markers, float markerSize, cv::Mat CameraMatrix, cv::Mat Distorsion)
Definition: markermap.cpp:433
markermap.h
aruco::MarkerMap::getImage
cv::Mat getImage(float METER2PIX=0) const
Definition: markermap.cpp:340
aruco::MarkerMap::getIndices
std::vector< int > getIndices(const vector< Marker > &markers) const
Definition: markermap.cpp:397
aruco::MarkerMap::readFromFile
void readFromFile(std::string sfile)
aruco::MarkerMap::toStream
void toStream(std::ostream &str)
Definition: markermap.cpp:414
aruco::MarkerMap::fromStream
void fromStream(std::istream &str)
Definition: markermap.cpp:424
aruco::MarkerMap::NONE
@ NONE
Definition: markermap.h:183
aruco::MarkerMap::MarkerMap
MarkerMap()
Definition: markermap.cpp:40
dictionary.h
aruco::MarkerMap::getIndexOfMarkerId
int getIndexOfMarkerId(int id) const
Definition: markermap.cpp:143
aruco::MarkerMap::getIdList
void getIdList(vector< int > &ids, bool append=true) const
Definition: markermap.cpp:312
aruco::MarkerMap::mInfoType
int mInfoType
Definition: markermap.h:195
std
aruco::MarkerMap::PIX
@ PIX
Definition: markermap.h:184
aruco::MarkerMap::getMarker3DInfo
const Marker3DInfo & getMarker3DInfo(int id) const
Definition: markermap.cpp:153
aruco
Definition: cameraparameters.h:24
aruco::MarkerMap::dictionary
std::string dictionary
Definition: markermap.h:199
aruco::MarkerMap::convertToMeters
MarkerMap convertToMeters(float markerSize) const
Definition: markermap.cpp:320
aruco::__glGetModelViewMatrix
void __glGetModelViewMatrix(double modelview_matrix[16], const cv::Mat &Rvec, const cv::Mat &Tvec)
Definition: markermap.cpp:162
aruco::MarkerMap::saveToFile
void saveToFile(std::string sfile)
aruco::Marker3DInfo
Definition: markermap.h:33


aruco
Author(s): Rafael Muñoz Salinas , Bence Magyar
autogenerated on Sat Sep 23 2023 02:26:45