]> Creatis software - CreaPhase.git/blobdiff - octave_packages/image-1.0.15/phantom.m
Add a useful package (from Source forge) for octave
[CreaPhase.git] / octave_packages / image-1.0.15 / phantom.m
diff --git a/octave_packages/image-1.0.15/phantom.m b/octave_packages/image-1.0.15/phantom.m
new file mode 100644 (file)
index 0000000..efd51a4
--- /dev/null
@@ -0,0 +1,215 @@
+## Copyright (C) 2010  Alex Opie  <lx_op@orcon.net.nz>
+##
+## This program is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+##
+## @defun {@var{P} =} phantom ('Shepp-Logan', @var{n})
+##
+## Produces the Shepp-Logan phantom, with size @var{n} x @var{n}.
+## If @var{n} is omitted, 256 is used.
+##
+## @defunx {@var{P} =} phantom ('Modified Shepp-Logan', @var{n})
+##
+## Produces a modified version of the Shepp-Logan phantom which has
+## higher contrast than the original,  with size @var{n} x @var{n}.
+## If @var{n} is omitted, 256 is used.
+##
+## @defunx {@var{P} =} phantom (@var{ellipses}, @var{n})
+##
+## Produces a custom phantom using the ellipses described in @var{ellipses}.
+## Each row of @var{ellipses} describes one ellipse, and must have 6 columns:
+## @{I, a, b, x0, y0, phi@}:
+##  @table @abbr
+##  @item I
+##    is the additive intensity of the ellipse
+##
+##  @item a
+##    is the length of the major axis
+##
+##  @item b
+##    is the length of the minor axis
+##
+##  @item x0
+##    is the horizontal offset of the centre of the ellipse
+##
+##  @item y0
+##    is the vercal offset of the centre of the ellipse
+##
+##  @item phi
+##    is the counterclockwise rotation of the ellipse in degrees,
+##    measured as the angle between the x axis and the ellipse major axis.
+##
+## @end table
+##
+## The image bounding box in the algorithm is @{[-1, -1], [1, 1]@}, so the
+## values of a, b, x0, y0 should all be specified with this in mind.
+## If @var{n} is omitted, 256 is used.
+##
+## @defunx {@var{P} =} phantom (@var{n})
+##
+## Creates a modified Shepp-Logan phantom with size @var{n} x @var{n}.
+##
+## @defunx {@var{P} = } phantom ()
+##
+## Creates a modified Shepp-Logan phantom with size 256 x 256.
+## @end defun
+##
+## Create a Shepp-Logan or modified Shepp-Logan phantom.
+##
+## A phantom is a known object (either real or purely mathematical) that
+## is used for testing image reconstruction algorithms.  The Shepp-Logan
+## phantom is a popular mathematical model of a cranial slice, made up
+## of a set of ellipses.  This allows rigorous testing of computed 
+## tomography (CT) algorithms as it can be analytically transformed with
+## the radon transform (see the function @command{radon}).
+##
+## Example:
+## 
+## @example
+##   P = phantom (512);
+##   imshow (P, []);
+## @end example
+##
+## References:
+##
+##  Shepp, L. A.; Logan, B. F.; Reconstructing Interior Head Tissue 
+##  from X-Ray Transmissions, IEEE Transactions on Nuclear Science,
+##  Feb. 1974, p. 232.
+##
+##  Toft, P.; "The Radon Transform - Theory and Implementation", Ph.D. thesis,
+##  Department of Mathematical Modelling, Technical University 
+##  of Denmark, June 1996.
+
+function p = phantom (varargin)
+
+  [n, ellipses] = read_args (varargin {:});
+
+  # Blank image
+  p = zeros (n);
+
+  # Create the pixel grid
+  xvals = (-1 : 2 / (n - 1) : 1);
+  xgrid = repmat (xvals, n, 1);
+
+  for i = 1:size (ellipses, 1)    
+    I   = ellipses (i, 1);
+    a2  = ellipses (i, 2)^2;
+    b2  = ellipses (i, 3)^2;
+    x0  = ellipses (i, 4);
+    y0  = ellipses (i, 5);
+    phi = ellipses (i, 6) * pi / 180;  # Rotation angle in radians
+    
+    # Create the offset x and y values for the grid
+    x = xgrid - x0;
+    y = rot90 (xgrid) - y0;
+    
+    cos_p = cos (phi); 
+    sin_p = sin (phi);
+    
+    # Find the pixels within the ellipse
+    locs = find (((x .* cos_p + y .* sin_p).^2) ./ a2 ...
+     + ((y .* cos_p - x .* sin_p).^2) ./ b2 <= 1);
+    
+    # Add the ellipse intensity to those pixels
+    p (locs) = p (locs) + I;
+  endfor
+endfunction
+
+function [n, ellip] = read_args (varargin)
+  n = 256;
+  ellip = mod_shepp_logan ();
+  
+  if (nargin == 1)
+    if (ischar (varargin {1}))
+      ellip = select_phantom (varargin {1});
+    elseif (numel (varargin {1}) == 1)
+      n = varargin {1};
+    else
+      if (size (varargin {1}, 2) != 6)
+        error ("Wrong number of columns in user phantom");
+      endif
+      ellip = varargin {1};
+    endif
+  elseif (nargin == 2)
+    n = varargin {2};
+    if (ischar (varargin {1}))
+      ellip = select_phantom (varargin {1});
+    else
+      if (size (varargin {1}, 2) != 6)
+        error ("Wrong number of columns in user phantom");
+      endif
+      ellip = varargin {1};
+    endif
+  elseif (nargin > 2)
+    warning ("Extra arguments passed to phantom were ignored");
+  endif
+endfunction
+
+function e = select_phantom (name)
+  if (strcmpi (name, 'shepp-logan'))
+    e = shepp_logan ();
+  elseif (strcmpi (name, 'modified shepp-logan'))
+    e = mod_shepp_logan ();
+  else
+    error ("Unknown phantom type: %s", name);
+  endif
+endfunction
+
+function e = shepp_logan
+  #  Standard head phantom, taken from Shepp & Logan
+  e = [  2,   .69,   .92,    0,      0,   0;  
+      -.98, .6624, .8740,    0, -.0184,   0;
+      -.02, .1100, .3100,  .22,      0, -18;
+      -.02, .1600, .4100, -.22,      0,  18;
+       .01, .2100, .2500,    0,    .35,   0;
+       .01, .0460, .0460,    0,     .1,   0;
+       .02, .0460, .0460,    0,    -.1,   0;
+       .01, .0460, .0230, -.08,  -.605,   0; 
+       .01, .0230, .0230,    0,  -.606,   0;
+       .01, .0230, .0460,  .06,  -.605,   0];
+endfunction
+
+function e = mod_shepp_logan
+  #  Modified version of Shepp & Logan's head phantom, 
+  #  adjusted to improve contrast.  Taken from Toft.
+  e = [  1,   .69,   .92,    0,      0,   0;
+      -.80, .6624, .8740,    0, -.0184,   0;
+      -.20, .1100, .3100,  .22,      0, -18;
+      -.20, .1600, .4100, -.22,      0,  18;
+       .10, .2100, .2500,    0,    .35,   0;
+       .10, .0460, .0460,    0,     .1,   0;
+       .10, .0460, .0460,    0,    -.1,   0;
+       .10, .0460, .0230, -.08,  -.605,   0; 
+       .10, .0230, .0230,    0,  -.606,   0;
+       .10, .0230, .0460,  .06,  -.605,   0];
+endfunction
+
+#function e = ??
+#  # Add any further phantoms of interest here
+#  e = [ 0, 0, 0, 0, 0, 0;
+#        0, 0, 0, 0, 0, 0];
+#endfunction
+
+%!demo
+%! P = phantom (512);
+%! imshow (P, []);
+
+% $Log$
+% 2010/03/31 lxop
+% Fixed typo that prevented the use of custom ellipses
+%
+% 2010/03/09 lxop
+% First commit to repo