相机标定

目录

  • 原理
  • 相机标定结果
  • 流程简介
  • 实验过程
  • 总结
  • 代码及调试问题

相机标定在机器人视觉和畸变校正上都是很关键的一部分,接下来用张正友相机标定法标定我的手机(Vivo xpaly5A)后置摄像头。

原理

首先先简单的了解一下相机标定的原理。
摄像机标定(Camera calibration)简单来说是从世界坐标系换到图像坐标系的过程,也就是求最终的投影矩阵 P 的过程。

一般来说,标定的过程分为两个部分:

  • 第一步是从世界坐标系转换为相机坐标系,这一步是三维点到三维点的转换,包括 R,t (相机外参)等参数;
  • 第二部是从相机坐标系转为图像坐标系,这一步是三维点到二维点的转换,包括 K(相机内参)等参数;
世界坐标系转换为相机坐标系


公式表达如下:

其中:

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


其中:

  • C C C 点表示camera centre,即相机的中心点,也是相机坐标系的中心点;

  • Z Z Z 轴表示principal axis,即相机的主轴;

  • p p p 点所在的平面表示image plane,即相机的像平面,也就是图片坐标系所在的二维平面;

  • p p p 点表示principal point,即主点,主轴与像平面相交的点;

  • C C C 点到 p p p 点的距离,也就是右边图中的 f f f 表示focal length,即相机的焦距;

  • 像平面上的 x x x 和 y y y 坐标轴是与相机坐标系上的 X X X 和 Y Y Y 坐标轴互相平行的;

  • 相机坐标系是以 X X X, Y Y Y, Z Z Z三个轴组成的且原点在 C C C 点,度量值为米(m);

  • 像平面坐标系是以 x x x, y y y(小写)两个轴组成的且原点在 p p p 点,度量值为米(m);

  • 图像坐标系一般指图片相对坐标系,在这里可以认为和像平面坐标系在一个平面上,不过原点是在图片的角上,而且度量值为像素的个数(pixel);

通过对上面坐标系的介绍,可以得到以下的转换公式:

加上偏移量:

如上图所示,其中主点 p p p 是像平面坐标系的原点,但在图像坐标系中的位置为 ( p x , p y ) (p_{x},p_{y}) (px​,py​),在这里,图形坐标系的原点是图片的左下角,所以可以得到:

把这个换成矩阵计算:

整理一下:

最后,可以得到矩阵K,就是相机内参:

投影矩阵P(在这里可以认为旋转矩阵 R 为单位矩阵 I,平移矩阵 t 都为0):

最终的转换式:
从上面两个转换的过程,我们可以得到从世界坐标轴转换到图像的过程可以把投影矩阵P表示为:


在这里, K K K 一般称为相机内参(intrinsic parameters),描述了相机的内部参数,包括焦距 f f f、主点 p p p 的位置、以及像素与真实环境的大小比例等,这个是固有属性,是提供好的; R R R 和 t t t 称为相机外参(extrinsic parameters), R R R 在这里是旋转矩阵,可以转换为三维的旋转向量,分别表示绕 x x x, y y y, z z z 三个轴的旋转角度, t t t 目前就是一个平移向量,分别表示在 x x x, y y y, z z z 三个方向上的平移量。

畸变参数

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

该部分参考:https://blog.csdn.net/honyniu/article/details/51004397

相机标定的结果

了解完一定原理之后,开始实践一下。
首先,要明确通过相机标记我们需要得到以下的参数:

  • 摄像机的内参和外参矩阵,内参和外参系数可以对之后相机拍摄的图像就进行矫正,得到畸变相对很小的图像。
  • 每一幅标定图像的选择和平移矩阵

流程

相机标定的流程可以简单的表述为:

  1. 准备图片。这里要注意,拍摄不同角度的图片时只需要对焦一次就好了,如果反复对焦,得到的每张图片的焦距就会一直变化。
  2. 对每张图片提取角点信息
  3. 对每张图片,进一步提取亚像素角点信息
  4. 相机标定
  5. 畸变矫正

实验数据准备

主要准备图片即可,10张左右的标定图片,黑白棋盘格即可。
可以给图片进行一定的缩小,加快运算速度。
拍摄过程中,如果方格纸是横着摆的就一直横着摆着拍,因为横纵角点个数是要提前设置好的。

实验过程

  1. 提取角点:
    使用函数:findChessboardCorners(image,(w,h),None);
    第一个参数为图片,第二个为图片横纵角点的个数。

  2. 找寻亚像素角点:cornerSubPix(gray, corners, (winsize, winsize), (-1, -1), criteria);
    winsize为搜索窗口边长的一半。
    zeroZone:搜索区域中间的dead region边长的一半,有时用于避免自相关矩阵的奇异性。如果值设为(-1,-1)则表示没有这个区域。
    criteria:角点精准化迭代过程的终止条件。也就是当迭代次数超过criteria.maxCount,或者角点位置变化小于criteria.epsilon时,停止迭代过程。

  3. 可以使用该函数把角点画出来:drawChessboardCorners(image, (w, h), corners, ret);
    其中corners和ret为第一个函数的输出值。
    效果如下:

  4. 标定

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

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

实验结果

mtx 内参数矩阵
dist 畸变系数
rvecs 旋转向量
tvecs 平移向量



准备了9张图片,可以有两张无论如何也不能完成标定,这两张和其他图片并没有很大的差别,角度光线也都很正常。
畸变矫正

左图为矫正过的图片,右边为原图

总结

通过相机标定得到了,vivo xplay5A的后置摄像头内置参数矩阵如下:

也得到了每张图片的外参数,并且实现了畸变矫正,虽然效果极其不明显。

代码及调试问题

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((6 * 8, 3), np.float32)
objp[:, :2] = np.mgrid[0:8, 0:6].T.reshape(-1, 2)  # 将世界坐标系建在标定板上,所有点的Z坐标全部为0,所以只需要赋值x和yobj_points = []  # 存储3D点
img_points = []  # 存储2D点images = glob.glob("D:/pycharmfile/biaoding/image/*.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, (8, 6), 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, (8, 6), 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)

参考:https://blog.csdn.net/firemicrocosm/article/details/48594897#

调试问题:

  1. 可以从上面的图看到我的图片角点是 8 ∗ 6 8*6 8∗6的,所以源代码中所有跟 8 ∗ 6 8*6 8∗6的相关数据都要改成相符合当前棋盘角点数量的值。调试过程可以在下方的图示的地方输出ret,如果它的输出值为true,说明你已经找到了正确的角点数。
  2. 如果调试过程出现这样的错误:
The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

需要在光标处,把corners2加上大括号变成[corners2]

python+OpenCV 相机标定相关推荐

  1. python opencv 相机标定_使用OpenCV校准鱼眼镜头的方法

    01.简介 当我们使用的鱼眼镜头视角大于160°时,OpenCV中用于校准镜头"经典"方法的效果可能就不是和理想了.即使我们仔细遵循OpenCV文档中的步骤,也可能会得到下面这个奇 ...

  2. opencv相机标定

    python 完整标注流程, python+opencv相机标定 - wenboz - 博客园 相机标定需要输出的参数: 焦距 像素或者物理单位mm 像素对应的物理长度 光心与物理senser中心的偏 ...

  3. 基于python的opencv相机标定(采用黑白棋盘格标定板)

    基于python的相机标定(采用黑白棋盘格图片) 系列文章目录 [第一章 基于python的相机标定(采用黑白棋盘格图片)](https://blog.csdn.net/HWHXXX/article/ ...

  4. Python OpenCV相机参数详解:实现准确的相机标定和图像处理

    Python OpenCV相机参数详解:实现准确的相机标定和图像处理 在计算机视觉领域,相机参数是非常重要的元素.通过相机参数的标定,可以将图像中的像素坐标转化为真实世界中的坐标,从而实现准确的图像处 ...

  5. 【ZED】从零开始使用ZED相机(五):Opencv+Python实现相机标定(双目)

    引言 同样Opencv+Python实现双目相机的标定,单目标定详见[ZED]从零开始使用ZED相机(五):Opencv+Python实现相机标定(单目) 1 cv2.stereoCalibrate ...

  6. 制作OpenCV相机标定板棋盘格图像

    一,OpenCV 相机标定中棋盘格图像要点 1,棋盘格的内部交点个数boardSize:水平方向(board_width, -w=4)和垂直方向(board_height, -h=5) 个人建议:棋盘 ...

  7. OpenCv相机标定——圆形标定板标定

    OpenCv相机标定--圆形标定板标定 0.前言 1.标定图案 2.OpenCv标定 3.标定结果分析 0.前言   OpenCv中,相机标定所使用的标定图案分为棋盘格.对称圆形及非对称圆形特征图.A ...

  8. 基于python的相机标定(采用圆形标定板图片)

    基于python的相机标定(采用圆形标定板图片) 系列文章目录 与黑白棋盘格差别主要在于寻找角点的函数,只需将第一章内第二段代码 ret, corners1 = cv.findChessboardCo ...

  9. Python OpenCV相机参数:如何获取和修改相机参数

    Python OpenCV相机参数:如何获取和修改相机参数 OpenCV是一个广泛使用的计算机视觉库,它提供了丰富的图像处理功能.在许多应用场景中,我们需要对相机进行参数设置,例如调整曝光时间.增益. ...

最新文章

  1. Python中“is”和“==”的区别
  2. wifi无线网卡移植到andorid
  3. 《JavaScript高效图形编程(修订版)》——第2章 DHTML基础 2.1创建DHTML sprite
  4. apt-get install用发
  5. html突出显示,javascript-记住html页面中突出显示的文本(向html页面添加注释)
  6. python kotlin_Java和Python中类似Kotlin的生成器,续:附加参数
  7. TCP中间件_Delphi_client
  8. mysql 局域网连接失败
  9. 网域高科家具行业网站开发管理系统
  10. Python实现感知器的逻辑电路(与门、与非门、或门、异或门)
  11. sql server 跨服务器查询数据
  12. 常见不等式考察(一)——Jensen不等式
  13. Flutter深色模式适配
  14. spark core源码分析16 Shuffle详解-读流程
  15. Panel的基本用法
  16. MOTO me525 DEFY 2.2 刷机全程详细指导
  17. thinkphp5.0漏洞修复
  18. 实习期间的一些思考整理(5)2018.4.17~4.18
  19. VulnHub - Pluck靶机
  20. 【hadoop生态之ZooKeeper】第四章ZooKeeper实战【笔记+代码】

热门文章

  1. Android5.0、6.0、7.0去除WIFI感叹号
  2. 350导热油 shell_导热油320与350的区别,克拉克给你详细解说
  3. 复制互联网2010全球最值得模仿的230个网站
  4. 唐诗宋词学习·100~105节
  5. 网络安全-黑帽白帽红客与网络安全法
  6. 广州php平均工资 2020,打工人注意!2020广州工资价位出炉
  7. 【sequoiadb|巨杉数据库】创建数据表
  8. CiteSpace关键词时区图含义详细解析与注意事项
  9. 元学习系列(零):小样本学习与元学习综述
  10. 儒家的礼与分配及社会契约