照相机标定

一.相机标定的原理

1.1 相机如何成像:

相机成像系统中,共包含四个坐标系:世界坐标系、相机坐标系、图像坐标系、像素坐标系。

1.1.1 世界坐标系:
世界坐标系(world coordinate),也称为测量坐标系,是一个三维直角坐标系,以其为基准可以描述相机和待测物体的空间位置。世界坐标系的位置可以根据实际情况自由确定。

1.1.2 相机坐标系:
相机坐标系(camera coordinate),也是一个三维直角坐标系,原点位于镜头光心处,x、y轴分别与相面的两边平行,z轴为镜头光轴,与像平面垂直
1.1.3 像素坐标系、图像坐标系:

像素坐标系(pixel coordinate)
如上图,像素坐标系是一个二维直角坐标系,反映了相机CCD/CMOS芯片中像素的排列情况。原点位于图像的左上角,轴、轴分别于像面的两边平行。像素坐标系中坐标轴的单位是像素(整数)。

像素坐标系不利于坐标变换,因此需要建立图像坐标系,其坐标轴的单位通常为毫米(mm),原点是相机光轴与相面的交点(称为主点),即图像的中心点,轴、轴分别与轴、轴平行。故两个坐标系实际是平移关系,即可以通过平移就可得到。

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

标定相机后通常是想做两件事:一个是由于每个镜头的畸变程度各不相同,通过相机标定可以校正这种镜头畸变矫正畸变,生成矫正后的图像;另一个是根据获得的图像重构三维场景。

1.2 相机标定的总体原理:
摄像机标定(Camera calibraTIon)简单来说就是从世界坐标系换到图像坐标系的过程,也就是求最终的投影矩阵的过程。

二.相机标定步骤

1)、准备一个张正友标定法的棋盘格,棋盘格大小已知,用相机对其进行不同角度的拍摄,得到一组图像;

2)、对图像中的特征点如标定板角点进行检测,得到标定板角点的像素坐标值,根据已知的棋盘格大小和世界坐标系原点,计算得到标定板角点的物理坐标值;

3)、求解内参矩阵与外参矩阵。

根据物理坐标值和像素坐标值的关系,求出 H 矩阵,进而构造 V 矩阵,求解 B 矩阵,利用B矩阵求解相机内参矩阵 A ,最后求解每张图片对应的相机外参矩阵 :

4)、求解畸变参数。

构造 D 矩阵,计算径向畸变参数;

5)、利用L-M(Levenberg-Marquardt)算法对上述参数进行优化

三、实现
3.1 数据准备

对标定板在不同角度拍照,得到10张图片。得到如下类似的图片。

3.2 代码(Python+OpenCV)

import cv2
import numpy as np
import glob

# 设置寻找亚像素角点的参数,采用的停止准则是最大循环次数30和最大误差容限0.001
criteria = (cv2.TERM_CRITERIA_MAX_ITER | cv2.TERM_CRITERIA_EPS, 30, 0.001)

# 获取标定板角点的位置
objp = np.zeros((4 * 4, 3), np.float32)
objp[:, :2] = np.mgrid[0:4, 0:4].T.reshape(-1, 2)  # 将世界坐标系建在标定板上,所有点的Z坐标全部为0,所以只需要赋值x和y

obj_points = []  # 存储3D点
img_points = []  # 存储2D点

images = glob.glob(r"D:\software\pycharm\PycharmProjects\computer-version\biaoding\images\*.jpg")
i = 0
for fname in images:
    img = cv2.imread(fname)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    size = gray.shape[::-1]
    ret, corners = cv2.findChessboardCorners(gray, (4, 4), None)
    # print(corners)

    if ret:

        obj_points.append(objp)

        corners2 = cv2.cornerSubPix(gray, corners, (5, 5), (-1, -1), criteria)  # 在原角点的基础上寻找亚像素角点
        # print(corners2)
        if [corners2]:
            img_points.append(corners2)
        else:
            img_points.append(corners)

        cv2.drawChessboardCorners(img, (4, 4), corners, ret)  # 记住,OpenCV的绘制函数一般无返回值
        i += 1
        cv2.imwrite('conimg' + str(i) + '.jpg', img)
        cv2.waitKey(1500)

print(len(img_points))
cv2.destroyAllWindows()

# 标定
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, size, None, None)

print("内参数矩阵:\n", mtx)  # 内参数矩阵
print("畸变系数:\n", dist)  # 畸变系数   distortion cofficients = (k_1,k_2,p_1,p_2,k_3)
print("旋转向量:\n", rvecs)  # 旋转向量  # 外参数
print("平移向量:\n", tvecs)  # 平移向量  # 外参数

print("-----------------------------------------------------")

img = cv2.imread(images[2])
h, w = img.shape[:2]
# 获取新的相机矩阵和ROI
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('undistorted.jpg', dst)
print("校正后的图片已保存到文件 'undistorted.jpg'")

结果如下:

D:\software\anaconda3\envs\homework\python.exe D:\software\pycharm\PycharmProjects\computer-version\biaoding\biaoding.py 
10
内参数矩阵:
 [[2.96560599e+04 0.00000000e+00 1.14649373e+03]
 [0.00000000e+00 2.27193976e+04 2.23086118e+03]
 [0.00000000e+00 0.00000000e+00 1.00000000e+00]]
畸变系数:
 [[-2.89172774e+00 -7.08266723e+02 -8.71069820e-02  9.23282091e-03
   2.69077473e+04]]
旋转向量:
 (array([[ 0.00393121],
       [-0.55572922],
       [ 0.00146949]]), array([[-0.24713914],
       [-0.62161368],
       [ 1.12164248]]), array([[0.03655035],
       [0.72426273],
       [0.58207192]]), array([[ 0.03267646],
       [-0.81493845],
       [ 0.33111165]]), array([[ 0.10136185],
       [-0.8188412 ],
       [ 0.0126507 ]]), array([[ 0.07815116],
       [-0.45667052],
       [ 0.04574239]]), array([[-0.06538785],
       [-0.45146705],
       [ 0.29559633]]), array([[0.19950015],
       [0.59439631],
       [1.05909245]]), array([[-0.61847323],
       [-0.65382223],
       [ 1.44780297]]), array([[-0.56075885],
       [-0.65910126],
       [ 1.21835979]]))
平移向量:
 (array([[-1.88349377],
       [-2.34826569],
       [79.07381781]]), array([[-3.71964945e-03],
       [-2.09696872e+00],
       [ 9.57830776e+01]]), array([[  2.82236969],
       [-10.16609008],
       [105.50710577]]), array([[  2.4498244 ],
       [ -9.91592803],
       [113.69245822]]), array([[  1.94032193],
       [ -9.41660327],
       [118.34213194]]), array([[  3.29323168],
       [-10.37799624],
       [150.0005035 ]]), array([[  1.90004234],
       [ -9.89181093],
       [136.81120801]]), array([[  3.81109485],
       [ -9.80118203],
       [131.55206487]]), array([[  0.12140321],
       [ -3.0523607 ],
       [114.3591686 ]]), array([[ 0.17173674],
       [-2.75540486],
       [80.26443015]]))
-----------------------------------------------------
校正后的图片已保存到文件 'undistorted.jpg'

Process finished with exit code 0

畸变矫正前的图像:

畸变矫正后的图像:

分析:

运行程序,成功的实现了自己手机参数的标定,计算出了照相机的内部参数和外部参数。通过此次实验让我进一步了解了张正友标定法的奇妙之处。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/23806.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Cobalt Strike工具基本使用

Cobalt Strike 安装启动启动server端启动client目标机器连接 工具基使用用户驱动攻击屏幕截图进程列表键盘记录文件管理远程vnc远程代理端口扫描 生成后门被攻击者运行后门文件后查看结果 钓鱼攻击信息收集网站克隆文件下载 安装 网盘地址:链接:https:/…

PyG的Planetoid无法直接下载Cora等数据集的解决方法

问题描述: 在使用PyG的时候,通常会涉及到一些公共数据集的下载,由于网络问题,导致无法下载出现以下问题: 尝试了很多的方法都没有成功(主要是个人比较菜!)。但是皇天不负有心人&am…

文心一言和ChatGPT最全对比

文心一言和ChatGPT都是基于深度学习技术的自然语言处理模型,有各自的优势和使用场景,无法简单地比较 ChatGPT 和文心一言哪一个功能更强大,它们各自具有优势和局限性,需要根据具体需求进行选择,以下一些具体对比&#…

分布式网络通信框架(十)——Mprpc框架使用示例

发布一个服务提供远程调用方法的流程 若想要发布一个服务提供一些远程调用方法,步骤如下: 先在protobuf文件中添加参数和返回值的message 类型,然后再添加希望提供的服务 service 类型(如UserServiceRpc)和 其中的方…

C++内存管理和模板

文章目录 内存管理new和delete 函数模板隐式实例化显式实例化 类模板 内存管理 有时候我们需要动态的申请内存,比如队列,栈,二叉树等数据结构,我们一开始并不知道要存储多少个数据,也就是不确定究竟要多大的内存,给小了存不下,给大了会造成内存资源的浪费,因此动态的申请内存是…

原工程运行正常,重新复制一份后再 npm install 后再运行就报错的解决办法

原工程,运行正常 将刚刚的工程复制一份呢,重新 npm install 再 npm run serve 就报错 出现这个问题十之八九都是依赖的问题。有可能是因为这个工程里面之前安装过一些东西,后来莫名其妙的就把 package.json 里面相关的依赖给删掉了。但由于原…

【数据结构】顺序二叉树的实现—以堆的实现为例、堆的调整、堆的创建、堆的插入和删除、堆排序

文章目录 1.堆的概念及结构2.堆的实现(以大堆为例)2.1堆的插入2.1.1堆的向上调整算法 2.2堆的删除2.2.1堆的向下调整算法 2.3堆的创建2.4有关建堆的时间复杂度 3.堆排序4.C语言堆实现源码 1.堆的概念及结构 堆就是顺序结构二叉树。 如果有一个关键码的集…

jetcache参考文档

jetcache简介 https://github.com/alibaba/jetcache/blob/master/docs/CN/GettingStarted.md 简介 JetCache是一个基于Java的缓存系统封装,提供统一的API和注解来简化缓存的使用。 JetCache提供了比SpringCache更加强大的注解,可以原生的支持TTL、两级…

shell变量类型含义 长方形面积计算 截取相应字段方法

1.总结变量的类型及含义? 2.实现课堂案例计算长方形面积?(6种方式) 3.定义变量urlhttps://blog.csdn.net/weixin_45029822/article/details/103568815(通过多种方法实现) 1)截取网站访问的协议 …

文心一言 VS 讯飞星火 VS chatgpt (22)-- 算法导论4.2 2题

二、为Strassen算法编写伪代码。 文心一言: Strassen算法是一种用于矩阵乘法的算法,它的核心思想是通过不断将原始矩阵分割成较小的子矩阵来实现高效的乘法运算。以下是Strassen算法的伪代码: function Strassen(A, B): if A[0][0] 0 or…

Springboot整合WebSocket

目录 1.WebSocket 简介 2.WebSocket 实战 1.WebSocket 简介 WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要…

基于html+css的图展示98

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

C++入门

文章目录 😀1. 命名空间😄1.1 命名空间定义😄1.2 命名空间使用 😊2. 输入和输出😉3. 缺省参数🫠3.1 缺省参数概念🫠3.2 缺省参数分类 😬4. 函数重载🙄4.1 函数重载概念&a…

TypeScript9-声明文件

本篇文章来讲 TypeScript 的声明文件。 当我们在使用第三方库的时候,很多第三方库不是用 TS 写的,它们是通过原生的 JavaScript 或者是浏览器 / 或者是 node 提供的 run time 对象。如果我们直接使用 TS 肯定就会报编译不通过。 1. 声明语句 假设一个…

浅析变电站无人值守管理的模式与特点

安科瑞虞佳豪 近年来,随着电网的发展,变电站实行无人值班管理模式已成为电网的发展方向。自1998年始,辉县市就开始了变电站综合自动化改造,截止目前全局所属24座变电站(其中35kV19座、110kV5座)已全部实现…

API自动化测试【postman生成报告】

PostMan生成测试报告有两种: 1、控制台的模式 2、HTML的测试报告 使用到一个工具newman Node.js是前端的一个组件,主要可以使用它来开发异步的程序。 一、控制台的模式 1、安装node.js 双击node.js进行安装,安装成功后在控制台输入node …

Java集合基础

4 集合基础 集合提供一种存储空间可变的存储模型,存储的数据容量可以改变ArrayLis<>: 可调整大小的数组实现<>:是一种特殊的数据类型,泛型可储存重复元素怎么使用呢 在出现E的地方我们使用引用数据类型替换即可举例:ArrayList<String>、ArrayList<Stu…

财务共享时代企业数智化应用能帮我们做些什么?

随着企业规模的不断扩大和业务范围的逐步扩展&#xff0c;财务工作的难度和复杂度也在不断提高&#xff0c;传统的手工录入和处理方式呈现出流程长、效率低、易出错等问题。为了提升财务工作的效率和准确性&#xff0c;越来越多的企业开始利用数智化应用打造企业内部的财务数智…

绝对不能错过的7个零基础免费的ChatGPT镜像网站

还在为打不开openai官网烦心&#xff1f;本文帮你实现ChatGPTMidJourney自由(&#xffe3;∇&#xffe3;)/ &#x1f4d2;收集了一些截至目前(2023年5月25日午12:00)可以免费访问&#xff0c;并且零基础也能正常使用的镜像网站&#xff0c;后续将持续维护更新(&#xff61;&a…

平安银行广州分行立足地域文化,增强差异化权益服务软实力

立足地域文化&#xff0c;拓展差异化权益服务 瓦屋纸窗之下&#xff0c;一盏清茶&#xff0c;三五好友&#xff0c;怡然自若。中国人对茶的喜爱由来已久&#xff0c;茶文化已成为中华传统文化中一张亮丽的名片&#xff0c;而广东茶文化则是中国四大茶文化系列之一。平安银行广州…