Skip to content
This repository was archived by the owner on Jul 20, 2023. It is now read-only.

Commit e4ebf82

Browse files
committed
Mask both frame 1 and 2 & replace inverse() by analytical formula
1 parent 384bf23 commit e4ebf82

File tree

3 files changed

+67
-15
lines changed

3 files changed

+67
-15
lines changed

interfaces/SolARDescriptorMatcherGeometricOpencv.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,9 @@ class SOLAROPENCV_EXPORT_API SolARDescriptorMatcherGeometricOpencv : public base
7373
/// @param[in] camParams1 The intrinsic parameters of the camera 1.
7474
/// @param[in] camParams2 The intrinsic parameters of the camera 2.
7575
/// @param[out] matches A vector of matches representing pairs of indices relatively to the first and second set of descriptors.
76-
/// @param[in] mask The indices of descriptors in the first frame are used for matching to the second frame. If it is empty then all will be used.
77-
/// @return FrameworkReturnCode::_SUCCESS if matching succeed, else FrameworkReturnCode::_ERROR_
76+
/// @param[in] mask1 The indices of descriptors in the first frame are used for matching to the second frame. If it is empty then all will be used.
77+
/// @param[in] mask2 The indices of descriptors in the second frame are used for matching to the first frame. If it is empty then all will be used.
78+
/// @return FrameworkReturnCode::_SUCCESS if matching succeed, else FrameworkReturnCode::_ERROR_
7879
FrameworkReturnCode match(const SRef<SolAR::datastructure::DescriptorBuffer> descriptors1,
7980
const SRef<SolAR::datastructure::DescriptorBuffer> descriptors2,
8081
const std::vector<SolAR::datastructure::Keypoint> &undistortedKeypoints1,
@@ -84,7 +85,8 @@ class SOLAROPENCV_EXPORT_API SolARDescriptorMatcherGeometricOpencv : public base
8485
const SolAR::datastructure::CameraParameters & camParams1,
8586
const SolAR::datastructure::CameraParameters & camParams2,
8687
std::vector<SolAR::datastructure::DescriptorMatch> & matches,
87-
const std::vector<uint32_t>& mask = {}) override;
88+
const std::vector<uint32_t>& mask1 = {},
89+
const std::vector<uint32_t>& mask2 = {}) override;
8890

8991
org::bcom::xpcf::XPCFErrorCode onConfigured() override final;
9092
void unloadComponent() override;

src/SolARDescriptorMatcherGeometricOpencv.cpp

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ FrameworkReturnCode SolARDescriptorMatcherGeometricOpencv::match(const SRef<SolA
6868
const SolAR::datastructure::CameraParameters & camParams1,
6969
const SolAR::datastructure::CameraParameters & camParams2,
7070
std::vector<SolAR::datastructure::DescriptorMatch> & matches,
71-
const std::vector<uint32_t>& mask)
71+
const std::vector<uint32_t>& mask1,
72+
const std::vector<uint32_t>& mask2)
7273
{
7374
matches.clear();
7475
// check conditions
@@ -120,17 +121,24 @@ FrameworkReturnCode SolARDescriptorMatcherGeometricOpencv::match(const SRef<SolA
120121

121122
// get input points in the first frame
122123
std::vector<cv::Point2f> pts1;
123-
std::vector<uint32_t> indices1;
124-
if (mask.size() == 0) {
124+
std::vector<uint32_t> indices1, indices2;
125+
if (mask1.size() == 0) {
125126
for (int i = 0; i < undistortedKeypoints1.size(); ++i) {
126127
pts1.push_back(cv::Point2f(undistortedKeypoints1[i].getX(), undistortedKeypoints1[i].getY()));
127128
indices1.push_back(i);
128129
}
129130
}
130131
else {
131-
indices1 = mask;
132-
for (int i = 0; i < mask.size(); ++i)
133-
pts1.push_back(cv::Point2f(undistortedKeypoints1[mask[i]].getX(), undistortedKeypoints1[mask[i]].getY()));
132+
indices1 = mask1;
133+
for (int i = 0; i < mask1.size(); ++i)
134+
pts1.push_back(cv::Point2f(undistortedKeypoints1[mask1[i]].getX(), undistortedKeypoints1[mask1[i]].getY()));
135+
}
136+
if (mask2.size() == 0) {
137+
for (int i = 0; i < undistortedKeypoints2.size(); ++i)
138+
indices2.push_back(i);
139+
}
140+
else {
141+
indices2 = mask2;
134142
}
135143

136144
// compute epipolar lines
@@ -139,10 +147,30 @@ FrameworkReturnCode SolARDescriptorMatcherGeometricOpencv::match(const SRef<SolA
139147

140148
// convert frame descriptor to opencv's descriptor
141149
uint32_t type_conversion = SolAR::MODULES::OPENCV::SolAROpenCVHelper::deduceOpenDescriptorCVType(descriptors1->getDescriptorDataType());
150+
#ifdef OPTIM_ON
151+
cv::Mat cvDescriptor1(indices1.size(), descriptors1->getNbElements(), type_conversion);
152+
uchar* buf_in = (uchar*)descriptors1->data();
153+
uchar* buf_out = cvDescriptor1.data;
154+
uint32_t num_elements = static_cast<uint32_t>(descriptors1->getNbElements());
155+
for (auto i = 0; i < indices1.size(); i++) {
156+
std::memcpy(buf_out, buf_in + num_elements * indices1[i], num_elements);
157+
buf_out += num_elements;
158+
}
159+
cv::Mat cvDescriptor2(indices2.size(), descriptors2->getNbElements(), type_conversion);
160+
buf_in = (uchar*)descriptors2->data();
161+
buf_out = cvDescriptor2.data;
162+
num_elements = static_cast<uint32_t>(descriptors2->getNbElements());
163+
for (auto i = 0; i < indices2.size(); i++) {
164+
std::memcpy(buf_out, buf_in + num_elements * indices2[i], num_elements);
165+
buf_out += num_elements;
166+
}
167+
#else
142168
cv::Mat cvDescriptor1(descriptors1->getNbDescriptors(), descriptors1->getNbElements(), type_conversion);
143169
cvDescriptor1.data = (uchar*)descriptors1->data();
144170
cv::Mat cvDescriptor2(descriptors2->getNbDescriptors(), descriptors2->getNbElements(), type_conversion);
145171
cvDescriptor2.data = (uchar*)descriptors2->data();
172+
#endif
173+
146174

147175
#ifdef OPTIM_ON
148176
// perform descriptor matching first on GPU using Cuda if SolARModuleOpenCVCuda
@@ -161,10 +189,10 @@ FrameworkReturnCode SolARDescriptorMatcherGeometricOpencv::match(const SRef<SolA
161189
#endif
162190

163191
// filter the matches by three conditions (best distance, 2nd best distance and epipolar constraint)
164-
std::vector<bool> checkMatches(undistortedKeypoints2.size(), true);
192+
std::vector<bool> checkMatches(indices2.size(), true);
165193
float acceptedDist = m_paddingRatio * camParams2.resolution.width;
166194
for (auto i = 0; i < indices1.size(); i++) {
167-
const auto& best_matches = nn_matches[indices1[i]];
195+
const auto& best_matches = nn_matches[i];
168196
if (!checkMatches[best_matches[0].trainIdx])
169197
continue;
170198
if (best_matches[0].distance >= m_matchingDistanceMax)
@@ -173,16 +201,16 @@ FrameworkReturnCode SolARDescriptorMatcherGeometricOpencv::match(const SRef<SolA
173201
continue;
174202
// the match is accepted
175203
// now we should check the epipolar constraint
176-
int idx1 = best_matches[0].queryIdx;
177-
int idx2 = best_matches[0].trainIdx;
204+
int idx1 = indices1[best_matches[0].queryIdx];
205+
int idx2 = indices2[best_matches[0].trainIdx];
178206
float distance = best_matches[0].distance;
179207
cv::Point3f l = lines2[i]; // line equation a*x + b*y +c = 0
180208
float x = undistortedKeypoints2[idx2].getX();
181209
float y = undistortedKeypoints2[idx2].getY();
182210
float disPointLine = std::abs(x * l.x + y * l.y + l.z) / std::sqrt(l.x * l.x + l.y * l.y);
183211
if (disPointLine < acceptedDist) {
184212
matches.push_back(DescriptorMatch(idx1, idx2, distance));
185-
checkMatches[idx2] = false;
213+
checkMatches[best_matches[0].trainIdx] = false;
186214
}
187215
}
188216
#else

src/SolARSVDTriangulationOpencv.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#include "SolAROpenCVHelper.h"
2121
#include "core/Log.h"
2222
#include "opencv2/calib3d/calib3d.hpp"
23-
23+
#define OPTIM_ON
2424
namespace xpcf = org::bcom::xpcf;
2525

2626
#define EPSILON 0.0001
@@ -274,8 +274,30 @@ double SolARSVDTriangulationOpencv::triangulate(SRef<SolAR::datastructure::Frame
274274
pcloud.clear();
275275
Transform3Df poseView1 = frame1->getPose();
276276
Transform3Df poseView2 = frame2->getPose();
277+
#ifdef OPTIM_ON
278+
// compute inverse of pose using pose's property (rigid transformation)
279+
Transform3Df poseView1Inverse, poseView2Inverse;
280+
for (int i = 0; i < 3; i++) {
281+
for (int j = 0; j < 3; j++) {
282+
poseView1Inverse(i, j) = poseView1(j, i);
283+
poseView2Inverse(i, j) = poseView2(j, i);
284+
}
285+
}
286+
for (int i = 0; i < 3; i++) {
287+
poseView1Inverse(3, i) = 0.f;
288+
poseView2Inverse(3, i) = 0.f;
289+
}
290+
poseView1Inverse(3, 3) = 1.f;
291+
poseView2Inverse(3, 3) = 1.f;
292+
for (int i = 0; i < 3; i++) {
293+
poseView1Inverse(i, 3) = -(poseView1(0, 3)*poseView1(0, i) + poseView1(1, 3)*poseView1(1, i) + poseView1(2, 3)*poseView1(2, i));
294+
poseView2Inverse(i, 3) = -(poseView2(0, 3)*poseView2(0, i) + poseView2(1, 3)*poseView2(1, i) + poseView2(2, 3)*poseView2(2, i));
295+
}
296+
#else
277297
Transform3Df poseView1Inverse = poseView1.inverse();
278298
Transform3Df poseView2Inverse = poseView2.inverse();
299+
#endif
300+
279301
cv::Mat Pose1 = (cv::Mat_<float>(3, 4) << poseView1Inverse(0, 0), poseView1Inverse(0, 1), poseView1Inverse(0, 2), poseView1Inverse(0, 3),
280302
poseView1Inverse(1, 0), poseView1Inverse(1, 1), poseView1Inverse(1, 2), poseView1Inverse(1, 3),
281303
poseView1Inverse(2, 0), poseView1Inverse(2, 1), poseView1Inverse(2, 2), poseView1Inverse(2, 3));

0 commit comments

Comments
 (0)