Skip to content
Snippets Groups Projects
Commit 473a8c6e authored by Nicola Vigano's avatar Nicola Vigano
Browse files

PSF: small fix for non-symmetric PSFs

parent e663fc29
No related branches found
No related tags found
No related merge requests found
...@@ -79,7 +79,7 @@ function [volume, res_norm] = gtAstra3DTV(proj, varargin) ...@@ -79,7 +79,7 @@ function [volume, res_norm] = gtAstra3DTV(proj, varargin)
psf_obj.set_psf_direct(proj.psf, [proj.num_cols, proj.num_rows]); psf_obj.set_psf_direct(proj.psf, [proj.num_cols, proj.num_rows]);
fp = @(x)psf_obj.apply_psf_direct(astra_mex_direct_c('FP3D', astra_projector_id, x)); fp = @(x)psf_obj.apply_psf_direct(astra_mex_direct_c('FP3D', astra_projector_id, x));
bp = @(x)astra_mex_direct_c('BP3D', astra_projector_id, psf_obj.apply_psf_transpose(x)); bp = @(x)astra_mex_direct_c('BP3D', astra_projector_id, psf_obj.apply_psf_adjoint(x));
else else
fp = @(x)astra_mex_direct_c('FP3D', astra_projector_id, x); fp = @(x)astra_mex_direct_c('FP3D', astra_projector_id, x);
bp = @(x)astra_mex_direct_c('BP3D', astra_projector_id, x); bp = @(x)astra_mex_direct_c('BP3D', astra_projector_id, x);
......
classdef GtPSF < handle classdef GtPSF < handle
properties properties
psf_direct = []; psf_direct = [];
psf_transpose = []; psf_adjoint = [];
otf_direct = []; otf_direct = [];
otf_transpose = []; otf_adjoint = [];
is_symmetric = true; is_symmetric = true;
is_projection_invariant = true; is_projection_invariant = true;
...@@ -24,38 +24,18 @@ classdef GtPSF < handle ...@@ -24,38 +24,18 @@ classdef GtPSF < handle
function set_psf_direct(self, psf_d, image_size) function set_psf_direct(self, psf_d, image_size)
self.reset(); self.reset();
% let's be sure that it will be in ASTRA's projection [psf_d, psf_a, self.is_symmetric, self.is_projection_invariant] ...
% convention = self.check_single_psf(psf_d);
if (size(psf_d, 1) == size(psf_d, 2))
psf_d = permute(psf_d, [1 3 2]);
elseif (size(psf_d, 1) ~= size(psf_d, 3))
error([mfilename ':wrong_argument'], ...
'PSFs should be in the form of _square images_, with odd edges')
elseif (mod(size(psf_d, 1), 2) ~= 1)
error([mfilename ':wrong_argument'], ...
'PSFs should be in the form of square images, with _odd edges_')
end
% let's renormalize the PSFs self.psf_direct = psf_d;
psfs_norm = 1 ./ sum(sum(abs(psf_d), 1), 3);
psf_d = bsxfun(@times, psf_d, psfs_norm);
self.psf_direct = cast(psf_d, self.data_type);
if (exist('image_size', 'var') && ~isempty(image_size))
self.image_size = image_size;
end
% Let's find out whether they are symmetric or not
psf_t = permute(psf_d, [3 2 1]);
self.is_symmetric = all(abs(psf_d(:) - psf_t(:)) < eps('single'));
if (~self.is_symmetric) if (~self.is_symmetric)
self.psf_transpose = psf_t; self.psf_adjoint = psf_a;
end end
self.is_projection_invariant = size(psf_d, 2) == 1; if (exist('image_size', 'var') && ~isempty(image_size))
self.image_size = image_size;
% if we know the images sizes, we can already compute the OTF % if we know the images sizes, we can already compute the OTF
if (~isempty(self.image_size))
self.init_otfs(); self.init_otfs();
end end
end end
...@@ -70,7 +50,7 @@ classdef GtPSF < handle ...@@ -70,7 +50,7 @@ classdef GtPSF < handle
end end
end end
function imgs = apply_psf_transpose(self, imgs) function imgs = apply_psf_adjoint(self, imgs)
self.check_incoming_images(imgs); self.check_incoming_images(imgs);
if (self.use_otf) if (self.use_otf)
...@@ -81,17 +61,44 @@ classdef GtPSF < handle ...@@ -81,17 +61,44 @@ classdef GtPSF < handle
end end
end end
methods (Access = private) methods (Access = protected)
function reset(self) function reset(self)
self.psf_direct = []; self.psf_direct = [];
self.psf_transpose = []; self.psf_adjoint = [];
self.otf_direct = []; self.otf_direct = [];
self.otf_transpose = []; self.otf_adjoint = [];
self.image_size = []; self.image_size = [];
end end
function [psf_d, psf_a, is_sym, is_p_inv] = check_single_psf(self, psf_d)
% let's be sure that it will be in ASTRA's projection
% convention
if (size(psf_d, 1) == size(psf_d, 2))
psf_d = permute(psf_d, [1 3 2]);
elseif (size(psf_d, 1) ~= size(psf_d, 3))
error([mfilename ':wrong_argument'], ...
'PSFs should be in the form of _square images_, with odd edges')
elseif (mod(size(psf_d, 1), 2) ~= 1)
error([mfilename ':wrong_argument'], ...
'PSFs should be in the form of square images, with _odd edges_')
end
% let's renormalize the PSFs
psfs_norm = 1 ./ sum(sum(abs(psf_d), 1), 3);
psf_d = bsxfun(@times, psf_d, psfs_norm);
psf_d = cast(psf_d, self.data_type);
% Let's find out whether they are symmetric or not
psf_a = flip(flip(psf_d, 1), 3);
is_sym = all(abs(psf_d(:) - psf_a(:)) < eps('single'));
is_p_inv = size(psf_d, 2) == 1;
end
function otf = init_single_otf(self, psf) function otf = init_single_otf(self, psf)
num_psfs = size(psf, 2); num_psfs = size(psf, 2);
psf_edge = (size(psf, 1) - 1) / 2; psf_edge = (size(psf, 1) - 1) / 2;
...@@ -122,7 +129,7 @@ classdef GtPSF < handle ...@@ -122,7 +129,7 @@ classdef GtPSF < handle
self.otf_direct = self.init_single_otf(self.psf_direct); self.otf_direct = self.init_single_otf(self.psf_direct);
if (~self.is_symmetric) if (~self.is_symmetric)
self.otf_transpose = self.init_single_otf(self.psf_transpose); self.otf_adjoint = self.init_single_otf(self.psf_adjoint);
end end
end end
...@@ -137,7 +144,7 @@ classdef GtPSF < handle ...@@ -137,7 +144,7 @@ classdef GtPSF < handle
imgs_size = [size(imgs, 1), size(imgs, 3)]; imgs_size = [size(imgs, 1), size(imgs, 3)];
if (isempty(self.image_size)) if (isempty(self.image_size))
self.otf_direct = []; self.otf_direct = [];
self.otf_transpose = []; self.otf_adjoint = [];
self.image_size = imgs_size; self.image_size = imgs_size;
elseif (any(self.image_size ~= imgs_size)) elseif (any(self.image_size ~= imgs_size))
...@@ -146,7 +153,7 @@ classdef GtPSF < handle ...@@ -146,7 +153,7 @@ classdef GtPSF < handle
self.image_size, imgs_size) self.image_size, imgs_size)
self.otf_direct = []; self.otf_direct = [];
self.otf_transpose = []; self.otf_adjoint = [];
self.image_size = imgs_size; self.image_size = imgs_size;
end end
...@@ -171,7 +178,7 @@ classdef GtPSF < handle ...@@ -171,7 +178,7 @@ classdef GtPSF < handle
if (is_direct || self.is_symmetric) if (is_direct || self.is_symmetric)
imgs = bsxfun(@times, imgs, self.otf_direct); imgs = bsxfun(@times, imgs, self.otf_direct);
else else
imgs = bsxfun(@times, imgs, self.otf_transpose); imgs = bsxfun(@times, imgs, self.otf_adjoint);
end end
imgs = ifftshift(imgs, 1); imgs = ifftshift(imgs, 1);
...@@ -193,7 +200,7 @@ classdef GtPSF < handle ...@@ -193,7 +200,7 @@ classdef GtPSF < handle
if (is_direct || self.is_symmetric) if (is_direct || self.is_symmetric)
psf = self.psf_direct; psf = self.psf_direct;
else else
psf = self.psf_transpose; psf = self.psf_adjoint;
end end
if (self.is_projection_invariant) if (self.is_projection_invariant)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment