ArUco marker translation deviation for some video frames
We are using ArUco markers for pose estimation and are encountering an issue.
The detected pose translation will sometimes be significantly off without any visible disturbance in the source image.
This is a follow-up to an issue that occurs when corner refinement is turned off. http://answers.opencv.org/question/14... The issue seems to be is less frequent than the one without corner refinement, but it still very desirable to work with the cleanest possible data before any filtering.
Is it possible to fix this issue with ArUco parameters or otherwise?
Below is a test program that takes a file name as argument and two example images to demonstrate the issue. The two images are two consecutive frames of a video and have very little differences.
The program output is:
$ ./arucobug frame104.png
R: [1.59948, -2.23327, 0.380623] T: [22.319, -4.29597, 94.5112]
$ ./arucobug frame103.png
R: [1.5954, -2.22185, 0.386173] T: [24.8896, -4.84338, 105.443]
So the marker is detected about 10cm (intrinsics are in cm) further away than it should be.
#include "opencv2/opencv.hpp"
#include "opencv2/aruco.hpp"
int main(int argc, char *argv[])
{
if (argc != 2)
return 1;
cv::Mat frame = cv::imread(argv[1]);
cv::Mat debugFrame = frame.clone();
// Intrinsic camera parameters.
cv::Mat camMatrix = cv::Mat::eye(3, 3, CV_64F);
cv::Mat distortionCoeffs = cv::Mat::zeros(8, 1, CV_64F);
camMatrix.at<double>(0, 0) = 2.3396381685789738e+03;
camMatrix.at<double>(0, 2) = 960.;
camMatrix.at<double>(1, 1) = 2.3396381685789738e+03;
camMatrix.at<double>(1, 2) = 540.;
distortionCoeffs.at<double>(0, 0) = -1.0982746232841779e-01;
distortionCoeffs.at<double>(1, 0) = 2.2689585715220828e-01;
distortionCoeffs.at<double>(2, 0) = 0.;
distortionCoeffs.at<double>(3, 0) = 0.;
distortionCoeffs.at<double>(4, 0) = -2.2112148171171589e-01;
cv::Ptr<cv::aruco::Dictionary> dict = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_4X4_50);
cv::Ptr<cv::aruco::DetectorParameters> params = cv::aruco::DetectorParameters::create();
std::vector<int> markerIds;
std::vector<std::vector<cv::Point2f>> markerCorners;
std::vector<cv::Vec3d> rotationVec, translationVec;
params->cornerRefinementMethod = cv::aruco::CORNER_REFINE_CONTOUR;
cv::aruco::detectMarkers(frame, dict, markerCorners, markerIds, params);
auto numMarkers = markerIds.size();
if (numMarkers > 0)
{
cv::aruco::drawDetectedMarkers(debugFrame, markerCorners, markerIds);
cv::aruco::estimatePoseSingleMarkers(markerCorners, 5.0, camMatrix, distortionCoeffs, rotationVec, translationVec);
for (int i = 0; i < numMarkers; i++)
{
// Official aruco axis drawing.
cv::aruco::drawAxis(debugFrame, camMatrix, distortionCoeffs, rotationVec[i], translationVec[i], 0.5 * 5.0);
std::cout << "R: " << rotationVec[i] << " T: " << translationVec[i] << std::endl;
// Project marker origin.
std::vector< cv::Point3f > axisPoints;
axisPoints.push_back(cv::Point3f(0, 0, 0));
std::vector< cv::Point2f > imagePoints;
cv::projectPoints(axisPoints, rotationVec[i], translationVec[i], camMatrix, distortionCoeffs, imagePoints);
// Convert rotation vector to rotation matrix.
cv::Mat rotMat;
cv::Rodrigues(rotationVec[i], rotMat);
// Check for proper rotation matrix.
assert(cv::determinant(rotMat) > 0.99 && cv::determinant(rotMat) < 1.01);
// Manually rotate the z-axis vector.
cv::Mat testVec(cv::Point3f(0, 0, 10.0f));
testVec.convertTo(testVec, CV_64FC1);
cv::Mat testTransformed = rotMat * testVec;
// Project the rotated z-axis vector.
std::vector<cv::Point3f> pts;
pts.push_back ...
We haven't got same results :
Difference could be :
Thanks. I didn't know imgur transcodes images. The builtin upload didn't work because the file size was too large. Since I didn't keep the files on disk, I'll have to redo the sample.
@LBerger Here is the same scenario https://picload.org/image/rcwrrgww/fr...https://picload.org/image/rcwrrrgr/fr...
Values: