简 介: 对于相机进行校正,是为之后视觉测量奠定基础。本文在总结了相机校正中的基本概念。使用cv2的函数说明校正的过程。

关键词相机校正内参外参

#mermaid-svg-0bogxxocrI1OFV3c {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-0bogxxocrI1OFV3c .error-icon{fill:#552222;}#mermaid-svg-0bogxxocrI1OFV3c .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-0bogxxocrI1OFV3c .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-0bogxxocrI1OFV3c .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-0bogxxocrI1OFV3c .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-0bogxxocrI1OFV3c .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-0bogxxocrI1OFV3c .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-0bogxxocrI1OFV3c .marker{fill:#333333;stroke:#333333;}#mermaid-svg-0bogxxocrI1OFV3c .marker.cross{stroke:#333333;}#mermaid-svg-0bogxxocrI1OFV3c svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-0bogxxocrI1OFV3c .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-0bogxxocrI1OFV3c .cluster-label text{fill:#333;}#mermaid-svg-0bogxxocrI1OFV3c .cluster-label span{color:#333;}#mermaid-svg-0bogxxocrI1OFV3c .label text,#mermaid-svg-0bogxxocrI1OFV3c span{fill:#333;color:#333;}#mermaid-svg-0bogxxocrI1OFV3c .node rect,#mermaid-svg-0bogxxocrI1OFV3c .node circle,#mermaid-svg-0bogxxocrI1OFV3c .node ellipse,#mermaid-svg-0bogxxocrI1OFV3c .node polygon,#mermaid-svg-0bogxxocrI1OFV3c .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-0bogxxocrI1OFV3c .node .label{text-align:center;}#mermaid-svg-0bogxxocrI1OFV3c .node.clickable{cursor:pointer;}#mermaid-svg-0bogxxocrI1OFV3c .arrowheadPath{fill:#333333;}#mermaid-svg-0bogxxocrI1OFV3c .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-0bogxxocrI1OFV3c .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-0bogxxocrI1OFV3c .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-0bogxxocrI1OFV3c .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-0bogxxocrI1OFV3c .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-0bogxxocrI1OFV3c .cluster text{fill:#333;}#mermaid-svg-0bogxxocrI1OFV3c .cluster span{color:#333;}#mermaid-svg-0bogxxocrI1OFV3c div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-0bogxxocrI1OFV3c :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}

相机标定
文章目录
相机标定
基本原理
世界坐标转换
为相机坐标
相机坐标转换
为图像坐标
图像坐标转换
为像素坐标
成像畸变参数
相机标定
实验过程
相机校正
处理图片
提取角点
寻找亚像素点
相机校正
完整程序
总 结

§01 相机标定


  这部分内容来自于 python+OpenCV 相机标定

1.1 相机标定基本原理

  摄像机标定(Camera calibration)简单来说是从世界坐标系换到图像坐标系的过程,也就是求最终的投影矩阵 P 的过程。 根据相机标定(一)-原理及内参、外参 博文中的定义,在整个转换过程中,包括有四个坐标系:

  • 图像像素坐标系
  • 图像物理坐标系
  • 相机坐标系
  • 世界坐标系

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

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

1.1.1 世界坐标转换为相机坐标

  世界坐标就是实际外部环境坐标,原点为OOO,三个正交坐标轴分别为X,Y,ZX,Y,ZX,Y,Z。相机位于世界坐标内,OX,Y,ZO_{X,Y,Z}OX,Y,Z​,原点为CCC,镜头方向坐标为ZcamZ_{cam}Zcam​,另外两个坐标轴Xcam,YcamX_{cam} ,Y_{cam}Xcam​,Ycam​与镜头方向垂直。

▲ 图1.1.1 世界坐标转换为相机坐标

  从OX,Y,ZO_{X,Y,Z}OX,Y,Z​到CXcam,Ycam,ZcamC_{Xcam,Ycam,Zcam}CXcam,Ycam,Zcam​的 映射转换公式为:X^cam=R(X^−C^)\hat X_{cam} = R\left( {\hat X - \hat C} \right)X^cam​=R(X^−C^)

其中:

  • RRR表示旋转矩阵;
  • X^\hat XX^表示XXX点在世界坐标OX,Y,ZO_{X,Y,Z}OX,Y,Z​中的位置;
  • C^\hat CC^表示相机原点CCC在世界坐标中的位置;
  • X^cam\hat X_{cam}X^cam​表示XXX点在相机坐标中的位置;

▲ 图1.1.2 世界坐标系与相机坐标系

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

  下图给出了在相机坐标系内的成像平面,px,yp_{x,y}px,y​与相机坐标主轴垂直,交点为图像坐标原点ppp,距离相机与原点距离为相机焦距fff。相机坐标中任何一点XXX在成像平面上的位置,也称为图像坐标,是由连线X,CX,CX,C在成像平面上的交点xxx确定。

▲ 图1.1.3 相机坐标中的点与成像平面

其中:

  • CCC表示 camera center,即相机的中心店,也是相机坐标系的原点;
  • ZZZ表示principal axis,即相机的主轴;
  • ppp点所在的平面表示 image plane,即相机的像平面,也就是图片坐标系所在的二维平面;
  • ppp 点表示 principal point,即主点,也就是主轴与想平明香蕉的点;

  成像坐标xxx的位置可以由三角几何比例关系确定。

▲ 图1.1.4 相机坐标系以及成像平面之间的关系

▲ 图1.1.5 利用三角几何比例关系确定成像位置

其中:

  • CCC 点到 ppp 点的距离,就是相机的焦距 fff;

  对于相机坐标中的点 (X,Y,Z)\left( {X,Y,Z} \right)(X,Y,Z),在成像平面上的位置为:
x=f⋅XZ,y=f⋅YZx = {{f \cdot X} \over Z},\,\,y = {{f \cdot Y} \over Z}x=Zf⋅X​,y=Zf⋅Y​

  简记为:(X,Y,Z)↦(f⋅X/Z,f⋅Y/Z)\left( {X,Y,Z} \right) \mapsto \left( {f \cdot X/Z,f \cdot Y/Z} \right)(X,Y,Z)↦(f⋅X/Z,f⋅Y/Z)。

  加上偏移量,如下图所示, 其中 ppp是像平面坐标系的 原点,在图像坐标系中的位置为(px,py)\left( {p_x ,p_y } \right)(px​,py​)。

▲ 图1.1.6 成像坐标原点在图像坐标中的位置

  上图所表示的图像坐标系的原点是在图片的左下角,所以:
(X,Y,Z)↦(f⋅XZ+px,f⋅YZ+py)\left( {X,Y,Z} \right) \mapsto \left( {{{f \cdot X} \over Z} + p_x ,{{f \cdot Y} \over Z} + p_y } \right)(X,Y,Z)↦(Zf⋅X​+px​,Zf⋅Y​+py​)

  换成矩阵计算:


  整理一下:


  定义相机的内参矩阵KKK,包括有焦距 fff 以及成像原点在图像的偏移量(px,py)\left( {p_x ,p_y } \right)(px​,py​):


投影矩阵PPP(这里认为旋转矩阵R为单位阵III,平移矩阵ttt为0):P=K[I∣0]P = K\left[ {I|0} \right]P=K[I∣0]

  从上面两个转换的过程,我们可以得到从世界坐标轴转换到图像的过程可以把投影矩阵P表示为:
P=K[R∣t]P = K\left[ {R|t} \right]P=K[R∣t]
  其中: t=−RC^t = - R\hat Ct=−RC^。

  在这里:

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

1.1.3 图像坐标转换为像素坐标

  前面也提到了在图像坐标系中用的不是现实生活中的m来度量,而是用的 pixel 的个数,所以在上面转换到图像坐标系中还有个问题,就是坐标的表示还是m,并没有转换到像素坐标系统;在这里需要引入一个新概念就是:

  • mxm_xmx​ 表示在水平方向1m的长度包含的像素的个数;
  • mym_ymy​ 表示在竖直方向1m的长度包含的像素的个数;

  通过分别指定 mx,mym_x ,m_ymx​,my​(有的时候也是用dX,dYdX,dYdX,dY),可以得到一个像素点(m度量)为:1mx×1my{1 \over {m_x }} \times {1 \over {m_y }}mx​1​×my​1​

  • 图像像素坐标系:是一个二维直角坐标系,反映了相机CCD芯片中像素的排列情况。其原点OOO位于图像的左上角,u,vu,vu,v坐标轴分别余图像的两条边重合。像素坐标为离散值(0,1,2,…),以像素(pixel)为单位。
  • 图像物理坐标系:为了将图像与物理空间相关联,需要将图像转换到物理坐标系下。原点OOO位于图像中心(理想状态下),是相机光轴与像平面的交点(称为主点)。X,YX,YX,Y坐标轴分别与u,vu,vu,v轴平行。两坐标系实为平移关系,平移量为(u0,v0)\left( {u_0 ,v_0 } \right)(u0​,v0​)。

▲ 图1.1.7 图像坐标与像素坐标之间的关系

{u=xdX+u0v=ydY+v0\left\{ \begin{matrix} {u = {x \over {dX}} + u_0 }\\{v = {y \over {dY}} + v_0 }\\\end{matrix} \right.{u=dXx​+u0​v=dYy​+v0​​

  对应的其次形式的方程,为:

[uv1]=[1dX0u001dYv0001][xy1]\begin{bmatrix} \begin{matrix} u\\v\\1\\\end{matrix} \end{bmatrix} = \begin{bmatrix} \begin{matrix} {{1 \over {dX}}} & 0 & {u_0 }\\0 & {{1 \over {dY}}} & {v_0 }\\0 & 0 & 1\\\end{matrix} \end{bmatrix}\begin{bmatrix} \begin{matrix} x\\y\\1\\\end{matrix} \end{bmatrix}⎣⎡​uv1​​⎦⎤​=⎣⎡​dX1​00​0dY1​0​u0​v0​1​​⎦⎤​⎣⎡​xy1​​⎦⎤​

  但是需要说明的是像素并不一定是一个正方形,有时候可能也是一个矩形,所以要分别指定。

  所以,把上面的相机内参;KKK更新为:

K=[mxmy1][fpxfpy1][αxβxαyβy1]K = \begin{bmatrix} \begin{matrix} {m_x } & {} & {}\\{} & {m_y } & {}\\{} & {} & 1\\\end{matrix} \end{bmatrix}\begin{bmatrix} \begin{matrix} f & {} & {p_x }\\{} & f & {p_y }\\{} & {} & 1\\\end{matrix} \end{bmatrix}\begin{bmatrix} \begin{matrix} {\alpha _x } & {} & {\beta _x }\\{} & {\alpha _y } & {\beta _y }\\{} & {} & 1\\\end{matrix} \end{bmatrix}K=⎣⎡​mx​​my​​1​​⎦⎤​⎣⎡​f​f​px​py​1​​⎦⎤​⎣⎡​αx​​αy​​βx​βy​1​​⎦⎤​

  一般来说,在使用相机内参KKK计算坐标系转换时,提供的都是已经转换后的值。

1.1.4 成像畸变参数

  在几何光学和阴极射线管(CRT)显示中,畸变(distortion) 是对直线投影(rectilinear projection)的一种偏移。简单来说直线投影是场景内的一条直线投影到图片上也保持为一条直线。那畸变简单来说就是一条直线投影到图片上不能保持为一条直线了,这是一种光学畸变(optical aberration)。可能由于摄像机镜头的原因,这里不讨论,有兴趣的可以查阅光学畸变的相关的资料。
  畸变一般可以分为两大类,包括径向畸变和切向畸变。主要的一般径向畸变有时也会有轻微的切向畸变。

  畸变一般可以分为两大类,包括径向畸变和切向畸变。主要的一般径向畸变有时也会有轻微的切向畸变。

这部分的内容来自于: 相机标定(Camera calibration) : https://blog.csdn.net/honyniu/article/details/51004397 。

(1)径向畸变参数

  径向畸变的效应有三种,一种是桶形畸变(barrel distortion),另一种是枕形畸变(pincushion distortion),还有一种是两种的结合叫做胡子畸变(mustache distortion),从图片中可以很容易看出区别,具体见下图(图片来自wikipedia)

▲ 图1.1.8 三种径向畸变

  径向畸变可以用如下公式修正:
xcorr=xdis(1+k1r2+k2r4+k3r6)x_{corr} = x_{dis} \left( {1 + k_1 r^2 + k_2 r^4 + k_3 r^6 } \right)xcorr​=xdis​(1+k1​r2+k2​r4+k3​r6)ycorr=ydis(1+k1r2+k2r4+k3r6)y_{corr} = y_{dis} \left( {1 + k_1 r^2 + k_2 r^4 + k_3 r^6 } \right)ycorr​=ydis​(1+k1​r2+k2​r4+k3​r6)

(2)切向畸变参数

xcorr=xdis+[2p1xy+p2(r2+2x2)]x_{corr} = x_{dis} + \left[ {2p_1 xy + p_2 \left( {r^2 + 2x^2 } \right)} \right]xcorr​=xdis​+[2p1​xy+p2​(r2+2x2)]ycorr=ydis+[p1(r2+2y2)+2p2xy]y_{corr} = y_{dis} + \left[ {p_1 \left( {r^2 + 2y^2 } \right) + 2p_2 xy} \right]ycorr​=ydis​+[p1​(r2+2y2)+2p2​xy]

其中:

  • xdisx_{dis}xdis​和ydisy_{dis}ydis​表示基表的坐标;
  • xcorrx_{corr}xcorr​和ycorry_{corr}ycorr​表示修复后的坐标;
  • k1,k2,k3k_1 ,k_2 ,k_3k1​,k2​,k3​表示径向畸变参数;
  • p1,p2p_1 ,p_2p1​,p2​表示切向畸变参数;

  所以最终得到5个畸变参数:

D=(k1,k2,k3,p1,p2)D = \left( {k_1 ,k_2 ,k_3 ,p_1 ,p_2 } \right)D=(k1​,k2​,k3​,p1​,p2​)

1.1.5 相机标定

  那么可以利用这些来进行最终的任务相机标定,简单的过程可以描述为通过标定板,如下图,可以得到nnn个对应的世界坐标三维点 XiX_iXi​和对应的图像坐标二维点 xix_ixi​。这些三维点到二维点的转换都可以通过上面提到的相机内参 KKK,相机外参 RRR 和 ttt,以及畸变参数 DDD 经过一系列的矩阵变换得到。现在就用这些对应关系来求解这些相机参数。最后就是用线性方法求解方程式,这里就不做讨论了。

▲ 图1.1.9 相机标定
   ◎ 图片来源 :https://img-blog.csdnimg.cn/img_convert/f8587211cfc9b4a15fb459727129b5eb.png

§02 实验过程


2.1 相机校正

2.1.1 处理图片

  测试 图片一个来自于博文 python+OpenCV 相机标定 中测试的图片。通过逐步验证其中的过程,对于程序使用方法进行熟悉。

▲ 图2.1.1 用于测试的棋盘格

  第二个图片来自于博文 旋转的Apriltag码 中的图片。

▲ 图2.1.2 用于校正的棋盘格

2.1.2 提取角点

  • 使用函数:findChessboardCorners(image,(w,h),None);

  第一个参数为图片,第二个为图片横纵角点的个数。

(1)识别程序

img = cv2.imread(outfile)
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
img = cv2.imread(outfile)
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
ret, corners = cv2.findChessboardCorners(gray, (11, 8), None)
print("ret: {}".format(ret), "corners: {}".format(corners))
ret: True
corners: [[[913.4712  592.5734 ]][[866.50525 592.911  ]][[489.97418 268.61267]]
......[[443.44836 269.0252 ]]]

  ◎ 注意: 在识别棋盘格的时候,参数(11,8)一定需要与图片中的棋盘格的交叉点相同。否则就会出现识别错误。

(2)绘制棋盘格角点

if ret:for c in corners:cv2.circle(img, tuple(c[0].astype(int)), 4, (255, 0, 0), 2)plt.clf()
plt.figure(figsize=(15,15))
plt.imshow(img)

▲ 图2.1.3 识别出所有的棋盘格角点

▲ 图2.1.4 识别出所有的棋盘格角点

  也可以使用cv2中的棋盘格角点绘制程序:

if ret:cv2.drawChessboardCorners(img, (8, 6), corners, ret)plt.clf()
plt.figure(figsize=(15,15))
plt.imshow(img)

▲ 图2.1.5 识别出所有的棋盘格角点

▲ 图2.1.6 识别出所有的棋盘格角点

2.1.3 寻找亚像素点

  找寻亚像素角点:cornerSubPix(gray, corners, (winsize, winsize), (-1, -1), criteria);

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

(1)寻求代码

criteria = (cv2.TERM_CRITERIA_MAX_ITER | cv2.TERM_CRITERIA_EPS, 30, 0.001)
objp = zeros((cornernum[0]*cornernum[1], 3), float32)
objp[:,:2] = mgrid[0:cornernum[0],0:cornernum[1]].T.reshape(-1,2)
print("objp: {}".format(objp))obj_points = []
img_points = []obj_points.append(objp)corners2 = cv2.cornerSubPix(gray, corners, (5,5), (-1,-1), criteria)
for a,b in zip(corners2,corners): printt("a: {}".format(a),"b: {}".format(b))
a: [[245.83833 161.20932]]
b: [[245.83833 161.20932]]
a: [[341.6322  160.35397]]
b: [[341.6322  160.35397]]
a: [[438.44073 161.43779]]
b: [[438.44073 161.43779]]
a: [[533.5533  162.39111]]
b: [[533.5533  162.39111]]
a: [[627.3474  162.24904]]
b: [[627.3474  162.24904]]
a: [[721.0551  161.38828]]
b: [[721.0551  161.38828]]
a: [[815.3565  159.85548]]
b: [[815.3565  159.85548]]
a: [[906.8091  160.57172]]
b: [[906.8091  160.57172]]
。。。。。。

  可以看到这里的亚像素的 位置与原来的基本上是一模一样。

2.1.4 相机校正

size = gray.shape[::-1]
ret,mtx,dist,rvecs,twecs = cv2.calibrateCamera(obj_points, img_points, size, None, None)print("ret: {}".format(ret),"mtx: {}".format(mtx),"dist: {}".format(dist),"rvecs: {}".format(rvecs),"twecs: {}".format(twecs))
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 ) # 平移向量  # 外参数
ret: 0.48959099937033296mtx: [[643.69459427   0.         570.78090348][  0.         634.76121519 337.46417094][  0.           0.           1.        ]]dist: [[ 1.66966910e-01 -5.52524637e-01 -1.35284932e-03  9.90815870e-055.24320869e-01]]rvecs: [array([[-0.16766571],[-0.02841835],[-0.00905039]])]twecs: [array([[-3.39390322],[-1.86924141],[ 6.80979205]])]

两个图片返回数值

▲ 图2.1.7 小型棋盘格图片

ret: 0.16631371580249057mtx: [[1.50786795e+04 0.00000000e+00 6.54541919e+02][0.00000000e+00 1.50724341e+04 3.14861969e+02][0.00000000e+00 0.00000000e+00 1.00000000e+00]]dist: [[-1.17308456e+00  3.13694680e-02  9.74886764e-03  1.88517128e-023.58626204e-05]]rvecs: [array([[ 0.08765833],[-0.046283  ],[ 3.13133205]])]twecs: [array([[  5.52753965],[  5.93662035],[322.32638381]])]

▲ 图2.1.8 大型棋盘格

ret: 0.48959317666424174mtx: [[643.58400163   0.         570.77563433][  0.         634.64905358 337.46372513][  0.           0.           1.        ]]dist: [[ 1.66904579e-01 -5.52113905e-01 -1.35304755e-03  9.90757020e-055.23743526e-01]]rvecs: [array([[-0.16763778],[-0.0284135 ],[-0.00904968]])]twecs: [array([[-3.39384701],[-1.86924546],[ 6.8086255 ]])]

  通过上面的结果可以看返回的结果,第一个图片校正的结果效果比第二个更好一些。

2.2 完整程序

#!/usr/local/bin/python
# -*- coding: gbk -*-
#============================================================
# TEST1.PY                     -- by Dr. ZhuoQing 2021-12-27
#
# Note:
#============================================================from headm import *                 # =
import wget
import cv2#------------------------------------------------------------
testid = 0#------------------------------------------------------------
if testid == 0:imgurl = 'https://img-blog.csdnimg.cn/fd5b6fa046a242a2bc639031b4377f13.png#pic_center'cornernum = (11,8)
else:imgurl = 'https://img-blog.csdnimg.cn/2019041214582967.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2JldHJhcHBlZA==,size_16,color_FFFFFF,t_70'cornernum = (8, 6)outfile = '/home/aistudio/data/chessbimg1.jpg'if os.path.isfile(outfile):os.remove(outfile)
wget.download(imgurl, outfile)#    printt("Download file OK.")
#else:
#    printf("File is already downloaded.")#------------------------------------------------------------img = cv2.imread(outfile)
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)#plt.clf()
#plt.figure(figsize=(10,10))
#plt.imshow(img)#------------------------------------------------------------
ret, corners = cv2.findChessboardCorners(gray, cornernum, None)#------------------------------------------------------------
if ret:cv2.drawChessboardCorners(img, cornernum, corners, ret)plt.clf()
plt.figure(figsize=(15,15))
plt.imshow(img)#------------------------------------------------------------
criteria = (cv2.TERM_CRITERIA_MAX_ITER | cv2.TERM_CRITERIA_EPS, 30, 0.001)
objp = zeros((cornernum[0]*cornernum[1], 3), float32)
objp[:,:2] = mgrid[0:cornernum[0],0:cornernum[1]].T.reshape(-1,2)
printt(objp:)obj_points = []
img_points = []obj_points.append(objp)
img_points.append(corners)#------------------------------------------------------------corners2 = cv2.cornerSubPix(gray, corners, (5,5), (-1,-1), criteria)#------------------------------------------------------------
size = gray.shape[::-1]
ret,mtx,dist,rvecs,twecs = cv2.calibrateCamera(obj_points, img_points, size, None, None)printt(ret:,mtx:,dist:,rvecs:,twecs:)#------------------------------------------------------------
#        END OF FILE : TEST1.PY
#============================================================

※ 总  结 ※


  对于相机进行校正,是为之后视觉测量奠定基础。本文在总结了相机校正中的基本概念。使用cv2的函数说明校正的过程。


■ 相关文献链接:

  • python+OpenCV 相机标定
  • 相机标定(一)-原理及内参、外参
  • 相机标定(Camera calibration)
  • 旋转的Apriltag码

● 相关图表链接:

  • 图1.1.1 世界坐标转换为相机坐标
  • 图1.1.2 世界坐标系与相机坐标系
  • 图1.1.3 相机坐标中的点与成像平面
  • 图1.1.4 相机坐标系以及成像平面之间的关系
  • 图1.1.5 利用三角几何比例关系确定成像位置
  • 图1.1.6 成像坐标原点在图像坐标中的位置
  • 图1.1.7 图像坐标与像素坐标之间的关系
  • 图1.1.8 三种径向畸变
  • 图1.1.9 相机标定
  • 图2.1.1 用于测试的棋盘格
  • 图2.1.2 用于校正的棋盘格
  • 图2.1.3 识别出所有的棋盘格角点
  • 图2.1.4 识别出所有的棋盘格角点
  • 图2.1.5 识别出所有的棋盘格角点
  • 图2.1.6 识别出所有的棋盘格角点
  • 图2.1.7 小型棋盘格图片
  • 图2.1.8 大型棋盘格

相机校正与相机内参、外参相关推荐

  1. 计算机视觉——棋盘格标定法获取相机内参外参

    计算机视觉--棋盘格标定法获取相机内参外参 一.原理 相机标定目的 相机标定的输入 相机标定的输出 相机标定策略 相机拍摄图像变换过程 相机内参 相机外参 二.环境 三.数据集 四.运行结果与分析 角 ...

  2. 【相机标定基于消失点的外参标定】

    [相机标定&基于消失点的外参标定] 文章一:Camera calibration using two or three vanishing points 文章二:Online Extrinsi ...

  3. 相机的内参会改变吗_相机内参外参及成像过程

    前段时间有人问我怎么由点的世界坐标计算计算对应的像素坐标,我详细的推导了下,现在把整个过程写篇博客.虽然网上有很多相关的文章,但是我可能会写的更详细些. 一.小孔成像模型 1.基本概念及公式 如图所示 ...

  4. Halcon内参外参畸变矫正

    相机畸变矫正 CameraParameters := [0.00367057,-809.403,2.20647e-006,2.2e-006,1136.84,1064.02,2592,1944] Cam ...

  5. 计算机视觉(相机标定;内参;外参;畸变系数)

    目录 一.预备知识 1.坐标系变换过程(相机成像过程) (1)相机坐标系转换为图像坐标系(透视投影变换遵循的是针孔成像原理) (2)齐次坐标的引入原因:(为什么引入齐次坐标???) 2.内参与外参矩阵 ...

  6. (九)相机内参、外参、反透视变换python opencv

    背景知识 任务需求:将相机上的一个点投影到真实世界平面上去. 原则上单目相机是不可以的,因为只记录了二维信息,真实世界是三维的,双目相机可以通过视差,或者单目+IMU组合,但是由于特征点在地面上的先验 ...

  7. ros --- 双目相机内参与外参标定

    ros --- 双目相机内参与外参标定 小觅相机直接获取参数 手动重新标定 1. 双目相机内外参标定 生成标定板 录制 stereo_calibra.bag 标定 标定结果 标定验证 2. 双目 + ...

  8. imu相机标定_解放双手——相机与IMU外参的在线标定

    本文作者 沈玥伶,公众号:计算机视觉life,编辑部成员 一.相机与IMU的融合 在SLAM的众多传感器解决方案中,相机与IMU的融合被认为具有很大的潜力实现低成本且高精度的定位与建图.这是因为这两个 ...

  9. 相机与激光测距仪的外参标定(提升相机标定)

    文章目录 Abstract I Introduction II Basic Equations A Geometric Constraints III Solving Extrinsic calibr ...

最新文章

  1. C# WinForm程序中强制退出程序以及启动程序
  2. 【Boost】boost库中function和bind一起使用的技巧(一)
  3. 本周两场直播丨PostgreSQL中的锁;数据库对象命名设计规范手册
  4. 新增对象Products 的流程说明
  5. 次坐标从0开始_全站仪使用方法及坐标计算,详细讲解!建议收藏!
  6. 科技创新 可持续发展 论坛_可持续发展时间
  7. java 获取class的方法_[Java教程]Java反射定义、获取Class三种方法
  8. 翻译: 2.5. 自动微分 深入神经网络 pytorch
  9. jsp简单案例(供小白学习)
  10. Zblog主题,Zblog响应式主题,免费Zblog主题
  11. 通过银行卡号查询银行卡信息
  12. Python入门学习二:列表
  13. 了解一下nested数据类型
  14. 拍手游戏Python
  15. Sentence-Transformer的使用及fine-tune教程
  16. 沈阳计算机ps自锁按键开关,点按式轻触开关如何实现自锁轻触开关带锁按键开关功能?...
  17. CVPR2019 Oral论文《Side Window Filtering》解读及算法 Python 实现
  18. Don’t Cross 32 GB!
  19. 前端如何引入vConsole
  20. 最新炼数成金Oracle 12C RAC集群原理与管理实战

热门文章

  1. Vuforia Android 6 Camera Error
  2. Centos 6.3 x86_64安装与配置bacula
  3. 做个有产品意识的工程师
  4. 通过 .gitlab-ci.yml配置任务-官方配置文件翻译
  5. VIEWGOOD流媒体平台推进广州图书馆数字化进程
  6. JAVA IF判断语句
  7. RHEL5+ImageMagick-6.4.0-0+jmagick-6.4.0+resin 解决方案
  8. 2019RPA财务行业峰会:财务数字化转型
  9. IntelliJ IDEA(五) :酷炫插件系列
  10. 《JavaScript高级程序设计》笔记:变量、作用域和内存问题(四)