Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/samples/python/calibrate.py
16337 views
1
#!/usr/bin/env python
2
3
'''
4
camera calibration for distorted images with chess board samples
5
reads distorted images, calculates the calibration and write undistorted images
6
7
usage:
8
calibrate.py [--debug <output path>] [--square_size] [<image mask>]
9
10
default values:
11
--debug: ./output/
12
--square_size: 1.0
13
<image mask> defaults to ../data/left*.jpg
14
'''
15
16
# Python 2/3 compatibility
17
from __future__ import print_function
18
19
import numpy as np
20
import cv2 as cv
21
22
# local modules
23
from common import splitfn
24
25
# built-in modules
26
import os
27
28
if __name__ == '__main__':
29
import sys
30
import getopt
31
from glob import glob
32
33
args, img_mask = getopt.getopt(sys.argv[1:], '', ['debug=', 'square_size=', 'threads='])
34
args = dict(args)
35
args.setdefault('--debug', './output/')
36
args.setdefault('--square_size', 1.0)
37
args.setdefault('--threads', 4)
38
if not img_mask:
39
img_mask = '../data/left??.jpg' # default
40
else:
41
img_mask = img_mask[0]
42
43
img_names = glob(img_mask)
44
debug_dir = args.get('--debug')
45
if debug_dir and not os.path.isdir(debug_dir):
46
os.mkdir(debug_dir)
47
square_size = float(args.get('--square_size'))
48
49
pattern_size = (9, 6)
50
pattern_points = np.zeros((np.prod(pattern_size), 3), np.float32)
51
pattern_points[:, :2] = np.indices(pattern_size).T.reshape(-1, 2)
52
pattern_points *= square_size
53
54
obj_points = []
55
img_points = []
56
h, w = cv.imread(img_names[0], 0).shape[:2] # TODO: use imquery call to retrieve results
57
58
def processImage(fn):
59
print('processing %s... ' % fn)
60
img = cv.imread(fn, 0)
61
if img is None:
62
print("Failed to load", fn)
63
return None
64
65
assert w == img.shape[1] and h == img.shape[0], ("size: %d x %d ... " % (img.shape[1], img.shape[0]))
66
found, corners = cv.findChessboardCorners(img, pattern_size)
67
if found:
68
term = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_COUNT, 30, 0.1)
69
cv.cornerSubPix(img, corners, (5, 5), (-1, -1), term)
70
71
if debug_dir:
72
vis = cv.cvtColor(img, cv.COLOR_GRAY2BGR)
73
cv.drawChessboardCorners(vis, pattern_size, corners, found)
74
_path, name, _ext = splitfn(fn)
75
outfile = os.path.join(debug_dir, name + '_chess.png')
76
cv.imwrite(outfile, vis)
77
78
if not found:
79
print('chessboard not found')
80
return None
81
82
print(' %s... OK' % fn)
83
return (corners.reshape(-1, 2), pattern_points)
84
85
threads_num = int(args.get('--threads'))
86
if threads_num <= 1:
87
chessboards = [processImage(fn) for fn in img_names]
88
else:
89
print("Run with %d threads..." % threads_num)
90
from multiprocessing.dummy import Pool as ThreadPool
91
pool = ThreadPool(threads_num)
92
chessboards = pool.map(processImage, img_names)
93
94
chessboards = [x for x in chessboards if x is not None]
95
for (corners, pattern_points) in chessboards:
96
img_points.append(corners)
97
obj_points.append(pattern_points)
98
99
# calculate camera distortion
100
rms, camera_matrix, dist_coefs, rvecs, tvecs = cv.calibrateCamera(obj_points, img_points, (w, h), None, None)
101
102
print("\nRMS:", rms)
103
print("camera matrix:\n", camera_matrix)
104
print("distortion coefficients: ", dist_coefs.ravel())
105
106
# undistort the image with the calibration
107
print('')
108
for fn in img_names if debug_dir else []:
109
path, name, ext = splitfn(fn)
110
img_found = os.path.join(debug_dir, name + '_chess.png')
111
outfile = os.path.join(debug_dir, name + '_undistorted.png')
112
113
img = cv.imread(img_found)
114
if img is None:
115
continue
116
117
h, w = img.shape[:2]
118
newcameramtx, roi = cv.getOptimalNewCameraMatrix(camera_matrix, dist_coefs, (w, h), 1, (w, h))
119
120
dst = cv.undistort(img, camera_matrix, dist_coefs, None, newcameramtx)
121
122
# crop and save the image
123
x, y, w, h = roi
124
dst = dst[y:y+h, x:x+w]
125
126
print('Undistorted image written to: %s' % outfile)
127
cv.imwrite(outfile, dst)
128
129
cv.destroyAllWindows()
130
131