Python计算机视觉实验五——针孔照相机模型

  • 1 针孔相机模型
    • 1.1 照相机矩阵
    • 1.2 三维点的投影
    • 1.3 照相机矩阵的分解
    • 1.4 照相机中心
  • 2 相机标定
    • 2.1 代码
    • 2.2 运行结果

1 针孔相机模型

针孔照相机模型(有时称为射影照相机模型)是计算机视觉中广泛使用的照相机模型。对于大多数应用来说,针孔照相机模型简单,并且具有足够的精准度。这个名字来源于一种类似暗箱机的照相机。该照相机从一个小孔采集射到暗箱内部的光线。在光线投影到图像平面之前,从唯一一个点经过,也就是照相机中心C。

由图像坐标轴和三维坐标系中的x轴和y轴对齐平行的假设,我们可以得出针孔照相机的投影性质。照相机的光学坐标轴和z轴一致,该投影几何一颗简化成相似三角形。在投影之前通过旋转和平移变换,对该坐标系加入三维点,会出现完整的投影变换。

在针孔照相机中,三维点X投影为图像点x(两个点都是用齐次坐标表示的),如下所示:

这里,3×4的矩阵P为照相机矩阵(或投影矩阵)。注意,在齐次坐标系中,三维点X的坐标由4个元素组成,X=[X,Y,Z,W]。这里的标量λ是三维点的逆深度。如果我们打算在齐次坐标中将最后一个数值归一化为1,那么就会使用到它。

1.1 照相机矩阵

照相机矩阵可以分解为:

其中,R是描述照相机方向的旋转矩阵,t是描述照相机中心位置的三维平移向量,内标定矩阵K描述照相机的投影性质。标定矩阵仅和照相机自身的情况相关,通常情况下可以写成:

图像平面和照相机中心间的距离为焦距f。当像素数组在传感器上偏斜的时候,需要用到倾斜参数s。在大多数情况下,s可以设置成0.也就是说:

这里,我们使用了另外的记号fx和fy,两者关系为fx=αfy。

纵横比例参数α是在像素元素非正方形的情况下使用的。通常情况下,我们还可以默认设置α=1.经过这些假设,标定矩阵变为:

除焦距之外,标定矩阵中剩余的唯一参数为光心(有时称为主点)的坐标c=[cx,cy],也就是光线坐标轴和图像平面的交点。因为光心通常在图像的中心,并且图像的坐标是从左上角开始计算的,所以光心的坐标常接近于图像宽度和高度的一半。特别强调一点,这这个例子中,唯一未知的变量是焦距f。

1.2 三维点的投影

以下是创建照相机类,用来处理我们对照相机和投影建模所需要的基本操作:

from scipy import linalg
from pylab import  *class Camera(object):"""表示针孔照相机的类"""def __init__(self, P):"""初始化 P = K[R|t] 照相机模型"""self.P = Pself.K = None   # 标定矩阵self.R = None   # 旋转self.t = None   # 平移self.c = None   # 照相机中心def project(self, X):"""X(4×n的数组)的投影点,并进行坐标归一化"""x = dot(self.P, X)for i in range(3):x[i] /= x[2]return xdef rotation_matrix(a):"""创建一个用于围绕向量a轴旋转的三维旋转矩阵"""R = eye(4)R[:3,:3] = linalg.expm([0,-a[2],a[1]],[a[2],0,-a[0]],[-a[1],a[0],0])return R

1.3 照相机矩阵的分解

如果给定方程(1.1节中)所示的照相机矩阵P,我们需要恢复内参数K以及照相机的位置t和姿势R。矩阵分块操作称为因子分解。这里,我们将使用一种矩阵因子分解的方法,称为RQ因子分解。

    '''RQ因子分解方法'''def factor(self):"""将照相机矩阵分解为 K,R,t,其中, R=K[R|t]"""# 分解前3×3的部分K, R = linalg.rq(self.P[:, :3])# 将K的对角线元素设为正值T = diag(sign(diag(K)))if linalg.det(T) < 0:T[1, 1] *= -1self.K = dot(K, T)self.R = dot(T, R)  # T的逆矩阵为其自身self.t = dot(linalg.inv(self.K), self.P[:, 3])return self.K, self.R, self.t

1.4 照相机中心

给定照相机投影矩阵P,我们可以计算出空间上照相机的所在位置。照相机的中心C,是一个三维点,满足约束PC=0。对于投影矩阵为P=K[R|t]的照相机,有:

照相机的中心可以由下述式子来计算:

注意,如预期一样,照相机的中心和内标定矩阵K无关。
下面的代码可以按照上面公式计算照相机的中心。将其添加到Camera类中,该方法会返回照相机的中心:

    '''照相机中心'''def center(self):"""计算并返回照相机的中心"""if self.c is not None:return self.celse:# 通过因子分解计算cself.factor()self.c = -dot(self.R.T, self.t)return self.c

2 相机标定

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

【1】进行摄像机标定的目的:求出相机的内、外参数,以及畸变参数。
【2】标定相机后通常是想做两件事:一个是由于每个镜头的畸变程度各不相同,通过相机标定可以校正这种镜头畸变矫正畸变,生成矫正后的图像;另一个是根据获得的图像重构三维场景。

总结一下公式大致如下:

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

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

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

  1. 准备标定图片
  2. 对每一张标定图片,提取角点信息
  3. 对每一张标定图片,进一步提取亚像素角点信息
  4. 在棋盘标定图上绘制找到的内角点(非必须,仅为了显示)
  5. 相机标定

我准备的是5张下图这种格子数为15×10,内角点为14×9的棋盘格图片,求解的是拍摄手机的内部参数和外部参数、畸变系数。

2.1 代码

import cv2
import numpy as np
import glob# 找棋盘格角点
# 阈值
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
#棋盘格模板规格
w = 14   #内角点个数,内角点是和其他格子连着的点
h = 9# 世界坐标系中的棋盘格点,例如(0,0,0), (1,0,0), (2,0,0) ....,(8,5,0),去掉Z坐标,记为二维矩阵
objp = np.zeros((w*h,3), np.float32)
objp[:,:2] = np.mgrid[0:w,0:h].T.reshape(-1,2)
# 储存棋盘格角点的世界坐标和图像坐标对
objpoints = [] # 在世界坐标系中的三维点
imgpoints = [] # 在图像平面的二维点images = glob.glob('picture1/*.jpg')
for fname in images:img = cv2.imread(fname)gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)# 找到棋盘格角点# 棋盘图像(8位灰度或彩色图像)  棋盘尺寸  存放角点的位置ret, corners = cv2.findChessboardCorners(gray, (w,h),None)# 如果找到足够点对,将其存储起来if ret == True:# 角点精确检测# 输入图像 角点初始坐标 搜索窗口为2*winsize+1 死区 求角点的迭代终止条件cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)objpoints.append(objp)imgpoints.append(corners)# 将角点在图像上显示cv2.drawChessboardCorners(img, (w,h), corners, ret)cv2.namedWindow('findCorners', cv2.WINDOW_NORMAL)cv2.resizeWindow('findCorners', 640, 480) #调整窗口大小cv2.imshow('findCorners',img)cv2.waitKey(1000)
cv2.destroyAllWindows()
#标定、去畸变
# 输入:世界坐标系里的位置 像素坐标 图像的像素尺寸大小 3*3矩阵,相机内参数矩阵 畸变矩阵
# 输出:标定结果 相机的内参数矩阵 畸变系数 旋转矩阵 平移向量
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
# mtx:内参数矩阵
# dist:畸变系数
# rvecs:旋转向量 (外参数)
# tvecs :平移向量 (外参数)
print (("ret:"),ret)
print (("内参数矩阵:\n"),mtx)      # 内参数矩阵
print (("畸变系数:\n"),dist)      # 畸变系数   distortion cofficients = (k_1,k_2,p_1,p_2,k_3)
print (("旋转向量:\n"),rvecs)     # 旋转向量  # 外参数
print (("平移向量:\n"),tvecs)     # 平移向量  # 外参数
# 去畸变
img2 = cv2.imread('picture1/5.jpg')
h,w = img2.shape[:2]
# 我们已经得到了相机内参和畸变系数,在将图像去畸变之前,
# 我们还可以使用cv.getOptimalNewCameraMatrix()优化内参数和畸变系数,
# 通过设定自由自由比例因子alpha。当alpha设为0的时候,
# 将会返回一个剪裁过的将去畸变后不想要的像素去掉的内参数和畸变系数;
# 当alpha设为1的时候,将会返回一个包含额外黑色像素点的内参数和畸变系数,并返回一个ROI用于将其剪裁掉
newcameramtx, roi=cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),0,(w,h)) # 自由比例参数dst = cv2.undistort(img2, mtx, dist, None, newcameramtx)
# 根据前面ROI区域裁剪图片
x,y,w,h = roi
dst = dst[y:y+h, x:x+w]
cv2.imwrite('calibresult.jpg',dst)# 反投影误差
# 通过反投影误差,我们可以来评估结果的好坏。越接近0,说明结果越理想。
# 通过之前计算的内参数矩阵、畸变系数、旋转矩阵和平移向量,使用cv2.projectPoints()计算三维点到二维图像的投影,
# 然后计算反投影得到的点与图像上检测到的点的误差,最后计算一个对于所有标定图像的平均误差,这个值就是反投影误差。
total_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)total_error += error
print (("total error: "), total_error/len(objpoints))

2.2 运行结果




Python计算机视觉实验五——针孔照相机模型相关推荐

  1. 山东大学类脑实验 五 HMAX 模型实现

    山东大学类脑实验 五 HMAX 模型实现 实验目的: 加深对 HMAX 模型的理解,能够使用 HMAX 模型解决简单问题 实验内容: 根据 HMAX 模型的相关知识,使用 Python 语言实现一个简 ...

  2. 四、【python计算机视觉编程】照相机模型与增强现实

    照相机模型与增强现实 (一)针孔照相机模型 (1)照相机矩阵 (2)三维点的投影 (3)照相机矩阵的分解 (4)计算照相机中心 (二)照相机标定 (三)以平面和标记物进行姿态估计 (四)增强现实 (A ...

  3. python综合程序设计-Python程序设计实验五:综合运用三种基本结构进行程序设计...

    安徽工程大学 Python程序设计实验报告 班级:物流192 姓名:李心悦 学号:3190505218成绩: 日期:2020. 4.26 指导教师:修宇 [实验名称] 实验五 综合运用三种基本结构进行 ...

  4. python计算机视觉第五次实验

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

  5. Python计算机视觉(五)——基于BOW的图像检索

    文章目录 一.图像搜索 二.BOW模型图像检索 1.BOW(Bag-of-words) 2.Bag-of-features 三.算法流程 1.特征提取 2.学习"视觉词典"(vis ...

  6. 【计算机视觉实验五】图像检索与识别

    一.图像特征匹配 暴力匹配法:十分耗时,对于大数据集根本不能用 对于大场景数据集(如城市场景), 只有少 于 0.1% 的图像对具有匹配关系 解决方案: 利用图像整体特征实现匹配/检索, 而非局部特征 ...

  7. Python 计算机视觉(五)—— OpenCV 进行图像几何变换

    几何变换不改变图像的像素值,只是实现图像像素点的重新安排:恰当的进行图像的几何变换,可以减小甚至避免由于角度等一些因素造成的图像失真问题,有利于我们在识别图像时将注意力集中到图像的有效信息中而不至于被 ...

  8. 双目立体视觉建立深度图_计算机视觉实验五 双目立体匹配获得视差图,深度图...

    完整源码链接 https://github.com/LamyaLi/cvLab 文章目录 一. 立体匹配的研究背景及意义 二. 立体匹配算法的基本实现思想 1.误差能量函数 2.基于最小平均误差能量的 ...

  9. 广州大学计算机视觉实验一:图像处理入门

    相关资料 广州大学计算机视觉实验一:图像处理入门 广州大学计算机视觉实验二:摄像机几何 广州大学计算机视觉实验三:图像滤波 广州大学计算机视觉实验四:图像分割 广州大学计算机视觉实验五:简易数字识别 ...

  10. Python 计算机视觉(十六)—— 图像和视频中的人脸识别

    参考的一些文章以及论文我都会给大家分享出来 -- 链接就贴在原文,论文我上传到资源中去,大家可以免费下载学习,如果当天资源区找不到论文,那就等等,可能正在审核,审核完后就可以下载了.大家一起学习,一起 ...

最新文章

  1. 深度学习最常用的10个激活函数!(数学原理+优缺点)
  2. python3 抛出异常_Python3 异常
  3. 'yii\base\InvalidRouteException' with message 'Unable to resolve the request site/error.'
  4. Tomcat工程部署常见问题
  5. 洛谷P1337 [JSOI2004]平衡点 / 吊打XXX(模拟退火)
  6. 好用的Span(富文本)api
  7. LAMP之Apache
  8. id nfc模拟_手机NFC也可以刷ID卡门禁?无聊测试居然成功了
  9. LiteOS内核源码分析:任务栈信息
  10. Servlet过滤器示例及分析----日志过滤器 以及对flush()理解
  11. executeQuery()方法
  12. 【六】Jmeter:断言
  13. mac读写ntfs工具
  14. oracle不显示表和过程,oracle表连接——处理连接过程中另外一张表没有相关数据不显示问题...
  15. 语言随机效应模型_R语言LME4混合效应模型研究教师的受欢迎程度
  16. 公里与英里的换算c语言函数_这些天然气单位换算你知道吗?
  17. 微信分享链接php,微信实现分享链接的缩略图和标题
  18. 数学分析:函数的可积条件
  19. ecshop源码教程
  20. xcode报ignoring file xxx missing required architecture x86_64 in file错误

热门文章

  1. 给大家推荐个jquery api 3.2 在线手册地址
  2. mysql脏写_图解脏写、脏读、不可重复读、幻读
  3. 用k-mer分析进行基因组调查:(一)基本原理
  4. 020:Django电商网站逻辑导图
  5. QQ农场启示录之:偷菜成本核算
  6. 测试工程师从面试到入职
  7. python机器学习案例-梯度提升模型搭建及评估(完整代码+实现效果)
  8. 阿里云国际香港服务器,入手到底行不行?
  9. SwiftUI界面制作之List Navigation实现国画图文混排《潇湘卧游图》
  10. 实验楼Linux入门:Linux用户管理