Ask Your Question
0

Aruco - draw position+orientation relative to marker

asked 2016-03-07 10:16:26 -0600

waldmeister gravatar image

Hi, I want to draw the orientation of my camera relative to a detected marker, I use the aruco module. So far I have a working code (basically the aruco example detect_markers.cpp from /opencv/opencv_contrib-master/modules/aruco/samples) that detects markers and draws a coordinate system onto them.

Now I want to draw that coordinate system i a way that it shows the orientation of the camera relative to the marker.

According to the opencv docs "the returned transformation from "estimatePoseSingleMarkers" (i.e. rvecs and tvecs) is the one that transforms points from each marker coordinate system to the camera coordinate system."

aruco::estimatePoseSingleMarkers(corners, markerLength, camMatrix, distCoeffs, rvecs,
                                             tvecs);

So if I take the function aruco::drawAxis(imageCopy, camMatrix, distCoeffs, rvecs[i], tvecs[i], markerLength * 0.8f); and pass it the inverse of the rotation matrix it should show me the orientation of my camera right? Unfortunately my code gives an error:

Here is how I do the transformation: CvMat rvecs_trans; cvTranspose(rvecs[i], &rvecs_trans);

If I pass rvecs_trans to the drawAxis function it wont compile:

invalid initialization of reference of type ‘cv::InputArray {aka const cv::_InputArray&}’ from expression of type ‘CvMat*’ aruco::drawAxis(imageCopy, camMatrix, distCoeffs, &rvecs_trans, tvecs[i], markerLength * 0.8f);

Can anyone help me? I'm very new to opencv...

edit retag flag offensive close merge delete

1 answer

Sort by » oldest newest most voted
2

answered 2016-03-07 18:11:31 -0600

Tetragramm gravatar image

You have the right idea, however rvecs is not a rotation matrix. It is a rotation vector, as described HERE.

That is the function you need to use. Convert your rotation vector to a rotation matrix with that function, transpose it, then convert it back.

However, that's not going to be enough. drawAxis uses the rvecs and tvecs to determine where to draw the axis lines. So if you simply change the rvecs, then you will be altering where it thinks the marker is in relation to the camera. You will need to make your own version of the drawAxis function that uses your original rvecs to draw, and your new rvecs to calculate what to draw.

Fortunately this is fairly simple.

The code to draw axis looks like this:

// project axis points
vector< Point3f > axisPoints;
axisPoints.push_back(Point3f(0, 0, 0));
axisPoints.push_back(Point3f(length, 0, 0));
axisPoints.push_back(Point3f(0, length, 0));
axisPoints.push_back(Point3f(0, 0, length));
vector< Point2f > imagePoints;
projectPoints(axisPoints, _rvec, _tvec, _cameraMatrix, _distCoeffs, imagePoints);

// draw axis lines
line(_image, imagePoints[0], imagePoints[1], Scalar(0, 0, 255), 3);
line(_image, imagePoints[0], imagePoints[2], Scalar(0, 255, 0), 3);
line(_image, imagePoints[0], imagePoints[3], Scalar(255, 0, 0), 3);

You need to rotate those axis points by your rotation matrix so they are aligned with the camera axis, and then draw those lines instead.

Give that a try, and let us know if you have any more questions.

edit flag offensive delete link more

Comments

Thank you, it worked, its really awesome that there are people who help!

I will post my code tomorrow because as new user I'm not allowed to answer my own question right now.

waldmeister gravatar imagewaldmeister ( 2016-03-08 09:59:55 -0600 )edit

Hi, unfortunately the link in answer doesn't follow to any function now. Could you post function name or, maybe, code that worked for you?

tischenkoalex gravatar imagetischenkoalex ( 2017-03-29 15:36:54 -0600 )edit

Right, sorry. It's the Rodrigues function.

Tetragramm gravatar imageTetragramm ( 2017-03-29 18:13:31 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2016-03-07 10:16:26 -0600

Seen: 7,994 times

Last updated: Mar 07 '16