gazesim/code/recording/opencv/calibrate_and_save.py

194 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()