Showing posts with label camera. Show all posts
Showing posts with label camera. Show all posts

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]