一、相机标定

1.1原理

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

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

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

1.2世界坐标系转换为相机坐标系


公式表达如下:

其中:

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


其中:

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

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

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

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

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

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

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

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

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

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

加上偏移量:
在这里,图形坐标系的原点是图片的左下角,所以可以得到:

最后,可以得到矩阵K,就是相机内参:
投影矩阵P(在这里可以认为旋转矩阵 R 为单位矩阵 I,平移矩阵 t 都为0):

1.4最终的转换式

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

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

1.5流程

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

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

二、实验

2.1 拍摄图片

将打印出的纸固定放到一个平面上,使用同一相机从不同的位置,不同的角度,拍摄标定板的多张照片(我拍了10张)手机型号是华为P20

2.2标定相机

2.3实验结果

newcameramtx外参:
[[1.09543237e+03 0.00000000e+00 1.15161557e+03]
[0.00000000e+00 9.76493347e+02 6.81863424e+02]
[0.00000000e+00 0.00000000e+00 1.00000000e+00]]
dist畸变值:
[[-5.31418095e-01 3.61316843e+00 3.41621845e-03 -1.67261358e-02
-9.20291030e+00]]
newcameramtx旋转(向量)外参:
[array([[0.02577749],
[0.40862485],
[1.52657479]]), array([[-0.79306228],
[ 0.77094312],
[ 1.37578838]]), array([[0.00179755],
[0.54632508],
[0.02013088]]), array([[ 0.04196639],
[-0.22174524],
[-0.00851909]]), array([[ 0.04196639],
[-0.22174524],
[-0.00851909]]), array([[0.26013366],
[0.26520145],
[1.54454481]]), array([[-0.39706644],
[-0.11103073],
[ 0.01213503]]), array([[-0.21161518],
[-0.01945597],
[ 0.00245364]]), array([[-0.08742881],
[-0.13754091],
[ 0.02754208]]), array([[-0.65565002],
[ 0.61239846],
[ 1.42042031]])]
dist平移(向量)外参:
[array([[ 3.89559181],
[-2.58816711],
[17.95017051]]), array([[ 1.85156293],
[ 3.3557696 ],
[25.3186641 ]]), array([[ 1.06274371],
[-1.82849128],
[24.60265585]]), array([[ 4.08364114],
[-1.77930336],
[20.57284092]]), array([[ 4.08364114],
[-1.77930336],
[20.57284092]]), array([[ 4.26223866],
[-2.7293332 ],
[17.39101118]]), array([[ 0.73077079],
[-7.45141267],
[25.7618198 ]]), array([[-3.225708 ],
[-0.84783713],
[16.57865762]]), array([[-0.48670407],
[-8.61318764],
[25.38451393]]), array([[ 0.17778048],
[ 6.39098376],
[28.93467406]])]
矫正前:

矫正后:

2.4代码

# coding=utf-8
import numpy as np
import cv2
import glob
# 终止标准
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
#w = 6
#h = 6
#准备对象点,如(0,0,0),(1,0,0),(2,0,0)......,(6,5,0)
#objp = np.zeros((w*h,3), np.float32)
objp = np.zeros((6*6,3), np.float32)
objp[:,:2] = np.mgrid[0:6,0:6].T.reshape(-1,2)# 用于存储所有图像中的对象点和图像点的数组。
objpoints = [] # 在现实世界空间的3d点
imgpoints = [] # 图像平面中的2d点。
#glob是个文件名管理工具
images = glob.glob('D:/image/*.jpg')
print('...loading')
for fname in images:#对每张图片,识别出角点,记录世界物体坐标和图像坐标print('processing img:{fname}')img = cv2.imread(fname)gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#转灰度print('grayed')#寻找角点,存入corners,ret是找到角点的flag#ret, corners = cv2.findChessboardCorners(gray, (w, h),None)ret, corners = cv2.findChessboardCorners(gray, (6, 6),None)# 如果找到,添加对象点,图像点(精炼后)if ret == True:print('chessboard detected')objpoints.append(objp)#执行亚像素级角点检测corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)imgpoints.append(corners2)# 绘制并显示角点#img = cv2.drawChessboardCorners(img, (w,h), corners2,ret)img = cv2.drawChessboardCorners(img, (6,6), corners2,ret)cv2.namedWindow('img',0)cv2.resizeWindow('img', 500, 500)cv2.imshow('img',img)cv2.waitKey(500)cv2.destroyAllWindows()
'''
传入所有图片各自角点的三维、二维坐标,相机标定。
每张图片都有自己的旋转和平移矩阵,但是相机内参和畸变系数只有一组。
mtx,相机内参;dist,畸变系数;revcs,旋转矩阵;tvecs,平移矩阵。
'''img2 = cv2.imread("D:/image/1.jpg")
print("type objpoints:{objpoints[0].shape}")
print("type imgpoints:{imgpoints[0].shape}")ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1],None,None)
h,  w = img2.shape[:2]'''
优化相机内参(camera matrix),这一步可选。
参数1表示保留所有像素点,同时可能引入黑色像素,
设为0表示尽可能裁剪不想要的像素,这是个scale,0-1都可以取。
'''
newcameramtx, roi=cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),1,(w,h))
#纠正畸变
dst = cv2.undistort(img2, mtx, dist, None, newcameramtx)# 裁剪图像,输出纠正畸变以后的图片
x,y,w,h = roi
dst = dst[y:y+h, x:x+w]
cv2.imwrite('calibresult11.jpg',dst)#打印我们要求的两个矩阵参数
print ("newcameramtx外参:\n",newcameramtx)
print ("dist畸变值:\n",dist)
print ("newcameramtx旋转(向量)外参:\n",rvecs)
print ("dist平移(向量)外参:\n",tvecs)
#计算误差
tot_error = 0
for i in range(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 += errorprint ("total error: ", tot_error/len(objpoints))

三、总结与问题

1.通过标定得到的后置摄像头的内置参数矩阵为:
[[1.09543237e+03 0.00000000e+00 1.15161557e+03]
[0.00000000e+00 9.76493347e+02 6.81863424e+02]
[0.00000000e+00 0.00000000e+00 1.00000000e+00]]

2.矫正后的图片没法打开

可能是拍摄的问题,没有将棋盘格完全占据大部分主题,而是混入了一半的玻璃桌,从而导致没有打开,后重新拍摄,将棋盘格放大,作为主体,才可以输出矫正后的图片。但也可以减少角点数从而可以实现矫正后图片输出,感觉本质上两种方法都是一样的,放大棋盘格。

3.矫正后的图片与矫正前的图片没有太大的区别,感觉矫正后将图片稍微的向上调整了些角度。其他地方如宽度,高度等无法特别大的变化,可能是因为没有出现太大的畸变。

计算机视觉——相机定位相关推荐

  1. 相机定位 | cv paper整理

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 作者:梦寐mayshine 链接:https://zhuanlan.zhihu.com/p/13449 ...

  2. CVPR 2021 | 基于稠密场景匹配的相机定位学习

    Learning Camera Localization via Dense Scene Matching 论文.代码地址:在公众号「3D视觉工坊」,后台回复「相机定位」,即可直接下载. 相机定位算法 ...

  3. 使用ROS和AprilTags进行相机定位(二维码定位全流程)

    使用ROS和AprilTags进行相机定位(二维码定位全流程) 配置环境 1 下载虚拟机 2 下载Ubuntu16.07 3 安装虚拟机和Ubuntu 4 安装ROS 5 USB相机驱动 标定.定位 ...

  4. V---双相机定位贴合的原理和实现过程

    主要讲解上下双相机定位贴合的原理和实现过程,包括各种标定.组合使用及具体的halcon源码实现, 适用于的X.Y.Z三轴加一旋转轴系统,如模组组成的多轴系统.Scara四轴机器.六轴机器人(在运行过程 ...

  5. MapNet:Geometry-Aware Learning of Maps for Camera Localization相机定位的几何感知学习地图

    摘要 地图是基于图像的相机定位和视觉SLAM系统的关键组成部分.本文MapNet除了图像之外还利用廉价且无处不在的感官输入,如视觉里程计和GPS,并将它们融合在一起以进行相机定位. 本文还提出了一种新 ...

  6. 水印相机定位不准确怎么办_禄来的广角双反相机(2020版)

    点击上方胶卷迷俱乐部快速关注,胶卷迷们坚实的阵地 内容主要原创,配图来自群友和网络,所有水印保留 最下方为微信自带广告,支持请点击(本号可获微量收入) 4.0 德国禄来公司以双反相机名震天下,其中的2 ...

  7. 水印相机定位不准确怎么办_第一台胶卷相机入门品鉴

    点击上方胶卷迷俱乐部快速关注,这里是胶卷迷们坚实的阵地 所有内容均为原创,配图来自群友和网络,所有水印保留 最下方为微信自带广告,支持本号点一点 入门品鉴 我最近想买一块好点的手表,但我没钱,看了这么 ...

  8. 【VisionMaster 行业应用案例】第二讲 多相机定位引导应用

    目录 1. 场景介绍 2. 方案设计 2.1 方案一 2.1.1 标定方案(主相机和机构12点+两次标定板标定) 2.1.2 偏差计算方案 2.2 方案二 2.2.1 标定方案(标定板和机构12点+两 ...

  9. 3D相机定位抓取介绍

    本文已参与「新人创作礼」活动,一起开启掘金创作之路. 本文从实际的案例触发介绍3D定位抓取的介绍 1.目前市面上的3D相机大体上分为一体式和分体式: 一体式的3D相机是吧相机和镜头组装在了一起,相机的 ...

最新文章

  1. 调用别的类中的变量(但是还是有问题)
  2. java的for循环取出数据只是拿到最后一个_新兴大数据分析榆中百合
  3. 探索感染了COVID-19的动物的数据
  4. OpenCL 第7课:旋转变换(1)
  5. ASCII中关于大小写字母间隔为32的思考
  6. git git 查看远程库_如何从Git远程存储库中提取
  7. 光流估计——从传统方法到深度学习
  8. Android中集成第三方库的方法和问题
  9. boost::asio::io_context的事件循环
  10. MYSQL 查看表空间占用情况
  11. comsol3.5安装教程
  12. Scintilla开源库使用指南
  13. 基于PHP的学生学籍管理系统
  14. 【PHP】面试经历总结之——新浪微博
  15. 现代大学英语精读第二版(第二册)学习笔记(原文及全文翻译)——3B - What My Garden Taught Me—the Hard Way(园艺给我的教训——历经磨难才学会)
  16. 深度学习WideDeep模型——记忆能力和泛化能力的综合
  17. R语言 配对t检验,对子变量到底填在哪?t.test paired=TRUE???
  18. 建设规划合理、高效便捷的现代物流中心——浙江嘉兴市局(公司)卷烟物流配送中心建设纪实...
  19. 好佳居软装十大品牌 每个人都有着适合自己的软装
  20. excel表格拆分多个表如何操作

热门文章

  1. npm install 报错 ERR! gyp ERR! cwd D:\workspace\node_modules\node-sass错误解决/npm ERR! gyp verb `which
  2. US100超声波测距模块的FPGA驱动
  3. xHiveAI-A311D:AI开发套件
  4. 视频剪辑软件哪个比较好用?这几款常用的视频剪辑软件你要知道
  5. 小白学习HCIA2022
  6. 电脑python编程软件哪个好用_5个最好用的Python编程开发工具(IDE)分享
  7. 【二维码识别】灰度+二值化+校正二维码生成与识别【含GUI Matlab源码 635期】
  8. 关于 RabbitMQ,应该没有比这更详细的教程了!
  9. 32位/64位操作系统的最大支持内存的空间
  10. 我的Spring入门