计算机视觉 相机标定

目录

一.相机标定原理:

1.相机标定简介:  

        在图像测量过程以及机器视觉应用中,为确定空间物体表面某点的三维几何位置与其在图像中对应点之间的相互关系,必须建立相机成像的几何模型,这些几何模型参数就是相机参数。在大多数条件下这些参数必须通过实验与计算才能得到,这个求解参数的过程就称之为相机标定(或摄像机标定)。

目的:求出相机的内、外参数,以及畸变参数。

 作用: 1.是由于每个镜头的畸变程度各不相同,通过相机标定可以校正这种镜头畸变矫正畸变,生成矫正后的图像;2.是根据获得的图像重构三维场景。

畸变校正:

2.求解原理:

2.1.针孔相机模型:

 

2.2.畸变现象:

图像径向畸变 :

透镜质量原因
光线在远离透镜中心的地方比靠近中心的地方更加弯曲
桶状畸变:

 枕形畸变:

2.3.像主点偏移:

 

 2.4.单应性矩阵H:

 最大似然估计

使用最大似然估计进行优化。假设拍摄了n张棋盘格图像,每张图像有m个角点。最终获得的最大似然估计公式为:

二.相机标定策略:

2.1.相关策略

同步标定内部参数和外部参数,一般包括两种策略:
1. 光学标定: 利用已知的几何信息(如定长棋盘格)实现参数求解。
2. 自标定: 在静态场景中利用 structure from motion估算参数。

2.2.棋盘格标定:

优点:
仅需要平面标定板,拍摄若干张图片
标定板中的模式十分灵活,可以是棋盘格,也可以是其他几何结构已知的图形
实验结果表明具有很好的标定精度
具有很强的灵活性
相关流程:
1. 打印一张棋盘格A4纸张(黑白间距已知),并贴在一个平板上
2. 针对棋盘格拍摄若干张图片(一般10-20张)
3. 在图片中检测特征点(Harris角点)
4. 根据角点位置信息及图像中的坐标,求解Homographic矩阵
5. 利用解析解估算方法计算出5个内部参数,以及6个外部参数
6. 根据极大似然估计策略,设计优化目标并实现 参数的refinement

 三.实验内容:

1.实验数据:

2.实验代码:

import cv2
import numpy as np
import glob

# 找棋盘格角点
# 棋盘格模板规格(内角点个数,内角点是和其他格子连着的点,如11 X 8)
w = 11
h = 8

# 世界坐标系中的棋盘格点,例如(0,0,0), (1,0,0), (2,0,0) ....,(8,5,0),去掉Z坐标,记为二维矩阵
objp = np.zeros((w * h, 3), np.float32)
objp[:, :2] = np.mgrid[0:w, 0:h].T.reshape(-1, 2)

# 储存棋盘格角点的世界坐标和图像坐标对
objpoints = []  # 在世界坐标系中的三维点
imgpoints = []  # 在图像平面的二维点

# 标定所用图像(路径不能有中文)

images = glob.glob('D:\\pythonProject\\computervision4\\picture\\*.jpg')

size = tuple()
for fname in images:
    img = cv2.imread(fname)

    # 修改图像尺寸,参数依次为:输出图像,尺寸,沿x轴,y轴的缩放系数,INTER_AREA在缩小图像时效果较好
    img = cv2.resize(img, None, fx=0.1, fy=0.1, interpolation=cv2.INTER_AREA)

    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 转灰度
    size = gray.shape[::-1]  # 矩阵转置

    # 找到棋盘格角点
    # 棋盘图像(8位灰度或彩色图像)  棋盘尺寸  存放角点的位置
    ret, corners = cv2.findChessboardCorners(gray, (w, h), None)

    # 角点精确检测
    # criteria:角点精准化迭代过程的终止条件(阈值)
    criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)

    # 执行亚像素级角点检测
    corners2 = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)

    objpoints.append(objp)
    imgpoints.append(corners2)

    # 将角点在图像上显示
    cv2.drawChessboardCorners(img, (w, h), corners2, ret)
    cv2.imshow('findCorners', img)
    cv2.waitKey(1000)

"""
标定、去畸变:
输入:世界坐标系里的位置 像素坐标 图像的像素尺寸大小 3*3矩阵,相机内参数矩阵 畸变矩阵
输出:标定结果 相机的内参数矩阵 畸变系数 旋转矩阵 平移向量
"""

ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, size, None, None)

# mtx:内参数矩阵
# dist:畸变系数
# rvecs:旋转向量 (外参数)
# tvecs :平移向量 (外参数)
print("ret:", ret)
print("内参数矩阵:\n", mtx, '\n')
print("畸变系数:\n", dist, '\n')
print("旋转向量(外参数):\n", rvecs, '\n')
print("平移向量(外参数):\n", tvecs, '\n')

# 去畸变
img2 = cv2.imread('D:\\pythonProject\\computervision4\\picture\\IMG_20220512_151929.jpg')
h, w = img2.shape[:2]

# 我们还可以使用cv.getOptimalNewCameraMatrix()优化内参数和畸变系数,
# 通过设定自由自由比例因子alpha。当alpha设为0的时候,
# 将会返回一个剪裁过的将去畸变后不想要的像素去掉的内参数和畸变系数;
# 当alpha设为1的时候,将会返回一个包含额外黑色像素点的内参数和畸变系数,并返回一个ROI用于将其剪裁掉
newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w, h), 0, (w, h))  # 自由比例参数

dst = cv2.undistort(img2, mtx, dist, None, newcameramtx)
# 根据前面ROI区域裁剪图片
x, y, w, h = roi
dst = dst[y:y + h, x:x + w]
cv2.imwrite('calibresult.jpg', dst)

# 反投影误差
# 通过反投影误差,我们可以来评估结果的好坏。越接近0,说明结果越理想。
total_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)
    total_error += error
print("total error: ", total_error / len(objpoints))

3.实验结果:

 

 

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
青葱年少的头像青葱年少普通用户
上一篇 2022年5月25日
下一篇 2022年5月25日

相关推荐