How to extract 3D position from the 2D projection using (an optimzation method + 3D Gaussian PDF)

12 次查看(过去 30 天)
Hi there,
I am currently working on a Matlab code for my homework (the attached PDF file). As a beginner with Matlab, I initially get help from ChatGPT, but unfortunately, it hasn't been very effective for me.
Here are some quick guidelines to clarify my approach:
In Step 1 of the code, I define a few system parameters—nothing more. I have assumed that I already have 3D datasets (true_T) and have subsequently used the code to compute 2D projections (lines 20-23) to estimate the projections ([xp, yp]).
In Step 2, I attempted to use the lsqnonlin method, along with the detailed information provided in the PDF file, to obtain the final covariance matrix (A). However, this part is not functioning as expected.
Any assistance or alternative approaches to resolve this issue would be greatly appreciated.
Thank in advance!
clc;
clear;
close all;
%% **Step 1: Load 2D Projection Data**
% Imaging system parameters
SAD = 100;
SID = 150;
num_projections = 15;
% Generate projection angles (e.g., uniformly spaced)
degrees = 30;
alpha = linspace(0, degrees, num_projections)';
theta_rad = deg2rad(alpha);
% Generate synthetic ground truth 3D position
rng(42); % Fix random seed for reproducibility
true_T = randn(3, num_projections);
% Projection Model: Compute 2D projections
f_theta = (SAD - (true_T(1, :) .* cos(theta_rad) + true_T(3, :) .* sin(theta_rad))) ./ SID;
Xp = (true_T(1, :) .* sin(theta_rad) - true_T(3, :) .* cos(theta_rad)) ./ f_theta;
Yp = true_T(2, :) ./ f_theta;
% Initialize 3D position estimates
f_theta = SAD ./ SID;
y_est = f_theta .* Yp;
% Initial guess for estimated target positions
x_est = zeros(1, num_projections);
z_est = zeros(1, num_projections);
%% **Step 2: Compute Probability for Each Projection & Optimize B**
% Initial Cholesky decomposition for B
initial_L = ones(3);
initial_params = ones(3);
% Define optimization settings for lsqnonlin
opts = optimoptions('lsqnonlin', 'Display', 'iter', 'TolFun', 1e-6);
lb = []; % No lower bounds
ub = []; % No upper bounds
% Optimize B using lsqnonlin
fMLE = @(L_vec) computeError(L_vec, Xp, Yp, alpha, SAD, SID);
opt_L_vec = lsqnonlin(fMLE, initial_params, lb, ub, opts);
Unable to perform assignment because the left and right sides have a different number of elements.

Error in solution>computeError (line 122)
L(tril(true)) = L_vec;

Error in solution>@(L_vec)computeError(L_vec,Xp,Yp,alpha,SAD,SID) (line 44)
fMLE = @(L_vec) computeError(L_vec, Xp, Yp, alpha, SAD, SID);

Error in lsqnonlin (line 221)
initVals.F = feval(funfcn{3},xCurrent,varargin{:});

Caused by:
Failure in initial objective function evaluation. LSQNONLIN cannot continue.
% Convert optimized L vector back to matrix form
L_opt = zeros(3,3);
L_opt(tril(true)) = opt_L_vec;
B_opt = L_opt * L_opt';
disp('Optimized Covariance Matrix B:');
disp(B_opt);
% Compute probability and estimate 3D positions
detB = det(B_opt);
for i = 1:num_projections
opt_L_vec = lsqnonlin(fMLE, initial_params, lb, ub, opts);
% Extract new optimzation values
var_LR = opt_L_vec(1);
var_CC = opt_L_vec(5);
var_AP = opt_L_vec(9);
cov_LR_CC = opt_L_vec(2);
cov_LR_AP = opt_L_vec(3);
cov_CC_AP = opt_L_vec(6);
A_opt = [ var_LR, cov_LR_CC, cov_LR_AP;
cov_LR_CC, var_CC, cov_CC_AP;
cov_LR_AP, cov_CC_AP, var_AP];
B_opt = inv(A_opt); % Inverse covariance matrix
detB_opt = det(B_opt);
% Projection Point on Imager (Eq. A.4)
p = [Xp(i) * cos(alpha(i)) - (SID - SAD) * sin(alpha(i));
Yp(i);
-Xp(i) * sin(alpha(i)) - (SID - SAD) * cos(alpha(i))];
% Focus Point (Eq. A.5)
f = [SAD * sin(alpha(i)); 0; SAD * cos(alpha(i))];
% Compute Unit Vector Along the Ray (Eq. A.6)
e = (f - p) / norm(f - p);
% Compute Standard Deviation Along the Ray (Eq. A.8)
sigma_ray = 1 / sqrt(e' * B_opt * e);
% Compute Mean Position Along the Ray (Eq. A.9)
mu_ray = ((p' * B_opt * e) / (e' * B_opt * e));
% Compute Scaling Factor (Eq. A.10)
K = sqrt(detB_opt / (2 * pi)^3) * exp(-0.5 * (p + e * mu_ray)' * B_opt * (p + e * mu_ray));
% Compute Probability (Eq. A.11)
P_xp_yp = K * sqrt(2 * pi) * sigma_ray;
% Estimate 3D coordinates from projection
X_est(i) = p(1) + e(1) * mu_ray;
Y_est(i) = p(2) + e(2) * mu_ray;
Z_est(i) = p(3) + e(3) * mu_ray;
end
%% **Step 3: Plot the 3D Reconstruction**
figure;
plot3(true_T(1,:), true_T(2,:), true_T(3,:), 'ro-', 'LineWidth', 2); hold on;
plot3(X_est, Y_est, Z_est, 'bo-', 'LineWidth', 2);
grid on;
xlabel('Left-Right (LR) Direction (cm)');
ylabel('Superior-Inferior (SI) Direction (cm)');
zlabel('Anterior-Posterior (AP) Direction (cm)');
title('True vs. Estimated 3D Tumor Position');
legend('True 3D Position', 'Estimated 3D Position');
view(3);
%% **computeError Function (lsqnonlin)**
function residuals = computeError(L_vec, Xp, Yp, alpha, SAD, SID)
% Convert L vector to lower triangular matrix
L = zeros(3,3);
L(tril(true)) = L_vec;
B = L * L'; % Ensure positive definite B
detB = det(B);
num_projections = length(alpha);
residuals = zeros(num_projections, 1); % Return vector for lsqnonlin
for i = 1:num_projections
% Projection Point on Imager
p = [Xp(i) * cos(alpha(i)) - (SID - SAD) * sin(alpha(i));
Yp(i);
-Xp(i) * sin(alpha(i)) - (SID - SAD) * cos(alpha(i))];
% Focus Point
f = [SAD * sin(alpha(i)); 0; SAD * cos(alpha(i))];
% Compute Unit Vector Along the Ray
e = (f - p) / norm(f - p);
% Compute Standard Deviation Along the Ray
sigma_ray = 1 / sqrt(e' * B * e);
if sigma_ray <= 0
residuals(i) = 1e6; % Large penalty
continue;
end
% Compute Mean Position Along the Ray
mu_ray = ((p' * B * e) / (e' * B * e));
% Compute Scaling Factor
K = sqrt(detB / (2 * pi)^3) * exp(-0.5 * (p + e * mu_ray)' * B * (p + e * mu_ray));
% Compute Probability
P_xp_yp = K * sqrt(2 * pi) * sigma_ray;
if P_xp_yp <= 0
residuals(i) = 1e6; % Large penalty for invalid values
continue;
end
% Compute residual as the difference from expected probability
residuals(i) = log(P_xp_yp);
end
end

回答(1 个)

William Rose
William Rose 2025-3-6
Good job by you to make a solid effort before asking for help on your homework. You are a good example.
The portion of the Appendix which you attached does not define AP, CC, LR. I assume those stand for anterior-posterior, caudal-cranial, left-right views. Is each one a vector or array or scalar?
Are the lines below doing what you want? My guess is you want views from angles 0, 30, 60,,...,330 degrees. If so, the lines below needs fixing. It's homework, so I'll let you figure it out.
num_projections = 15;
degrees = 30;
alpha = linspace(0, degrees, num_projections)';
Instead of using random data, I suggest you use exact data (like points on the corners of a cube) to test your algorithm. Make sure the projections of the cube points are giving the results you expect.
More later.
  28 个评论
William Rose
William Rose 2025-3-13
@payam samadi, please send me a secure message so we can continue this dicussion offline. If you click on the "WR" circle next to my posts, you will see an envelope icon at top right of the pop-up window. Click it to send me a message. Thank you.

请先登录,再进行评论。

类别

Help CenterFile Exchange 中查找有关 Applications 的更多信息

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by