相机标定的原理及实现

相机标定的原理及实现本文参考文档:原理部分: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、相机标定的原理摄像…

大家好,又见面了,我是你们的朋友全栈君。

本文参考文档:
原理部分:https://blog.csdn.net/honyniu/article/details/51004397
代码部分:https://www.cnblogs.com/wildbloom/p/8320351.htmlhttps://blog.csdn.net/firemicrocosm/article/details/48594897#

1、相机标定的原理

摄像机标定(Camera calibration)简单来说是从世界坐标系转换为相机坐标系,再由相机坐标系转换为图像坐标系的过程,也就是求最终的投影矩阵P的过程。

世界坐标系(world coordinate system):用户定义的三维世界的坐标系,为了描述目标物在真实世界里的位置而被引入。单位为m。

相机坐标系(camera coordinate system):在相机上建立的坐标系,为了从相机的角度描述物体位置而定义,作为沟通世界坐标系和图像/像素坐标系的中间一环。单位为m。

图像坐标系(image coordinate system):为了描述成像过程中物体从相机坐标系到图像坐标系的投影透射关系而引入,方便进一步得到像素坐标系下的坐标。 单位为m。

从世界坐标系到相机坐标系:

这一步是三维点到三维点的转换,包括R,t(相机外参)等参数;
在这里插入图片描述

相机坐标系转换为图像坐标系:

这一步是三维点到二维点的转换,包括K(相机内参)等参数;在这里插入图片描述
在这里插入图片描述
根据上述的关系图可以推导出下面的变换公式:
在这里插入图片描述在这里插入图片描述

像主点的偏移:

在这里插入图片描述
可以推出:
在这里插入图片描述

内参矩阵K:

在这里插入图片描述

外参矩阵[R丨t]:

表示三个方向的偏转:
在这里插入图片描述

投影矩阵P

(在这里可以认为旋转矩阵 R 为单位矩阵 I,平移矩阵 t 都为0):
在这里插入图片描述
根据上述变换最终可以得到一个投影矩阵P的公式为:
在这里插入图片描述
总结一下公式大致如下:
在这里插入图片描述

畸变参数

在几何光学和阴极射线管显示中,畸变是对直线投影的一种偏移。简单来说直线投影是场景内的一条直线投影到图片上也保持为一条直线。那畸变简单来说就是一条直线投影到图片上不能保持为一条直线了,这是一种光学畸变。畸变一般可以分为两大类,包括径向畸变和切向畸变。主要的一般径向畸变有时也会有轻微的切向畸变。

2、相机标定的实现

相机标定的目的:获取摄像机的内参和外参矩阵(同时也会得到每一幅标定图像的选择和平移矩阵),内参和外参系数可以对之后相机拍摄的图像就进行矫正,得到畸变相对很小的图像。

相机标定的输入:标定图像上所有内角点的图像坐标,标定板图像上所有内角点的空间三维坐标(一般情况下假定图像位于Z=0平面上)。

相机标定的输出:摄像机的内参、外参系数。

这三个基础的问题就决定了使用Opencv实现张正友法标定相机的标定流程、标定结果评价以及使用标定结果矫正原始图像的完整流程:

  1. 准备标定图片
  2. 对每一张标定图片,提取角点信息
  3. 对每一张标定图片,进一步提取亚像素角点信息
  4. 在棋盘标定图上绘制找到的内角点(非必须,仅为了显示)
  5. 相机标定
  6. 对标定结果进行评价
  7. 查看标定效果——利用标定结果对棋盘图进行矫正

我准备的是下图这种格子数为7×5,内角点为6×4的棋盘格图片,手机型号为荣耀PLAY。
在这里插入图片描述
将它放在一个平面上从不同角度拍摄10张照片作为实验素材。
代码如下:

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 * 6, 3), np.float32)
objp[:, :2] = np.mgrid[0:6, 0:4].T.reshape(-1, 2)  # 将世界坐标系建在标定板上,所有点的Z坐标全部为0,所以只需要赋值x和y

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

images = glob.glob("image4/*.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, (6, 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, (6, 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("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 ) # 平移向量  # 外参数

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

img = cv2.imread(images[2])
h, w = img.shape[:2]
newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),1,(w,h))#显示更大范围的图片(正常重映射之后会删掉一部分图像)
print (newcameramtx)
print("------------------使用undistort函数-------------------")
dst = cv2.undistort(img,mtx,dist,None,newcameramtx)
x,y,w,h = roi
dst1 = dst[y:y+h,x:x+w]
cv2.imwrite('calibresult3.jpg', dst1)
print ("方法一:dst的大小为:", dst1.shape)

代码中的9、10、21、35行中的角点数根据自己的棋盘格大小进行更改。
实验分为两步,第一步主要是对每张图片进行角点的提取,结果如下:
在这里插入图片描述
第二步就是实现相机的标定,运行结果如下:

mtx为内参数矩阵,dist为畸变系数:
在这里插入图片描述
rvecs为旋转向量:
其中mtx为内参数矩阵,dist为畸变系数
tvecs为平移向量:
在这里插入图片描述
畸变矫正:
在这里插入图片描述
矫正前后的图片
在这里插入图片描述
在这里插入图片描述

总结

通过标定得到荣耀PLAY的后置摄像头的内置参数矩阵为:
在这里插入图片描述
矫正后的图和原图通过对比发现差距并不大,只是在宽度上有一点拉伸(肉眼能看出的差距只有图片右上角的白字因为图片的拉伸而消失了),原因应该是原图基本上没有出现明显的畸变。(应该是现在的手机相机比较厉害吧…)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/140209.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 项目活动图 – 举例说明

    项目活动图 – 举例说明关键路径:从开始到结束的所有路径中,时间最长的一条为关键路径。(特点:在关键路径上,所有任务的松弛时间都为0);松弛时间:第一种方法:最晚开始时间-最早开始时间;第二种方法:关键路径的总时间-包含该任务的任务路径花的时间;(前提条件:必须不影响该任务以后的任务路径)举例:关键路径:A-B-D-G-I-K-L=22由前向后推可得出…

    2022年5月13日
    47
  • 基于大数据平台的互联网数据采集平台架构介绍

    基于大数据平台的互联网数据采集平台架构介绍互联网的飞速发展将社会带入数据高度发达且公开的信息时代,数据对于企业经营、政府决策及社会动态分析等具有极其重要的作用,而如何大规模、快速采集数据成为技术焦点。网络爬虫是按照一定规则自动游走爬取互联网文本网页的程序或者脚本。文本数据大多嵌套于网页程序代码中。数据采集的效率直接决定数据的有效及时性,数据的快速采集成为重中之重。基于大数据平台的的互联网数据采集,可以有效适用于海量数据采集场景,为…

    2022年6月3日
    35
  • Odin Inspector 系列教程 — 常见问题解答(FAQ)

    Odin Inspector 系列教程 — 常见问题解答(FAQ)1.Odin多达约90种不同的特性,有可以快速预览每种特性的效果吗?可以选择Tools/OdinInspector/AttributeOverview进行快速预览,如果需要更详细的说明,可以查看主页革命性Unity编辑器扩展工具—OdinInspector系列教程,配合示例工程服用效果更佳2.可以禁用指定的Odin绘制特性吗?Odin…

    2022年7月21日
    19
  • RPC基本原理_基本原理是什么意思

    RPC基本原理_基本原理是什么意思RPC非常重要,很多人面试的时候都挂在了这个地方!你要是还不懂RPC是什么?他的基本原理是什么?你一定要把下边的内容记起来!好好研究一下!特别是文中给出的一张关于RPC的基本流程图,重点中的重点,Du

    2022年8月5日
    5
  • PS套索工具抠图及快捷键[通俗易懂]

    PS套索工具抠图及快捷键[通俗易懂]一、首先打开Photoshop,并打开一张所需的要抠图的文件,并按Ctrl+J复制一层二、套索工具在工具栏的上方,快捷键为L。鼠标点击工具栏选择套索工具,或按快捷键L选择,套索工具有三个子工具菜单,套索,多边形套索和磁性套索1.普通套索工具。这个工具时根据操作者控制鼠标的路径来选取选取的,且精度不易控制,完全靠制作者的手法来控制精度我们只要选择这个工具,然后按着鼠标左键开始跟着鼠标轨迹把选取描绘出来,最后松开鼠标,即可完成2.多边形套索工具。适合选取比较规则的几何图形首先点区图片要扣取的一

    2022年6月22日
    58
  • Linux 运行jar包命令[通俗易懂]

    Linux 运行jar包命令[通俗易懂]方式一:java-jarshareniu.jar特点:当前ssh窗口被锁定,可按CTRL+C打断程序运行,或直接关闭窗口,程序退出那如何让窗口不锁定?方式二java-jarshareniu.jar&&代表在后台运行。特定:当前ssh窗口不被锁定,但是当窗口关闭时,程序中止运行。继续改进,如何让窗口关闭时,程序仍然运行?方式三nohupj…

    2025年6月21日
    1

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号