Wednesday, October 30, 2013

Camera Cailbration

 I have been looking for a Java camera calibration code for a long time.  There is a C++ example of camera calibration at the official OpenCV documentation site.  Now that Java OpenCV is available, I decided that I will make a Java version.

The C++ example is quite complicated, in that it can use multiple calibration patterns, and can using a list of image as well as live video. I decided that this example only uses a folder of several chessboard photos as input.




import java.io.File;
import java.util.ArrayList;
import org.opencv.calib3d.Calib3d;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint2f;
import org.opencv.core.MatOfPoint3f;
import org.opencv.core.Point3;
import org.opencv.core.Size;
import org.opencv.core.TermCriteria;
import org.opencv.highgui.Highgui;
import org.opencv.imgproc.Imgproc;

public class CalibChessBoard {
    int flagsCorner = Calib3d.CALIB_CB_ADAPTIVE_THRESH
            | Calib3d.CALIB_CB_FAST_CHECK 
            | Calib3d.CALIB_CB_NORMALIZE_IMAGE;
    int flagsCalib = Calib3d.CALIB_ZERO_TANGENT_DIST
            | Calib3d.CALIB_FIX_PRINCIPAL_POINT 
            | Calib3d.CALIB_FIX_K4
            | Calib3d.CALIB_FIX_K5;
    TermCriteria criteria = new TermCriteria(TermCriteria.EPS
            + TermCriteria.MAX_ITER, 40, 0.001);
    Size winSize = new Size(5, 5), zoneSize = new Size(-1, -1);
    Size patternSize;
    ArrayList objectPoints, imagePoints = new ArrayList();
    ArrayList vCorners;
    ArrayList vImg;
    Mat cameraMatrix = Mat.eye(3, 3, CvType.CV_64F);
    Mat distCoeffs = Mat.zeros(8, 1, CvType.CV_64F);
    ArrayList rvecs = new ArrayList();
    ArrayList tvecs = new ArrayList();

    CalibChessBoard() {
    }

    CalibChessBoard(Size patternSize) {
        this.patternSize = patternSize;
    }

    boolean getCorners(Mat gray, MatOfPoint2f corners) {
        if (!Calib3d.findChessboardCorners(gray, patternSize,
                corners, flagsCorner))
            return false;
        Imgproc.cornerSubPix(gray, corners, winSize, zoneSize,
                                   criteria);
        return true;
    }

    MatOfPoint3f getCorner3f() {
        MatOfPoint3f corners3f = new MatOfPoint3f();
        double squareSize = 50;
        Point3[] vp = new Point3[(int) (patternSize.height * 
                                            patternSize.width)];
        int cnt = 0;
        for (int i = 0; i < patternSize.height; ++i)
            for (int j = 0; j < patternSize.width; ++j, cnt++)
                vp[cnt] = new Point3(j * squareSize, 
                                     i * squareSize, 0.0d);
        corners3f.fromArray(vp);
        return corners3f;
    }

    public static void main(String[] args) {
        test0();
    }

    static void test0() {
        CalibChessBoard cb = new CalibChessBoard(new Size(8, 6));
        cb.getAllCornors("/the/photo/folder");
        cb.calibrate();
    }

    void calibrate() {
        double errReproj = Calib3d.calibrateCamera(objectPoints, 
                imagePoints,vImg.get(0).size(), cameraMatrix, 
                distCoeffs, rvecs, tvecs,flagsCalib);
        System.out.println("done, \nerrReproj = " + errReproj);
        System.out.println("cameraMatrix = \n" + cameraMatrix.dump());
        System.out.println("distCoeffs = \n" + distCoeffs.dump());
    }

    void getAllCornors(String path) {
        vImg = new ArrayList();
        objectPoints = new ArrayList();
        imagePoints = new ArrayList();
        MatOfPoint3f corners3f = getCorner3f();
        for (File f : new File(path).listFiles()) {
            Mat mat = Highgui.imread(f.getPath(), 
                           Highgui.CV_LOAD_IMAGE_COLOR);
            if (mat == null || mat.channels() != 3)
                continue;
            System.out.println("fn = " + f.getPath());
            System.out.println("mat.channels() = " + mat.channels() 
                    + ", " + mat.cols() + ", " + mat.rows());
            Mat gray = new Mat();
            Imgproc.cvtColor(mat, gray, Imgproc.COLOR_BGR2GRAY);
            MatOfPoint2f corners = new MatOfPoint2f();
            if (!getCorners(gray, corners))
                continue;
            objectPoints.add(corners3f);
            imagePoints.add(corners);
            vImg.add(mat);
        }
    }

    static {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    }
}

Here are the list of images that give the following results:

errReproj = 0.25108
cameraMatrix =
[614.561, 0, 319.5;
  0, 615.445, 239.5;
  0, 0, 1]
distCoeffs = [0.155040; 0.075046; 0; 0; -2.318117]




3 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. Sir, can you give me the current link for the images?

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete