SLProject  4.2.000
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
CVTrackedArucoCube.cpp
Go to the documentation of this file.
1 /**
2  * \file CVTrackedArucoCube.cpp
3  * \date September 2021
4  * \authors Marino von Wattenwyl
5  * \copyright http://opensource.org/licenses/GPL-3.0
6  * \remarks Please use clangformat to format the code. See more code style on
7  * https://github.com/cpvrlab/SLProject4/wiki/SLProject-Coding-Style
8 */
9 
10 #include <CVTrackedArucoCube.h>
11 #include <Utils.h>
12 #include <Instrumentor.h>
13 
14 // TODO: Replace with OpenCV classes, SL not allowed in OpenCV module
15 #include <SLMat4.h>
16 #include <Averaged.h>
17 
18 #include <utility>
19 
20 //-----------------------------------------------------------------------------
21 CVTrackedArucoCube::CVTrackedArucoCube(string calibIniPath, float edgeLength)
22  : CVTrackedAruco(-1, std::move(calibIniPath)),
23  _edgeLength(edgeLength),
24  _averagePosition(2, CVVec3f(0.0f, 0.0f, 0.0f)),
25  _averageRotation(2, SLQuat4f(0.0f, 0.0f, 0.0f, 1.0f))
26 {
27 }
28 //-----------------------------------------------------------------------------
30  CVMat imageBgr,
31  CVCalibration* calib)
32 {
34 
35  /////////////////
36  // TRACK FACES //
37  /////////////////
38 
39  if (!trackAll(imageGray, imageBgr, calib, _roi))
40  {
41  return false;
42  }
43 
44  ///////////////////////////////////////////////
45  // COLLECT FACE TRANSFORMATIONS AND WEIGHTS //
46  ///////////////////////////////////////////////
47 
48  vector<CVVec3f> translations;
49  vector<SLQuat4f> rotations;
50  vector<float> weights;
51 
52  for (size_t i = 0; i < arucoIDs.size(); i++)
53  {
54  // Convert the OpenCV matrix to an SL matrix
55  SLMat4f faceViewMatrix(objectViewMats[i].val);
56  faceViewMatrix.transpose();
57 
58  // Calculate how much this face contributes to the total transformation
59  // The steeper a face is relative to the camera,
60  // the less it should contribute because the accuracy is generally poorer in this case
61  float weight = faceViewMatrix.axisZ().dot(SLVec3f::AXISZ);
62 
63  // Weights below 0.3 are very inaccurate
64  // If the weight is negative, this means that the z axis is pointing the wrong way
65  if (weight < 0.3f)
66  {
67  continue;
68  }
69 
70  weight = Utils::clamp(weight, 0.0f, 1.0f);
71 
72  // Move to the center of the cube
73  faceViewMatrix.translate(0.0f, 0.0f, -0.5f * _edgeLength);
74 
75  // Rotate face to cube space
76  SLVec3f translation = faceViewMatrix.translation();
77  if (arucoIDs[i] == 0)
78  ; // front (no rotation)
79  else if (arucoIDs[i] == 1)
80  faceViewMatrix.rotate(-90, SLVec3f::AXISY); // right
81  else if (arucoIDs[i] == 2)
82  faceViewMatrix.rotate(-180, SLVec3f::AXISY); // back
83  else if (arucoIDs[i] == 3)
84  faceViewMatrix.rotate(90, SLVec3f::AXISY); // left
85  else if (arucoIDs[i] == 4)
86  faceViewMatrix.rotate(90, SLVec3f::AXISX); // top
87  else if (arucoIDs[i] == 5)
88  faceViewMatrix.rotate(-90, SLVec3f::AXISX); // bottom
89  else
90  {
91  SL_LOG("ArUco cube: Invalid ID: %d", arucoIDs[i]);
92  continue;
93  }
94 
95  // Reset translation
96  faceViewMatrix.m(12, translation.x);
97  faceViewMatrix.m(13, translation.y);
98  faceViewMatrix.m(14, translation.z);
99 
100  // Create a quaternion from the rotation of the matrix
101  SLQuat4f rotation;
102  rotation.fromMat3(faceViewMatrix.mat3());
103 
104  translations.emplace_back(translation.x, translation.y, translation.z);
105  rotations.push_back(rotation);
106  weights.push_back(weight);
107  }
108 
109  //////////////////////////////////
110  // AVERAGE FACE TRANSFORMATIONS //
111  //////////////////////////////////
112 
113  if (!translations.empty())
114  {
115  // Average the translations and rotations
116  CVVec3f posNow = averageVector(translations, weights);
117  SLQuat4f rotNow = averageQuaternion(rotations, weights);
118 
119  _averagePosition.set(posNow);
120  _averageRotation.set(rotNow);
121 
123  SLQuat4f rotQuat = _averageRotation.average();
124  SLMat3f rot = rotQuat.toMat3();
125 
126  // clang-format off
127  // Convert to an OpenCV matrix
128  _objectViewMat = CVMatx44f(rot.m(0), rot.m(3), rot.m(6), pos.val[0],
129  rot.m(1), rot.m(4), rot.m(7), pos.val[1],
130  rot.m(2), rot.m(5), rot.m(8), pos.val[2],
131  0, 0, 0, 1);
132  // clang-format on
133 
134  return true;
135  }
136 
137  return false;
138 }
139 //-----------------------------------------------------------------------------
cv::Matx44f CVMatx44f
Definition: CVTypedefs.h:59
cv::Vec3f CVVec3f
Definition: CVTypedefs.h:52
cv::Mat CVMat
Definition: CVTypedefs.h:38
#define PROFILE_FUNCTION()
Definition: Instrumentor.h:41
#define SL_LOG(...)
Definition: SL.h:233
void set(SLQuat4f value)
Sets the current value in the value array and builds the average.
Live video camera calibration class with OpenCV an OpenCV calibration.
Definition: CVCalibration.h:71
Averaged< CVVec3f > _averagePosition
AveragedQuat4f _averageRotation
CVTrackedArucoCube(string calibIniPath, float edgeLength)
bool track(CVMat imageGray, CVMat imageBgr, CVCalibration *calib)
Tracks the all Aruco markers in the given image for the first sceneview.
OpenCV ArUco marker tracker class derived from CVTracked.
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 SLQuat4f averageQuaternion(vector< SLQuat4f > quaternions, vector< float > weights)
Definition: CVTracked.cpp:153
static CVVec3f averageVector(vector< CVVec3f > vectors, vector< float > weights)
Definition: CVTracked.cpp:134
void m(int i, T val)
Definition: SLMat3.h:67
void transpose()
Sets the transposed matrix by swaping around the main diagonal.
Definition: SLMat4.h:1341
SLVec3< T > translation() const
Definition: SLMat4.h:184
SLMat3< T > mat3() const
Definition: SLMat4.h:98
void m(int i, T val)
Definition: SLMat4.h:93
void rotate(T degAng, T axisx, T axisy, T axisz)
Definition: SLMat4.h:656
SLVec3< T > axisZ() const
Definition: SLMat4.h:187
void translate(T tx, T ty, T tz=0)
Definition: SLMat4.h:601
SLMat3< T > toMat3() const
Definition: SLQuat4.h:318
void fromMat3(const SLMat3< T > &m)
Definition: SLQuat4.h:149
T y
Definition: SLVec3.h:43
static SLVec3 AXISY
Definition: SLVec3.h:298
T x
Definition: SLVec3.h:43
static SLVec3 AXISX
Definition: SLVec3.h:297
T dot(const SLVec3 &v) const
Definition: SLVec3.h:117
T z
Definition: SLVec3.h:43
static SLVec3 AXISZ
Definition: SLVec3.h:299
void set(T value)
Sets the current value in the value array and builds the average.
Definition: Averaged.h:53
T clamp(T a, T min, T max)
Definition: Utils.h:253