一.原理:

1.四个坐标系:

世界坐标系、相机坐标系、像素坐标系、成像平面坐标系。
我们可以把现实生活遇到的任何事物用坐标系表示出来,也可以用坐标系表示整个世界,于是便建立起了世界坐标系。想象一下,摄像机拍摄的是一张二维图片,因此整个摄像机可以用一个坐标系去标识它获取到的某个物体的位置,这是相机坐标系。像素坐标系就是相片的坐标系。成像平面坐标系类似于像素坐标系。
原本我们期望的拍摄效果:是每个坐标系中的像素都相互对应,类似于一种一元一次方程,但由于镜头或者其他关系,现在这条“直线”弯了,得到的图像也会出现“弯曲”,因此我们需要把它矫正。

2.相机参数

相机都有不同的内部参数、外部参数;

内部参数:有一个参数矩阵(fx,fy,cx,cy)和一个畸变系数(三个径向k1,k2,k3;两个切向p1,p2);内部参数是唯一的,就是一部相机只有一组内部参数。
相机将场景中的三维点变换为图像中的二维点,也就是各个坐标系变换的组合,可将变换过程整理为矩阵相乘的形式:

3.标定结束

标定完成后,你会得到标定的内部参数,标定完之后就可以直接用内参数和畸变参数得到畸变校正图像。接下来就可以使用OpenCV了,即用内参数和畸变参数作为initUndistortRectifyMap()函数的输入,得到原图像与畸变校正图像的x,y坐标映射关系,即两个变换矩阵。再以这两个变换矩阵作为remap()函数的输入,得到畸变校正图像。

二.步骤:

  1. 准备一张打印好的棋盘格,对棋盘格进行不同角度的拍摄,10-20张图片为宜;
  2. 对每张图片提取角点信息;
  3. 在图片中画出提取出的角点;
  4. 相机标定;
  5. 对标定结果评价,计算误差;
  6. 使用标定结果对原图片进行矫正;

三.数据采集:

四.相机标定

4.1 角点提取

(获取角点两个坐标系下的坐标,作为求解方程中的已知量)

首先,基于cv2.findChessboardCorners寻找棋盘格角点:

# 定位角点
def find_chessboard_cor(img):# 转为灰度图gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# OpenCV内置函数提取棋盘格角点, (11,8)为棋盘格尺寸-1(12x9)is_success, corner = cv2.findChessboardCorners(gray_img, (11,8), None)# 计算亚像素时停止迭代的标准# 后者表示迭代次数达到了最大次数时停止,前者表示角点位置变化的最小值已经达到最小时停止迭代criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.001)# 亚像素角点检测,提高角点定位精度, (7, 7)为考虑角点周围区域的大小corner = cv2.cornerSubPix(gray_img, corner, (7, 7), (-1, -1), criteria) return is_success, corner

值得注意的是,这里我们必须使用cv2.cornerSubPix再进行一次迭代定位亚像素角点,使得角点的定位更为精确。

基于cv2.drawChessboardCorners可视化棋盘格角点:

# 可视化角点
def draw_chessboard_cor(img, cor, is_success):cv2.drawChessboardCorners(img, (11,8), cor, is_success)cv2.imshow('cor', img)cv2.waitKey(50)

OpenCV提取棋盘角点可视化:

别忘了我们提取了棋盘格角点坐标的目的:这一步是为了获取角点在图像坐标系中的坐标。为了求解相机内外参矩阵,紧接着我们还需要获取棋盘格在原始世界坐标系中的坐标。

值得一提的是,无论是固定相机移动棋盘格进行拍摄,还是固定棋盘格移动相机进行拍摄,在张正友标定法的假设中,棋盘格永远处在世界坐标系Z=0的平面上,棋盘格最左上角的角点为世界坐标系原点,往右为x轴正方向,往下为y轴正方向:

由于同一张标定板的规格不会改变,因此,世界坐标系通过人为定义即可:

# 注:相机参数的计算只要求角点之间的世界坐标比例一致,因此可以单位化
        world_coord = np.zeros((w * h, 3), np.float32)
        world_coord[:, :2] = np.mgrid[0:w, 0:h].T.reshape(-1, 2)

世界坐标(单位化):[[ 0. 0. 0.]
[ 1. 0. 0.]
[ 2. 0. 0.]
[ 3. 0. 0.]
[ 4. 0. 0.]
[ 5. 0. 0.]
[ 6. 0. 0.]
[ 7. 0. 0.]… …]]shape = (88, 3) # 每个棋盘格上提取11*8=88个角点

4.2 参数求解

# 求解摄像机的内在参数和外在参数
    # ret 非0表示标定成功 mtx 内参数矩阵,dist 畸变系数,rvecs 旋转向量,tvecs 平移向量
    # 注:求解的结果的单位为像素,若想化为度量单位还需乘上每个像素代表的实际尺寸(如:毫米/像素)


# 求解内外参数
def CamCalibrate(w, h, num, root):# 图像缩放比例(如果你的图像进行了缩放,与实际拍摄的分辨率不一致,最终求得的参数需要乘上这个比例进行校正)ratio = 1 # 3648 / 1920   world, cam = [], []# 多张图像进行标定,减小误差:for i in range(num):img = cv2.imread(root + str(i+1)+'.jpg')# img,_,_ = utils.auto_reshape(img, 1920)# 定位角点is_success, cam_coord = find_chessboard_cor(img)print('第'+str(i+1)+'张角点提取完毕, 角点数 =',cam_coord.shape[0])# 可视化角点# draw_chessboard_cor(img, cam_coord, is_success)# 角点的世界坐标:# 注:相机参数的计算只要求角点之间的世界坐标比例一致,因此可以单位化world_coord = np.zeros((w * h, 3), np.float32)world_coord[:, :2] = np.mgrid[0:w, 0:h].T.reshape(-1, 2)world_coord[:,1] = -world_coord[:,1]# world_coord[:,:2] = np.mgrid[0:w*len:len,0:h*len:len].T.reshape(-1,2)# 将世界坐标与像素坐标加入待求解系数矩阵world.append(world_coord)cam.append(cam_coord)# 求解摄像机的内在参数和外在参数# ret 非0表示标定成功 mtx 内参数矩阵,dist 畸变系数,rvecs 旋转向量,tvecs 平移向量# 注:求解的结果的单位为像素,若想化为度量单位还需乘上每个像素代表的实际尺寸(如:毫米/像素)ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(world, cam, (img.shape[1], img.shape[0]), None, None)rvecs = np.array(rvecs).reshape(-1,3)tvecs = np.array(tvecs).reshape(-1,3)# 单位:像素(1像素=??mm)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)  # 平移向量  # 外参数np.save('./param/mtx.npy',mtx)np.save('./param/dist.npy',dist)np.save('./param/rvecs.npy',rvecs)np.save('./param/tvecs.npy',tvecs)np.save('./param/world.npy',np.array(world))np.save('./param/cam.npy',np.array(cam))return ret, mtx, dist, rvecs, tvecs

4.3 结果

标定结果 ret: 1.4146770040984205
内参矩阵 mtx:
[[2.88760072e+03 0.00000000e+00 1.82151647e+03]
[0.00000000e+00 2.88741538e+03 1.37233666e+03]
[0.00000000e+00 0.00000000e+00 1.00000000e+00]]
畸变系数 dist:
[[ 0.01488259 0.03388964 -0.00044845 -0.00178608 0.03024054]]
旋转向量(外参) rvecs:
[[ 2.77705978 -0.46989843 0.1686412 ]
[-2.8145649 -0.91512141 -0.43737601]
… …
[ 2.67447733 0.66658815 -0.11254641]
[ 2.818184 -0.02291704 0.51413859]]
平移向量(外参) tvecs:
[[-5.06957615 -2.43006408 16.33928058]
[ 0.29829902 -4.17287918 13.05665933]
… …
[-3.8811355 -4.39040007 19.95916291]
[-4.53034049 -4.16521408 14.12011733]]

【计算机视觉4】相机标定相关推荐

  1. 计算机视觉(相机标定)-1.1-针孔摄像机透镜

    计算机视觉(相机标定)-1.1-针孔摄像机&透镜 学习前言 一.针孔摄像机  1.基本想法  2.实现原理  3.针孔摄像机模型(重点) 二.透镜  1.为什么需要透镜  2.加入透镜后的模型 ...

  2. 计算机视觉(相机标定)-2.1 摄像机标定

    计算机视觉(相机标定)- 2.1 摄像机标定 学习前言 一. 摄像机标定是啥?为什么要进行摄像机标定? 二.求MMM 问题一:求解投影矩阵需要多少对应点? 问题二:怎么算? 二.求MMM中的摄像机的内 ...

  3. 【计算机视觉】相机标定原理(像素点与三维坐标点的转换)

    一.相机标定概述 相机标定目的 计算机视觉的任务之一:从相机获取的图像信息出发计算三维空间中物体的几何信息,并由此重建和识别物体. 相机标定内容 空间物体表面某点的三维几何位置与其在图像中对应点之间的 ...

  4. 计算机视觉(相机标定;内参;外参;畸变系数)

    目录 一.预备知识 1.坐标系变换过程(相机成像过程) (1)相机坐标系转换为图像坐标系(透视投影变换遵循的是针孔成像原理) (2)齐次坐标的引入原因:(为什么引入齐次坐标???) 2.内参与外参矩阵 ...

  5. 【计算机视觉】相机标定

    目录 一.物理模型 1.引入库 2.透视投影模型 3.主点偏移 4.图像传感器特性 5.径向畸变 6.相机外参 二.模型求解 1.内参和单应矩阵关系 三.matlab求相机参数 1.应用程序中找到Ca ...

  6. Python计算机视觉之相机标定

    目录 一.介绍 1.1 概念 1.2 目的 1.3 意义 二.图像畸变 2.1 概念 2.2 常见问题 2.3 常见类型 2.4 影响因素 三.方法 3.1 传统相机标定法 3.2 相机自标定法 3. ...

  7. 从像素坐标到相机坐标_相机标定方法

    在图像测量过程以及机器视觉应用中,为确定空间物体表面某点的三维几何位置与其在图像中对应点之间的相互关系,必须建立相机成像的几何模型,这些几何模型参数就是相机参数.在大多数条件下这些参数(内参.外参.畸 ...

  8. matlab相机标定_综述 | 相机标定方法

    点击上方"计算机视觉life",选择"星标" 快速获得最新干货 在图像测量过程以及机器视觉应用中,为确定空间物体表面某点的三维几何位置与其在图像中对应点之间的相 ...

  9. 2022.3.17 关于镜头标称焦距和相机标定的焦距的差异

    2022.3.17 关于镜头标称焦距和相机标定的焦距的差异 来源 https://jah10527.github.io/articles/about_focol_length.html 有些日子没聊点 ...

  10. python相机标定流程图_相机标定——OpenCV-Python Tutorials

    目标 我们将了解导致相机失真.扭曲的内因与外因 我们将试着找到这些畸变参数,并消除畸变 基础 如今大量廉价的摄像机导致了很多照片畸变.两个主要的畸变是径向畸变和切向畸变. 由于径向畸变,直线会变弯.距 ...

最新文章

  1. js如何判断一个对象是不是Array?
  2. SpringMVC+ZTree实现树形菜单权限配置
  3. 技术部门 Leader 与团队那些事
  4. 北斗导航 | NB-IoT——了解什么是NB-IoT,与短报文有什么关系
  5. 算法系列之赫夫曼树的精解【构造流程及原理分析】
  6. docker学习笔记(一)docker入门
  7. pcb过孔与电流对照一览表_PCB设计项目能不能成功,这个因素占了30%
  8. oracle数据库迁移 增大空间,Oracle数据库迁移、创建表空间、创建数据表实例讲解-Oracle...
  9. Java IO: InputStreamReader和OutputStreamWriter
  10. IDEA集成Scala图文教程详细步骤
  11. jsoup爬虫简书首页数据做个小Demo
  12. [BZOJ] 1614: [Usaco2007 Jan]Telephone Lines架设电话线
  13. 数组玩法(1):下标移位
  14. ARVR技术 | AR, VR, MR和XR?想搞清楚不?
  15. 服务器维护 灵魂兽,魔兽怀旧服:没有灵魂兽的猎人还厉害吗?还有这些宠物撑场子...
  16. LATEX之对文章排版的相关设置
  17. 【英语学习】【WOTD】hamartia 释义/词源/示例
  18. hadoop2.7.2下载
  19. 《图形图像处理》— 使用matlab对图像进行二值化和灰度化处理
  20. numpy .npz文件处理

热门文章

  1. MySQL 学习资源整理
  2. google地图api之简单轨迹(四)
  3. Kali 局域网 DNS 劫持
  4. drupal安装教程mysql_Drupal8 安装教程
  5. 2021年施工升降机司机模拟考试题库-百分百安全生产模拟考试平台
  6. set集合,深浅拷贝
  7. Python3网络设备巡检(交换机篇)
  8. JS的使用之列表操作
  9. FB推出App Center背后的秘密
  10. java jsonobject 转义字符_JSONObject包含转义字符