Advertisement

计算机视觉(四)--- 相机标定

阅读量:

针孔模型 & 透镜

让我们先来了解针孔成像的基本原理。Pinhole Camera Model(有时也被称为Projection Camera Model)是计算机视觉领域中广泛采用的一种相机模型。在大多数应用场景中,Pinhole Camera Model因其简单性和高精度而被广泛应用。在我们的初中物理课程中学习的小孔成像原理中,例如,在小孔成像实验中使用的蜡烛就是一个很好的实例。

摄像机几何

真实世界到像素平面(坐标装换)

在相机成像系统中主要涉及四个不同的坐标体系:世界坐标体系、相机本体坐标体系、影像平面坐标体系和像素点位置基准。

齐次坐标 (加一维) 三维齐次到二维装换不是唯一的

内外参数矩阵

计算机视觉中的三维重建技术——深入浅出SfM与SLAM核心算法——1相机模型(bilibili.com

https://www.bilibili.com/medialist/play/592250247?from=space&business=space_collection&business_id=155845&desc=0](https://www.bilibili.com/medialist/play/592250247?from=space&business=space_collection&business_id=155845&desc=0 "计算机视觉之三维重建(深入浅出SfM与SLAM核心算法)——1.摄像机几何 (bilibili.com)")

摄像机标定

进行求解摄像机内外参赛矩阵

我们运用最小二乘法求解

如下图所示

张正友标定

但是传统标定法要求使用三维标准板,并且精确度非常高,在实际制作过程中非常困难;为了克服这一缺陷,在这里我们介绍张正友教授提出的一种新型的计算机视觉中的点位标记方法。这种方法介于传统的固定模式标记方法与自适应自动校准方法之间;不过它相比传统的固定模式标记技术的优势在于无需像后者那样依赖精确制作的标准模板;而与自动校准技术相比,则能显著提高定位精度的同时又简化了实现过程;因此这种改进型的方法被广泛应用于现代计算机视觉系统中

论文: A versatile innovative method enabling camera calibration - Pattern Analysis and Machine Intelligence, IEEE Transactions on (swardtoolbox.github.io)

icon-default.png?t=M4AD

A novel approach for camera calibration has been developed, as it offers enhanced flexibility compared to traditional methods. Additionally, the coplanar object can be moved freely during the calibration process, which simplifies the setup and improves accuracy.

公式的推导过程大家可以看论文

实现流程

代码实践

复制代码
 import cv2

    
 import numpy as np
    
 import glob
    
  
    
 # 找棋盘格角点
    
 # 阈值
    
 criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
    
 #棋盘格模板规格
    
 w = 14  #内角点个数,内角点是和其他格子连着的点
    
 h = 9
    
  
    
 # 世界坐标系中的棋盘格点,例如(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('../images/chp4/*.jpg') # 标定所用图像
    
 for fname in images:
    
     img = cv2.imread(fname)
    
     gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    
     # 找到棋盘格角点
    
     # 棋盘图像(8位灰度或彩色图像)  棋盘尺寸  存放角点的位置
    
     ret, corners = cv2.findChessboardCorners(gray, (w,h),None)
    
     # 如果找到足够点对,将其存储起来
    
     if ret == True:
    
     # 角点精确检测
    
     # 输入图像 角点初始坐标 搜索窗口为2*winsize+1 死区 求角点的迭代终止条件
    
     cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
    
     objpoints.append(objp)
    
     imgpoints.append(corners)
    
     # 将角点在图像上显示
    
     cv2.drawChessboardCorners(img, (w,h), corners, ret)
    
     cv2.imshow('findCorners',img)
    
     cv2.waitKey(1000)
    
 cv2.destroyAllWindows()
    
 #标定、去畸变
    
 # 输入:世界坐标系里的位置 像素坐标 图像的像素尺寸大小 3*3矩阵,相机内参数矩阵 畸变矩阵
    
 # 输出:标定结果 相机的内参数矩阵 畸变系数 旋转矩阵 平移向量
    
 ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
    
 # mtx:内参数矩阵
    
 # dist:畸变系数
    
 # rvecs:旋转向量 (外参数)
    
 # tvecs :平移向量 (外参数)
    
 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)    # 平移向量  # 外参数
    
 # 去畸变
    
 img2 = cv2.imread('../images/chp4/7.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,说明结果越理想。
    
 # 通过之前计算的内参数矩阵、畸变系数、旋转矩阵和平移向量,使用cv2.projectPoints()计算三维点到二维图像的投影,
    
 # 然后计算反投影得到的点与图像上检测到的点的误差,最后计算一个对于所有标定图像的平均误差,这个值就是反投影误差。
    
 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))

标定拍摄图片

运行结果 (通过Matlab标定)

全部评论 (0)

还没有任何评论哟~