理想相机成像模型

看到一篇博客,介绍的十分详细.参考 链接
(为了好理解,个人还是喜欢分四大坐标系,世界坐标系,摄像机坐标系,图像物理坐标系,图像像素坐标系)
1)世界坐标系->摄像机坐标系

R矩阵为旋转矩阵,T矩阵为平移矩阵,RT矩阵变换,属于刚体转换,旋转矩阵具体分为世界坐标系如何分别绕x,y,z三个轴旋转多少度后坐标系方向与摄像机坐标系一致,平移矩阵则对应世界坐标系原点需如何平移至相机坐标系原点.opencv标定后每图的旋转/平移参数都是3个,应该就是对应三个轴的旋转角度alpha,beta,gama和三个方向的平移量.
齐次表达式

其中R矩阵由三个轴的旋转得到,如下图所示(来源黑土的Halcon学习教程)

2)摄像机坐标下->图像物理坐标系
图像物理坐标系其实可以理解为CCD芯片平面的坐标系

3)图像物理坐标系->图像像素坐标系

dx,dy是芯片像素单元的物理尺寸,u0,v0是光轴中心的图像像素坐标
综上得到世界坐标系->图像像素坐标系

opencv标定实验

我的想法是,按照模型原理,自己设置相机内外参数,畸变参数,生成畸变数据点,然后用opencv标定后得到的参数做一个比较.我用opencv-python写的程序如下

# -*- coding:utf-8 -*-
# @Author : ZYKimport numpy as np
import cv2
"""
这里根据相机成像模型,参考 https://www.cnblogs.com/zyly/p/9366080.html
手动构建相关参数,构建畸变像素点后,用opencv标定求解参数,最终对比.
为简化模型,世界坐标系与相机坐标系方向一致
"""#定义基本参数
pixsize=0.1 #假设像素精度是0.1mm
imgw=1280
imgh=1024
Zc=150 #物距
f=15 #像距
row=7 #棋盘点行数
col=9#棋盘点列数
space=10 #棋盘点间隔
u0=imgw/2#光轴中心
v0=imgh/2
k1=-2e-3 #径向畸变系数(这里不考虑切向畸变)
k2=-5e-5
k3=-1e-6chipw=imgw*pixsize*f/Zc #传感器尺寸
chiph=imgh*pixsize*f/Zc
dx=chipw/imgw #每个像素的硬件物理尺寸
dy=chiph/imgh#构建棋盘世界坐标点(齐次坐标)
obj_point = np.zeros((4,row * col), np.float32)
for idx in range(row*col):obj_point[:3,idx]=[idx%col*space,idx//col*space,0]
obj_point[3,:]=1
each_obj_point=obj_point[:3, :].T#小孔成像转换矩阵
prjmat=np.array([[f,0,0,0],[0,f,0,0],[0,0,1,0]],np.float32)
#相机内参矩阵
kmat=np.array([[1 / dx, 0 ,u0],[0, 1 / dy, v0],[0, 0, 1]],np.float32)init_rvecs=[] #旋转矩阵参数集合
init_tvecs=[]
obj_points=[]
img_points=[]
picnum=10 #模拟用于标定的图片数,这里简化每张图世界坐标系仅仅绕Z轴旋转Gama角度
Testimg=(np.ones((imgh,imgw,3))*255).astype(np.uint8)
for idx in range(picnum):angle=np.pi/3*(np.random.rand()-0.5)#-30~30度if idx==0:angle=0init_rvecs.append([0,0,angle])src_offsetx = -(col - 1) * space / 2src_offsety = -(row - 1) * space / 2tvec=[src_offsetx * np.cos(angle) - src_offsety * np.sin(angle),#平移参数Tx,Ty,Tz,这里使点中心在光轴上src_offsetx * np.sin(angle) + src_offsety * np.cos(angle),Zc]init_tvecs.append(tvec)#平移旋转齐次矩阵rtmat=np.eye(4,4,dtype=np.float32)rtmat[0,0]=rtmat[1,1]=np.cos(angle)rtmat[0, 1]=-np.sin(angle)rtmat[1, 0] = np.sin(angle)rtmat[:3,3]=tvec#构建像素坐标点camera_point=np.dot(rtmat,obj_point)   #相机坐标系c_point=np.dot(prjmat,camera_point)/Zc #图像物理坐标系#由理想点生成畸变点r2=c_point[:1,:]**2+c_point[1:2,:]**2r2=np.repeat(r2,2,axis=0)scale=1+k1*r2+k2*r2**2+k3*r2**3c_point[:2,:]=c_point[:2,:]*scaleimg_point=np.dot(kmat,c_point)#图像像素坐标系#显示测试corners=img_point[:2,:].T#加入噪声,噪声范围-0.05-0.05noise=(np.random.rand(corners.shape[0],corners.shape[1])-0.5)*0.1corners+=noisecorners=np.expand_dims(corners,axis=1)showimg = (np.ones((imgh, imgw, 3)) * 255).astype(np.uint8)cv2.drawChessboardCorners(showimg, (col, row), corners, True)if idx==0:Testimg=showimg.copy()#cv2.namedWindow('img',cv2.WINDOW_NORMAL)cv2.imshow('img',showimg)cv2.waitKey(500)obj_points.append(each_obj_point)img_points.append(corners)#对虚拟生成的数据进行相机标定
use_init_k=True
if use_init_k:ret, mtx, dist, rvecs, tvecs=cv2.calibrateCamera(obj_points,img_points,(imgw,imgh), kmat,None,flags=cv2.CALIB_USE_INTRINSIC_GUESS|cv2.CALIB_ZERO_TANGENT_DIST)
else:ret, mtx, dist, rvecs, tvecs=cv2.calibrateCamera(obj_points,img_points,(imgw,imgh), None,None)if(ret):print('K error: 1/dx:',mtx[0,0]-kmat[0,0],',1/dy:',mtx[1,1]-kmat[1,1])print('D error: k1:', dist[0,0] - k1,',k2:',dist[0,1] - k2,',k3:', dist[0, 4] - k3)#undist = cv2.undistort(showimg, mtx, dist, None, mtx)map1, map2 = cv2.initUndistortRectifyMap(mtx, dist, np.eye(3), mtx, (imgw,imgh), cv2.CV_32FC2)undist = cv2.remap(Testimg, map1, map2,interpolation=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT)result = np.concatenate((Testimg, undist), axis=1)cv2.imshow("img", result)cv2.waitKey(0)

生成的桶形畸变点看起来应该没啥问题
最终标定后,去除畸变的效果如下
对比的相机参数也差不多

不过是在传递了初始化相机内参数矩阵的情况下
如果不传,发现相机参数相差还是很大,这个可能是因为我标定点数据都是同一个平面导致的吧,后面有时间再研究.

opencv相机标定(1)-畸变校正原理相关推荐

  1. OpenCV相机标定与畸变校正

    点击我爱计算机视觉标星,更快获取CVML新技术 本文转载自OpenCV学堂. OpenCV单目相机标定,图像畸变校正 相机标定定义与原理 01 在图像测量过程以及机器视觉应用中,为确定空间物体表面某点 ...

  2. 相机标定(三) —— 畸变校正

    一.前言 根据针孔模型,物体和成像之间参数会满足相似三角形的关系.但现实中会存在装配误差和透视失真等原因,导致这种关系无法成立,使理想成像与实际成像存在误差,这种误差即称为畸变. 畸变分为径向畸变,切 ...

  3. 手机广角相机标定和畸变校正

    摄像头或者相机会因为镜片的光学特性而发生有规律的变形或者畸变,包括桶型畸变,枕型畸变和线性畸变.普通相机的这些畸变十分轻微,人的肉眼几乎分辨不出,所以这时可以不需要校正.对于广角相机,鱼眼相机,由于视 ...

  4. 双目相机标定以及立体测距原理及OpenCV实现

    转载 双目相机标定以及立体测距原理及OpenCV实现 http://blog.csdn.net/dcrmg/article/details/52986522?locationNum=15&fp ...

  5. 鱼眼摄像头标定与畸变校正(OPENCV版)

    转载请注明作者和出处:http://blog.csdn.net/u011475210 代码地址:https://github.com/WordZzzz/fisheye_calibration 软件版本 ...

  6. 鱼眼摄像头标定与畸变校正(双OPENCV版本)

    转载请注明作者和出处:http://blog.csdn.net/u011475210 代码地址:https://github.com/WordZzzz/fisheye_calibration 软件版本 ...

  7. 双目相机标定以及立体测距原理及OpenCV实现(下)

    前篇:双目相机标定以及立体测距原理及实现(上) 双目相机标定后,可以看到左右相机对应匹配点基本上已经水平对齐. 之后在该程序基础上运行stereo_match.cpp,求左右相机的视差. 注:下边Op ...

  8. opencv相机标定

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

  9. 双目相机标定以及立体测距原理及实现(上)

    作者丨童虎 编辑丨3D视觉开发者社区 单目相机标定的目标是获取相机的内参和外参,内参(1/dx,1/dy,Cx,Cy,f)表征了相机的内部结构参数,外参是相机的旋转矩阵R和平移向量t.内参中dx和dy ...

最新文章

  1. SQL学习教程:基础教程高级教程
  2. Swift 泛型函数补充
  3. python从入门到精通怎么样-《Python编程从入门到精通》
  4. shopee本土店怎么做,一些运营技巧分享
  5. C#操作Excel文件(转)
  6. 《云图计划》的动效简析
  7. 让僵冷的翅膀飞起来—从实例谈OOP、工厂模式和重构[by Wayfarer]
  8. sys/queue.h
  9. KendoUI 基础:Grid 绑定template展示
  10. python部署到服务器上解析不到模块_在服务器上部署kafka-python包
  11. linux命令面试题大全,Linux系统命令面试题大全
  12. chmod755的含义
  13. 最全CSS3实现水平垂直居中的10种方案
  14. 纸的大小图解_手工折纸大全图解 不一定是A4大小)一般都有7
  15. 记录:前端框架Bootstrap学习使用之组件——Collapse(折叠)
  16. error: C++ requires a type specifier for all declarations
  17. 转 SPOOLING技术——操作系统
  18. artwork will be rounded down because......
  19. linux 系统swap设置,Linux 系统swap 设置
  20. 5-QR code识别

热门文章

  1. 使用makefile启动vcs, verdi 进行仿真
  2. Python简单实现爬取快递物流实时信息!到了及时提醒!
  3. 红米note2能刷机没显示无服务器,红米note2刷机变砖了怎么办? 红米note2救砖的方法...
  4. logback-logger和root
  5. 森海塞尔经典老耳机的参数
  6. Java Activiti 工作流引擎 springmvc SSM 流程审批 后台框架源码
  7. 简单scrapyd使用
  8. MATLAB基础操作,矩阵乘法、数组矩阵索引、最大最小运算符、零矩阵/随机矩阵/单位矩阵的生成、log函数、Inf和NaN的含义,语句过长用连接符换行、逻辑运算符以及区别
  9. 互联网直播平台Storm金融项目-杨帅-专题视频课程
  10. 微信小程序表单提交PHP后台