国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

張正友相機(jī)標(biāo)定(全流程,含畸變,matlab源代碼解析)

這篇具有很好參考價(jià)值的文章主要介紹了張正友相機(jī)標(biāo)定(全流程,含畸變,matlab源代碼解析)。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

張正友標(biāo)定的具體原理很多文章已經(jīng)介紹,這里主要結(jié)合源代碼對其中的基本原理及本人遇到的問題進(jìn)行介紹。(僅介紹基本原理供本人復(fù)習(xí),同時(shí)方便他人,如有問題,請及時(shí)指正勿噴)

1. 標(biāo)定基本思路介紹

相機(jī)標(biāo)定,即獲取其內(nèi)參、外參、畸變系數(shù)(內(nèi)參與外參及相機(jī)成像模型的解釋可以參考SLAM入門之視覺里程計(jì))。
具體可以描述為
s m ? ? = K [ R T ] M s\overset{-}{\mathop{m}}\,=K[\begin{matrix} R & T \\ \end{matrix}]M sm?=K[R?T?]M
其中s為世界坐標(biāo)系到圖像坐標(biāo)系的尺度因子,K為內(nèi)參矩陣,具體為
K = [ f x 0 c 1 0 f y c 2 0 0 1 ] K=\left[ \begin{matrix} {{f}_{x}} & 0 & {{c}_{1}} \\ 0 & {{f}_{y}} & {{c}_{2}} \\ 0 & 0 & 1 \\ \end{matrix} \right] K= ?fx?00?0fy?0?c1?c2?1? ?
[R T]為旋轉(zhuǎn)矩陣與平移向量,M為三維坐標(biāo)點(diǎn)。

張正友標(biāo)定方法的核心即是采用平面標(biāo)定板,從而可以方便的將標(biāo)定點(diǎn)的真值Z置為0,以此方便計(jì)算。

具體流程主要為
1、計(jì)算相機(jī)內(nèi)參(由于采用平面標(biāo)定板,可以很方面的計(jì)算出單應(yīng)矩陣,然后根據(jù)單應(yīng)矩陣計(jì)算出內(nèi)參)

  1. 計(jì)算初始相機(jī)外參(計(jì)算出內(nèi)參后,根據(jù)單應(yīng)矩陣直接計(jì)算即可獲得外參)
  2. 最大似然優(yōu)化相機(jī)內(nèi)參與外參(1、2得到的結(jié)果必定是帶有誤差的,因此需進(jìn)行優(yōu)化,此處誤差函數(shù)不考慮畸變)
  3. 計(jì)算畸變系數(shù)(以上一步算到的結(jié)果作為真值計(jì)算畸變系數(shù))
  4. 所有參數(shù)一起最大似然優(yōu)化 (將所有參數(shù)內(nèi)參、外參、畸變系數(shù)一起優(yōu)化)
%% 1. 計(jì)算初始相機(jī)內(nèi)參
K=[];
D=[];
RT_list=[];
[K,H_list] = CalInitK(CaliBoard,img_points);

%% 2. 計(jì)算初始相機(jī)外參
RT_list = CalInitRT(K,H_list);

%% 3. 最大似然優(yōu)化 
[K,RT_list] = MinReprojErrorKRT(K,RT_list,CaliBoard,img_points);

%% 4. 計(jì)算畸變系數(shù) 
%   D : 畸變參數(shù),分別為k1,k2,k3,p1,p2
D = CalDAll(K,RT_list,CaliBoard,img_points);

%% 5. 所有參數(shù)一起最大似然優(yōu)化 
[K,D,RT_list] = MinReprojErrorKDRT(K,D,RT_list,CaliBoard,img_points);

2. 相機(jī)內(nèi)參計(jì)算

function [K,H_list] = CalInitK(CaliBoard,img_points)
% 相機(jī)初始內(nèi)參計(jì)算
% 1.計(jì)算單應(yīng)矩陣
% 2.根據(jù)旋轉(zhuǎn)矩陣的特性,構(gòu)建方程
% 3.根據(jù)旋轉(zhuǎn)矩陣的特性,構(gòu)建方程


% inputs,
%   CaliBoard : 標(biāo)定板真實(shí)坐標(biāo)點(diǎn)
%   img_points :相機(jī)拍攝到的圖像提取到的標(biāo)定板點(diǎn)
%
% outputs,
%   K : 相機(jī)內(nèi)參
%   H_list : 單應(yīng)矩陣序列

K = [];
H_list = [];
%% 1.計(jì)算單應(yīng)矩陣
for i = 1:size(img_points,1)
    img_points_tmp = cell2mat(img_points(i));
    index = img_points_tmp(:,1);
    tmp1 = CaliBoard(index,1:2);
    tmp2 = img_points_tmp(:,2:3);
    H = CalH(tmp1,tmp2);
    H_list(i,:,:) = H;
end

%% 2.計(jì)算lambda*K^{-T}*k^{-1},lambda為放縮因子
B = CalB(H_list);

%% 3.根據(jù)B=lambda*K^{-T}*k^{-1}計(jì)算K,lambda為放縮因子
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));
B_inv = inv(B); 
lambda = B_inv(3,3);
B_inv = B_inv/lambda;
c_x = B_inv(1,3);
c_y = B_inv(2,3);
f_x = sqrt((B_inv(1,1)-c_x*c_x));
f_y = sqrt((B_inv(2,2)-c_y*c_y));
K=[f_x,0,c_x;
    0,f_y,c_y;
    0,0,1];

end

2.1 單應(yīng)矩陣計(jì)算

為方便計(jì)算,張正友采用了平面標(biāo)定板,因此內(nèi)參矩陣與旋轉(zhuǎn)平移矩陣的乘積可以視作單應(yīng)矩陣H即可得
s m ? ? = K [ R T ] M = H M s\overset{-}{\mathop{m}}\,=K[\begin{matrix} R & T \\ \end{matrix}]M\text{=}HM sm?=K[R?T?]M=HM
張正友相機(jī)標(biāo)定(全流程,含畸變,matlab源代碼解析)

上面的公式若僅依靠這個(gè)變換自然是不成立的,但是考慮到Z為0,則可以變換為

張正友相機(jī)標(biāo)定(全流程,含畸變,matlab源代碼解析)

根據(jù)上述公式,可以列出等式
張正友相機(jī)標(biāo)定(全流程,含畸變,matlab源代碼解析)

將其變換為對應(yīng)的矩陣(為方便計(jì)算,將 H 33 H_{33} H33?視為1)
則可得
張正友相機(jī)標(biāo)定(全流程,含畸變,matlab源代碼解析)

根據(jù)多個(gè)對應(yīng)點(diǎn)構(gòu)建多個(gè)上述方程,即可求解單應(yīng)矩陣H。如上述矩陣所述,一個(gè)對應(yīng)點(diǎn)可構(gòu)建2個(gè)方程,H矩陣總共有8個(gè)未知數(shù),則至少需要4個(gè)對應(yīng)點(diǎn)。

function H = CalH(CaliBoard,img_points)
% % 相機(jī)單應(yīng)矩陣計(jì)算
% 為方便計(jì)算,張正友采用了平面標(biāo)定板,因此內(nèi)參矩陣與旋轉(zhuǎn)平移矩陣的乘積可以視作單應(yīng)矩陣H即可得
% sm=K[r1 r2 T]M,將其K[r1 r2 T]視為H,重構(gòu)方程可得P1=H*P,s為尺度因子,暫時(shí)隱藏
% 根據(jù)P1=H*P得到兩個(gè)方程,將H視為向量,構(gòu)建方程
% 轉(zhuǎn)變成A*X=B的矩陣形式
% P1(X1,Y1),表示img_points
% P(X,Y),表示CaliBoard
% inputs,
%   CaliBoard : 標(biāo)定板真實(shí)坐標(biāo)點(diǎn)
%   img_points :相機(jī)拍攝到的圖像提取到的標(biāo)定板點(diǎn)(單張圖像)
%
% outputs,
%   H : 單應(yīng)矩陣

H=[];
XX1 = CaliBoard(:,1).*img_points(:,1);
X1Y = img_points(:,1).*CaliBoard(:,2);
XY1 = CaliBoard(:,1).*img_points(:,2);
YY1 = CaliBoard(:,2).*img_points(:,2);

A = zeros(size(CaliBoard,1)*2,8);
for i=1:size(CaliBoard,1)
    A(2*i-1,1:3) = [CaliBoard(i,1:2),1];
    A(2*i-1,7:8) = [-XX1(i,1),-X1Y(i,1)];
    A(2*i,4:6) = [CaliBoard(i,1:2),1];
    A(2*i,7:8) = [-XY1(i,1),-YY1(i,1)];
end
B=reshape(img_points.',[size(CaliBoard,1)*size(CaliBoard,2),1]);

H = A\B;
H=[H;1];
H = reshape(H,[3,3])';
end




2.2 基于單應(yīng)矩陣計(jì)算相機(jī)內(nèi)參

如2.1中所說,單應(yīng)矩陣H=K[r1 r2 T],但因?yàn)橛?jì)算H時(shí)添加了 H 99 H_{99} H99?為1的約束,因此計(jì)算出來的結(jié)果應(yīng)當(dāng)添加一個(gè)尺寸因子,即計(jì)算出來的 H = λ ? K ? H = \lambda*K* H=λ?K?[r1 r2 T] ,可轉(zhuǎn)為
k 1 ? [ H 1 H 2 H 3 ] = λ ? [ r 1 r 2 T ] k_1*[H_1 H_2 H_3] = \lambda*[r1 r2 T] k1??[H1?H2?H3?]=λ?[r1r2T]
其中 H 1 , H 2 , H 3 H_1,H_2,H_3 H1?,H2?,H3?為單應(yīng)矩陣的列?;诖私Y(jié)果,以及旋轉(zhuǎn)矩陣的定義特性,可以構(gòu)建兩個(gè)方程,即
張正友相機(jī)標(biāo)定(全流程,含畸變,matlab源代碼解析)

為了方便計(jì)算,可將 k ? T K ? 1 k^{-T}K^{-1} k?TK?1視為一個(gè)矩陣B先行求解,可得
張正友相機(jī)標(biāo)定(全流程,含畸變,matlab源代碼解析)
其中,由于B為 k ? T K ? 1 k^{-T}K^{-1} k?TK?1,可得 k ? T K ? 1 = ( k ? T K ? 1 ) T k^{-T}K^{-1}=(k^{-T}K^{-1})^T k?TK?1=(k?TK?1)T,則B為對稱矩陣,可將B定義為
張正友相機(jī)標(biāo)定(全流程,含畸變,matlab源代碼解析)
由上式可知B中有6個(gè)未知數(shù),即最少需要3個(gè)H矩陣。同時(shí),上述B中的式子如果計(jì)算出來,可以看出 B 12 B_{12} B12?為0,因此,增加了一個(gè)約束條件,最少只需要兩個(gè)H即可計(jì)算出結(jié)果。(此處為考慮下面n=2的情況)
附:關(guān)于標(biāo)定圖片數(shù)量n和內(nèi)參獲取的關(guān)系(來自參考文獻(xiàn)[2])

  • 如果 n>=3,就可以得到唯一解b(帶有一個(gè)比例因子λ)。
  • 如果 n=2,也就是只有兩張標(biāo)定圖片,那么我們可以設(shè)置內(nèi)參中的γ=0(γ表示由于制造誤差產(chǎn)生的兩個(gè)坐標(biāo)軸偏斜參數(shù),通常很小,可忽略),將前面式子(搬運(yùn)到下圖)中γ=0可以看到對應(yīng) B12=0,換句話說,就是增加了一個(gè)約束條件:[0, 1, 0, 0, 0, 0]b = 0。(此處從運(yùn)算角度上不理解,但若僅考慮未知數(shù)的數(shù)目,假設(shè)K只有4個(gè)未知數(shù),則2個(gè)H足夠計(jì)算)
  • 如果n=1,只能假設(shè)u0, v0已知(位于圖像中心)且 γ=0,這樣只能解出fx, fy兩個(gè)參數(shù)。
    張正友相機(jī)標(biāo)定(全流程,含畸變,matlab源代碼解析)
    基于此,即可計(jì)算出B的值。(公式圖片來自參考文獻(xiàn)[2])
    張正友相機(jī)標(biāo)定(全流程,含畸變,matlab源代碼解析)
    然后基于B的值直接進(jìn)行求解即可計(jì)算出內(nèi)參。
    張正友相機(jī)標(biāo)定(全流程,含畸變,matlab源代碼解析)
    附:此處本人采用直接計(jì)算出B的逆矩陣,得到 B ? 1 = K ? K T B^{-1}=K*K^{T} B?1=K?KT,即
    張正友相機(jī)標(biāo)定(全流程,含畸變,matlab源代碼解析)
    所得結(jié)果也一致(暫時(shí)不知道區(qū)別)
function B = CalB(H_list)
% 相機(jī)內(nèi)參K^{-T}*k^{-1}計(jì)算
% 根據(jù)旋轉(zhuǎn)矩陣的性質(zhì),每個(gè)單應(yīng)矩陣可以得到兩個(gè)方程
% 最終得到 v_{12}*b=0,(v_{11}-v_{22})*b=0,其中b為[B11,B12,B13,B22,B23,B33]^T
% v為~{{v}_{ij}}={{\left[ \begin{matrix}
%    \begin{matrix}
%    {{h}_{i1}}{{h}_{j1}} & {{h}_{i1}}{{h}_{j2}}+{{h}_{i2}}{{h}_{j1}} & {{h}_{i2}}{{h}_{j2}}  \\
% \end{matrix} & \begin{matrix}
%    {{h}_{i3}}{{h}_{j1}}+{{h}_{i1}}{{h}_{j3}} & {{h}_{i3}}{{h}_{j2}}+{{h}_{i2}}{{h}_{j3}} & {{h}_{i3}}{{h}_{j3}}  \\
% \end{matrix}  \\
% \end{matrix} \right]}^{T}}

% inputs,
%   H_list : 單應(yīng)矩陣列表
%
% outputs,
%   B : K^{-T}*k^{-1}

B=[];

% 計(jì)算v
for i=1:size(H_list,1)
    h = squeeze(H_list(i,:,:));
    h=h'; % 公式計(jì)算時(shí)考慮按照列劃分的1,2,3,所以需轉(zhuǎn)置一下
    tmp_v(1,1) = h(1,1)*h(2,1);
    tmp_v(1,2) = h(1,2)*h(2,1)+h(1,1)*h(2,2);
    tmp_v(1,3) = h(1,3)*h(2,1)+h(1,1)*h(2,3);
    tmp_v(1,4) = h(1,2)*h(2,2);
    tmp_v(1,5) = h(1,3)*h(2,2)+h(1,2)*h(2,3);
    tmp_v(1,6) = h(1,3)*h(2,3);
    
    tmp_v(2,1) = h(1,1)*h(1,1)-h(2,1)*h(2,1);
    tmp_v(2,2) = 2*(h(1,2)*h(1,1)-h(2,2)*h(2,1));
    tmp_v(2,3) = 2*(h(1,3)*h(1,1)-h(2,3)*h(2,1));
    tmp_v(2,4) = h(1,2)*h(1,2)-h(2,2)*h(2,2);
    tmp_v(2,5) = 2*(h(1,3)*h(1,2)-h(2,3)*h(2,2));
    tmp_v(2,6) = h(1,3)*h(1,3)-h(2,3)*h(2,3);

    v(2*i-1:2*i,:) = tmp_v;
end

[U,S,V] = JOS_SVD(v);
b=V(:,6)';
B =[b(1,1),b(1,2),b(1,3);
    b(1,2),b(1,4),b(1,5);
     b(1,3),b(1,5),b(1,6)];
end

3 計(jì)算相機(jī)外參

相機(jī)內(nèi)參知道后,根據(jù)公式 H = λ ? K ? H = \lambda*K* H=λ?K?[r1 r2 T] 可直接計(jì)算外參,即
K ? 1 H = λ ? K^{-1}H = \lambda* K?1H=λ?[r1 r2 T]
由于旋轉(zhuǎn)矩陣每列的模為1,可直接計(jì)算出外參矩陣。

function [RT_list] = CalInitRT(K,H_list)
% 相機(jī)初始內(nèi)參計(jì)算
% r1 = lambda*M^-1*h_1,lambda與求解內(nèi)參時(shí)的不同,
% 個(gè)人理解求第二個(gè)尺度因子時(shí)需添加R為1的約束,求第一個(gè)時(shí)H本身是up to scale的,無關(guān)緊要。
% r2 = lambda*M^-1*h_2
% r3 = r1 x r2
% t = lambda*M_1*h_3
%
% inputs,
%   K : 相機(jī)內(nèi)參
%   H_list :單應(yīng)矩陣序列
%
% outputs,
%   RT_list : 相機(jī)外參序列

RT_list = [];
K_inv = inv(K);
for i=1:size(H_list,1)
    h = squeeze(H_list(i,:,:));
    lambda = 1/norm(K_inv*h(:,1));
    r1 = lambda*K_inv*h(:,1);
    r2 = lambda*K_inv*h(:,2);
    r3 = cross(r1,r2);
    t = lambda*K_inv*h(:,3);
    rt = [r1,r2,r3,t];
    RT_list(i,:,:) = rt;
end
end

4. 最大似然優(yōu)化

根據(jù)上述計(jì)算出的內(nèi)參、外參矩陣,構(gòu)建最小重投影誤差函數(shù),優(yōu)化內(nèi)參外參。其中需要注意的幾個(gè)點(diǎn)主要為

  1. 旋轉(zhuǎn)矩陣應(yīng)轉(zhuǎn)換為向量
  2. 優(yōu)化是參數(shù)輸入進(jìn)去應(yīng)為一個(gè)向量
  3. 重投影誤差輸出可以為二維矩陣(即X,Y兩個(gè)方向)
function [K_new,RT_list_new] = MinReprojErrorKRT(K,RT_list,CaliBoard,img_points)
% 最小化重投影誤差函數(shù)
% inputs,
%   K : 待優(yōu)化相機(jī)內(nèi)參
%   RT_list : 待優(yōu)化旋轉(zhuǎn)平移矩陣
%   CaliBoard : 標(biāo)定板真實(shí)坐標(biāo)點(diǎn)
%   img_points :相機(jī)拍攝到的圖像提取到的標(biāo)定板點(diǎn)
%
% outputs,
%   K_new : 優(yōu)化后的相機(jī)內(nèi)參
%   RT_list : 優(yōu)化后的旋轉(zhuǎn)平移矩陣

K_new=[];
RT_list_new=[];

% 構(gòu)建變量及初始值
X_init (1:4) = [K(1,1),K(2,2),K(1,3),K(2,3)];
for i=1:size(RT_list,1)
    X_init (i*6-1:i*6+1) = rodrigues(squeeze(RT_list(i,:,1:3)));
    X_init (2+i*6:4+i*6) = RT_list(i,:,4)';
end

% 優(yōu)化參數(shù)
options = optimoptions(@lsqnonlin,'Algorithm','levenberg-marquardt');
f = @(x)ReprojErrorKRT(x,CaliBoard,img_points);
[result,resnorm,residual ] = lsqnonlin(f,X_init,[],[],options);

%結(jié)果重構(gòu)
K_new = K;
K_new(1,1) = result(1);
K_new(2,2) = result(2);
K_new(1,3) = result(3);
K_new(2,3) = result(4);
for i=1:size(RT_list,1)
    RT_list_new(i,:,1:3) = rodrigues(result (i*6-1:i*6+1));
    RT_list_new(i,:,4) =  result (2+i*6:4+i*6);
end

end

function erros_list = ReprojErrorKRT(X,CaliBoard,img_points)
% 重投影誤差函數(shù)
% inputs,
%   X: 待優(yōu)化的參數(shù),
%       X(1:4),f_x,f_y,c_x,c_y
%       X(5:7) r
%       X(8:10) t
%       以此類推,直到結(jié)束
%   CaliBoard : 標(biāo)定板真實(shí)坐標(biāo)點(diǎn)
%   img_points :相機(jī)拍攝到的圖像提取到的標(biāo)定板點(diǎn)
%
% outputs,
%   erros_list : 重投影誤差(x,y兩個(gè)方向,二維矩陣)

repro= 0;
repro_list=[];
erros_list=[];
K=[X(1),0,X(3);
    0,X(2),X(4);
    0,0,1];
CaliBoard = [CaliBoard(:,1:2),ones(size(CaliBoard,1),1)];
for i=1:size(img_points,1)
    img_points_tmp = cell2mat(img_points(i));
    index = img_points_tmp(:,1);
    CaliBoard_tmp = CaliBoard(index,:);
    R= rodrigues( X (i*6-1:i*6+1) );
    T= X (2+i*6:4+i*6)';
    RT = [R(:,1:2),T];
    img_points_proj = K*RT*CaliBoard_tmp';
    img_points_proj(1,:)=img_points_proj(1,:)./img_points_proj(3,:);
    img_points_proj(2,:)=img_points_proj(2,:)./img_points_proj(3,:);
    img_points_proj(3,:)=1;
    img_points_proj=img_points_proj';
    error =squeeze(img_points_tmp(:,2:3))-img_points_proj(:,1:2);
    erros_list=[erros_list;error];
    
    % 調(diào)試用
    erros_dis =vecnorm(error,2,2);
    repro = repro+sum(erros_dis.*erros_dis);
    repro_list=[repro_list;sum(erros_dis.*erros_dis)];
end
end

5. 計(jì)算畸變系數(shù)

在不考慮畸變系數(shù)的情況下優(yōu)化完內(nèi)外參數(shù)后,可以計(jì)算畸變系數(shù)。需要注明,畸變變換是在歸一化平面進(jìn)行的,因此計(jì)算時(shí)可以直接將坐標(biāo)變換到歸一化坐標(biāo)系方便進(jìn)行計(jì)算,也方便進(jìn)行理解。
設(shè)(u,v)為標(biāo)定板根據(jù)外參投影到歸一化平面上的點(diǎn)坐標(biāo), ( u d i s , v d i s ) (u_{dis},v_{dis}) (udis?,vdis?)為畸變后的坐標(biāo),也即實(shí)際圖像坐標(biāo)根據(jù)內(nèi)參反向映射到歸一化平面。則可得
張正友相機(jī)標(biāo)定(全流程,含畸變,matlab源代碼解析)
其中 r 2 = u 2 + v 2 r^2=u^2+v^2 r2=u2+v2
將其轉(zhuǎn)化為方程,則是
張正友相機(jī)標(biāo)定(全流程,含畸變,matlab源代碼解析)
可以寫成
A D = d AD=d AD=d
則可直接計(jì)算出畸變參數(shù)。
附:注意事項(xiàng)

  • 注意變換是在歸一化坐標(biāo)系,所以最好的辦法就是轉(zhuǎn)換到歸一化坐標(biāo)系進(jìn)行計(jì)算,不然容易發(fā)生錯(cuò)誤。
function D = CalDAll(K,RT_list,CaliBoard,img_points)
% 畸變參數(shù)計(jì)算函數(shù),徑向畸變與切向畸變

%將函數(shù)記成A*D=d
% inputs,
%   K : 相機(jī)內(nèi)參
%   RT_list : 旋轉(zhuǎn)平移矩陣
%   CaliBoard : 標(biāo)定板真實(shí)坐標(biāo)點(diǎn)
%   img_points :相機(jī)拍攝到的圖像提取到的標(biāo)定板點(diǎn)
%
% outputs,
%   dis : 畸變參數(shù),分別為k1,k2,k3,p1,p2

img_points_all = [];
CaliBoard = [CaliBoard(:,1:2),ones(size(CaliBoard,1),1)];
img_points__proj_norm_all = [];

% 重投影獲取歸一化坐標(biāo)點(diǎn)
for i=1:size(img_points,1)
    
    img_points_tmp = cell2mat(img_points(i));
    RT = [squeeze(RT_list(i,:,1:2)),squeeze(RT_list(i,:,4))'];
    
    %獲取所有圖像點(diǎn)
    img_points_all=[img_points_all;squeeze(img_points_tmp(:,2:3))];
    
    % 理想點(diǎn)在歸一化坐標(biāo)系上的點(diǎn) x
    img_points_proj_norm = RT*CaliBoard';
    img_points_proj_norm(1,:)=img_points_proj_norm(1,:)./img_points_proj_norm(3,:);
    img_points_proj_norm(2,:)=img_points_proj_norm(2,:)./img_points_proj_norm(3,:);
    img_points_proj_norm(3,:)=1;
    img_points_proj_norm=img_points_proj_norm';
    img_points__proj_norm_all= [img_points__proj_norm_all;img_points_proj_norm(:,1:2)];
end


% 畸變后的點(diǎn)在歸一化坐標(biāo)系上的點(diǎn) x_dis
img_points_norm_all = inv(K)*[img_points_all,ones(size(img_points_all,1),1)]';
img_points_norm_all =img_points_norm_all';
% 計(jì)算D,d
r2 = sum(img_points__proj_norm_all.*img_points__proj_norm_all,2);
r4 = r2.*r2;
r6 = r2.*r4;

u = img_points__proj_norm_all(:,1);
v = img_points__proj_norm_all(:,2);
u_dis = img_points_norm_all(:,1);
v_dis = img_points_norm_all(:,2);

for i=1:size(img_points_all,1)
    A(2*i-1,1) = u(i,1)*r2(i,1);
    A(2*i-1,2) = u(i,1)*r4(i,1);
    A(2*i-1,3) = u(i,1)*r6(i,1);
    A(2*i-1,4) = 2*u(i,1)*v(i,1);
    A(2*i-1,5) = r2(i,1)+2*u(i,1)*u(i,1);
    
    A(2*i,1) = v(i,1)*r2(i,1);
    A(2*i,2) = v(i,1)*r4(i,1);
    A(2*i,3) = v(i,1)*r6(i,1);
    A(2*i,4) = r2(i,1)+2*v(i,1)*v(i,1);
    A(2*i,5) = 2*u(i,1)*v(i,1);
    
    d(2*i-1,1) = u_dis(i,1)-u(i,1);
    d(2*i,1) = v_dis(i,1)-v(i,1);
end

D = A\d;

end

6. 考慮畸變系數(shù)的優(yōu)化

與4中基本一致,只是投影時(shí)考慮到了畸變參數(shù)。

function [K_new,D_new,RT_list_new] = MinReprojErrorKDRT(K,D,RT_list,CaliBoard,img_points)
% 最小化重投影誤差函數(shù)
% inputs,
%   K : 待優(yōu)化相機(jī)內(nèi)參
%   D: 待優(yōu)化的相機(jī)畸變參數(shù)
%   RT_list : 待優(yōu)化旋轉(zhuǎn)平移矩陣
%   CaliBoard : 標(biāo)定板真實(shí)坐標(biāo)點(diǎn)
%   img_points :相機(jī)拍攝到的圖像提取到的標(biāo)定板點(diǎn)
%
% outputs,
%   K_new : 優(yōu)化后的相機(jī)內(nèi)參
%   D_new: 優(yōu)化后的相機(jī)畸變參數(shù)
%   RT_list : 優(yōu)化后的旋轉(zhuǎn)平移矩陣

K_new=[];
RT_list_new=[];
D_new= [];
% 構(gòu)建變量及初始值
X_init (1:4) = [K(1,1),K(2,2),K(1,3),K(2,3)];
X_init(5:9) = D;
for i=1:size(RT_list,1)
    X_init (i*6+4:i*6+6) = rodrigues(squeeze(RT_list(i,:,1:3)));
    X_init (7+i*6:9+i*6) = RT_list(i,:,4)';
end

% 優(yōu)化參數(shù)
options = optimoptions(@lsqnonlin,'Algorithm','levenberg-marquardt');
f = @(x)ReprojErrorKDRT(x,CaliBoard,img_points);
[result,resnorm,residual ] = lsqnonlin(f,X_init,[],[],options);

%結(jié)果重構(gòu)
K_new = K;
K_new(1,1) = result(1);
K_new(2,2) = result(2);
K_new(1,3) = result(3);
K_new(2,3) = result(4);
D_new = result(5:9);
for i=1:size(RT_list,1)
    RT_list_new(i,:,1:3) = rodrigues(result (i*6+4:i*6+6));
    RT_list_new(i,:,4) =  result (7+i*6:9+i*6);
end

end

function error = ReprojErrorKDRT(X,CaliBoard,img_points)
% 重投影誤差函數(shù),考慮畸變參數(shù)
% inputs,
%   X: 待優(yōu)化的參數(shù),
%       X(1:4),f_x,f_y,c_x,c_y
%       X(5:9),k1,k2,k3,p1,p2
%       X(10:12) r
%       X(12:14) t
%       以此類推,直到結(jié)束
%   CaliBoard : 標(biāo)定板真實(shí)坐標(biāo)點(diǎn)
%   img_points :相機(jī)拍攝到的圖像提取到的標(biāo)定板點(diǎn)
%
% outputs,
%   erros_list : 重投影誤差(x,y兩個(gè)方向,二維矩陣)

repro= 0;
repro_list=[];
K=[X(1),0,X(3);
    0,X(2),X(4);
    0,0,1];
k1 = X(5);
k2 = X(6);
k3 = X(7);
p1 = X(8);
p2 = X(9);

CaliBoard = [CaliBoard(:,1:2),ones(size(CaliBoard,1),1)];
img_points_proj_norm_all=[];
img_points_all=[];
% 重投影獲取像素坐標(biāo)點(diǎn)
for i=1:size(img_points,1)
    img_points_tmp = cell2mat(img_points(i));
    index = img_points_tmp(:,1);
    CaliBoard_tmp = CaliBoard(index,:);
    
    R= rodrigues( X (i*6+4:i*6+6) );
    T= X (7+i*6:9+i*6)';
    RT = [R(:,1:2),T];
    
    % 理想點(diǎn)在歸一化坐標(biāo)系上的點(diǎn) x
    img_points_proj_norm = RT*CaliBoard';
    img_points_proj_norm(1,:)=img_points_proj_norm(1,:)./img_points_proj_norm(3,:);
    img_points_proj_norm(2,:)=img_points_proj_norm(2,:)./img_points_proj_norm(3,:);
    img_points_proj_norm(3,:)=1;
    img_points_proj_norm=img_points_proj_norm';
    img_points_proj_norm_all= [img_points_proj_norm_all;img_points_proj_norm(:,1:2)];
    %獲取所有圖像點(diǎn)
    img_points_all=[img_points_all;squeeze(img_points_tmp(:,2:3))];end

% 計(jì)算D,d
r2 = sum(img_points_proj_norm_all.*img_points_proj_norm_all,2);
r4 = r2.*r2;
r6 = r2.*r4;

x = img_points_proj_norm_all(:,1);
y = img_points_proj_norm_all(:,2);

x_dis = x.*(1+k1.*r2+k2.*r4+k3.*r6)+2*p1*(x.*y)+p2*(r2+2*x.*x);
y_dis = y.*(1+k1.*r2+k2.*r4+k3.*r6)+2*p2*(x.*y)+p1*(r2+2*y.*y);

img_points_proj_all = K*[x_dis,y_dis,ones(size(x_dis,1),1)]';
img_points_proj_all = img_points_proj_all';
error = img_points_proj_all(:,1:2)-img_points_all;
end

參考文獻(xiàn)

[1] 張正友標(biāo)定算法原理詳解.https://www.jianshu.com/p/9d2fe4c2e3b7
[2]張正友標(biāo)定法-完整學(xué)習(xí)筆記-從原理到實(shí)戰(zhàn). https://zhuanlan.zhihu.com/p/136827980
[3]張正友標(biāo)定法.https://www.cnblogs.com/linzzz98/articles/13604279.html

相關(guān)資源代碼

部分庫可以下載看
https://download.csdn.net/download/zhangpan333/85445628文章來源地址http://www.zghlxwxcb.cn/news/detail-441516.html

到了這里,關(guān)于張正友相機(jī)標(biāo)定(全流程,含畸變,matlab源代碼解析)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包