-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathcalib-camera.py
161 lines (119 loc) · 4.83 KB
/
calib-camera.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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#!/usr/bin/env python
"""
From https://opencv-python-tutroals.readthedocs.org/en/latest/py_tutorials/py_calib3d/py_calibration/py_calibration.html#calibration
Calling:
cameracalib.py <folder> <image type> <num rows> <num cols> <cell dimension>
like cameracalib.py folder_name png
--h for help
"""
import numpy as np
import cv2
import glob
import sys
import argparse
#---------------------- SET THE PARAMETERS
nRows = 8
nCols = 8
dimension = 20 #- mm
workingFolder = "./camera_01"
imageType = 'jpg'
#------------------------------------------
# termination criteria
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, dimension, 0.001)
# prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
objp = np.zeros((nRows*nCols,3), np.float32)
objp[:,:2] = np.mgrid[0:nCols,0:nRows].T.reshape(-1,2)
# Arrays to store object points and image points from all the images.
objpoints = [] # 3d point in real world space
imgpoints = [] # 2d points in image plane.
if len(sys.argv) < 6:
print("\n Not enough inputs are provided. Using the default values.\n\n" \
" type -h for help")
else:
workingFolder = sys.argv[1]
imageType = sys.argv[2]
nRows = int(sys.argv[3])
nCols = int(sys.argv[4])
dimension = float(sys.argv[5])
if '-h' in sys.argv or '--h' in sys.argv:
print("\n IMAGE CALIBRATION GIVEN A SET OF IMAGES")
print(" call: python cameracalib.py <folder> <image type> <num rows (9)> <num cols (6)> <cell dimension (25)>")
print("\n The script will look for every image in the provided folder and will show the pattern found." \
" User can skip the image pressing ESC or accepting the image with RETURN. " \
" At the end the end the following files are created:" \
" - cameraDistortion.txt" \
" - cameraMatrix.txt \n\n")
sys.exit()
# Find the images files
filename = workingFolder + "/*." + imageType
images = glob.glob(filename)
print(len(images))
if len(images) < 9:
print("Not enough images were found: at least 9 shall be provided!!!")
sys.exit()
else:
nPatternFound = 0
imgNotGood = images[1]
for fname in images:
if 'calibresult' in fname: continue
#-- Read the file and convert in greyscale
img = cv2.imread(fname)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
print("Reading image ", fname)
# Find the chess board corners
ret, corners = cv2.findChessboardCorners(gray, (nCols,nRows),None)
# If found, add object points, image points (after refining them)
if ret == True:
print("Pattern found! Press ESC to skip or ENTER to accept")
#--- Sometimes, Harris cornes fails with crappy pictures, so
corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
# Draw and display the corners
cv2.drawChessboardCorners(img, (nCols,nRows), corners2,ret)
cv2.imshow('img',img)
# cv2.waitKey(0)
k = cv2.waitKey(0) & 0xFF
if k == 27: #-- ESC Button
print("Image Skipped")
imgNotGood = fname
continue
print("Image accepted")
nPatternFound += 1
objpoints.append(objp)
imgpoints.append(corners2)
# cv2.waitKey(0)
else:
imgNotGood = fname
cv2.destroyAllWindows()
if (nPatternFound > 1):
print("Found %d good images" % (nPatternFound))
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1],None,None)
# Undistort an image
img = cv2.imread(imgNotGood)
h, w = img.shape[:2]
print("Image to undistort: ", imgNotGood)
newcameramtx, roi=cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),1,(w,h))
# undistort
mapx,mapy = cv2.initUndistortRectifyMap(mtx,dist,None,newcameramtx,(w,h),5)
dst = cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR)
# crop the image
x,y,w,h = roi
dst = dst[y:y+h, x:x+w]
print("ROI: ", x, y, w, h)
cv2.imwrite(workingFolder + "/calibresult.png",dst)
print("Calibrated picture saved as calibresult.png")
print("Calibration Matrix: ")
print(mtx)
print("Disortion: ", dist)
#--------- Save result
filename = workingFolder + "/cameraMatrix.txt"
np.savetxt(filename, mtx, delimiter=',')
filename = workingFolder + "/cameraDistortion.txt"
np.savetxt(filename, dist, delimiter=',')
mean_error = 0
for i in xrange(len(objpoints)):
imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)
error = cv2.norm(imgpoints[i],imgpoints2, cv2.NORM_L2)/len(imgpoints2)
mean_error += error
print("total error: ", mean_error/len(objpoints))
else:
print("In order to calibrate you need at least 9 good pictures... try again")