Advertisement

计算机视觉实验四-相机标定

阅读量:

目录

一、相机标定原理

1.1 简介

1.2 两类参数​编辑

1.3 标定参数线性回归

1.4棋盘格标定

二、实验代码


一、相机标定原理

1.1 简介

在图像测量和机器视觉应用领域中,在确定空间物体表面某一点的空间几何位置与其相应的图像平面位置之间的关系时,则需构建相机成像的数学模型;这些模型中的参数即代表相机本身的特性参数;通常情况下,在实验与计算的基础上才能获得这些参数值;而这一用于确定参数的过程则被定义为相机标定(亦称摄像机标定)。

1.2 两类参数

同步确定内部参数与外部参数, 通常采用两种策略:

  1. 基于已知的几何信息(如固定长度的棋盘格)实现参数求解.
  2. 自标定: 基于静态场景中的结构从运动模型估算参数.

1.3 标定参数线性回归

通过已知空间中坐标的特征点(Xi, Yi, Zi),以及它们在图像中的对应坐标(ui, vi),计算出内外参数的数量达到11个。

优点 :
– 所有的相机参数均以矩阵的形式呈现,便于计算
– 矩阵能够清晰地映射世界坐标系中的三维空间点到图像平面中的二维坐标
– 该方法具备较高的容错性特征

缺点 :
– 方法未能直接提供相机内外参数的具体数值
– 计算出的未知数数量超过预期值(9个待标定参数)
– 内参与外参之间存在明显相关性问题
– 方法对于噪声和误差较为敏感

1.4棋盘格标定

相关流程:

  1. 制作一张黑色与白色间距已知的A4方格纸,并粘附于平板表面
  2. 对棋盘格进行多角度拍摄(约10至20张)
  3. 识别图像中的关键点(如Harris角点)
  4. 基于角点坐标计算对应的Homography矩阵
  5. 通过解析法确定五个内参数和六个外参数
  6. 采用极大似然估计优化目标,并通过迭代优化技术提升参数精度

二、实验代码

复制代码
 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:\ DLsite\ 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.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))

全部评论 (0)

还没有任何评论哟~