SLProject  4.2.000
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
CVTrackedAruco.cpp
Go to the documentation of this file.
1 /**
2  * \file CVTrackedAruco.cpp
3  * \date Winter 2016
4  * \remarks Please use clangformat to format the code. See more code style on
5  * https://github.com/cpvrlab/SLProject4/wiki/SLProject-Coding-Style
6  * \authors Marcus Hudritsch, Michael Goettlicher, Marino von Wattenwyl
7  * \copyright http://opensource.org/licenses/GPL-3.0
8 */
9 
10 /*
11 The OpenCV library version 3.4 or above with extra module must be present.
12 If the application captures the live video stream with OpenCV you have
13 to define in addition the constant APP_USES_CVCAPTURE.
14 All classes that use OpenCV begin with CV.
15 See also the class docs for CVCapture, CVCalibration and CVTracked
16 for a good top down information.
17 */
18 #include <CVTrackedAruco.h>
19 #include <Utils.h>
20 #include <Profiler.h>
21 
22 //-----------------------------------------------------------------------------
23 CVTrackedAruco::CVTrackedAruco(int arucoID, string calibIniPath)
24  : _calibIniPath(calibIniPath),
25  _arucoID(arucoID)
26 {
27  SLbool paramsLoaded = _params.loadFromFile(_calibIniPath);
28 
29  if (!paramsLoaded)
30  Utils::exitMsg("SLProject",
31  "CVTrackedAruco::track: Failed to load Aruco parameters.",
32  __LINE__,
33  __FILE__);
34 }
35 //-----------------------------------------------------------------------------
36 //! Tracks the all Aruco markers in the given image for the first sceneview
38  CVMat imageBgr,
39  CVCalibration* calib)
40 {
41  if (!trackAll(imageGray, imageBgr, calib))
42  {
43  return false;
44  }
45 
46  if (!arucoIDs.empty())
47  {
48  // Find the marker with the matching id
49  for (size_t i = 0; i < arucoIDs.size(); ++i)
50  {
51  if (arucoIDs[i] == _arucoID)
52  {
54  return true;
55  }
56  }
57  }
58 
59  return false;
60 }
61 //-----------------------------------------------------------------------------
63  CVMat imageBgr,
64  CVCalibration* calib,
65  CVRect roi)
66 {
68 
69  assert(!imageGray.empty() && "ImageGray is empty");
70  assert(!imageBgr.empty() && "ImageBGR is empty");
71  assert(!calib->cameraMat().empty() && "Calibration is empty");
72 
73 #if CV_MAJOR_VERSION < 4 || CV_MINOR_VERSION < 7
74  if (_params.arucoParams.empty() || _params.dictionary.empty())
75  {
76  Utils::warnMsg("SLProject",
77  "CVTrackedAruco::track: Aruco paramters are empty.",
78  __LINE__,
79  __FILE__);
80  return false;
81  }
82 #endif
83 
84  ////////////
85  // Detect //
86  ////////////
87 
88  CVMat croppedImageGray = roi.empty() ? imageGray : imageGray(roi);
89 
90  float startMS = _timer.elapsedTimeInMilliSec();
91 
92  arucoIDs.clear();
93  objectViewMats.clear();
94  CVVVPoint2f corners, rejected;
95 
96 #if CV_MAJOR_VERSION < 4 || CV_MINOR_VERSION < 7
97  cv::aruco::detectMarkers(croppedImageGray,
99  corners,
100  arucoIDs,
102  rejected);
103 #else
104  cv::aruco::ArucoDetector detector(_params.dictionary, _params.arucoParams);
105  detector.detectMarkers(croppedImageGray,
106  corners,
107  arucoIDs,
108  rejected);
109 #endif
110 
111  for (auto& corner : corners)
112  {
113  for (auto& j : corner)
114  {
115  j.x += (float)roi.x;
116  j.y += (float)roi.y;
117  }
118  }
119 
121 
122  if (!arucoIDs.empty())
123  {
124  if (_drawDetection)
125  cv::aruco::drawDetectedMarkers(imageBgr,
126  corners,
127  arucoIDs,
128  cv::Scalar(0, 0, 255));
129 
130  /////////////////////
131  // Pose Estimation //
132  /////////////////////
133 
134  startMS = _timer.elapsedTimeInMilliSec();
135 
136  // find the camera extrinsic parameters (rVec & tVec)
137  CVVPoint3d rVecs, tVecs;
138  cv::aruco::estimatePoseSingleMarkers(corners,
140  calib->cameraMat(),
141  calib->distortion(),
142  rVecs,
143  tVecs);
144 
146 
147  // Get the object view matrix for all aruco markers
148  for (size_t i = 0; i < arucoIDs.size(); ++i)
149  {
150  CVMatx44f ovm = createGLMatrix(cv::Mat(tVecs[i]), cv::Mat(rVecs[i]));
151  objectViewMats.push_back(ovm);
152 
153  if (_drawDetection)
154  {
155 #if CV_MAJOR_VERSION < 4 || CV_MINOR_VERSION < 6
156 #else
157  cv::drawFrameAxes(imageBgr,
158  calib->cameraMat(),
159  calib->distortion(),
160  cv::Mat(rVecs[i]),
161  cv::Mat(tVecs[i]),
162  0.01f);
163 #endif
164  }
165  }
166  }
167 
168  return true;
169 }
170 //-----------------------------------------------------------------------------
171 /*! CVTrackedAruco::drawArucoMarkerBoard draws and saves an aruco board
172 into an image.
173 @param dictionaryId integer id of the dictionary
174 @param numMarkersX NO. of markers in x-direction
175 @param numMarkersY NO. of markers in y-direction
176 @param markerEdgeM Length of one marker in meters
177 @param markerSepaM Separation between markers in meters
178 @param imgName Image filename inklusive format extension
179 @param dpi Dots per inch (default 256)
180 @param showImage Shows image in window (default false)
181 */
183  int numMarkersX,
184  int numMarkersY,
185  float markerEdgeM,
186  float markerSepaM,
187  const string& imgName,
188  float dpi,
189  bool showImage)
190 {
191 #if CV_MAJOR_VERSION < 4 || CV_MINOR_VERSION < 7
192  cv::Ptr<cv::aruco::Dictionary> dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::PREDEFINED_DICTIONARY_NAME(dictionaryId));
193  cv::Ptr<cv::aruco::GridBoard> board = cv::aruco::GridBoard::create(numMarkersX,
194  numMarkersY,
195  markerEdgeM,
196  markerSepaM,
197  dictionary);
198  CVSize imageSize;
199  imageSize.width = (int)((markerEdgeM + markerSepaM) * 100.0f / 2.54f * dpi * (float)numMarkersX);
200  imageSize.height = (int)((markerEdgeM + markerSepaM) * 100.0f / 2.54f * dpi * (float)numMarkersY);
201 
202  imageSize.width -= (imageSize.width % 4);
203  imageSize.height -= (imageSize.height % 4);
204 
205  // show created board
206  CVMat boardImage;
207  board->draw(imageSize, boardImage, 0, 1);
208 
209  if (showImage)
210  {
211  imshow("board", boardImage);
212  cv::waitKey(0);
213  }
214 #else
215  cv::aruco::Dictionary dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::PredefinedDictionaryType(dictionaryId));
216  cv::aruco::GridBoard board = cv::aruco::GridBoard(cv::Size(numMarkersX, numMarkersY),
217  markerEdgeM,
218  markerSepaM,
219  dictionary);
220 
221  CVSize imageSize;
222  imageSize.width = (int)((markerEdgeM + markerSepaM) * 100.0f / 2.54f * dpi * (float)numMarkersX);
223  imageSize.height = (int)((markerEdgeM + markerSepaM) * 100.0f / 2.54f * dpi * (float)numMarkersY);
224 
225  imageSize.width -= (imageSize.width % 4);
226  imageSize.height -= (imageSize.height % 4);
227 
228  // show created board
229  CVMat boardImage;
230  cv::aruco::drawPlanarBoard(&board,
231  imageSize,
232  boardImage,
233  0,
234  1);
235 # ifndef __EMSCRIPTEN__
236  if (showImage)
237  {
238  imshow("board", boardImage);
239  cv::waitKey(0);
240  }
241 # endif
242 #endif
243 
244 #ifndef __EMSCRIPTEN__
245  imwrite(imgName, boardImage);
246 #endif
247 }
248 //-----------------------------------------------------------------------------
249 void CVTrackedAruco::drawArucoMarker(int dictionaryId,
250  int minMarkerId,
251  int maxMarkerId,
252  int markerSizePX)
253 {
254  assert(dictionaryId > 0);
255  assert(minMarkerId > 0);
256  assert(minMarkerId < maxMarkerId);
257 
258 #if CV_MAJOR_VERSION < 4 || CV_MINOR_VERSION < 7
259  cv::Ptr<cv::aruco::Dictionary> dict = getPredefinedDictionary(cv::aruco::PREDEFINED_DICTIONARY_NAME(dictionaryId));
260  if (maxMarkerId > dict->bytesList.rows)
261  maxMarkerId = dict->bytesList.rows;
262 
263  CVMat markerImg;
264 
265  for (int i = minMarkerId; i < maxMarkerId; ++i)
266  {
267  cv::aruco::drawMarker(dict, i, markerSizePX, markerImg, 1);
268 # ifndef __EMSCRIPTEN__
269  imwrite(Utils::formatString("ArucoMarker_Dict%d_%dpx_Id%d.png",
270  dictionaryId,
271  markerSizePX,
272  i),
273  markerImg);
274 # endif
275  }
276 #else
277  cv::aruco::Dictionary dict = getPredefinedDictionary(cv::aruco::PredefinedDictionaryType(dictionaryId));
278  if (maxMarkerId > dict.bytesList.rows)
279  maxMarkerId = dict.bytesList.rows;
280 
281  CVMat markerImg;
282 
283  for (int i = minMarkerId; i < maxMarkerId; ++i)
284  {
285  cv::aruco::generateImageMarker(dict,
286  i,
287  markerSizePX,
288  markerImg,
289  1);
290 # ifndef __EMSCRIPTEN__
291  imwrite(Utils::formatString("ArucoMarker_Dict%d_%dpx_Id%d.png",
292  dictionaryId,
293  markerSizePX,
294  i),
295  markerImg);
296 # endif
297  }
298 #endif
299 }
300 //-----------------------------------------------------------------------------
static SLint dpi
Dot per inch resolution of screen.
Definition: AppGLFW.cpp:41
cv::Matx44f CVMatx44f
Definition: CVTypedefs.h:59
vector< cv::Point3d > CVVPoint3d
Definition: CVTypedefs.h:80
cv::Rect CVRect
Definition: CVTypedefs.h:39
cv::Size CVSize
Definition: CVTypedefs.h:55
cv::Mat CVMat
Definition: CVTypedefs.h:38
vector< vector< cv::Point2f > > CVVVPoint2f
Definition: CVTypedefs.h:96
#define PROFILE_FUNCTION()
Definition: Instrumentor.h:41
bool SLbool
Definition: SL.h:175
bool loadFromFile(string calibIniPath)
cv::Ptr< cv::aruco::DetectorParameters > arucoParams
detector parameter structure for aruco detection function
float edgeLength
marker edge length
cv::Ptr< cv::aruco::Dictionary > dictionary
predefined dictionary
Live video camera calibration class with OpenCV an OpenCV calibration.
Definition: CVCalibration.h:71
const CVMat & cameraMat() const
const CVMat & distortion() const
bool track(CVMat imageGray, CVMat imageBgr, CVCalibration *calib)
Tracks the all Aruco markers in the given image for the first sceneview.
static void drawArucoMarkerBoard(int dictionaryId, int numMarkersX, int numMarkersY, float markerEdgeLengthM, float markerSepaM, const string &imgName, float dpi=254.0f, bool showImage=false)
Helper function to draw and save an aruco marker board image.
CVArucoParams _params
Aruco parameters.
int _arucoID
Aruco Marker ID for this node.
static void drawArucoMarker(int dictionaryId, int minMarkerId, int maxMarkerId, int markerSizePX=200)
Helper function to draw and save an aruco marker set.
CVTrackedAruco(int arucoID, string calibIniPath)
bool trackAll(CVMat imageGray, CVMat imageBgr, CVCalibration *calib, CVRect roi=CVRect(0, 0, 0, 0))
vector< int > arucoIDs
detected Aruco marker IDs
CVVMatx44f objectViewMats
object view matrices for all found markers
CVMatx44f _objectViewMat
view transformation matrix
Definition: CVTracked.h:93
static AvgFloat detectTimesMS
Averaged time for video feature detection & description in ms.
Definition: CVTracked.h:83
bool _drawDetection
Flag if detection should be drawn into image.
Definition: CVTracked.h:92
static cv::Matx44f createGLMatrix(const CVMat &tVec, const CVMat &rVec)
Create an OpenGL 4x4 matrix from an OpenCV translation & rotation vector.
Definition: CVTracked.cpp:46
HighResTimer _timer
High resolution timer.
Definition: CVTracked.h:94
static AvgFloat poseTimesMS
Averaged time for video feature pose estimation in ms.
Definition: CVTracked.h:88
float elapsedTimeInMilliSec()
Definition: HighResTimer.h:38
void set(T value)
Sets the current value in the value array and builds the average.
Definition: Averaged.h:53
string formatString(string fmt_str,...)
Returns a formatted string as sprintf.
Definition: Utils.cpp:320
void warnMsg(const char *tag, const char *msg, const int line, const char *file)
Platform independent warn message output.
Definition: Utils.cpp:1145
void exitMsg(const char *tag, const char *msg, const int line, const char *file)
Terminates the application with a message. No leak checking.
Definition: Utils.cpp:1135