相机标定,内参数与外参数

article/2025/10/22 5:44:10

相机标定

简介

所谓的相机标定就是将外界世界的坐标信息转化为计算机(自带相机/摄像头)可以理解的“距离”,将世界坐标系转换到相机坐标系。我们可以理解为从一个坐标系转换到另一个坐标系所需要的转换关系就是相机标定。

简单滴说:A=F(B),其中F()就是相机标定要做的工作。 其标定的目的就是为了相机内参、外参、畸变参数。

基本原理

求解Homographic矩阵

在这里插入图片描述
在这里插入图片描述
其中 H是描述Homographic矩阵
H 矩阵可以根据特征点/棋盘格角点的空间坐标,以及其图像坐标用最小二乘法很容易求解。
在这里插入图片描述
Homography 有 8 个自由度,
由r1和r2正交,且r1和r2的模相等,可以得到如下约束:
在这里插入图片描述

计算内参数矩阵

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述

计算外参数矩阵

在这里插入图片描述

相机标定步骤:

1、打印一张棋盘格,把它贴在一个平面上,作为标定物。
2、通过调整标定物或摄像机的方向,为标定物拍摄一些不同方向的照片。
3、从照片中提取棋盘格角点。
4、估算理想无畸变的情况下,五个内参和六个外参。
5、应用最小二乘法估算实际存在径向畸变下的畸变系数。
6、极大似然法,优化估计,提升估计精度。

标定过程

准备标定板

OpenCV使用棋盘格板进行标定。为了标定相机,我们需要输入一系列三维点和它们对应的二维图像点。在黑白相间的棋盘格上,二维图像点很容易通过角点检测找到。而对于真实世界中的三维点呢?由于我们采集中,是将相机放在一个地方,而将棋盘格定标板进行移动变换不同的位置,然后对其进行拍摄。所以我们需要知道(X,Y,Z)的值。但是简单来说,我们定义棋盘格所在平面为XY平面,即Z=0。
在这里插入图片描述
在这里插入图片描述

检测棋盘格角点

为了找到棋盘格模板,我们使用openCV中的函数cv2.findChessboardCorners()。我们也需要告诉程序我们使用的模板是什么规格的,例如88的棋盘格或者55棋盘格等,建议使用x方向和y方向个数不相等的棋盘格模板。下面实验中,我们使用的是107的棋盘格,每个方格边长是20mm,即含有96的内部角点。这个函数如果检测到模板,会返回对应的角点,并返回true。当然不一定所有的图像都能找到需要的模板,所以我们可以使用多幅图像进行定标。除了使用棋盘格,我们还可以使用圆点阵,对应的函数为cv2.findCirclesGrid()。
  找到角点后,我们可以使用cv2.cornerSubPix()可以得到更为准确的角点像素坐标。我们也可以使用cv2.drawChessboardCorners()将角点绘制到图像上显示。

ret, corners = cv2.findChessboardCorners(gray1, (9, 6), None)
img = cv2.drawChessboardCorners(gray1, (9,6), corners,ret)
cv2.waitKey(1000)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
corners2 = cv2.cornerSubPix(gray1, corners, (9, 6), (-1, -1), criteria)
objpoints.append(objp)
imgpoints.append(corners2)
img = cv2.drawChessboardCorners(gray1, (9, 6), corners2, ret)

在这里插入图片描述

标定

ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray1.shape[::-1], None, None)

通过上面的步骤,我们得到了用于标定的三维点和与其对应的图像上的二维点对。我们使用cv2.calibrateCamera()进行标定,这个函数会返回标定结果、相机的内参数矩阵、畸变系数、旋转矩阵和平移向量。
第三步我们已经得到了相机内参和畸变系数,在将图像去畸变之前,我们还可以使用cv.getOptimalNewCameraMatrix()优化内参数和畸变系数,通过设定自由自由比例因子alpha。当alpha设为0的时候,将会返回一个剪裁过的将去畸变后不想要的像素去掉的内参数和畸变系数;当alpha设为1的时候,将会返回一个包含额外黑色像素点的内参数和畸变系数,并返回一个ROI用于将其剪裁掉。
然后我们就可以使用新得到的内参数矩阵和畸变系数对图像进行去畸变了。有两种方法进行去畸变:

实验结果

只有正面照片时

在这里插入图片描述

内参数矩阵,newcameramtx :

 [[1.39247888e+03 0.00000000e+00 4.21531719e+02][0.00000000e+00 1.39737781e+03 9.65615613e+02][0.00000000e+00 0.00000000e+00 1.00000000e+00]]

归一化焦距

fx= 1392.4788818359375 ,fy= 1397.3778076171875

像主点(光心)的坐标

cx,cy 421.53171941416076 965.6156127999784

dist为畸变系数。dist:

 [[-3.02007106e-01  7.88399855e+00 -2.46474817e-02  1.70686761e-03-4.04756976e+01]]

ret:

 1.543195731560363

mtx,

 [[1.39695861e+03 0.00000000e+00 4.21660147e+02][0.00000000e+00 1.39810589e+03 9.66118704e+02][0.00000000e+00 0.00000000e+00 1.00000000e+00]]

revcs,旋转矩阵,

 [[[-0.44309197][ 1.07147812][ 2.54591039]][[-0.84261395][-0.41259128][-0.67023628]][[-0.68681096][ 0.48542523][ 1.39249712]][[-0.46926989][ 0.85300712][ 2.35431065]][[-0.90272359][-0.16052316][-0.06843877]][[-0.53683367][ 0.72170338][ 1.88219057]][[-0.58768252][-0.86576238][-1.78717314]][[-0.11030619][-0.95418799][-2.14221165]][[-0.75441289][-0.58611659][-1.21926087]]]

tvecs,平移矩阵

 (array([[ 4.88345717],[ 0.05394641],[26.82703677]]), array([[-4.50241296],[-2.47457431],[24.1376541 ]]), array([[ 1.6678211 ],[-6.65197784],[21.42807732]]), array([[ 6.1818145 ],[-3.33303195],[26.24933552]]), array([[-4.74254289],[-2.1579989 ],[25.51213894]]), array([[ 4.19599853],[-6.14602571],[24.7580413 ]]), array([[-1.69668164],[-0.61900485],[18.5261494 ]]), array([[ 1.12094953],[ 3.90569145],[16.84087091]]), array([[-2.72197755],[-2.52729824],[20.64903984]]))

total error为总体误差:

  0.20800721454025364```python

只有侧面的照片时

在这里插入图片描述


```python[[1.82535645e+03 0.00000000e+00 4.18737546e+02][0.00000000e+00 3.35064893e+03 8.69153073e+02][0.00000000e+00 0.00000000e+00 1.00000000e+00]]

归一化焦距

fx= 1825.3564453125 ,fy= 3350.64892578125

像主点(光心)的坐标`

cx,cy 418.73754642918357 869.153072791858`

dist为畸变系数。dist:

 [[-1.40512508e+00  5.11022470e+01 -7.72332110e-02 -4.38502255e-02-2.59448179e+02]]

ret:

 3.5459118388096216

mtx,相机内参:

 [[1.81551877e+03 0.00000000e+00 4.41070962e+02][0.00000000e+00 3.27082753e+03 9.49563451e+02][0.00000000e+00 0.00000000e+00 1.00000000e+00]]

revcs,旋转矩阵,

 [[[-0.80727033][-1.01171386][-1.38129347]][[-0.75218536][ 1.14355184][ 1.84500315]][[-0.52719775][ 1.45639709][ 2.29389315]][[-0.63501651][-1.21903686][-1.67978362]][[-1.09993196][-0.21990954][-0.11986996]]]

tvecs,平移矩阵

 (array([[-2.89017706],[ 0.98237799],[21.24180682]]), array([[ 4.81100307],[-3.58585171],[26.84381837]]), array([[ 4.79268410e+00],[-5.12204200e-03],[ 2.77421342e+01]]), array([[-0.75778873],[ 1.25678028],[22.1323928 ]]), array([[-4.34387342],[-0.49682161],[25.88038286]]))

total error为总体误差:

`0.4767580123269295`

正面和侧面都有时

内参数矩阵,newcameramtx :

 [[1.47756372e+03 0.00000000e+00 3.84641645e+02][0.00000000e+00 1.47626343e+03 8.22453102e+02][0.00000000e+00 0.00000000e+00 1.00000000e+00]]

归一化焦距

`fx= 1477.563720703125 ,fy= 1476.263427734375`

像主点(光心)的坐标

cx,cy 384.6416450763427 822.4531022500742

dist为畸变系数。dist:

 [[-9.26352628e-01  2.87704635e+01 -6.32812203e-02 -1.19180863e-02-2.38869326e+02]]

ret:

 2.153142220889635

mtx,

 [[1.50446561e+03 0.00000000e+00 3.76968572e+02][0.00000000e+00 1.71088936e+03 9.53167429e+02][0.00000000e+00 0.00000000e+00 1.00000000e+00]]

revcs,旋转矩阵,

 [[[-0.40954189][ 1.23275464][ 2.499671  ]][[-0.57533214][-0.83954196][-1.41737043]][[-0.95020771][-0.41739403][-0.64296516]][[-0.76361682][ 0.60652417][ 1.37935282]][[-0.53011171][ 1.12347077][ 2.48832118]][[-0.4729612 ][ 1.03220648][ 2.31536491]][[-1.00259535][-0.12403123][-0.05485035]][[-0.58901605][ 0.86765807][ 1.85667864]][[-0.67763739][-0.94516277][-1.73384762]][[-0.23942408][-1.05697544][-2.09534043]]]

tvecs,平移矩阵

(array([[ 5.75125712],[ 0.30145146],[28.50095635]]), array([[-2.11435859],[ 1.47584997],[17.05490001]]), array([[-3.72925642],[-1.98627606],[26.15021609]]), array([[ 2.35337777],[-5.64738809],[23.16349946]]), array([[ 5.69328695],[-0.04058948],[22.8784759 ]]), array([[ 7.02740175],[-2.64972244],[27.99528916]]), array([[-3.93080855],[-1.686195  ],[27.55035256]]), array([[ 4.99191567],[-5.15586085],[26.61341699]]), array([[-1.10128061],[-0.39738934],[19.96949129]]), array([[ 1.68065367],[ 3.62482022],[17.86602482]]))

total error为总体误差:

0.27106081554424943

只有正面照片时误差 0.20800721454025364
正面侧面都有时误差0.27106081554424943
只有侧面时误差0.4767580123269295
由于正面拍时旋转角度较小所以最后的误差也相对较小

程序代码

import cv2
import glob
import numpy as np
from ipython_genutils.py3compat import xrange
import matplotlib.pyplot as plt
from pylab import *# from work1.Harris import plot_harris_points
# from work1.refine_all_param import refinall_all_paramcbraw = 9  # 有6行角点
cbcol = 6  # 有4列角点objp = np.zeros((cbraw * cbcol, 3), np.float32)
objp[:, :2] = np.mgrid[0:cbraw, 0:cbcol].T.reshape(-1, 2)objpoints = []  # 3d point in real world space
imgpoints = []  # 2d points in image plane.# glob是个文件名管理工具
images = glob.glob(r"./image/zm/*.jpg")
print("images",images)
for fname in images:# 对每张图片,识别出角点,记录世界物体坐标和图像坐标img = cv2.imread(fname)  # source image# 我用的图片太大,缩小了一半# img = cv2.resize(img, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_CUBIC)gray1 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 转灰度# 寻找角点,存入corners,ret是找到角点的flagret, corners = cv2.findChessboardCorners(gray1, (9, 6), None)img = cv2.drawChessboardCorners(gray1, (9,6), corners,ret)cv2.waitKey(1000)# criteria:角点精准化迭代过程的终止条件criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)# 执行亚像素级角点检测corners2 = cv2.cornerSubPix(gray1, corners, (9, 6), (-1, -1), criteria)objpoints.append(objp)imgpoints.append(corners2)# 在棋盘上绘制角点,只是可视化工具img = cv2.drawChessboardCorners(gray1, (9, 6), corners2, ret)cv2.imshow('img', img)
# cv2.waitKey(1000)'''
传入所有图片各自角点的三维、二维坐标,相机标定。
每张图片都有自己的旋转和平移矩阵,但是相机内参和畸变系数只有一组。
mtx,相机内参;dist,畸变系数;外参数:revcs,旋转矩阵;tvecs,平移矩阵。
'''
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray1.shape[::-1], None, None)
img = cv2.imread(r'./image/zm/4ffe6fa6c7732896b58c0ef7cfd8cb7.jpg')
# print(img)
# extrinsics_param\
rvecs = np.array(rvecs)
# print("rvecs="+str(rvecs))
# rvecsnp, _ = cv2.Rodrigues(rvecs)# print("rvecsnp="+str(rvecsnp))
# print("tvecs="+str(tvecs))
# 注意这里跟循环开头读取图片一样,如果图片太大要同比例缩放,不然后面优化相机内参肯定是错的。
# img = cv2.resize(img, None, fx=0.5, fy=0.5, interpolation=cv2.INTER_CUBIC)
# img1 = (9,6)
# h ,w = img1
h, w = img.shape[:2]'''
优化相机内参(camera matrix),这一步可选。
参数1表示保留所有像素点,同时可能引入黑色像素,
设为0表示尽可能裁剪不想要的像素,这是个scale,0-1都可以取。
'''
newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w, h), 1, (w, h))#显示更大范围的图片(正常重映射之后会删掉一部分图像)# 纠正畸变
dst = cv2.undistort(img, mtx, dist, None, newcameramtx)# 这步只是输出纠正畸变以后的图片
x, y, w, h = roi
dst = dst[y:y + h, x:x + w]
cv2.imwrite('calibresult.png', dst)# 打印我们要求的两个矩阵参数
"""参数newcameramtx为内参数矩阵,
dist为畸变系数,total error为总体误差。
newcameramtx:
归一化焦距fx=1.25045215e+03,fy=7.76162048e+02,
像主点(光心)的坐标cx=1.48972123e+03,cy=1.31742293e+03。
所有图像投影坐标和亚像素角点坐标之间的总体的平均误差大概为0.10,误差较小,标定结果不错"""print("内参数矩阵,newcameramtx  :\n", newcameramtx)
print("归一化焦距fx,fy=",newcameramtx[0][0],newcameramtx[1][1])
print("像主点(光心)的坐标cx,cy",newcameramtx[0][2],newcameramtx[1][2])
print("dist为畸变系数。dist:\n", dist)
print("ret:\n",ret)
print("mtx,相机内参:\n",mtx)
print("revcs,旋转矩阵,",rvecs)
print("tvecs,平移矩阵",tvecs)
# mtx,相机内参;dist,畸变系数;外参数:revcs,旋转矩阵;tvecs,平移矩阵
# 计算误差
tot_error = 0
for i in xrange(len(objpoints)):imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)error = cv2.norm(imgpoints[i], imgpoints2, cv2.NORM_L2) / len(imgpoints2)tot_error += error
print("total error为总体误差: ", tot_error / len(objpoints))

http://chatgpt.dhexx.cn/article/s7sAQZU0.shtml

相关文章

相机标定——张氏标定法

目录 前言动机为什么要进行相机标定什么是张氏标定法 张氏标定法的原理透镜成像原理世界坐标系到相机坐标系的转换相机坐标系到图像坐标系的转换图像坐标系到像素坐标系单应性矩阵内参求解外参求解Matlab实操 前言 动机 前段时间在整机械臂的手眼标定,也就是标定3D…

相机标定系列(三)利用matlab进行相机标定

相机标定系列(三)利用matlab进行相机标定 文章目录 相机标定系列(三)利用matlab进行相机标定前言一、棋盘格图像的采集二、单目相机标定三、双目相机标定 前言 matlab的应用程序中含有对双目相机和单目相机的标定工具箱&#xff…

机器视觉——相机标定

1 机器视觉为什么要做相机标定 机器视觉是采用相机成像来实现对三维场景的测量、定位、重建等过程。是一个利用二维图像进行三维反推的过程,我们所处的世界是三维的,而图像或者照片是二维的,可以把相机认为是一个函数,输入量是一…

相机标定篇——相机标定

认为相机标定是三维重建的核心,研究生期间主要方向为结构光三维重建 必要的数学知识 线性方程求解 Gauss消元法;LU分解;Cholesky分解 最小二乘问题-线性方法 特征值分解;奇异值分解;超定线性方程;最小二乘…

【相机标定】相机内参

相机标定 相机在计算机视觉方面的一些应用一般需要相机标定。我们总是听到标定这个词,那么具体标定的是什么呢?相机的拍摄是一个三维到二维(透视投影)的过程,这个过程可以用数学模型去表述,标定便是计算这…

什么是相机标定

1. 相机标定的定义及作用 相机标定是指借助标定板来计算单个或多个相机的内参、外参和镜头畸变参数。 作用: 将畸变的图像恢复为正常的图像,为后续进行拼接、SLAM等奠定基础。 多相机标定可以将所有相机输出变换到同一个坐标系。 相机标定是三维视觉…

相机标定究竟在标定什么?

点击上方“小白学视觉”,选择加"星标"或“置顶” 重磅干货,第一时间送达 相机标定可以说是计算机视觉/机器视觉的基础,但是初学者不易上手,本文将给读者整理一遍相机标定的逻辑,并在文末回答评论区提出的问题…

相机标定(Camera calibration)

简介 摄像机标定(Camera calibration)简单来说是从世界坐标系换到图像坐标系的过程,也就是求最终的投影矩阵 P P P 的过程,下面相关的部分主要参考UIUC的计算机视觉的课件(网址Spring 2016 CS543 / ECE549 Computer vision)。 …

相机参数标定(camera calibration)及标定结果如何使用

重要更新:本文的第二次更新已发布。为了不破坏现有内容的结构,故重新开始新的一篇文章。同时本文的一些内容也会涵盖进去。 欢迎关注。 《第二更,相机参数标定基础:从小孔成像开始到单双目标定》 关于实践部分,可参…

相机标定详解

内参、外参、畸变参数三种参数与相机的标定方法与相机坐标系的理解 相机标定(Camera calibration)原理、步骤 相机标定详解 最近做项目要用到标定,因为是小白,很多东西都不懂,于是查了一堆的博客,但没有…

相机标定-机器视觉基础(理论推导、Halcon和OpenCV相机标定)

相机标定是获得目标工件精准坐标信息的基础。首先,必须进行相机内参标定,构建一个模型消除图像畸变;其次,需要对相机和机器人的映射关系进行手眼标定,构建一个模型将图像坐标系上的点映射到世界坐标系。主要分为背景知…

计算机视觉——相机标定

相机标定 1. 相机标定1.1相机内外参数(重点)1.2 为什么要做相机标定 2. 相机标定的意义3. 相机成像模型3.1 像素坐标系3.2 图像坐标系3.3 相机坐标系3.4 世界坐标系 4.坐标系转换4.1 世界坐标到相机坐标4.2 相机坐标到图像坐标4.3 像素坐标到世界坐标的变…

相机标定、双目相机标定(原理)、三维重建效果展示

1.相机标定的目的: (1)通过单目相机标定分别求出左右相机的内参数和外参数。 (2)矫正由于镜头畸变造成的图片的变形,例如,现实中的直线,拍摄成图像后会外凸或内凹,进行相…

相机标定(Camera calibration)原理及步骤

这已经是我第三次找资料看关于相机标定的原理和步骤,以及如何用几何模型,我想十分有必要留下这些资料备以后使用。这属于笔记总结。 1.为什么要相机标定? 在图像测量过程以及机器视觉应用中,为确定空间物体表面某点的三维几何位置…

计算机视觉—— 相机标定

目录 简介 一、相机模型 1.坐标系 2.坐标系变化 3.相机畸变模型 二、相机标定原理 三、张正友黑白棋盘格标定 2.1.算法思想 2.2.求解内参和外参的积 2.3.求解内参矩阵 2.4.求解外参矩阵 2.5.得到相机畸变矫正参数 2.6.L-M算法参数优化 三、实验 3.1 实验要求…

相机标定的原理及实现

本文参考文档: 原理部分:https://blog.csdn.net/honyniu/article/details/51004397 代码部分:https://www.cnblogs.com/wildbloom/p/8320351.html ;https://blog.csdn.net/firemicrocosm/article/details/48594897# 1、相机标定的…

计算机视觉-相机标定(Camera Calibration)

1.相机标定基本原理 1.1 简介 在图像测量过程以及机器视觉应用中,为确定空间物体表面某点的三维几何位置与其在图像中对应点之间的相互关系,必须建立摄像机成像的几何模型,这些几何模型参数就是摄像机参数。在大多数条件下这些参数必须通过实验与计算才…

相机标定(Camera calibration)原理、步骤

这已经是我第三次找资料看关于相机标定的原理和步骤,以及如何用几何模型,我想十分有必要留下这些资料备以后使用。这属于笔记总结。 1.为什么要相机标定? 在图像测量过程以及机器视觉应用中,为确定空间物体表面某点的三维几何位置…

采用Matlab的Filter Designer设计低通滤波器并对信号进行低通滤波

今天在使用Filter Designer设计低通滤波器进行低通滤波发现滤波总是得不到理想中的结果,经过一番折腾后终于解决了问题,特写博文供大家学习参考。 1、找到工具箱中的Filter Designer并打开: 2、按照如下图所示设计参数,注意Fs最好…

利用Matlab filterDesigner 工具生成FIR滤波器函数,并调用实现低通滤波

本文使用的开发环境为:Win10 Matlab2018a 版本。 在matlab命令窗口输入:filterDesigner命令,即可打开filterDesigner设计工具。 按照下图调整FIR低通滤波器的参数: 我们设计的是采样频率100Hz,截止频率10Hz的8阶FIR低…