相机标定实践1-获取内参

本文介绍了相机标定中内参的获取方法,包括理论和实践两部分。通过使用棋盘图,利用最少3幅图像和4个特征点求解单应矩阵,进而计算相机的内部参数和畸变参数。文章详细阐述了内参标定的步骤,涉及单应矩阵的构建、最小二乘法求解以及如何从B矩阵求得内参矩阵A。

相机标定,获取内参
至少3幅影响(求B,6参数,每幅影像对应求2个),每幅影像至少4个特征点(求H,8参数,每个特征点对应求2个)
参考资料:https://blog.youkuaiyun.com/zkl99999/article/details/48372203?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

https://blog.youkuaiyun.com/a6333230/article/details/83478064

理论1
相机标定分:内参标定、外参标定、c矩阵
内参标定:采用棋盘图或者点阵图,将相机固定(焦距、光圈等内部元素)。用相机拍摄多组不同角度的棋盘图,这点和普通的matlab的棋盘图标定类似。matlab利用棋盘图标定,它也给出了标定的外参,但是给定的并非我们所求,而是将世界坐标系定在了棋盘图上,我们需要的世界坐标系是固定不变的或者至少是与相机的相对位置不会发生改变。
内参标定输入为:像素坐标u、v和世界坐标x、y、z,该z没有定义具体的数值,因为在此处的求解不会应用到,并且我们此步也无法求得。那么这些参数怎么来的呢?u、v为图像中棋盘格的角点坐标,与其对应的x、y表示该角点在整个棋盘图下的坐标,该坐标系定在棋盘图上,因此我们拍摄5次图像,这些图像相应的坐标应该相同。为了计算时数据的变换较为方便,这里z也给出,值给0或1都行,不影响计算。
内参标定输出为:内部参数+相机畸变参数。内部参数:fu、fv、u、v;相机畸变参数:k1,k2
内参求解步骤:
1.求单应矩阵
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里的h33设置为1……课本中给出的理由是它可以设置为任意数,二郎也和同事讨论过,没有定论,有一种理解有道理:计算中h33能都提到右边,那么在根据公式进行求解时,它变成几,都是对所有公式进行操作的,因此公式之间的关系不会发生改变,所求出来代表关系的h参数也不会受到影响,只是按h33进行了缩放。
比如:两边先同时除以h33(由于没有找到这里的h33=1的解释,因此二郎做了这种假设)
每个特征点,可以求得两个方程。这里有8个未知数,因此可以用4个特征点完成求解。
这里用到了棋盘格,在一张棋盘格图中,我们得到了很多(u,v)与(x,y)的对应,因此可以解出我们的单应矩阵。
这里每个棋盘格图对应了一个单应矩阵,这些单应矩阵主要的不同在于(R,t),每个棋盘图都有自己的世界坐标系,原点在棋盘图的一个角点上,这个matlab内部程序已经指定,一般情况下为左上角。此处单应矩阵的求解用到的最小二乘法。下面的推导和求解,均是建立在单应矩阵已知的情况下进行的。

实践1
1.拍摄标定板照片

function CreatePlate()
J = (checkerboard(300,3,4)>0.5);    %生成黑白棋盘图像
figure, imshow(J)   %显示黑白棋盘图像
imwrite(J,'plate.jpg'); %保存黑白棋盘图像
end 

在这里插入图片描述
然后手机拍照存储作为相机拍摄的标定板照片
设照片名称为“MyPlate1.jpg”

在这里插入图片描述
2.标定板角点检测
harris算法

function Myharris()
X = imread('MyPlate1.jpg');         % 读取图像
% figure,imshow(X);                       %在窗口1中打开原始图像
Info = imfinfo('MyPlate1.jpg');     %获取图像相关信息
if (Info.BitDepth > 8)
    f = rgb2gray(X);                    %若图像的位深大于8,则用rgb2gray将彩色图像转换为灰度图像 
end
%计算图像亮度f(x,y)在点(x,y)处的梯度-----------------------------------------------
ori_im = double(f) / 255;               %unit8转化为64位双精度double64,取值在0~1
fx = [-2 -1 0 1 2];                     % x方向梯度算子(用于Harris角点提取算法)
fy = [-2; -1; 0; 1; 2];                 % y方向梯度算子(用于Harris角点提取算法)
gx = filter2(fx, ori_im);               % x方向滤波
gy = filter2(fy, ori_im);               % y方向滤波
%构造自相关矩阵---------------------------------------------------------------
gx2 = gx .^ 2;
gy2 = gy .^ 2;
gxy = gx .* gy;
% clear gx;
% clear gy;
h= fspecial('gaussian', [7 7], 0.6);    % 产生5*5的高斯窗函数,sigma取值在0.3~0.9,此处取0.6
gx2 = filter2(h,gx2);
gy2 = filter2(h,gy2);
gxy = filter2(h,gxy);
%提取特征点---------------------------------------------------------------
[height,width]=size(ori_im);            %读取图像的高和宽
result = zeros(height, width);          % 纪录角点位置,角点处值为1
I = zeros(height, width);
Imax = 0;                               % 图像中最大的R值
k = 0.2;                               %k为常系数,经验取值范围为0.04~0.06
for i = 1 : height
    for j = 1 : width
        M = [gx2(i, j) gxy(i, j); gxy(i, j) gy2(i, j)];         % auto correlation matrix
        I(i,j) = det(M) - k * (trace(M)) ^ 2;                   % 计算R
        if I(i,j) > Imax
            Imax = I(i, j);
        end;
    end;
end;
T = 0.06 * Imax;%固定阈值,当R(i, j) > T时,则被判定为候选角点
%在计算完各点的值后,进行局部非极大值抑制-------------------------------------
cnt = 0;
for i = 2 : height-1
    for j = 2 : width-1
        % 进行非极大抑制,窗口大小3*3
        if (I(i, j) > T && I(i, j) > I(i-1, j-1) && I(i, j) > I(i-1, j) && I(i, j) > I(i-1, j+1) && I(i, j) > I(i, j-1) && ...
                I(i, j) > I(i, j+1) && I(i, j) > I(i+1, j-1) && I(i, j) > I(i+1, j) && I(i, j) > I(i+1, j+1))
            result(i, j) = 1;
            cnt = cnt+1;
        end;
    end;
end;
[posc, posr] = find(result == 1);%返回矩阵result元素等于1处的横纵坐标,就是图像中的角点
disp(cnt);                       %输出角点个数
figure,imshow(X);                %在窗口2中打开提取特征点的图像
hold on;                         %保留当前窗口的图像,再画另一幅图,使叠加显示
plot(posr, posc, 'ro');          %将图像中找到的角点用品红色的星号标出
uv=[posc, posr] ;
disp(uv);  
end 

在这里插入图片描述
并存储了检测到的角点坐标

 uv=[232         255
         399         269
         560         283
         228         424
         558         445
         716         454
         868         465
         224         593
         391         602
         554         610
         714         617
         868         623
         219         764
         388         769
         551         775
         868         784
         214         937
         384         939
         549         942
         711         945
         866         948
           208        1115
         381        1114
         548        1114
         710        1114
        866        1112
         203        1294
         545        1287
         708        1282
        863        1277];
xy=[-30 20
   -30 10
   -30 0 
   -20 20
   -20 0
   -20 -10
   -20 -20
   -10 20
   -10 10
   -10 0
   -10 -10
   -10 -20
   0 20 
   0 10
   0 0 
   0 -20
   10 20
   10 10
   10 0
   10 -10
   10 -20
   20 20
   20 10
   20 0
   20 -10
   20 -20
   30 20
   30 0
   30 -10
   30 -20];

超定方程最小二乘解法:
在这里插入图片描述
在这里插入图片描述

function H=MyFunSolveHomography(uv,xy)
[count,~]=size(uv);
matrix_uv=zeros(count*2,1);
matrix_fxy=zeros(count*2,1);
u=0;
v=0;
x=0;
y=0;

for i=1:count 
    u=uv(i,1);
    v=uv(i,2);
    x=xy(i,1);
    y=xy(i,2);
    matrix_uv(i*2-1,1)=u;
     matrix_uv(i*2,1)=v;
     matrix_fxy(i*2-1,1:8)=[x,y,1,0,0,0,-u*x,-u*y];
       matrix_fxy(i*2,1:8)=[0,0,0,x,y,1,-v*x,-v*y];
end 

result=inv(matrix_fxy'*matrix_fxy)*matrix_fxy'*matrix_uv;
H=[result(1,1) result(2,1) result(3,1)
    result(4,1) result(5,1) result(6,1)
    result(7,1) result(8,1) 1];
end 
H=[   -0.6017  -17.1080  552.9464
   16.2357   -1.7699  774.8146
   -0.0006   -0.0016    1.0000]

理论2
2.单应矩阵构造v,进行B的求解

在这里插入图片描述这里有人会不理解,r1=和r2=是怎么来的?其实自己可以推导一下,把A设成[3X3]的矩阵,乘进去,应该能够看到,组成了[Ar1 Ar2 Ar3],它们互相还是独立的。至于为什么A到A逆,这个是最基本的转换,左右同时左乘A逆,看一下,是不是变过来了。

在这里插入图片描述
这里的A矩阵为内参矩阵,上面两个式子其实不难证明,

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
由于B为对称矩阵,因此B中元素可以写为

在这里插入图片描述
大家可以从上面看到B是由A矩阵组成的,那们A的组合满足的关系,B也满足
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
V的由来……大部分文献都没有提到,其实比较简单,直接计算hBh,计算完构造vb,b已经在前面定义。
后面的vb等于0的两项也来自前面约束条件
在这里插入图片描述
用奇异值分解最小奇异值对应的特征向量便可以表示为b

[u s v]=svd(V);        %用正交分解解出b
b=v(:,6);

注意:
这个方程组的本质和前面那两个用h和A组成的约束条件方程组是一样的。在此重复一遍解释:如果我们想完全解出这五个未知量,则需要3个单应性矩阵。3个单应性矩阵在2个约束下可以产生6个方程。这样可以解出全部的五个内参了。大家想一下,我们怎样才能获得三个不同的单应性矩阵呢?答案就是,用三幅标定物平面的照片。我们可以通过改变摄像机与标定板间的相对位置来获得三张不同的照片。(当然也可以用两张照片,但这样的话就要舍弃掉一个内参了γ=0)
通过至少含一个棋盘格的三幅图像,应用上述公式我们就可以估算出B了。得到B后,我们通过cholesky分解 ,就可以轻松地得到摄像机的内参阵A。
实践2
同实践1,获得三副标定板影像,以及对应得uv,xy坐标以及H矩阵如下:
图片2

uv=[303 553
       310 746
       315 932
       457 541
       462 745
       470 1137
       630 303
       632 526
       634 743
       639 1159
       642 1365
       644 1562];

       xy=[-20 10
           -10 10
           0 10
           -20 0
           -10 0
           10 0
           -30 -10
           -20 -10
           -10 -10
           10 -10
           20 -10
           30 -10];

 H=[    0.9209  -13.1715  465.9604
   20.6899    4.7150  942.7371
    0.0011    0.0062    1.0000]

图片3
 uv=[266 520 
       272 741
       275 957
       279 1170
       462 535
       467 947
       469 1145
       635 346
       635 745
       637 1125];

       xy=[-20 20
           -10 20
           0 20
           10 20
           -20 10
           0 10
           10 10
           -30 0
           -10 0
           10 0];
    
          H=[0.6984  -19.5586  636.1907
   20.0233   -4.2438  936.6151
    0.0010   -0.0055    1.0000] 

求解B
函数:

function V=MyFunCreateV(H)
i=1;
j=2;
v12=[H(i,1)*H(j,1) 
    H(i,1)*H(j,2)+H(i,2)*H(j,1) 
    H(i,2)*H(j,2) 
    H(i,3)*H(j,1)+H(i,1)*H(j,3) 
    H(i,3)*H(j,2)+H(i,2)*H(j,3)
    H(i,3)*H(j,3)];
i=1;
j=1;
v11=[H(i,1)*H(j,1) 
    H(i,1)*H(j,2)+H(i,2)*H(j,1) 
    H(i,2)*H(j,2) 
    H(i,3)*H(j,1)+H(i,1)*H(j,3) 
    H(i,3)*H(j,2)+H(i,2)*H(j,3)
    H(i,3)*H(j,3)];
i=2;
j=2;
v22=[H(i,1)*H(j,1) 
    H(i,1)*H(j,2)+H(i,2)*H(j,1) 
    H(i,2)*H(j,2) 
    H(i,3)*H(j,1)+H(i,1)*H(j,3) 
    H(i,3)*H(j,2)+H(i,2)*H(j,3)
    H(i,3)*H(j,3)];
V=[v12'
    (v11-v22)'];
% [a,b,c]=svd(V);
% B=a(:,6);
end

数据输入输出

H1=[   -0.6017  -17.1080  552.9464
    16.2357   -1.7699  774.8146
    -0.0006   -0.0016    1.0000];
H2=[    0.9209  -13.1715  465.9604
    20.6899    4.7150  942.7371
    0.0011    0.0062    1.0000];
H3=[0.6984  -19.5586  636.1907
    20.0233   -4.2438  936.6151
    0.0010   -0.0055    1.0000] ;
V1=MyFunCreateV(H1);
V2=MyFunCreateV(H2);
V3=MyFunCreateV(H3);
V=[V1
    V2
    V3];
[a,b,c]=svd(V);
B=c(:,6)
b =
    0.7102
   -0.5751
    0.4055
   -0.0167
    0.0128
    0.0004
B =

    0.7102   -0.5751   -0.0167
   -0.5751    0.4055    0.0128
   -0.0167    0.0128    0.0004

理论3
利用B,求出内参矩阵A
在这里插入图片描述
在这里插入图片描述
注意:
由于照片数量较少,所以结果可能出现非数字或虚数,但是理论没有问题,增加照片数量即能成功

clear all
clc
H1=MyH('MyPlate1.jpg') ;
H2=MyH('MyPlate2.jpg') ;
H3=MyH('MyPlate3.jpg') ;
H4=MyH('MyPlate4.jpg') ;
H5=MyH('MyPlate5.jpg') ;
H6=MyH('MyPlate6.jpg') ;
H7=MyH('MyPlate7.jpg') ;
H8=MyH('MyPlate8.jpg') ;
H9=MyH('MyPlate9.jpg') ;
H10=MyH('MyPlate10.jpg') ;
H11=MyH('MyPlate11.jpg') ;
H12=MyH('MyPlate12.jpg') ;
H13=MyH('MyPlate13.jpg') ;
H14=MyH('MyPlate14.jpg') ;
H15=MyH('MyPlate15.jpg') ;
H16=MyH('MyPlate16.jpg') ;

V1=MyFunCreateV(H1);
V2=MyFunCreateV(H2);
V3=MyFunCreateV(H3);
V4=MyFunCreateV(H4);
V5=MyFunCreateV(H5);
V6=MyFunCreateV(H6);
V7=MyFunCreateV(H7);
V8=MyFunCreateV(H8);
V9=MyFunCreateV(H9);
V10=MyFunCreateV(H10);
V11=MyFunCreateV(H11);
V12=MyFunCreateV(H12);
V13=MyFunCreateV(H13);
V14=MyFunCreateV(H14);
V15=MyFunCreateV(H15);
V16=MyFunCreateV(H16);

V=[V1
    V2
    V3
    V4
    V5
    V6
    V7
    V8
    V9
    V10
    V11
    V12
    V13
    V14
    V15
    V16];
V=V'*V;
[u, s, v]=svd(V);

%张氏解法
% b=v(:,6)
% B=[b(1,1),b(2,1),b(4,1)
%     b(2,1),b(3,1),b(5,1)
%     b(4,1),b(5,1),b(6,1)]
% v0=(B(1,2)*B(1,3)-B(1,1)*B(2,3))/(B(1,1)*B(2,2)-B(1,2)*B(1,2));
% ramda=B(3,3)-((B(1,3)*B(1,3)+v0*(B(1,2)*B(1,3)-B(1,1)*B(2,3))))/B(1,1);
% fu=sqrt(ramda/B(1,1));
% fv=sqrt(ramda*B(1,1)/(B(1,1)*B(2,2)-B(1,2)*B(1,2)));
% s=-B(1,2)*fu*fu*fv/ramda;
% u0=s*v0/fv-B(1,3)*fu*fu/ramda;
% A=[fu s u0
%     0 fv v0
%     0 0 1]

% A =
% 
%     0.0013   -0.0002    0.0006
%          0    0.0013    0.0009
%          0         0    1.0000

%网上私人解法
 b=v(:,6);
    v0=(b(2)*b(4)-b(1)*b(5))/(b(1)*b(3)-b(2)^2);
    s=b(6)-(b(4)^2+v0*(b(2)*b(4)-b(1)*b(5)))/b(1)
    alpha_u=sqrt(s/b(1));
    alpha_v=sqrt(s*b(1)/(b(1)*b(3)-b(2)^2));
    skewness=-b(2)*alpha_u*alpha_u*alpha_v/s;
    u0=skewness*v0/alpha_u-b(4)*alpha_u*alpha_u/s;
    A=[alpha_u skewness u0
        0      alpha_v  v0
        0      0        1]
   mytest=1
    
%     A =
% 
%     0.0013   -0.0002    0.0006
%          0    0.0013    0.0009
%          0         0    1.0000

% A =
% 
%     0.0018   -0.0002    0.0008
%          0    0.0017    0.0013
%          0         0    1.0000

% r1=s*inv(A)*H1(:,1);
% r2=s*inv(A)*H1(:,2);
% r3=r1*r2;
% t=s*inv(A)*H1(:,3);
% RL=[r1 r2 r3]; 
% [u s v]=svd(RL);
% RL=u*v';    
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值