-
Notifications
You must be signed in to change notification settings - Fork 15
/
camera_calibration.py
95 lines (74 loc) · 3.43 KB
/
camera_calibration.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Mar 7 01:36:40 2017
@author: pierluigiferrari
"""
import numpy as np
import cv2
import glob
import pickle
def get_calibration_points(images, nx, ny):
'''
Generate two lists of calibration points from a set of calibration images
of chess boards to needed for `cv2.calibrateCamera()`.
It is recommended that `images` contain at least 20 images. All images
are expected to be of identical size and to contain the same, complete
chess board pattern.
Args:
images (array-like): A list of file names of the images to be
used for calibration.
nx (int): The number of horizontal inner corners (i.e. corners where two
white and two black tiles meet) of the chess board.
ny (int): The number of vertical inner corners (i.e. corners where two
white and two black tiles meet) of the chess board.
Returns:
object_points (list): The list of 3-D object points for calibration.
image_points (list): The list of 2-D image points for calibration.
'''
image_size = []
# Arrays to store object points and image points
# of all calibration images for `cv2.calibrateCamera()`.
object_points = [] # 3-D points in real world space
image_points = [] # 2-D points in image plane.
# All calibration images are expected to contain the same calibration pattern,
# so the object points are the same for all images.
# Format: (0,0,0), (1,0,0), (2,0,0), ...., (8,5,0)
# The third coordinate is always zero as the points lie in a plane.
objp = np.zeros((nx*ny,3), np.float32)
objp[:,:2] = np.mgrid[0:nx, 0:ny].T.reshape(-1,2)
# Step through the list and search for chess board corners
for i, fname in enumerate(images):
img = cv2.imread(fname)
size = (img.shape[1], img.shape[0])
if i == 0:
image_size = size
if size != image_size:
raise ValueError("Expected all images to have identical size, but found varying sizes.")
image_size = size
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Find the chess board corners
ret, corners = cv2.findChessboardCorners(gray, (nx, ny), None)
# If found, add object points, image points
if ret == True:
object_points.append(objp)
image_points.append(corners)
return object_points, image_points, image_size
def calibrate_camera(filepaths, nx, ny):
# Compute camera matrix and distortion coefficients
# Get the calibration points
object_points, image_points, image_size = get_calibration_points(images, nx, ny)
# Compute camera calibration given object points and image points
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(object_points, image_points, image_size, None, None)
# Save the camera calibration result to disk (we won't worry about rvecs / tvecs)
cam_calib = {"cam_matrix": mtx,
"dist_coeffs": dist}
with open("cam_calib.p", "wb") as f:
pickle.dump(cam_calib, f)
return mtx, dist
# Run the calibration process
# Specify the filepaths to the calibration images
# The images are expected to contain only chessboard patterns and bright background
images = glob.glob('camera_calib/calibration*.jpg')
# Run the calibration
calibrate_camera(images, 9, 6) # Our images contain 9x6 chessboard patterns