Question

Libs: OpenCV Target: Android (OpenCV4Android)

I try to compute the Homography of a world plane (e.g. monitor screen) to get the camera pose, transform it and reproject the points back for tracking tasks. I'm using OpenCVs findHomography() / getPerspectiveTransform() to get the homography. The reprojection of the points using perspectiveTransform() (as explained here: http://docs.opencv.org/doc/tutorials/features2d/feature_homography/feature_homography.html) which works pretty well. The "screenPoints" are the world coordinates of the monitor edges (using the aspect ratio and a z-value of 0) and the "imagePoints" are the x/y-coordinates of the screen edges in the image.

Mat homography = org.opencv.imgproc.Imgproc.getPerspectiveTransform(screenPoints, imagePoints);

I have the camera calibration matrix (I have used the matlab calibration toolbox) and I found a hint (in the comments @ https://dsp.stackexchange.com/questions/2736/step-by-step-camera-pose-estimation-for-visual-tracking-and-planar-markers) for considering the camera parameters in the homography.

H' = K^-1 * H

(H' - Homography-Matrix considering camera calibration, H - Homography-Matrix, K^-1 - inverse camera calibration matrix).

Mat intrinsicInverse = new Mat(3, 3, CvType.CV_32FC1);
Core.invert(intrinsic, intrinsicInverse);
intrinsicInverse.convertTo(intrinsicInverse, CvType.CV_32FC1);          
homography.convertTo(homography, CvType.CV_32FC1);
// compute H respect the intrinsics
Core.gemm(intrinsicInverse, homography, 1, new Mat(), 0, homography);

My next step ist to compute the camera pose from homography as decribed here Computing camera pose with homography matrix based on 4 coplanar points.

Since im trying to do this on Android i had to port the C++ Code to Java:

private Mat cameraPoseFromHomography(Mat h) {
    Log.d("DEBUG", "cameraPoseFromHomography: homography " + matToString(h));

    Mat pose = Mat.eye(3, 4, CvType.CV_32FC1);  // 3x4 matrix, the camera pose
    float norm1 = (float) Core.norm(h.col(0));
    float norm2 = (float) Core.norm(h.col(1));
    float tnorm = (norm1 + norm2) / 2.0f;       // Normalization value

    Mat normalizedTemp = new Mat();
    Core.normalize(h.col(0), normalizedTemp);
    normalizedTemp.convertTo(normalizedTemp, CvType.CV_32FC1);
    normalizedTemp.copyTo(pose.col(0));

    Core.normalize(h.col(1), normalizedTemp);
    normalizedTemp.convertTo(normalizedTemp, CvType.CV_32FC1);    
    normalizedTemp.copyTo(pose.col(1));

    Mat p3 = pose.col(0).cross(pose.col(1));
    p3.copyTo(pose.col(2));

    Mat temp = h.col(2);
    double[] buffer = new double[3];
    h.col(2).get(0, 0, buffer);
    pose.put(0, 3, buffer[0] / tnorm);
    pose.put(1, 3, buffer[1] / tnorm);
    pose.put(2, 3, buffer[2] / tnorm);

    return pose;
}

I can't check if the code is doing the right thing but it's running. At this point I assume to have the full camera pose considering the camera calibration.

As described here http://opencv.willowgarage.com/documentation/python/calib3d_camera_calibration_and_3d_reconstruction.html#rodrigues2, the reprojection of a 3D-Point is just

p = K * CP * P

(p - 2D-Position, K - calibration matrix, CP - camera pose, P - 3D-Point)

    Core.gemm(intrinsic, cameraPosition, 1, new Mat(), 0, vec4t);
    Core.gemm(vec4t, point, 1, new Mat(), 0, result);

The result is far away from the source image positions of the screen edges. But I can identify all three edges by its relative differences - so it might be just some factor which is wrong.

It's the first time I'm doing such a Computer Vision task and it's possible I did some basically wrong. I have the "Multiple View Geometry" book from Zisserman and I read all related parts - but to be honest - I didn't get most of it.

UPDATE:

Found a bug in my camera matrix - the implementation above is just working fine!

Was it helpful?

Solution

Get it to work on another way. Instead of using findHomography()/getP erspectiveTransform() i found another function called solvePnP() which returns the camera pose based on world and images points and an intrinsic camera matrix.

Using that function in combination with the projectPoints() method - i was able to reproject the 3d points back to the image.

In case of the screen edges there are placed on the right spot in the image.

UPDATE:

I found a bug in my implementation - my camera intrinsic matrix was wrong. The camera pose from homography implementation above is working for me!

OTHER TIPS

The relationship between Homography in calibrated case (H) and uncalibrated case (H') is

H′=𝐾𝐻𝐾^(−1), where K is intrinsic matrix of camera.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top