Skip to content

Commit 6fdb6e2

Browse files
committed
Merge remote-tracking branch 'upstream/3.4' into merge-3.4
2 parents b2904b9 + 0eda296 commit 6fdb6e2

File tree

6 files changed

+112
-18
lines changed

6 files changed

+112
-18
lines changed

modules/aruco/include/opencv2/aruco.hpp

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ the use of this software, even if advised of the possibility of such damage.
4040
#define __OPENCV_ARUCO_HPP__
4141

4242
#include <opencv2/core.hpp>
43+
#include <opencv2/calib3d.hpp>
4344
#include <vector>
4445
#include "opencv2/aruco/dictionary.hpp"
4546

@@ -243,7 +244,55 @@ struct CV_EXPORTS_W DetectorParameters {
243244
CV_EXPORTS_W void detectMarkers(InputArray image, const Ptr<Dictionary> &dictionary, OutputArrayOfArrays corners,
244245
OutputArray ids, const Ptr<DetectorParameters> &parameters = DetectorParameters::create(),
245246
OutputArrayOfArrays rejectedImgPoints = noArray());
247+
/** @brief
248+
* rvec/tvec define the right handed coordinate system of the marker.
249+
* PatternPos defines center this system and axes direction.
250+
* Axis X (red color) - first coordinate, axis Y (green color) - second coordinate,
251+
* axis Z (blue color) - third coordinate.
252+
* @sa estimatePoseSingleMarkers(), @ref tutorial_aruco_detection
253+
*/
254+
enum PatternPos {
255+
/** @brief The marker coordinate system is centered on the middle of the marker.
256+
* The coordinates of the four corners (CCW order) of the marker in its own coordinate system are:
257+
* (-markerLength/2, markerLength/2, 0), (markerLength/2, markerLength/2, 0),
258+
* (markerLength/2, -markerLength/2, 0), (-markerLength/2, -markerLength/2, 0).
259+
*
260+
* These pattern points define this coordinate system:
261+
* ![Image with axes drawn](images/singlemarkersaxes.jpg)
262+
*/
263+
CCW_center,
264+
/** @brief The marker coordinate system is centered on the top-left corner of the marker.
265+
* The coordinates of the four corners (CW order) of the marker in its own coordinate system are:
266+
* (0, 0, 0), (markerLength, 0, 0),
267+
* (markerLength, markerLength, 0), (0, markerLength, 0).
268+
*
269+
* These pattern points define this coordinate system:
270+
* ![Image with axes drawn](images/singlemarkersaxes2.jpg)
271+
*/
272+
CW_top_left_corner
273+
};
274+
275+
/** @brief
276+
* Pose estimation parameters
277+
* @param pattern Defines center this system and axes direction (default PatternPos::CCW_center).
278+
* @param useExtrinsicGuess Parameter used for SOLVEPNP_ITERATIVE. If true (1), the function uses the provided
279+
* rvec and tvec values as initial approximations of the rotation and translation vectors, respectively, and further
280+
* optimizes them (default false).
281+
* @param solvePnPMethod Method for solving a PnP problem: see @ref calib3d_solvePnP_flags (default SOLVEPNP_ITERATIVE).
282+
* @sa PatternPos, solvePnP(), @ref tutorial_aruco_detection
283+
*/
284+
struct CV_EXPORTS_W EstimateParameters {
285+
CV_PROP_RW PatternPos pattern;
286+
CV_PROP_RW bool useExtrinsicGuess;
287+
CV_PROP_RW SolvePnPMethod solvePnPMethod;
288+
289+
EstimateParameters(): pattern(CCW_center), useExtrinsicGuess(false),
290+
solvePnPMethod(SOLVEPNP_ITERATIVE) {}
246291

292+
CV_WRAP static Ptr<EstimateParameters> create() {
293+
return makePtr<EstimateParameters>();
294+
}
295+
};
247296

248297

249298
/**
@@ -264,21 +313,28 @@ CV_EXPORTS_W void detectMarkers(InputArray image, const Ptr<Dictionary> &diction
264313
* @param tvecs array of output translation vectors (e.g. std::vector<cv::Vec3d>).
265314
* Each element in tvecs corresponds to the specific marker in imgPoints.
266315
* @param _objPoints array of object points of all the marker corners
316+
* @param estimateParameters set the origin of coordinate system and the coordinates of the four corners of the marker
317+
* (default estimateParameters.pattern = PatternPos::CCW_center, estimateParameters.useExtrinsicGuess = false,
318+
* estimateParameters.solvePnPMethod = SOLVEPNP_ITERATIVE).
267319
*
268320
* This function receives the detected markers and returns their pose estimation respect to
269321
* the camera individually. So for each marker, one rotation and translation vector is returned.
270322
* The returned transformation is the one that transforms points from each marker coordinate system
271323
* to the camera coordinate system.
272-
* The marker corrdinate system is centered on the middle of the marker, with the Z axis
273-
* perpendicular to the marker plane.
274-
* The coordinates of the four corners of the marker in its own coordinate system are:
275-
* (0, 0, 0), (markerLength, 0, 0),
276-
* (markerLength, markerLength, 0), (0, markerLength, 0)
324+
* The marker coordinate system is centered on the middle (by default) or on the top-left corner of the marker,
325+
* with the Z axis perpendicular to the marker plane.
326+
* estimateParameters defines the coordinates of the four corners of the marker in its own coordinate system (by default) are:
327+
* (-markerLength/2, markerLength/2, 0), (markerLength/2, markerLength/2, 0),
328+
* (markerLength/2, -markerLength/2, 0), (-markerLength/2, -markerLength/2, 0)
277329
* @sa use cv::drawFrameAxes to get world coordinate system axis for object points
330+
* @sa @ref tutorial_aruco_detection
331+
* @sa EstimateParameters
332+
* @sa PatternPos
278333
*/
279334
CV_EXPORTS_W void estimatePoseSingleMarkers(InputArrayOfArrays corners, float markerLength,
280335
InputArray cameraMatrix, InputArray distCoeffs,
281-
OutputArray rvecs, OutputArray tvecs, OutputArray _objPoints = noArray());
336+
OutputArray rvecs, OutputArray tvecs, OutputArray _objPoints = noArray(),
337+
Ptr<EstimateParameters> estimateParameters = EstimateParameters::create());
282338

283339

284340

modules/aruco/src/aruco.cpp

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -784,19 +784,31 @@ static void _identifyCandidates(InputArray grey,
784784

785785

786786
/**
787-
* @brief Return object points for the system centered in a single marker, given the marker length
787+
* @brief Return object points for the system centered in a middle (by default) or in a top left corner of single
788+
* marker, given the marker length
788789
*/
789-
static void _getSingleMarkerObjectPoints(float markerLength, OutputArray _objPoints) {
790+
static void _getSingleMarkerObjectPoints(float markerLength, OutputArray _objPoints,
791+
EstimateParameters estimateParameters) {
790792

791793
CV_Assert(markerLength > 0);
792794

793795
_objPoints.create(4, 1, CV_32FC3);
794796
Mat objPoints = _objPoints.getMat();
795797
// set coordinate system in the top-left corner of the marker, with Z pointing out
796-
objPoints.ptr< Vec3f >(0)[0] = Vec3f(0.f, 0.f, 0);
797-
objPoints.ptr< Vec3f >(0)[1] = Vec3f(markerLength, 0.f, 0);
798-
objPoints.ptr< Vec3f >(0)[2] = Vec3f(markerLength, markerLength, 0);
799-
objPoints.ptr< Vec3f >(0)[3] = Vec3f(0.f, markerLength, 0);
798+
if (estimateParameters.pattern == CW_top_left_corner) {
799+
objPoints.ptr<Vec3f>(0)[0] = Vec3f(0.f, 0.f, 0);
800+
objPoints.ptr<Vec3f>(0)[1] = Vec3f(markerLength, 0.f, 0);
801+
objPoints.ptr<Vec3f>(0)[2] = Vec3f(markerLength, markerLength, 0);
802+
objPoints.ptr<Vec3f>(0)[3] = Vec3f(0.f, markerLength, 0);
803+
}
804+
else if (estimateParameters.pattern == CCW_center) {
805+
objPoints.ptr<Vec3f>(0)[0] = Vec3f(-markerLength/2.f, markerLength/2.f, 0);
806+
objPoints.ptr<Vec3f>(0)[1] = Vec3f(markerLength/2.f, markerLength/2.f, 0);
807+
objPoints.ptr<Vec3f>(0)[2] = Vec3f(markerLength/2.f, -markerLength/2.f, 0);
808+
objPoints.ptr<Vec3f>(0)[3] = Vec3f(-markerLength/2.f, -markerLength/2.f, 0);
809+
}
810+
else
811+
CV_Error(Error::StsBadArg, "Unknown estimateParameters pattern");
800812
}
801813

802814
/**
@@ -1208,12 +1220,13 @@ void detectMarkers(InputArray _image, const Ptr<Dictionary> &_dictionary, Output
12081220
*/
12091221
void estimatePoseSingleMarkers(InputArrayOfArrays _corners, float markerLength,
12101222
InputArray _cameraMatrix, InputArray _distCoeffs,
1211-
OutputArray _rvecs, OutputArray _tvecs, OutputArray _objPoints) {
1223+
OutputArray _rvecs, OutputArray _tvecs, OutputArray _objPoints,
1224+
Ptr<EstimateParameters> estimateParameters) {
12121225

12131226
CV_Assert(markerLength > 0);
12141227

12151228
Mat markerObjPoints;
1216-
_getSingleMarkerObjectPoints(markerLength, markerObjPoints);
1229+
_getSingleMarkerObjectPoints(markerLength, markerObjPoints, *estimateParameters);
12171230
int nMarkers = (int)_corners.total();
12181231
_rvecs.create(nMarkers, 1, CV_64FC3);
12191232
_tvecs.create(nMarkers, 1, CV_64FC3);

modules/aruco/test/test_charucodetection.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -439,10 +439,12 @@ void CV_CharucoDiamondDetection::run(int) {
439439
}
440440
}
441441

442+
Ptr<aruco::EstimateParameters> estimateParameters = aruco::EstimateParameters::create();
443+
estimateParameters->pattern = aruco::CW_top_left_corner;
442444
// estimate diamond pose
443445
vector< Vec3d > estimatedRvec, estimatedTvec;
444-
aruco::estimatePoseSingleMarkers(diamondCorners, squareLength, cameraMatrix,
445-
distCoeffs, estimatedRvec, estimatedTvec);
446+
aruco::estimatePoseSingleMarkers(diamondCorners, squareLength, cameraMatrix, distCoeffs, estimatedRvec,
447+
estimatedTvec, noArray(), estimateParameters);
446448

447449
// check result
448450
vector< Point2f > projectedDiamondCornersPose;
78 KB
Loading

modules/aruco/tutorials/aruco_detection/aruco_detection.markdown

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,8 +286,9 @@ translation vectors of the estimated poses will be in the same unit
286286
- The output parameters `rvecs` and `tvecs` are the rotation and translation vectors respectively, for each of the markers
287287
in `markerCorners`.
288288

289-
The marker coordinate system that is assumed by this function is placed at the center of the marker
290-
with the Z axis pointing out, as in the following image. Axis-color correspondences are X: red, Y: green, Z: blue. Note the axis directions of the rotated markers in this image.
289+
The marker coordinate system that is assumed by this function is placed in the center (by default) or
290+
in the top left corner of the marker with the Z axis pointing out, as in the following image.
291+
Axis-color correspondences are X: red, Y: green, Z: blue. Note the axis directions of the rotated markers in this image.
291292

292293
![Image with axes drawn](images/singlemarkersaxes.jpg)
293294

modules/sfm/src/libmv_light/libmv/simple_pipeline/bundle.cc

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#include "ceres/ceres.h"
2626
#include "ceres/rotation.h"
27+
#include "ceres/version.h"
2728
#include "libmv/base/vector.h"
2829
#include "libmv/logging/logging.h"
2930
#include "libmv/multiview/fundamental.h"
@@ -485,7 +486,11 @@ void EuclideanBundleCommonIntrinsics(
485486
PackCamerasRotationAndTranslation(tracks, *reconstruction);
486487

487488
// Parameterization used to restrict camera motion for modal solvers.
489+
#if CERES_VERSION_MAJOR >= 3 || (CERES_VERSION_MAJOR >= 2 && CERES_VERSION_MINOR >= 1)
490+
ceres::SubsetManifold *constant_translation_manifold = NULL;
491+
#else
488492
ceres::SubsetParameterization *constant_translation_parameterization = NULL;
493+
#endif
489494
if (bundle_constraints & BUNDLE_NO_TRANSLATION) {
490495
std::vector<int> constant_translation;
491496

@@ -494,8 +499,13 @@ void EuclideanBundleCommonIntrinsics(
494499
constant_translation.push_back(4);
495500
constant_translation.push_back(5);
496501

502+
#if CERES_VERSION_MAJOR >= 3 || (CERES_VERSION_MAJOR >= 2 && CERES_VERSION_MINOR >= 1)
503+
constant_translation_manifold =
504+
new ceres::SubsetManifold(6, constant_translation);
505+
#else
497506
constant_translation_parameterization =
498507
new ceres::SubsetParameterization(6, constant_translation);
508+
#endif
499509
}
500510

501511
// Add residual blocks to the problem.
@@ -538,8 +548,13 @@ void EuclideanBundleCommonIntrinsics(
538548
}
539549

540550
if (bundle_constraints & BUNDLE_NO_TRANSLATION) {
551+
#if CERES_VERSION_MAJOR >= 3 || (CERES_VERSION_MAJOR >= 2 && CERES_VERSION_MINOR >= 1)
552+
problem.SetParameterization(current_camera_R_t,
553+
constant_translation_manifold);
554+
#else
541555
problem.SetParameterization(current_camera_R_t,
542556
constant_translation_parameterization);
557+
#endif
543558
}
544559

545560
zero_weight_tracks_flags[marker.track] = false;
@@ -586,10 +601,17 @@ void EuclideanBundleCommonIntrinsics(
586601
// Always set K3 constant, it's not used at the moment.
587602
constant_intrinsics.push_back(OFFSET_K3);
588603

604+
#if CERES_VERSION_MAJOR >= 3 || (CERES_VERSION_MAJOR >= 2 && CERES_VERSION_MINOR >= 1)
605+
ceres::SubsetManifold *subset_manifold =
606+
new ceres::SubsetManifold(OFFSET_MAX, constant_intrinsics);
607+
608+
problem.SetManifold(ceres_intrinsics, subset_manifold);
609+
#else
589610
ceres::SubsetParameterization *subset_parameterization =
590611
new ceres::SubsetParameterization(OFFSET_MAX, constant_intrinsics);
591612

592613
problem.SetParameterization(ceres_intrinsics, subset_parameterization);
614+
#endif
593615
}
594616

595617
// Configure the solver.

0 commit comments

Comments
 (0)