天天看點

matlab解決pnp問題,實作後方交會一、原理流程二、代碼

matlab實作pnp問題,實作後方交會

  • 一、原理流程
    • 0、BLH2XYZ
    • 1、求解 P
      • 1.1、坐标歸一化 T
      • 1.2、 系數矩陣A 定義
      • 1.3 DLT 求解初值P0'
      • 1.4 疊代優化
      • 1.5 解除歸一化,求得P
    • 2、求解C = -M^(-1)P_4
    • 3、 M --QR分解得到 R&K
    • 4、R(相機-世界坐标) 到RC,并求姿态(難點!!!)
    • 5、利用單像求解像點對應三維點(增加輔助限制:DEM/DSM)
  • 二、代碼
    • 1、主程式
    • 2、函數function .m檔案
      • 2.1、normalize.m
      • 2.2、normalize_2d.m
      • 2.3、normalize_3d.m
      • 2.4、get_plane.m
      • 2.5、geometric_error.m

一、原理流程

0、BLH2XYZ

經緯度坐标轉換空間之間坐标

1、求解 P

1.1、坐标歸一化 T

質心為原點,到原點距離的均值為sqrt(2)

fsolve函數:

用此函數解算滿足要求的T矩陣的各非零元素,函數fsolve中的function參數采用.m檔案來定義

1.2、 系數矩陣A 定義

由xi,Xi的數值構成

1.3 DLT 求解初值P0’

A矩陣SVD分解後,右奇異矩陣最小特征值對應的特征向量,為AP=0 的線性解,以此作為P的初值P0

1.4 疊代優化

算法-levenberg marquardt 最小化幾何(投影)誤差,優化P

lsqnonlin:

采用該函數實作疊代優化,函數lsqnonlin中的function參數采用.m檔案來定義

1.5 解除歸一化,求得P

2、求解C = -M^(-1)P_4

M是P 3x3的子矩陣

3、 M --QR分解得到 R&K

針對分解得到的R&K,結合射影的實際空間情形,進行簡單變換,參考連結

make diagonal of K positive:

T = diag(sign(diag(K)));
K = K * T;
R = T * R; % (T is its own inverse)
           

如果圖像y軸和錄影機y軸指向相反方向,将K第二列以及R的第二行取反:

K = K.*[1,-1,1;1,-1,1;1,-1,1];
R = R.* [1,1,1;-1,-1,-1;1,1,1];
           

4、R(相機-世界坐标) 到RC,并求姿态(難點!!!)

(相機姿态變換,世界坐标-相機坐标系 R_c)R = R_cT(參考連結)

矩陣的分解針對于R_c

旋轉矩陣的分解:

坐标系1-坐标系2的旋轉矩陣為R12,則針對R12的以X軸為主軸的分解得到的角度為坐标系2相對于坐标系1的3個姿态角(輪轉角、偏航角、俯仰角)
matlab解決pnp問題,實作後方交會一、原理流程二、代碼

參考連結

5、利用單像求解像點對應三維點(增加輔助限制:DEM/DSM)

平面拟合:

采用fsolve函數,解算平面參數,function參數設定同上

采用xi = P *Xi 以及限制條件 S(Xi) =0 求解Xi:

采用inv處理求解由限制條件構造的系數陣,進而求得Xi的解

二、代碼

1、主程式

point_count = 6;
m = [xx,xx,xx,xx,xx,xx];% x坐标矩陣
n = [xx,xx,xx,xx,xx,xx];% y坐标矩陣
M = [xx,xx,xx,xx,xx,xx];% X坐标矩陣
N = [xx,xx,xx,xx,xx,xx];% Y坐标矩陣
V = [xx,xx,xx,xx,xx,xx];%Z 坐标矩陣
% %0 坐标轉換BLH 2 XYZ
% 
% lat = [xx,xx,xx,xx,xx,xx];% 
% lon = [xx,xx,xx,xx,xx,xx];% 
% H1 = [xx,xx,xx,xx,xx,xx];%Z 坐标矩陣
% f = 1 / 298.257223563;
% a= 6378137;
% b = a * (1 - f);
% e = sqrt(a * a - b * b) / a;
% 
% for i = 1:point_count
%     N(i) = a / sqrt(1 - e * e * sin(lat(i) * pi / 180) * sin(lat(i) * pi/ 180));
%     WGS84_X(i) = (N(i) + H1(i)) * cos(lat(i) * pi / 180) * cos(lon(i) * pi / 180);
%     WGS84_Y(i) = (N(i) + H1(i)) * cos(lat(i) * pi / 180) * sin(lon(i) * pi / 180);
%     WGS84_Z(i) = (N(i)* (1 - (e * e)) + H1(i)) * sin(lat(i) * pi / 180);
%     
% end

% M = WGS84_X% X坐标矩陣
% N = WGS84_Y% Y坐标矩陣
% V = WGS84_Z%Z 坐标矩陣


% 1、求解 P


%1.1坐标歸一化 T:質心為原點,到原點距離的均值為sqrt(2)
%2d

T_2d = normalize([m;n])

mn = T_2d * [m;n;ones(1,point_count)];
m = mn(1,:);
n = mn(2,:);


%3d
T_3d = normalize([M;N;V])


MNV = T_3d*[M;N;V;ones(1,point_count)];

M = MNV(1,:);
N = MNV(2,:);
V = MNV(3,:);



% 1.2 系數矩陣A 定義

A = [];
for i = 1:point_count
    
     A = [A;[0,0,0,0,-M(i),-N(i),-V(i),-1,n(i)*M(i),n(i)*N(i),n(i)*V(i),n(i);
         M(i),N(i),V(i),1,0,0,0,0,-m(i)*M(i),-m(i)*N(i),-m(i)*V(i),-m(i)]];
end

%1.3 DLT 求解初值P0'
[U,S,V]=svd(A);
P0 = V(:,end);
% size(P0)

sv = P0.*  P0;     %the vector with elements 
                % as square of v's elements
dp = sum(sv);    % sum of squares -- the dot product
mag = sqrt(dp)  % magnitude

% aa = norm(P0)

%1.4 疊代算法-levenberg marquardt 最小化幾何誤差

% options = optimoptions(@lsqnonlin,'Algorithm','Levenberg-Marquardt','Display','iter');
options = optimoptions(@lsqnonlin,'Algorithm','Levenberg-Marquardt');
[x,resnorm,residual,exitflag,output] = lsqnonlin(@geometric_error,P0,[],[],options);
output;
P= reshape(x,3,4);
% norm(P)
sv = x.*  x;     %the vector with elements 
                % as square of v's elements
dp = sum(sv);    % sum of squares -- the dot product
mag = sqrt(dp);  % magnitude

%1.5 解除歸一化,求得P

P = inv(T_2d)*P*T_3d;



% 2、求解C = -M^(-1)P4

M= P(:,1:3);
p4 = P(:,end);
C = -inv(M)*p4


%3、 M QR分解得到 R&K

[Q,R]=qr(M);
K = Q;
%make diagonal of K positive
T = diag(sign(diag(K)));
K = K * T;
R = T * R; % (T is its own inverse)

%如果圖像y軸和錄影機y軸指向相反方向,将K第二列以及R的第二行取反

K = K.*[1,-1,1;1,-1,1;1,-1,1];
R = R.* [1,1,1;-1,-1,-1;1,1,1];

% 4、R(相機-世界坐标) 到RC(相機姿态變換,世界坐标-相機坐标系)R = RCT
Rc = R';

% 分解Rc,以Z 為主軸的轉角系統

theta_z = atan2(Rc(2,1),Rc(1,1))/pi*180
theta_y = atan2(-Rc(3,1),sqrt(Rc(1,1).^2+Rc(2,1).^2))/pi*180
theta_x = atan2(Rc(3,2),Rc(3,3))/pi*180

% 5、求解成像最遠點

% 5.1 求解四角點三維坐标

%5.1.1 平面拟合


plane0 = [1,1,1];
options = optimoptions('fsolve','Display','none','Algorithm','Levenberg-Marquardt');
plane = fsolve(@get_plane,plane0,options);


height = 1080;
width = 1920;
corner_point_2d = [0,0,1;0,height,1;width,0,1;width,height,1]';

corner_point_3d = inv([P;[plane,1]])*[corner_point_2d;zeros(1,4)];
corner_point_3d = corner_point_3d /diag(corner_point_3d(end,:));
corner_point_3d = corner_point_3d(1:3,:)%轉為非齊次坐标
vector_3d = corner_point_3d-C;

for i = 1:4
    distance(i) = norm(vector_3d(1:2,i));
end

distance_max = max( distance)


           

2、函數function .m檔案

2.1、normalize.m

function T = normalize(cors)
[height,width] = size(cors);
x0 = [1,zeros(1,height)];
% options = optimoptions('fsolve','Display','none','PlotFcn',@optimplotfirstorderopt);
options = optimoptions('fsolve','Display','none');
if (height ==2)
    
    t = fsolve(@normalize_2d,x0,options);% T矩陣的三個參數
    
else
    
    t = fsolve(@normalize_3d,x0,options);% T矩陣的三個參數
end

T = [[diag(t(1)*ones(1,height));zeros(1,height)],[t(:,2:end)';1]];
           

2.2、normalize_2d.m

function F = normalize_2d(x)

point_count = 6;
m = [292,671,1444,1500,1265,902];% x坐标矩陣
n = [748,606,404,275,506,599];% y坐标矩陣
sum_m = sum(m);
sum_n = sum(n);
eqn_dis =0;
for i  = 1:point_count
    eqn_dis = eqn_dis + sqrt((x(1)*m(i)+x(2)).^2+(x(1)*n(i)+x(3)).^2);
end

F(1) = sum_m*x(1)+point_count*x(2);
F(2) = sum_n*x(1)+point_count*x(3);
F(3) = eqn_dis-sqrt(2)*point_count;
           

2.3、normalize_3d.m

function F = normalize_3d(x)

point_count = 6;
M = [xx,xx,xx,xx,xx,xx];% X坐标矩陣
N = [xx,xx,xx,xx,xx,xx];% Y坐标矩陣
V = [xx,xx,xx,xx,xx,xx];%Z 坐标矩陣
sum_M = sum(M);
sum_N = sum(N);
sum_V = sum(V);
eqn_dis =0;
for i  = 1:point_count
    eqn_dis = eqn_dis + sqrt((x(1)*M(i)+x(2)).^2+(x(1)*N(i)+x(3)).^2+(x(1)*V(i)+x(4)).^2);
end

F(1) = sum_M*x(1)+point_count*x(2);
F(2) = sum_N*x(1)+point_count*x(3);
F(3) = sum_V*x(1)+point_count*x(4);
F(4) = eqn_dis-sqrt(2)*point_count;
           

2.4、get_plane.m

function F = get_plane(x)

M = [xx,xx,xx,xx,xx,xx];% X坐标矩陣
N = [xx,xx,xx,xx,xx,xx];% Y坐标矩陣
V = [xx,xx,xx,xx,xx,xx];%Z 坐标矩陣
for i = 1 : 6
    
    F(i) = x(1)* M(i)+x(2)*N(i)+ x(3)* V(i)+1;
end
           

2.5、geometric_error.m

function F = geometric_error(P)


m = [xx,xx,xx,xx,xx,xx];% x坐标矩陣
n = [xx,xx,xx,xx,xx,xx];% y坐标矩陣

M = [xx,xx,xx,xx,xx,xx];% X坐标矩陣
N = [xx,xx,xx,xx,xx,xx];% Y坐标矩陣
V = [xx,xx,xx,xx,xx,xx];%Z 坐标矩陣


%坐标歸一化
%2d


x0 = [1,0,0];

% options = optimset('Display','iter','TolFun','1e-8');
% options = optimoptions('fsolve','Display','none','PlotFcn',@optimplotfirstorderopt);
fun = @normalize_2d;
x_result= fsolve(fun,x0);% T矩陣的三個參數

T_2d = [x_result(1),0,x_result(2);0,x_result(1),x_result(3);0,0,1];

m = m*x_result(1)+x_result(2);
n = n*x_result(1)+x_result(3);

%3d
xx_0 = [1,0,0,0];

fun_3d = @normalize_3d;
xx_result= fsolve(fun_3d,xx_0);% T矩陣的三個參數

T_3d = [xx_result(1),0,0,xx_result(2);0,xx_result(1),0,xx_result(3);0,0,xx_result(1),xx_result(4);0,0,0,1];

%歸一化
M = M *xx_result(1)+xx_result(2);
N = N *xx_result(1)+ xx_result(3);
V = V*xx_result(1)+ xx_result(4);
F = 0;
point_count = 6;
for i = 1:point_count
    x = [m(i),n(i),1]';
    X = [M(i),N(i),V(i),1]';
    P = reshape(P,3,4);
    F = F + norm(x-P*X).^2;
end    
           

繼續閱讀