Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Difference between Java and Python

Hello! I have a strange problem and I am not able to resolve it myself. I am trying to do a 3D camera pose estimation using findChessboardCorners() and solvePnPRansac(). It really is a simple program that basically:

1. reads image from disk with imread()
2. finds chessboard corners with findChessboardCorners()
3. compute sub-pixel corners with cornerSubPix()
4. estimate pose with solvePnPRansac()
5. project points to image using projectPoints()

I wrote two versions of the above algorithm, one using Python and one with Java binding. Each uses OpenCV version 3.0.0. However, I get totally different results from solvePnPRansac with Python and Java. I confirmed that all the other data (computed corners etc.) are exactly the same up to this point. Solving PnP gives two different rotation and translation matrices.

This is resulting image in Python: image description

and Java: image description

Of course, bottom plane should be aligned with the chessboard, but in Java it clearly isn't. Can you give me some hints what can be wrong with that? I am including source code, in case you don't have any general suggestions.

Java source

Mat image = new Mat();
        image = Imgcodecs.imread("<something>");

        CamUtils.Pair calib = CamUtils.readCalibrationData();
        Mat mtx = calib.first;
        MatOfDouble dist = calib.second;

        TermCriteria criteria = new TermCriteria(TermCriteria.EPS + TermCriteria.MAX_ITER, 30, 0.001);

        ArrayList<Point3> p = new ArrayList<Point3>();
        for(int i = 0; i < 6; i++) {
            for(int j = 0; j < 9; j++) {
                p.add(new Point3(j, i, 0));
            }
        }
        MatOfPoint3f objp = new MatOfPoint3f(p.toArray(new Point3[1]));

        ArrayList<Point3> pp = new ArrayList<Point3>();
        pp.add(new Point3(0, 0, 0));
        pp.add(new Point3(0, 3, 0));
        pp.add(new Point3(3, 3, 0));
        pp.add(new Point3(3, 0, 0));
        pp.add(new Point3(0, 0, -3));
        pp.add(new Point3(0, 3, -3));
        pp.add(new Point3(3, 3, -3));
        pp.add(new Point3(3, 0, -3));
        MatOfPoint3f axis = new MatOfPoint3f(pp.toArray(new Point3[1]));

        Mat gray = new Mat();
        Imgproc.cvtColor(image, gray, Imgproc.COLOR_BGR2GRAY);

        MatOfPoint2f corners = new MatOfPoint2f();
        boolean ret = Calib3d.findChessboardCorners(gray, new Size(9, 6), corners);

        if(ret) {
            Calib3d.drawChessboardCorners(image, new Size(9, 6), corners, true);
            Imgproc.cornerSubPix(gray, corners, new Size(11, 11), new Size(-1, -1), criteria);

            Mat rvecs = new Mat();
            Mat tvecs = new Mat();

            Calib3d.solvePnPRansac(objp, corners, mtx, dist, rvecs, tvecs);

            MatOfPoint2f imgpts = new MatOfPoint2f();
            Calib3d.projectPoints(axis, rvecs, tvecs, mtx, dist, imgpts);
            Point[] points = imgpts.toArray();

            List<MatOfPoint> bottom = new ArrayList<MatOfPoint>();
            bottom.add(new MatOfPoint(points[0], points[1], points[2], points[3]));
            Imgproc.drawContours(image, bottom, -1, new Scalar(200, 150, 10), -3);

            List<MatOfPoint> top = new ArrayList<MatOfPoint>();
            bottom.add(new MatOfPoint(points[4], points[5], points[6], points[7]));
            Imgproc.drawContours(image, bottom, -1, new Scalar(200, 150, 10), -3);
        }

Python code

image = cv2.imread('<something>')
# load calibration data
with np.load('<something>') as X:
    mtx, dist, _, _ = [X[i] for i in ('mtx','dist','rvecs','tvecs')]
print mtx
print dist

criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)

objp = np.zeros((6*9,3), np.float32)
objp[:,:2] = np.mgrid[0:9,0:6].T.reshape(-1,2)

axis = np.float32([[0,0,0], [0,3,0], [3,3,0], [3,0,0],
               [0,0,-3],[0,3,-3],[3,3,-3],[3,0,-3] ])

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
ret, corners = cv2.findChessboardCorners(gray, (9,6), None)

if ret == True:
    cv2.drawChessboardCorners(image, (9,6), corners, True)
    cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)

    rvecs, tvecs, _ = cv2.solvePnPRansac(objp, corners, mtx, dist)

    imgpts, _ = cv2.projectPoints(axis, rvecs, tvecs, mtx, dist)

    imgpts = np.int32(imgpts).reshape(-1,2)

    # draw floor
    cv2.drawContours(image, [imgpts[:4]],-1,(200,150,10),-3)

    # draw roof
    cv2.drawContours(image, [imgpts[4:]],-1,(200,150,10),-3)