张正友相机标定实践

一、制作标定板以及准备图片
首先将以下图片打印出来
张正友相机标定实践
打印出来后,用手机(机型为iphone7)从不同角度拍摄出10张照片作为素材
张正友相机标定实践
二、提取标定板的世界坐标
标定板的大小指的是标定板上的横向和竖向不挨着边界的内角点的个数,例如图一的标定板的大小为6*4
三、张正友标定相机的原理
1.求得相机内参数:

用于标定的棋盘格是特制的,其角点坐标已知。标定棋盘格是三维场景中的一个平面∏,棋盘格在成像平面为π(知道了∏与π的对应点坐标之后,可求解两个平面1对应的单应矩阵H)。
根据相机成像模型,P为标定的棋盘坐标,p为其像素点坐标。则P=K[R丨T]P=HP,通过对应的点坐标求解H后,可用于求K,R,T。
2.设棋盘格所在平面为世界坐标系上XOY平面,则棋盘格上任一角点P世界坐标系为(X,Y,0)。
张正友相机标定实践
3、内参约束条件
张正友相机标定实践
算得张正友相机标定实践
张正友相机标定实践
张正友相机标定实践
四、实验结果及源代码
1、角点检测
张正友相机标定实践
2、相机参数
mtx为内参数矩阵,dist为畸变系数,rvecs为旋转向量,tvecs为平移向量
张正友相机标定实践
张正友相机标定实践
3、矫正过后的结果图
张正友相机标定实践
4、实验代码
import cv2
import numpy as np
import glob

设置寻找亚像素角点的参数,采用的停止准则是最大循环次数30和最大误差容限0.001

criteria = (cv2.TERM_CRITERIA_MAX_ITER | cv2.TERM_CRITERIA_EPS, 30, 0.001)

获取标定板角点的位置

objp = np.zeros((4 * 6, 3), np.float32)
objp[:, :2] = np.mgrid[0:6, 0:4].T.reshape(-1, 2) # 将世界坐标系建在标定板上,所有点的Z坐标全部为0,所以只需要赋值x和y

obj_points = [] # 存储3D点
img_points = [] # 存储2D点

images = glob.glob(“imagesC/*.jpg”)
i=0;
for fname in images:
img = cv2.imread(fname)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
size = gray.shape[::-1]
ret, corners = cv2.findChessboardCorners(gray, (6, 4), None)
#print(corners)

if ret:

    obj_points.append(objp)

    corners2 = cv2.cornerSubPix(gray, corners, (5, 5), (-1, -1), criteria)  # 在原角点的基础上寻找亚像素角点
    #print(corners2)
    if [corners2]:
        img_points.append(corners2)
    else:
        img_points.append(corners)

    cv2.drawChessboardCorners(img, (6, 4), corners, ret)  # 记住,OpenCV的绘制函数一般无返回值
    i+=1;
    cv2.imwrite('conimg'+str(i)+'.jpg', img)
    cv2.waitKey(1500)

print(len(img_points))
cv2.destroyAllWindows()

标定

ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, size, None, None)

print(“ret:”, ret)
print(“mtx:\n”, mtx) # 内参数矩阵
print(“dist:\n”, dist) # 畸变系数 distortion cofficients = (k_1,k_2,p_1,p_2,k_3)
print(“rvecs:\n”, rvecs) # 旋转向量 # 外参数
print(“tvecs:\n”, tvecs ) # 平移向量 # 外参数

print("-----------------------------------------------------")

img = cv2.imread(images[2])
h, w = img.shape[:2]
newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),1,(w,h))#显示更大范围的图片(正常重映射之后会删掉一部分图像)
print (newcameramtx)
print("------------------使用undistort函数-------------------")
dst = cv2.undistort(img,mtx,dist,None,newcameramtx)
x,y,w,h = roi
dst1 = dst[y:y+h,x:x+w]
cv2.imwrite(‘calibresult3.jpg’, dst1)
print (“方法一:dst的大小为:”, dst1.shape)