# 9.1. 摄像机校准¶

## 9.1.1. 目标¶

-我们将学习相机中的失真、相机的内在和外在参数等-我们将学习寻找这些参数、不失真图像等。

## 9.1.2. 基础¶

开始{aligned}x{corrected}=x（1+k 1 r^2+k 2 r^4+k 3 r^6）\y{corrected}=y（1+k1 r^2+k2 r^4+k3 r^6）结束{aligned}

\begin{split}\begin{aligned} x_{corrected} = x + [ 2p_1xy + p_2(r^2+2x^2)] \\ y_{corrected} = y + [ p_1(r^2+ 2y^2)+ 2p_2xy] \end{aligned}\end{split}

$畸变系数=（kÓ1hspace{10pt}k 2hspace{10pt}p 1hspace{10pt}p2hspace{10pt}k 3）$

\begin{split}\begin{aligned} camera \; matrix = \left [ \begin{matrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{matrix} \right ] \end{aligned}\end{split}

## 9.1.3. 代码¶

### 安装程序¶

>>> %matplotlib inline
>>> import matplotlib.pyplot as plt
>>>
>>> import os
>>> import numpy as np
>>> import cv2
>>> import glob
>>>
>>> # termination criteria
>>> criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
>>>
>>> # prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
>>> objp = np.zeros((6*7,3), np.float32)
>>> objp[:,:2] = np.mgrid[0:7,0:6].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.
>>>
>>> os.chdir('/cvdata/')
>>> images = glob.glob('*.jpg')
>>>
>>> for fname in images:
>>>     gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
>>>
>>>     # Find the chess board corners
>>>     ret, corners = cv2.findChessboardCorners(gray, (7,6),None)
>>>
>>>     # If found, add object points, image points (after refining them)
>>>     if ret == True:
>>>         objpoints.append(objp)
>>>
>>>         corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
>>>         imgpoints.append(corners2)
>>>
>>>         # Draw and display the corners
>>>         img = cv2.drawChessboardCorners(img, (7,6), corners2,ret)
>>>         plt.imshow(img)
>>>
>>>
>>>         # cv2.imshow('img',img)
>>>         # cv2.waitKey(500)
>>>
>>> # cv2.destroyAllWindows()


### 校准¶

>>> ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1],None,None)

>>> np.savez('/tmp/x_B.npz', ret = ret, mtx= mtx, dist = dist, rvecs = rvecs, tvecs = tvecs)


### 不失真¶

>>> img = cv2.imread('/cvdata/left12.jpg')
>>> h,  w = img.shape[:2]
>>> newcameramtx, roi=cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),1,(w,h))


#### 一。使用 cv2.不中断（）¶

>>> # undistort
>>> dst = cv2.undistort(img, mtx, dist, None, newcameramtx)
>>>
>>> # crop the image
>>> x,y,w,h = roi
>>> dst = dst[y:y+h, x:x+w]
>>> cv2.imwrite('calibresult.png',dst)

True


#### 2。使用 重新映射¶

>>> # 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]
>>> cv2.imwrite('calibresult.png',dst)

True

>>> plt.imshow(dst)

<matplotlib.image.AxesImage at 0x7f4805ee0d68>


## 9.1.4. 重投影误差¶

>>> mean_error = 0
>>> for i in range(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: {}".format(mean_error/len(objpoints)) )

total error: 0.02831772349383625


## 9.1.6. 练习¶

1. 尝试使用圆形网格进行相机校准。