Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Convert Pose from ARToolkit into OpenCV Screen Coordinates

I have modified the ARToolkit nftSimple Application to work with OpenCV Mat and without OpenGL dependencies. I have got the tracking to work successfully and i am able to extract the pose matrix ARPose.

Output

The ARPose is of the format (16 x 1) :

_Documentation : // Position and orientation, column-major order. (position(x,y,z) = {T[12], T[13], T[14]}_

T = 0.833453 0.148213 0.532342 0.000000 -0.055585 0.980959 -0.186091 0.000000
-0.549787 0.125508 0.825822 0.000000 60.233962 -307.641967 -964.580499 1.000000

Problem

I am trying to use this to draw a pink circle on OpenCV side using the x,y,z values returned from the pose. According to the documentation in the code
T[12] = 60.233962 , T[13] = -307.641967 , T[14] = -964.580499

Screenshot from the Application

The coordinates obtained from the pose matrix are not giving the correct value. How do we transform the pose matrix from ARToolkit into OpenCV Screen coordinates?

Edit :- I have already read how to convert the OpenGL matrix into Transformation , rotation and scaling matrix but the output is not working as expected

Convert Pose from ARToolkit into OpenCV Screen Coordinates

I have modified the ARToolkit nftSimple Application to work with OpenCV Mat and without OpenGL dependencies. I have got the tracking to work successfully and i am able to extract the pose matrix ARPose.

Code for project :- https://github.com/njanirudh/OpenCV-ARTK

Output

The ARPose is of the format (16 x 1) :

_Documentation : // Position and orientation, column-major order. (position(x,y,z) = {T[12], T[13], T[14]}_

T = 0.833453 0.148213 0.532342 0.000000 -0.055585 0.980959 -0.186091 0.000000
-0.549787 0.125508 0.825822 0.000000 60.233962 -307.641967 -964.580499 1.000000

Problem

I am trying to use this to draw a pink circle on OpenCV side using the x,y,z values returned from the pose. According to the documentation in the code
T[12] = 60.233962 , T[13] = -307.641967 , T[14] = -964.580499

Screenshot from the Application

The coordinates obtained from the pose matrix are not giving the correct value. How do we transform the pose matrix from ARToolkit into OpenCV Screen coordinates?

Edit :- I have already read how to convert the OpenGL matrix into Transformation , rotation and scaling matrix but the output is not working as expected

Convert Pose from ARToolkit into OpenCV Screen Coordinates

I have modified the ARToolkit nftSimple Application to work with OpenCV Mat and without OpenGL dependencies. I have got the tracking to work successfully and i am able to extract the pose matrix ARPose.

Code for project :- https://github.com/njanirudh/OpenCV-ARTK

Output

The ARPose is of the format (16 x 1) :

_Documentation : // Position and orientation, column-major order. (position(x,y,z) = {T[12], T[13], T[14]}_

T = 0.833453 0.148213 0.532342 0.000000 -0.055585 0.980959 -0.186091 0.000000
-0.549787 0.125508 0.825822 0.000000 60.233962 -307.641967 -964.580499 1.000000

Problem

I am trying to use this to draw a pink circle on OpenCV side using the x,y,z values returned from the pose. According to the documentation in the code
T[12] = 60.233962 , T[13] = -307.641967 , T[14] = -964.580499

Screenshot from the Application

The coordinates obtained from the pose matrix are not giving the correct value. How do we transform the pose matrix from ARToolkit into OpenCV Screen coordinates?

static void runDetection(Mat &input_mat)

Edit :- I { ARUint8 *gARTImage = NULL; gARTImage = (uchar *)input_mat.data; float trackingTrans[3][4] = {0,0,0,0,0,0,0,0,0,0,0,0}; cv::Mat rot_vec = Mat::zeros(1,3,CV_64F), trn_vec = Mat::zeros(1,3,CV_64F) , rot_mat = Mat::zeros(3,3,CV_64F);

if(true){
    // NFT results.
    static int detectedPage = -2; // -2 Tracking not inited, -1 tracking inited OK, >= 0 tracking online on page.

    int i, j, k;

    // Grab a video frame.
    if (gARTImage != NULL) {

        gCallCountMarkerDetect++; // Increment ARToolKit FPS counter.

        // Run marker detection on frame
        if (threadHandle) {
            // Perform NFT tracking.
            float            err;
            int              ret;
            int              pageNo;

            if( detectedPage == -2 ) {
                trackingInitStart( threadHandle, gARTImage );
                detectedPage = -1;
            }
            if( detectedPage == -1 ) {
                ret = trackingInitGetResult( threadHandle, trackingTrans, &pageNo);
                if( ret == 1 ) {
                    if (pageNo >= 0 && pageNo < surfaceSetCount) {
                        ARLOGd("Detected page %d.\n", pageNo);
                        detectedPage = pageNo;
                        ar2SetInitTrans(surfaceSet[detectedPage], trackingTrans);
                    } else {
                        ARLOGe("Detected bad page %d.\n", pageNo);
                        detectedPage = -2;
                    }
                } else if( ret < 0 ) {
                    ARLOGd("No page detected.\n");
                    detectedPage = -2;
                }
            }
            if( detectedPage >= 0 && detectedPage < surfaceSetCount) {
                if( ar2Tracking(ar2Handle, surfaceSet[detectedPage], gARTImage, trackingTrans, &err) < 0 ) {
                    ARLOGd("Tracking lost.\n");
                    detectedPage = -2;
                } else {
                    ARLOGd("Tracked page %d (max %d).\n", detectedPage, surfaceSetCount - 1);
                }
            }
        } else {
            ARLOGe("Error: threadHandle\n");
            detectedPage = -2;
        }

        // Update markers.
        for (i = 0; i < markersNFTCount; i++) {
            markersNFT[i].validPrev = markersNFT[i].valid;
            if (markersNFT[i].pageNo >= 0 && markersNFT[i].pageNo == detectedPage) {
                markersNFT[i].valid = TRUE;
                for (j = 0; j < 3; j++)
                    for (k = 0; k < 4; k++){
                        markersNFT[i].trans[j][k] = trackingTrans[j][k];
                    }

            }
            else markersNFT[i].valid = FALSE;


            if (markersNFT[i].valid) {

                // Filter the pose estimate.
                if (markersNFT[i].ftmi) {
                    if (arFilterTransMat(markersNFT[i].ftmi, markersNFT[i].trans, !markersNFT[i].validPrev) < 0) {
                        ARLOGe("arFilterTransMat error with marker %d.\n", i);
                    }
                }

                if (!markersNFT[i].validPrev) {
                    // Marker has become visible, tell any dependent objects.
                    // --->
                }

                // We have already read how a new pose, so set that.
                arglCameraViewRH((const ARdouble (*)[4])markersNFT[i].trans, markersNFT[i].pose.T, VIEW_SCALEFACTOR);
                //Print(markersNFT[i].pose.T);

                //************Rotation Matrix************
                rot_mat.at<float>(0,0) = trackingTrans[0][0];
                rot_mat.at<float>(0,1) = trackingTrans[0][1];
                rot_mat.at<float>(0,2) = trackingTrans[0][2];
                rot_mat.at<float>(1,0) = trackingTrans[1][0];
                rot_mat.at<float>(1,1)= trackingTrans[1][1];
                rot_mat.at<float>(1,2) = trackingTrans[1][2];
                rot_mat.at<float>(2,0) = trackingTrans[2][0];
                rot_mat.at<float>(2,1) = trackingTrans[2][1];
                rot_mat.at<float>(2,2) = trackingTrans[2][2];

                Rodrigues(rot_mat, rot_vec);

                //************Translation Matrix***********
                trn_vec.at<float>(0,0) = markersNFT[i].pose.T[12];
                trn_vec.at<float>(0,1) = markersNFT[i].pose.T[13];
                trn_vec.at<float>(0,2) = markersNFT[i].pose.T[14];

                //************Camera Matrix*****************
                cv::Mat intrisicMat(3, 3, cv::DataType<double>::type); // Intrisic matrix
                intrisicMat.at<double>(0, 0) = 674.171631;
                intrisicMat.at<double>(1, 0) = 0;
                intrisicMat.at<double>(2, 0) = 0;

                intrisicMat.at<double>(0, 1) = 0;
                intrisicMat.at<double>(1, 1) = 633.898087;
                intrisicMat.at<double>(2, 1) = 0;

                intrisicMat.at<double>(0, 2) = 318.297791;
                intrisicMat.at<double>(1, 2) = 237.900467;
                intrisicMat.at<double>(2, 2) = 1;

                //************Dist Matrix**********************
                cv::Mat distCoeffs(5, 1, cv::DataType<double>::type);   // Distortion vector
                distCoeffs.at<double>(0) = 0;
                distCoeffs.at<double>(1) = 0;
                distCoeffs.at<double>(2) = 0;
                distCoeffs.at<double>(3) = 0;
                distCoeffs.at<double>(4) = 0;


                std::vector<cv::Point3d> inputPnt ;
                std::vector<cv::Point2d> outPnt;
                cv::Point3d pnt = Point3d(markersNFT[i].pose.T[12],markersNFT[i].pose.T[13],markersNFT[i].pose.T[14]);
                inputPnt.push_back(pnt);

                cv::projectPoints(inputPnt,rot_vec,trn_vec,intrisicMat,distCoeffs,outPnt);

                // Convert from ARToolkit Image type to convert OpenCV Mat
                IplImage* iplImg;
                iplImg = cvCreateImage(cvSize(640, 480), IPL_DEPTH_8U,3);

                // Get video frame from ARToolkit
                iplImg->imageData = (char *)gARTImage;
                input_mat = cv::cvarrToMat(iplImg);

                cout<<outPnt<<"**********"<<endl;
                //****Draw a Circle using the OpenGL matrix into Transformation , rotation and scaling matrix but the output is not working as expectedpose data****
                cv::circle(input_mat,Point(outPnt[0].y,0),30,Scalar(255,255,255) ,4);

            } else {

                if (markersNFT[i].validPrev) {
                    // Marker has ceased to be visible, tell any dependent objects.
                    // --->
                }
            }
        }
    }
}

}