[VP] 简易相机标定装置实现—计算相机标定矩阵K - 多视觉几何


一、算法原理

用相机拍摄一张带有三个正方形框的照片,确定其 4*3=12 个点,如下图所示:

在这里插入图片描述

设定单应矩阵 H {\bf H} H 为:

H = [ H 11 H 12 H 13 H 21 H 22 H 23 H 31 H 32 H 33 ] (1) H = \begin{bmatrix} H_{11} & H_{12} & H_{13} \\ H_{21} & H_{22} & H_{23} \\ H_{31} & H_{32} & H_{33} \end{bmatrix} \tag{1} H=H11H21H31H12H22H32H13H23H33(1)

[ x i y i 1 ] \begin{bmatrix} x_{i} \\ y_{i} \\1 \end{bmatrix} xiyi1是角点 ( 0 , 0 ) T , ( 0 , 1 ) T , ( 1 , 0 ) T , ( 1 , 1 ) T (0, 0)^{T}, (0, 1)^{T}, (1, 0)^{T}, (1, 1)^{T} (0,0)T,(0,1)T,(1,0)T,(1,1)T,

[ x i ′ y i ′ 1 ] \begin{bmatrix} x_{i}^{'} \\ y_{i}^{'} \\ 1 \end{bmatrix} xiyi1是图中正方形的四个角点

[ x i ′ y i ′ 1 ] = H [ x i y i 1 ] (2) \begin{bmatrix} x_{i}^{'} \\ y_{i}^{'} \\ 1 \end{bmatrix} = H \begin{bmatrix} x_{i} \\ y_{i} \\1 \end{bmatrix} \tag{2} xiyi1=Hxiyi1(2)

根据公式 ( 1 ) ( 2 ) {\bf (1)(2)} (1)(2), 我们可以计算 x ′ 和   y ′ x^{'} 和 \space y^{'} x y, 此处 H 33 = 1 H_{33} =1 H33=1,因为变换使用的是齐次点, aH和 H 一样的, 所以我们可以忽略缩放. 然后得到下列式子:

x i ′ = H 11 x i + H 12 y i + H 13 H 31 x i + H 32 y i + 1 (3) x_{i}^{'} = \frac{H_{11}x_{i} + H_{12}y_{i}+H_{13}}{H_{31}x_{i}+H_{32}y_{i}+1}\tag{3} xi=H31xi+H32yi+1H11xi+H12yi+H13(3)

y i ′ = H 21 x i + H 22 y i + H 23 H 31 x i + H 32 y i + 1 (3) y_{i}^{'} = \frac{H_{21}x_{i} + H_{22}y_{i}+H_{23}}{H_{31}x_{i}+H_{32}y_{i}+1}\tag{3} yi=H31xi+H32yi+1H21xi+H22yi+H23(3)

分别计算完三个正方形的单应矩阵 H 后,由于图像的圆点是 h 1 ± i h 2 h_{1} ± ih_{2} h1±ih2, 如果 h 1 ± i h 2 h_{1} ± ih_{2} h1±ih2 ω \omega ω 上, 那么 ( h 1 ± i h 2 ) ω ( h 1 ± i h 2 ) = 0 (h_{1} ± ih_{2}) \omega (h_{1} ± ih_{2}) = 0 (h1±ih2)ω(h1±ih2)=0

那么实部和虚部分别给出:
h 1 T ω h 2 = 0 (4) h_{1}^{T}\omega h_{2} = 0\tag{4} h1Tωh2=0(4)
h 1 T ω h 1 = h 2 T ω h 2 (4) h_{1}^{T}\omega h_{1} = h_{2}^{T}\omega h_{2}\tag{4} h1Tωh1=h2Tωh2(4)

之前已经得到了 H 1 , H 2   a n d   H 3 H_{1}, H_{2}\ and \ H_{3} H1,H2 and H3, 使用他们和公式 ( 4 ) {\bf (4)} (4), 就可以计算出 ω \omega ω i.e. Matrix C.

最后根据下式得到标定矩阵 K:
ω = ( k k T ) − 1 = K − T K − 1 \omega = (kk^{T})^{-1} = K^{-T}K^{-1} ω=(kkT)1=KTK1

二、代码实现

import cv2
from sympy import *
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt

0、显示图像和正方形的点

img = cv2.imread('Ex-4.PNG')
plt.plot(77, 73, 'o', color='r')
plt.plot(244, 37, 'o', color='r')
plt.plot(247, 165, 'o', color='r')
plt.plot(111, 209, 'o', color='r')

plt.plot(300, 40, 'o', color='g')
plt.plot(454, 98, 'o', color='g')
plt.plot(424, 231, 'o', color='g')
plt.plot(300, 172, 'o', color='g')

plt.plot(247, 196, 'o', color='b')
plt.plot(395, 235, 'o', color='b')
plt.plot(347, 363, 'o', color='b')
plt.plot(174, 305, 'o', color='b')

plt.imshow(img)

在这里插入图片描述

1、计算单应矩阵 H

根据之前写的公式(1)(2)(3),计算出 H

# Compute homography  𝐇
def getH(P1, P2, P3, P4, P01, P02, P03, P04):
    H11 = Symbol('H11')
    H12 = Symbol('H12')
    H13 = Symbol('H13')
    H21 = Symbol('H21')
    H22 = Symbol('H22')
    H23 = Symbol('H23')
    H31 = Symbol('H31')
    H32 = Symbol('H32')
    
    def formula(originalPoint, squarePoint):
        f1 = (H11*originalPoint[0] + H12*originalPoint[1] + H13) / (H31*originalPoint[0] + H32*originalPoint[1] + 1) - squarePoint[0]
        f2 = (H21*originalPoint[0] + H22*originalPoint[1] + H23) / (H31*originalPoint[0] + H32*originalPoint[1] + 1) - squarePoint[1]
        return f1, f2
    
    f1, f2 = formula(P01, P1)
    f3, f4 = formula(P02, P2)
    f5, f6 = formula(P03, P3)
    f7, f8 = formula(P04, P4)
    
    result = []
    answer = solve([f1, f2, f3, f4, f5, f6, f7, f8], [H11, H12, H13, H21, H22, H23, H31, H32])
    
    for i, j in answer.items():
        result.append(j)
    H = Matrix([[result[0], result[1], result[2]], 
                [result[3], result[4], result[5]], 
                [result[6], result[7], 1]])
    return H

1.1 确定正方形的角点

P01 = [0, 0]
P02 = [0, 1]
P03 = [1, 1]
P04 = [1, 0]

P1 = [77, 73]
P2 = [244, 37]
P3 = [247, 165]
P4 = [111, 209]

P5 = [300, 40]
P6 = [454, 98]
P7 = [424, 231]
P8 = [300, 172]

P9 = [247, 196]
P10 = [395, 235]
P11 = [347, 363]
P12 = [174, 305]

1.2 计算单应矩阵 H

H1 = getH(P1, P2, P3, P4, P01, P02, P03, P04)
H2 = getH(P5, P6, P7, P8, P01, P02, P03, P04)
H3 = getH(P9, P10, P11, P12, P01, P02, P03, P04)
simplify(H1)

在这里插入图片描述

simplify(H2)

在这里插入图片描述

simplify(H3)

在这里插入图片描述

2、计算图像正方形的成像圆点

# COmpute omega 
def getOmega(H1, H2, H3):
    a = Symbol('a')
    b = Symbol('b')
    c = Symbol('c')
    d = Symbol('d')
    e = Symbol('e')
    f = Symbol('f')

    C = Matrix([[a, b/2, d/2], 
                [b/2, c, e/2], 
                [d/2, e/2, f]])
    
    # h1, h2 of H1 Matrix 
    h11 = H1.col(0)
    h12 = H1.col(1)

    # h1, h2 of H2 Matrix 
    h21 = H2.col(0)
    h22 = H2.col(1)

    # h1, h2 of H3 Matrix 
    h31 = H3.col(0)
    h32 = H3.col(1)
    
    f1 = h11.T * C * h12
    f2 = h11.T * C * h11 - h12.T * C * h12
    f3 = h21.T * C * h22
    f4 = h21.T * C * h21 - h22.T * C * h22
    f5 = h31.T * C * h32
    f6 = h31.T * C * h31 - h32.T * C * h32
    
    result = []
    answer = solve([f1, f2, f3, f4, f5], [a, b, c, d, e])
    
    for i, j in answer.items():
        result.append(N(j, 5) / f)
        
    return result

abcde = getOmega(H1, H2, H3)

C = Matrix([[abcde[0], abcde[1]/2, abcde[3]/2], 
           [abcde[1]/2, abcde[2], abcde[4]/2], 
           [abcde[3]/2, abcde[4]/2, 1]])
C

在这里插入图片描述

3、使用Cholesky因子计算标定矩阵 K

we finally get calibration matrix K, according to this following formula:

ω = ( k k T ) − 1 = K − T K − 1 \omega = (kk^{T})^{-1} = K^{-T}K^{-1} ω=(kkT)1=KTK1


K = C.cholesky(false).inv().T
K = K / K[8]
K.xreplace({n : round(n, 1) for n in K.atoms(Number)}) # Constrained decimal precision

在这里插入图片描述

和书上的结果对比下,数据相似但是不相同,这是由于图像缩放和选点位置误差造成的。
在这里插入图片描述

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是土豆大叔啊!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值