193 lines
6.9 KiB
Python
193 lines
6.9 KiB
Python
#!/usr/bin/env python
|
|
'''
|
|
This is a modified version of opencv's calibrate.py that stores the camera
|
|
parameters in the YAML format required by ArUco. an example of this format
|
|
is given by:
|
|
|
|
%YAML:1.0
|
|
calibration_time: "Sa 08 Aug 2015 16:32:35 CEST"
|
|
nr_of_frames: 30
|
|
image_width: 752
|
|
image_height: 480
|
|
board_width: 8
|
|
board_height: 6
|
|
square_size: 24.
|
|
fix_aspect_ratio: 1.
|
|
# flags: +fix_aspect_ratio +fix_principal_point +zero_tangent_dist
|
|
flags: 14
|
|
camera_matrix: !!opencv-matrix
|
|
rows: 3
|
|
cols: 3
|
|
dt: d
|
|
data: [ 418.164617459, 0., 372.480325679, 0., 417.850564673, 229.985538918, 0., 0., 1.]
|
|
distortion_coefficients: !!opencv-matrix
|
|
rows: 5
|
|
cols: 1
|
|
dt: d
|
|
data: [ -0.3107371474, 0.1187673445, -0.0002552599, -0.0001158436, -0.0233324616]
|
|
|
|
(Reference: https://wiki.mpi-inf.mpg.de/d2/ArUco)
|
|
|
|
How to use:
|
|
- Copy and paste this in /<OPENCV_SOURCE_DIR>/samples/python2
|
|
- Run it like
|
|
python calibrate_and_save.py --save "/<PATH_TO_SAVE_CAMERA_MATRIX>/camera.yml" "/<PATH_TO_IMAGE_DIR>/*.png"
|
|
- Then you can use ArUco like
|
|
./<PATH_TO_ARUCO_SRC>/build/utils/aruco_test_gl live /<PATH_TO_SAVE_CAMERA_MATRIX>/camera.yml 0.039
|
|
|
|
More on calibration: http://www.janeriksolem.net/2014/05/how-to-calibrate-camera-with-opencv-and.html
|
|
|
|
UPDATE:
|
|
Alternatively, you can follow the steps below
|
|
- After disabling integrated webcam:
|
|
echo "0" > /sys/bus/usb/devices/2-1.6/bConfigurationValue
|
|
(need to first find which usb device corresponds to your webcam)
|
|
- Plug in pupil tracker and use the official precompiled cpp script like:
|
|
/<PATH_TO_OPENCV>/build/bin/cpp-example-calibration -w 8 -h 6 -s 0.039 -o camera.yml -op
|
|
'''
|
|
|
|
import time
|
|
|
|
import numpy as np
|
|
import cv2, cv
|
|
import os
|
|
from common import splitfn
|
|
|
|
|
|
def saveCameraParams(save_dir, nframes, w, h, bw, bh, square_size,
|
|
camera_matrix, distortion_coefficients, fix_aspect_ratio = None, flags = 0):
|
|
time_str = time.strftime('%a %d %b %Y %H:%M:%S %Z')
|
|
lines = []
|
|
lines.append('%YAML:1.0')
|
|
lines.append('calibration_time: "%s"' %time_str)
|
|
lines.append('nframes: %s' %nframes)
|
|
lines.append('image_width: %s' %w)
|
|
lines.append('image_height: %s' %h)
|
|
lines.append('board_width: %s' %bw)
|
|
lines.append('board_height: %s' %bh)
|
|
lines.append('square_size: %s' %square_size)
|
|
if fix_aspect_ratio:
|
|
lines.append('fix_aspect_ratio: %s' %fix_aspect_ratio)
|
|
lines.append('flags: %s' %flags)
|
|
lines.append('camera_matrix: !!opencv-matrix')
|
|
lines.append(' rows: 3')
|
|
lines.append(' cols: 3')
|
|
lines.append(' dt: d')
|
|
lines.append(' data: %s' %repr(camera_matrix.reshape(1,9)[0])[6:-1]) # [6:-1] removes "array(" and ")"
|
|
lines.append('distortion_coefficients: !!opencv-matrix')
|
|
lines.append(' rows: 5')
|
|
lines.append(' cols: 1')
|
|
lines.append(' dt: d')
|
|
lines.append(' data: %s' %repr(distortion_coefficients)[6:-1])
|
|
with open(save_dir, 'w') as f:
|
|
f.writelines(map(lambda l: l+'\n', lines))
|
|
|
|
|
|
def readCameraParams(cam_mat = None):
|
|
'''
|
|
Reads an openCV camera.yml file and returns camera_matrix and distortion_coefficients
|
|
'''
|
|
if not cam_mat:
|
|
cam_mat = CAMERA_MATRIX
|
|
|
|
data = ''.join(open(cam_mat.strip(), 'r').readlines()).replace('\n', '').lower()
|
|
try:
|
|
ind1 = data.index('[', data.index('camera_matrix'))
|
|
ind2 = data.index(']', ind1)
|
|
camera_matrix = eval(data[ind1:ind2+1])
|
|
camera_matrix = np.array([camera_matrix[:3],
|
|
camera_matrix[3:6],
|
|
camera_matrix[6:]])
|
|
ind1 = data.index('[', data.index('distortion_coefficients'))
|
|
ind2 = data.index(']', ind1)
|
|
dist_coeffs = np.array(eval(data[ind1:ind2+1]))
|
|
return camera_matrix, dist_coeffs
|
|
except Exception:
|
|
print 'Could not load camera parameters'
|
|
print 'Invalid camera.yml file.'
|
|
|
|
if __name__ == '__main__':
|
|
import sys, getopt
|
|
from glob import glob
|
|
|
|
args, img_mask = getopt.getopt(sys.argv[1:], '', ['save=', 'debug=', 'square_size='])
|
|
args = dict(args)
|
|
try: img_mask = img_mask[0]
|
|
except: img_mask = '../cpp/left*.jpg'
|
|
# print 'mask is', img_mask
|
|
# img_mask = img_mask.replace('10.png', '*.png')
|
|
img_names = glob(img_mask)
|
|
debug_dir = args.get('--debug')
|
|
square_size = float(args.get('--square_size', 1.0))
|
|
square_size = 0.00122
|
|
|
|
save_dir = args.get('--save')
|
|
|
|
pattern_size = (8, 6)
|
|
|
|
pattern_points = np.zeros( (np.prod(pattern_size), 3), np.float32 )
|
|
pattern_points[:,:2] = np.indices(pattern_size).T.reshape(-1, 2)
|
|
pattern_points *= square_size
|
|
|
|
obj_points = []
|
|
img_points = []
|
|
h, w = 0, 0
|
|
for fn in img_names:
|
|
print 'processing %s...' % fn,
|
|
img = cv2.imread(fn, 0)
|
|
h, w = img.shape[:2]
|
|
found, corners = cv2.findChessboardCorners(img, pattern_size)
|
|
if found:
|
|
term = ( cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_COUNT, 30, 0.1 )
|
|
cv2.cornerSubPix(img, corners, (5, 5), (-1, -1), term)
|
|
if debug_dir:
|
|
vis = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
|
|
cv2.drawChessboardCorners(vis, pattern_size, corners, found)
|
|
path, name, ext = splitfn(fn)
|
|
cv2.imwrite('%s/%s_chess.bmp' % (debug_dir, name), vis)
|
|
if not found:
|
|
print 'chessboard not found'
|
|
continue
|
|
img_points.append(corners.reshape(-1, 2))
|
|
obj_points.append(pattern_points)
|
|
|
|
print 'ok'
|
|
|
|
# rms, camera_matrix, dist_coefs, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, (w, h))
|
|
|
|
root_dir = '/home/mmbrian/Pictures/eye_camera_images/'
|
|
cameraMatrixguess, distCoeffsguess = readCameraParams(os.path.join(root_dir,'_camera.yml'))
|
|
print "cameraM: ", cameraMatrixguess
|
|
print "dist: ", distCoeffsguess
|
|
|
|
cameraMatrixguess[1][1] = cameraMatrixguess[0][0]
|
|
cameraMatrixguess[0][2] = 320
|
|
cameraMatrixguess[1][2] = 180
|
|
|
|
# Calibrate camera intrinsics
|
|
rms, camera_matrix, dist_coefs, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, (w,h),
|
|
cameraMatrixguess, distCoeffsguess, None, None, flags = \
|
|
cv.CV_CALIB_USE_INTRINSIC_GUESS + cv.CV_CALIB_FIX_PRINCIPAL_POINT + cv.CV_CALIB_FIX_ASPECT_RATIO)
|
|
np.save(os.path.join(root_dir,'dist.npy'), dist_coefs)
|
|
np.save(os.path.join(root_dir,'cameraMatrix.npy'), camera_matrix)
|
|
np.savetxt(os.path.join(root_dir,'dist.csv'),np.asarray(dist_coefs), delimiter=";", fmt="%s")
|
|
np.savetxt(os.path.join(root_dir,"cameraMatrix.csv"),np.asarray(camera_matrix), delimiter=";", fmt="%s")
|
|
|
|
print "RMS:", rms
|
|
print "camera matrix:\n", camera_matrix
|
|
print "distortion coefficients: ", dist_coefs.ravel()
|
|
|
|
print 'Width:', w, 'Height:', h
|
|
print 'nframes:', len(img_names)
|
|
print 'square_size:', square_size
|
|
print 'board_width:', pattern_size[0]
|
|
print 'board_height:', pattern_size[1]
|
|
|
|
saveCameraParams(save_dir, len(img_names), w, h, pattern_size[0], pattern_size[1], square_size,
|
|
camera_matrix, dist_coefs.ravel())
|
|
print "Saved camera matrix to", save_dir
|
|
|
|
cv2.destroyAllWindows()
|
|
|
|
|
|
|