changeset 265:c7a13f09e8d0

Added 'imfilter'
author hauberg
date Sat, 15 Dec 2007 14:00:13 +0000
parents 8fbed59e1448
children b06ed1e249e3
files inst/imfilter.m
diffstat 1 files changed, 138 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/inst/imfilter.m
@@ -0,0 +1,138 @@
+## Copyright (C) 2007  Soren Hauberg
+## 
+## 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, 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 file.  If not, write to the Free Software Foundation,
+## 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} @var{J} = imfilter(@var{I}, @var{f})
+## @deftypefnx{Function File} @var{J} = imfilter(@var{I}, @var{f}, @var{options}, ...)
+## Computes the linear filtering of the image @var{I} and the filter @var{f}.
+## The computation is performed using double precision floating point numbers,
+## but the class of the input image is preserved as the following example shows.
+## @example
+## I = 255*ones(100, 100, "uint8");
+## f = fspecial("average", 3);
+## J = imfilter(I, f);
+## class(J)
+## @result{} ans = uint8
+## @end example
+##
+## The function also accepts a number of optional arguments that control the
+## details of the filtering. The following options is currently accepted
+## @table @samp
+## @item S
+## If a scalar input argument is given, the image is padded with this scalar
+## as part of the filtering. The default value is 0.
+## @item "symmetric"
+## The image is padded symmetrically. 
+## @item "replicate"
+## The image is padded using the border of the image.
+## @item "circular"
+## The image is padded by circular repeating of the image elements.
+## @item "same"
+## The size of the output image is the same as the input image. This is the default
+## behaviour.
+## @item "full"
+## Returns the full filtering result.
+## @item "corr"
+## The filtering is performed using correlation. This is the default behaviour.
+## @item "conv"
+## The filtering is performed using convolution.
+## @end table
+## @seealso{conv2, filter2, fspecial, padarray}
+## @end deftypefn
+
+function retval = imfilter(im, f, varargin)
+  ## Check number of input arguments
+  if (nargin < 2)
+    print_usage();
+  endif
+  
+  ## Check image
+  if (!ismatrix(im))
+    error("imfilter: first input argument must be an image");
+  endif
+  [imrows, imcols, imchannels, tmp] = size(im);
+  if (tmp != 1 || (imchannels != 1 && imchannels != 3))
+    error("imfilter: first input argument must be an image");
+  endif
+  C = class(im);
+  
+  ## Check filter (XXX: matlab support 3D filter, but I have no idea what they do with them)
+  if (!ismatrix(f))
+    error("imfilter: second input argument must be a matrix");
+  endif
+  [frows, fcols, tmp] = size(f);
+  if (tmp != 1)
+    error("imfilter: second argument must be a 2-dimensional matrix");
+  endif
+  
+  ## Parse options
+  res_size = "same";
+  res_size_options = {"same", "full"};
+  pad = 0;
+  pad_options = {"symmetric", "replicate", "circular"};
+  ftype = "corr";
+  ftype_options = {"corr", "conv"};
+  for i = 1:length(varargin)
+    v = varargin{i};
+    if (any(strcmpi(v, pad_options)) || isscalar(v))
+      pad = v;
+    elseif (any(strcmpi(v, res_size_options)))
+      res_size = v;
+    elseif (any(strcmpi(v, ftype_options)))
+      ftype = v;
+    else
+      warning("imfilter: cannot handle input argument number %d", i+2);
+    endif
+  endfor
+  
+  ## Pad the image
+  im = padarray(im, floor([frows/2, fcols/2]), pad);
+  if (mod(frows,2) == 0)
+    im = im(1:end-1, :, :);
+  endif
+  if (mod(fcols,2) == 0)
+    im = im(:, 1:end-1, :);
+  endif
+  
+  ## Do the filtering
+  if (strcmpi(res_size, "same"))
+    res_size = "valid";
+  else # res_size == "full"
+    res_size = "same";
+  endif
+  if (imchannels == 1)
+    if (strcmpi(ftype, "corr"))
+      retval = filter2(f, im, res_size);
+    else
+      retval = conv2(im, f, res_size);
+    endif
+  else # imchannelse == 3
+    if (strcmpi(ftype, "corr"))
+      for i = 3:-1:1
+        retval(:,:,i) = filter2(f, im(:,:,i), res_size);
+      endfor
+    else
+      for i = 3:-1:1
+        retval(:,:,i) = conv2(im(:,:,i), f, res_size);
+      endfor
+    endif
+  endif
+  
+  ## Change the class of the output to the class of the input
+  ## (the filtering functions returns doubles)
+  retval = cast(retval, C);
+  
+endfunction