Index: main/image/inst/maketform.m
===================================================================
--- main/image/inst/maketform.m	(révision 11796)
+++ main/image/inst/maketform.m	(copie de travail)
@@ -16,6 +16,7 @@
 
 ## -*- texinfo -*-
 ## @deftypefn  {Function File} {@var{T} =} maketform (@var{ttype}, @var{tmat})
+## @deftypefnx  {Function File} {@var{T} =} maketform (@var{ttype}, @var{inc}, @var{outc})
 ## @deftypefnx {Function File} {@var{T} =} maketform ("custom", @var{ndims_in}, @var{ndims_out}, @var{forward_fcn}, @var{inverse_fcn}, @var{tdata})
 ## Returns a transform structure containing fields @var{ndims_in},
 ## @var{ndims_out}, @var{forward_fcn}, @var{inverse_fcn} and @var{tdata}. The content
@@ -35,12 +36,27 @@
 ##                         c f i]
 ## [x y] =  [xx./zz yy./zz];
 ## @end example
+## 
+## Alternatively the transform can be specified using a quadilateral
+## coordinates (typically the 4 corners of the
+## image)  in the input space (@var{inc}, 4-by-ndims_in matrix) and in
+## the  output space (@var{outc}, 4-by-ndims_out matrix). This is
+## equivalent to building the transform using "T = cp2tform (@var{inc}, @var{outc},
+## 'projective')".
 ## @item "affine"
 ## Affine is a subset of projective transform (see above). A ndims_in = N ->
 ## ndims_out = N  affine transformation structure is returned.
 ## The second input argument @var{tmat} must be a (N+1)-by-(N+1) or
 ## (N+1)-by-(N) transformation matrix. If present, the (N+1)th column  must
 ## contain [zeros(N,1); 1] so that projection is suppressed.
+##
+## Alternatively the transform can be specified a using a triangle
+## coordinates (typically the 3 corners of the
+## image)  in the input space (@var{inc}, 3-by-ndims_in matrix) and in
+## the  output space (@var{outc}, 3-by-ndims_out matrix). This is
+## equivalent to building the transform using "T = cp2tform (@var{inc}, @var{outc},
+## 'affine')".
+## 
 ## @item "custom"
 ## For user defined transforms every field of the transform structure
 ## must be supplied. The prototype of the transform functions,
@@ -53,8 +69,6 @@
 ## @seealso{tformfwd, tforminv, cp2tform}
 ## @end deftypefn
 
-## Author: Pantxo Diribarne <pantxo@dibona>
-## Created: 2012-09-05
 
 function T = maketform (ttype, varargin)
 
@@ -70,7 +84,7 @@
     elseif ((ndin-ndout) > 1 || (ndout > ndin))
       print_usage ();
     endif
-
+    
     switch (tolower (ttype))
       case "affine"
         if ((ndin - ndout) == 1)
@@ -94,6 +108,24 @@
     T.inverse_fcn = inverse_fcn;
     T.tdata.T = tmat;
     T.tdata.Tinv = inv (tmat);
+  elseif (numel (varargin) == 2)
+    inc = varargin{1};
+    outc = varargin{2};
+    if (strcmp (ttype, "affine"))
+      if (all (size (inc) == size (outc)) &&
+          all (size (inc) == [3 2]))
+        T = cp2tform (inc, outc, ttype);
+      else
+        error ("maketform: expect INC and OUTC to be 3-by-2 vectors.");
+      endif
+    elseif (strcmp (ttype, "projective"))
+      if (all (size (inc) == size (outc)) &&
+          all (size (inc) == [4 2]))
+        T = cp2tform (inc, outc, ttype);
+      else
+        error ("maketform: expect INC and OUTC to be 4-by-2 vectors.");
+      endif
+    endif
   elseif (numel (varargin) == 5 && strcmpi (ttype, "custom"))
     if (isscalar (varargin{1}) && isscalar (varargin{2})
         && varargin{1} > 0 && varargin{2} > 0)
Index: main/image/inst/findbounds.m
===================================================================
--- main/image/inst/findbounds.m	(révision 0)
+++ main/image/inst/findbounds.m	(copie de travail)
@@ -0,0 +1,60 @@
+## Copyright (C) 2012 Pantxo Diribarne
+## 
+## 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 Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+## 
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {@var{outbnd} =} findbounds (@var{T}, @var{inbnd})
+## 
+## Given a transformation structure @var{T} (see e.g. maketform) 
+## and bounds @var{inbnd} (2-by-ndims_in) in an input space, returns
+## an estimation of the bounds in the output space @var{outbnd} 
+## (2-by-ndims_out). For instance two dimensionnal bounds could 
+## be represented as : [xmin ymin; xmax ymax]. If @var{T} does not
+## define a forward trasform (i.e. for 'polynomial'), the output
+## bounds are infered using fsolve and the inverse transform.
+## @seealso{maketform, cp2tform, tformfwd}
+## @end deftypefn
+
+function [ outbnd ] = findbounds (T = [], inbnd = [])
+  if (!istform (T))
+    print_usage ();
+  elseif (! all (size (inbnd) == [2 T.ndims_in]))
+    print_usage ();
+  endif
+  
+  ## Control points grid
+  if (columns (inbnd) == 2)
+    [xcp, ycp] = meshgrid (linspace (inbnd(1,1), inbnd(2,1), 3),
+                           linspace (inbnd(1,2), inbnd(2,2), 3));
+    xcp = reshape (xcp, numel (xcp), 1);
+    ycp = reshape (ycp, numel (ycp), 1);
+    xycp = [xcp, ycp];
+  else
+    error ("findbounds: support only 2D inputbounds.")
+  endif
+  
+  ## Output bounds
+  if (!is_function_handle (T.forward_fcn))
+    outbnd = zeros (size (xycp));
+    for ii = 1:rows (xycp)
+      fun = @(x) tforminv (T, x) - xycp(ii,:);
+      outbnd(ii,:) = fsolve (fun, xycp(ii,:));
+    endfor
+  else
+    outbnd = tformfwd (T, xycp);
+  endif
+  outbnd = [min(outbnd); max(outbnd)];
+endfunction

Modification de propriétés sur main/image/inst/findbounds.m
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: main/image/inst/imtransform.m
===================================================================
--- main/image/inst/imtransform.m	(révision 0)
+++ main/image/inst/imtransform.m	(copie de travail)
@@ -0,0 +1,336 @@
+## Copyright (C) 2012 Pantxo Diribarne
+## 
+## 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 Octave; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn  {Function File} {@var{B} =} imtransform (@var{A}, @var{T})
+## @deftypefnx  {Function File} {@var{B} =} imtransform (@var{A}, @var{T}, @var{interp})
+## @deftypefnx  {Function File} {@var{B} =} imtransform (..., @var{prop}, @var{val})
+## 
+## Given an image @var{A} in  one space, returns an image @var{B}
+## resulting from the forward transform defined in the transformation
+## structure @var{T}. An additionnal input argument @var{interp},
+## 'bicubic', 'bilinear' (default) or 'nearest', 
+## specifies the interpolation method to be used. Finally, the
+## transformation can be tuned using  @var{prop}/@var{val} pairs. The
+## following properties are supported:
+## 
+## @table @asis
+## @item "udata"
+## Specifies the input space horizontal limits. Value must be a two
+## elements vector [minval maxval].
+##
+## @item "vdata"
+## Specifies the input space vertical limits. Value must be a two
+## elements vector [minval maxval].
+##
+## @item "xdata"
+## Specifies the requiered output space horizontal limits. Value must
+## be a two elements vector [minval maxval].
+##
+## @item "ydata"
+## Specifies the requiered output space vertical limits. Value must
+## be a two elements vector [minval maxval].
+##
+## @item "xyscale"
+## Specifies the output scale in outputspace_units/pixel. If a scalar
+## is provided, both vertical and horizontal dimensions are scaled the
+## same way. If @var{val} is a two element vector, it must indicate
+## consecutively horizontal and vertical scales. Default value is
+## computed using the actual input space scale provided
+## that the number of pixel of any dimension of the output image does
+## not exceed 20000.
+##
+## @item "size"
+## Size of the output image (1-by-2 vector). Overrides the effect of
+## "xyscale" property. 
+## 
+## @item "fillvalues"
+## Color of the areas where no interpolation where possible, e.g. when
+## coorfinates of points in the output space are out of the limits of
+## the input space (RGB three elements vector). 
+##
+## @end table
+# @seealso{maketform, cp2tform, tforminv}
+## @end deftypefn
+
+function [ varargout ] = imtransform (im, T, varargin)
+  if (! istform (T))
+    error ("imtransform: expect a transformation structure as second argument")
+  endif
+  
+  ## Parameters
+  interp = "linear";
+  imdepth = size (im, 3);
+  maximsize = [20000 20000];
+  
+  udata = [1; columns(im)];
+  vdata = [1; rows(im)];
+  xdata = ydata = [];
+  xyscale = [];
+  imsize = [];
+  fillvalues = ones (1, imdepth) * NaN;
+  
+  if (isempty (varargin))
+    xydata = findbounds (T, [udata vdata]);
+    xdata = xydata(:,1);
+    ydata = xydata(:,2);
+  else
+    ## interp
+    if (floor (numel (varargin)/2) != numel (varargin)/2)
+      allowed = {"bicubic", "bilinear", "nearest"};
+      tst = strcmp (varargin{1}, allowed);
+      if (!any (tst))
+        error ("imtransform: expect one of %s as interp method", 
+               disp (allowed));
+      else
+        interp = {"pchip", "linear", "nearest"}{find (tst)};  
+      endif
+      varargin = varargin(2:end);
+    endif
+
+    ## options
+    allowed = {"udata", "vdata", "xdata", "ydata", ...
+               "xyscale", "size", "fillvalues"};
+    props = varargin(1:2:end);
+    vals = varargin(2:2:end);
+    np = numel (props);
+    if (!all (cellfun (@ischar, props)))
+      error ("imtransform: expect property/value pairs.");
+    endif
+    
+    props = tolower (props);
+    tst = cellfun (@(x) any (strcmp (x, allowed)), props);
+    if (!all (tst))
+      error ("imtransform: unknown property %s", disp (props{!tst}));
+    endif
+
+    ## u(vxy)data
+    iolims = allowed(1:4);
+    for ii = 1:numel (iolims)
+      tst = cellfun (@(x) any (strcmp (x, iolims{ii})), props);
+      if (any (tst))
+        prop = props{find (tst)(1)};
+        val = vals{find (tst)(1)};
+        if (isnumeric (val) && numel (val) == 2)
+          if (isrow (val))
+            val = val';
+          endif
+          eval (sprintf ("%s = val;", prop),
+                "error (\"imtransform: %s\n\", lasterr ());");
+        else
+          error ("imtransform: expect 2 elements real vector for %s", prop)
+        endif
+      endif
+    endfor
+    if (isempty (xdata) && isempty (ydata))
+      xydata = findbounds (T, [udata vdata]);
+      xdata = xydata(:,1);
+      ydata = xydata(:,2);
+    elseif (isempty (xdata))
+      xydata = findbounds (T, [udata vdata]);
+      xdata = xydata(:,1);
+    elseif (isempty (ydata))
+      xydata = findbounds (T, [udata vdata]);
+      ydata = xydata(:,2);
+    endif
+    
+
+    ## size and xyscale
+    tst = strcmp ("size", props);
+    if (any (tst))
+      val = vals{find (tst)(1)};
+      if (isnumeric (val) && numel (val) == 2 &&
+          all (val > 0))
+        imsize = val;
+      else
+        error ("imtransform: expect 2 elements real vector for size")
+      endif
+    elseif (any (tst = strcmp ("xyscale", props)))
+      val = vals{find (tst)(1)};
+      if (isnumeric (val) && all (val > 0))
+        if (numel (val) == 1)
+          xyscale(1:2) = val;
+        elseif (numel (val) == 2)
+          xyscale = val;
+        else
+          error ("imtransform: expect 1 or 2 element(s) real vector for xyscale")
+        endif
+      else
+        error ("imtransform: expect 1 or 2 element(s) real vector for xyscale")
+      endif
+    else
+      xyscale = [(diff (udata) / columns (im)) (diff (vdata) / rows (im))];
+    endif
+    
+    ## Fillvalues
+    tst = strcmp ("fillvalues", props);
+    switch class (im)
+      case "uint8"
+        sclfact = 2^8;
+      case "uint16"
+        sclfact = 2^16;
+      case "double"
+        sclfact = 1;
+    endswitch
+    if (any (tst))
+      val = vals{find (tst)(1)};
+      if (isnumeric (val) && numel (val) == 1)
+        fillvalues(1:end) = val * sclfact;
+      elseif (isnumeric (val) && numel (val) == 3)
+        fillvalues = val *sclfact;
+      else
+        error ("imtransform: expect 1 or 3 elements real vector for %s",
+               3, "fillvalues")
+      endif
+    endif
+  endif
+
+  ## Ouput/Input pixels
+  if (isempty (imsize))
+    if (isempty (xyscale))
+      xyscale = [(diff (udata) / columns (im)) (diff (vdata) / rows (im))];
+    endif
+    xscale = xyscale(1);
+    yscale = xyscale(2);
+    xsize = floor (diff (xdata) / xscale);
+    ysize = floor (diff (ydata) / yscale);
+    if (xsize > maximsize(2) || ysize > maximsize(1))
+      if (xsize >= ysize)
+        scalefactor = (diff (xdata) / maximsize(2)) / xscale;
+      else
+        scalefactor = (diff (ydata) / maximsize(1)) / yscale;
+      endif
+      xscale *= scalefactor
+      yscale *= scalefactor
+      xsize = floor (diff (xdata) / xscale);
+      ysize = floor (diff (ydata) / yscale);
+      warning ("imtransform: output image two large, adjusting the largest dimension to %d", maximsize)
+    endif
+    imsize = [ysize xsize];
+  endif
+  [xx yy] = meshgrid (linspace (xdata(1), xdata(2), imsize(2)),
+                      linspace (ydata(1), ydata(2), imsize(1)));
+
+  [uu vv] = meshgrid (linspace (udata(1), udata(2), size(im)(2)),
+                      linspace (vdata(1), vdata(2), size(im)(1)));
+
+  ## Input coordinates
+  [uui, vvi] = tforminv (T, reshape (xx, numel (xx), 1),
+                         reshape (yy, numel (yy), 1));
+  uui = reshape (uui, size (xx));
+  vvi = reshape (vvi, size (yy));                
+  ## Interpolation
+  for layer = 1:imdepth
+    imout(:,:,layer) = interp2 (uu, vv, im(:,:,layer), ...
+                                uui, vvi, interp, fillvalues(layer));
+  endfor
+  if (nargout == 1)
+    varargout{1} = imout;
+  else
+    varargout = {imout, xdata, ydata};
+  endif
+endfunction
+
+%!demo
+%! ## Various linear transforms
+%! figure (); 
+%! im = [checkerboard(20, 2, 4); checkerboard(40, 1, 2)];
+%! %input space corners
+%! incp = [1 1; 160 1; 160 160; 1 160];
+%! udata = [min(incp(:,1)) max(incp(:,1))];
+%! vdata = [min(incp(:,2)) max(incp(:,2))];
+%! subplot (2,3,1); 
+%! imshow (im)
+%! hold on
+%! plot (incp(:,1), incp(:,2), 'ob')
+%! axis on
+%! xlabel ('Original')
+%! 
+%! % Translation and scaling
+%! outcp = incp * 2;
+%! outcp(:,1) += 200; 
+%! outcp(:,2) += 500;
+%! T = maketform ('affine', incp(1:3,:), outcp(1:3,:));
+%! subplot (2,3,2); 
+%! [im2 xdata ydata] = imtransform (im, T, 'udata', udata,
+%!                                  'vdata', vdata, 'fillvalues', 1 );
+%! imshow (im2, 'xdata', xdata, 'ydata', ydata)
+%! axis on, hold on, xlabel ('Translation / Scaling');
+%! plot (outcp(:,1), outcp(:,2), 'or')
+%! 
+%! % Shear
+%! outcp = [1 1; 160 1; 140 160; -19 160]; % affine only needs 3 control points
+%! T = maketform ('affine', incp(1:3,:), outcp(1:3,:));
+%! subplot (2,3,3); 
+%! [im2 xdata ydata] = imtransform (im, T, 'udata', udata,
+%!                                  'vdata', vdata, 'fillvalues', 1 );
+%! imshow (im2, 'xdata', xdata, 'ydata', ydata)
+%! axis on, hold on, xlabel ('Shear');
+%! plot (outcp(:,1), outcp(:,2), 'or')
+%! 
+%! % Rotation 
+%! theta = pi/4;
+%! T = maketform ('affine', [cos(theta) -sin(theta); ...
+%!                           sin(theta) cos(theta); 0 0]);
+%! outcp = tformfwd (T, incp);
+%! subplot (2,3,4); 
+%! [im2 xdata ydata] = imtransform (im, T, 'udata', udata,
+%!                                  'vdata', vdata, 'fillvalues', 1 );
+%! imshow (im2, 'xdata', xdata, 'ydata', ydata)
+%! axis on, hold on, xlabel ('Rotation');
+%! plot (outcp(:,1), outcp(:,2), 'or')
+%!
+%! % Reflection around x axis
+%! outcp = incp;
+%! outcp(:,2) *= -1;
+%! T = cp2tform (incp, outcp, 'similarity');
+%! subplot (2,3,5); 
+%! [im2 xdata ydata] = imtransform (im, T, 'udata', udata,
+%!                                  'vdata', vdata, 'fillvalues', 1 );
+%! imshow (im2, 'xdata', xdata, 'ydata', ydata)
+%! axis on, hold on, xlabel ('Reflection');
+%! plot (outcp(:,1), outcp(:,2), 'or')
+%!
+%! % Projection
+%! outcp = [1 1; 160 1; 180 190; 12 140];
+%! T = maketform ('projective', incp, outcp);
+%! subplot (2,3,6); 
+%! [im2 xdata ydata] = imtransform (im, T, 'udata', udata,
+%!                                  'vdata', vdata, 'fillvalues', 1 );
+%! imshow (im2, 'xdata', xdata, 'ydata', ydata)
+%! axis on, hold on, xlabel ('Projection');
+%! plot (outcp(:,1), outcp(:,2), 'or')
+
+%!demo
+%! ## Fish-eye like transform: image streched on a sphere and
+%! ## projected on a plane
+%! rad = 2; % minimum value: 4/pi
+%! [uu vv] = meshgrid ((-2:2)/rad, (-2:2)/rad);
+%! rescfactor = sin ((uu.^2 + vv.^2).^.5);
+%! inpts = [(reshape (uu, numel (uu), 1)), (reshape (vv, numel (uu), 1))]; 
+%! xx = rescfactor .* sign(uu);
+%! yy = rescfactor .* sign(vv);
+%! outpts = [(reshape (xx, numel (xx), 1)) sin(reshape (yy, numel (yy), 1))];
+%! 
+%! T = cp2tform (inpts, outpts, "polynomial", 4);
+%! figure;
+%! subplot (1,2,1), imshow (imtransform (checkerboard (100), T,
+%!                                       "udata", [-1 1],
+%!                                       "vdata", [-1 1]));
+%! [im cmap] = imread ('default.img');
+%! subplot (1,2,2), imshow (imtransform (im, T, "udata", [-1 1],
+%!                                       "vdata", [-1 1]), cmap);
+

Modification de propriétés sur main/image/inst/imtransform.m
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
