标定手机相机参数

本文利用张正友相机标定方法,标定手机相机的相关参数。手机型号:华为mate8

1,张正友相机标定实验原理
 

标定手机相机参数_第1张图片

(1)计算单应性矩阵

  设三维世界坐标的点为X=[X,Y,Z,1]TX=[X,Y,Z,1]T,二维相机平面像素坐标为m=[u,v,1]Tm=[u,v,1]T,所以标定用的棋盘格平面到图像平面的单应性关系为: 

                                                                            s_{0}m=K[R,T]X 

其中s为尺度因子,K为摄像机内参数,R为旋转矩阵,T为平移向量。令 

                                                             标定手机相机参数_第2张图片

注意,s对于齐次坐标来说,不会改变齐次坐标值。张氏标定法中,将世界坐标系狗仔在棋盘格平面上,令棋盘格平面为Z=0的平面。则可得 

                                  标定手机相机参数_第3张图片 

我们把K[r1, r2, t]叫做单应性矩阵H,即 

                                                           标定手机相机参数_第4张图片 

H是一个齐次矩阵,所以有8个未知数,至少需要8个方程,每对对应点能提供两个方程,所以至少需要四个对应点,就可以算出世界平面到图像平面的单应性矩阵H。

(2)计算内参矩阵

 由上式可得 

                                                                     

标定手机相机参数_第5张图片

 

由于旋转矩阵是个酉矩阵,r1和r2正交,可得     

代入可得:

标定手机相机参数_第6张图片

 

即每个单应性矩阵能提供两个方程,而内参数矩阵包含5个参数,要求解,至少需要3个单应性矩阵。为了得到三个不同的单应性矩阵,我们使用至少三幅棋盘格平面的图片进行标定。通过改变相机与标定板之间的相对位置来得到三个不同的图片。为了方便计算,定义如下: 

标定手机相机参数_第7张图片

 可以看到,B是一个对称阵,所以B的有效元素为六个,让这六个元素写成向量b,即 

 

可以推导得到 

 利用约束条件可以得到: 

 

标定手机相机参数_第8张图片

通过上式,我们至少需要三幅包含棋盘格的图像,可以计算得到B,然后通过cholesky分解,得到相机的内参数矩阵K

(3)计算外部参数矩阵

根据以上推导的:

标定手机相机参数_第9张图片

(4)最大似然估计

上述的推导结果是基于理想情况下的解,但由于可能存在高斯噪声,所以可以使用最大似然估计进行优化。 

(5)径向畸变估计

 张氏标定法只关注了影响最大的径向畸变。

2,标定步骤

 (1)打印一张棋盘格A4纸张(黑白间距已知),并贴在一个平板上

 (2)针对棋盘格拍摄若干张图片(一般10-20张) 本实验用11张图片

 (3)在图片中检测特征点(Harris特征)

(4)利用解析解估算方法计算出5个内部参数,以及6个外部参数

  (5)根据极大似然估计策略,设计优化目标并实现参数的refinement

3,python-opencv实现

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

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

images = glob.glob("D:/img/*.jpg")
for fname in images:
    img = cv2.imread(fname)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    size = gray.shape[::-1]
    ret, corners = cv2.findChessboardCorners(gray, (9, 13), None)
    print(ret)

    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, (9,13), corners, ret)  # 记住,OpenCV的绘制函数一般无返回值
        cv2.imshow('img', img)
        cv2.waitKey(1550)

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

实验结果:

标定手机相机参数_第10张图片

内参矩阵K:

标定手机相机参数_第11张图片 

畸变系数:

 

旋转向量:

rvecs:
 [array([[-0.15498336],
       [ 0.08299058],
       [ 1.57825619]]), array([[-0.17700503],
       [ 0.13513091],
       [ 1.54444289]]), array([[-0.1969227 ],
       [ 0.06791505],
       [ 1.42547299]]), array([[-0.10582712],
       [ 0.13866824],
       [ 1.57904503]]), array([[-0.10027729],
       [ 0.14172248],
       [ 1.66829567]]), array([[-0.06210765],
       [ 0.13368951],
       [ 1.52657835]]), array([[-0.09108756],
       [ 0.08716393],
       [ 1.55527437]]), array([[-0.1503406 ],
       [ 0.07851393],
       [ 1.53904991]]), array([[-0.14010565],
       [ 0.13986868],
       [ 1.54698176]]), array([[-0.18304361],
       [ 0.05257621],
       [ 1.55159216]]), array([[-0.07789582],
       [-0.19367696],
       [-1.60933796]])]

平移向量:
tvecs:
 [array([[ 6.49072436],
       [-5.29625546],
       [15.25918388]]), array([[ 7.52990441],
       [-3.88858914],
       [21.47230557]]), array([[ 2.43990326],
       [-5.85870394],
       [21.46053901]]), array([[ 6.28452525],
       [-4.70325779],
       [14.08126117]]), array([[ 5.41459937],
       [-4.1338246 ],
       [16.91337961]]), array([[ 4.72644156],
       [-5.75589647],
       [17.69613248]]), array([[ 8.32334749],
       [-5.98643736],
       [18.55356728]]), array([[ 6.7718184 ],
       [-4.97348129],
       [19.848855  ]]), array([[ 7.49688689],
       [-5.10980997],
       [19.88458187]]), array([[ 4.38663715],
       [-5.9598907 ],
       [21.18326816]]), array([[-4.84527183],
       [ 3.73164533],
       [19.56180214]])]

4,标定注意事项:

以下问题是由于标定的角点数错误造成,代码里的9*13表示棋盘格里的内角点数

 Traceback (most recent call last):
  File "D:/python计算机视觉/Camare_test.py", line 42, in
    ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, size, None, None)
cv2.error: OpenCV(3.4.2) C:\projects\opencv-python\opencv\modules\calib3d\src\calibration.cpp:3143: error: (-215:Assertion failed) ni == ni1 in function 'cv::collectCalibrationData'

参考文章:

https://blog.csdn.net/u010128736/article/details/52860364

https://blog.csdn.net/a6333230/article/details/83478064 

你可能感兴趣的:(标定手机相机参数)