这两天学习相机标定,根据opencv的文档(OpenCV: Camera Calibration),整理的代码
包含了角点检测、标定、remap、重投影误差计算。在小的标定板上,findChessboardCorners和cornerSubPix的差异很小。还要再验证下大的标定板。
#-*-coding:utf-8-*-
from audioop import error
import numpy as np
import cv2
import os
import copy
path = 'D:\\try\\calib_img'
save = 'D:\\try\\calib_img\\result'
save2 = 'D:\\try\\calib_img\\result2'
calib_path = 'D:\\try\\calib_img\\calibresult'
remap_path = 'D:\\try\\calib_img\\remap'
grays = []
names = []
pObjs = []
pImgs = []
w, h = 9, 6 #corners per a chessboard row and column
pobj = np.zeros((w*h, 3), np.float32)
pobj[:, :2] = np.mgrid[0:w, 0:h].T.reshape(-1, 2)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.01)
f = os.listdir(path)
'''
step one: find chessboard corners and drawchessboardCorners
'''
for i in f:
fname = os.path.join(path, i)
if(os.path.isdir(fname)):
continue
img = cv2.imread(fname)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, corners = cv2.findChessboardCorners(gray, (w, h), None)
if(ret == True):
print(i, '-----find chessboard cornors ')
grays.append(gray)
names.append(i)
corners2 = cv2.cornerSubPix(gray, corners.astype(np.float32), (5, 5), (-1, -1), criteria)
pImgs.append(corners2)
pObjs.append(pobj)
img2 = copy.deepcopy(img)
cv2.drawChessboardCorners(img, (w ,h), corners, ret)
save_name = os.path.join(save, i)
cv2.imwrite(save_name, img)
cv2.drawChessboardCorners(img2, (w, h), corners, ret)
save_name2 = os.path.join(save2, i)
cv2.imwrite(save_name2, img2)
else:
continue
'''
step 2: calibrate
'''
ret, matrix, dist, r_vecs, t_vecs = cv2.calibrateCamera(pObjs, pImgs, grays[0].shape[::-1], None, None)
'''
step 3: undistor and remap
'''
for i in range(len(grays)):
img_h, img_w = grays[i].shape[::-1]
newMtx, roi = cv2.getOptimalNewCameraMatrix(matrix, dist, (img_w, img_h), 1, (img_w, img_h))
x, y, w1, h1 = roi
#undistort
dst = cv2.undistort(grays[i], matrix, dist, None, newMtx)
dst = dst[y:y+h1, x:w+w1]
_name = os.path.join(calib_path, names[i])
cv2.imwrite(_name, dst)
#remapping
mapx, mapy = cv2.initUndistortRectifyMap(matrix, dist, None, newMtx, (img_w, img_h), 5)
dst2 = cv2.remap(grays[i], mapx, mapy, cv2.INTER_LINEAR)
dst2 = dst2[y:y+h1, x:x+w1]
_remap = os.path.join(remap_path, names[i])
cv2.imwrite(_remap, dst2)
'''
step 4: calculate means
'''
mean_error = 0
for i in range(len(pObjs)):
img2_obj, _ = cv2.projectPoints(pObjs[i], r_vecs[i], t_vecs[i], matrix, dist)
ierror = cv2.norm(pImgs[i], img2_obj, cv2.NORM_L2) / len(img2_obj)
mean_error += ierror
mean_error = mean_error / len(pObjs)
print('------mean error is: ', mean_error)