changeset 845:f91e9ecc57ba octave-forge

rotate_scale
author aadler
date Mon, 03 Mar 2003 21:15:51 +0000
parents 6474589480be
children ceef245828b5
files main/image/rotate_scale.cc
diffstat 1 files changed, 181 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main/image/rotate_scale.cc	Mon Mar 03 21:15:51 2003 +0000
@@ -0,0 +1,181 @@
+/*
+ * ROTATE_SCALE: rotate and scale a matrix using bilinear interpolation
+ * imo= block(im, xregs, yregs);
+ *
+ * Copyright (C) 2003 Andy Adler
+ * This code has no warrany whatsoever.
+ * Do what you like with this code as long as you
+ *     leave this copyright in place.
+ *
+ * $Id$
+ */
+
+#include <octave/oct.h>
+
+void
+calc_rotation_params(
+              double x0l,double y0l,double x0r,double y0r,
+              double x1l,double y1l,double x1r,double y1r,
+              double* Tx_x, double* Ty_x,
+              double* Tx_y, double* Ty_y,
+              double* Tx_1, double* Ty_1 );
+void
+do_interpolation (
+              double Tx_x, double Ty_x,
+              double Tx_y, double Ty_y,
+              double Tx_1, double Ty_1,
+              int x0max, int y0max,// initial size
+              int x1max, int y1max,// output size
+              const double * img0,
+              double       * img1 );
+
+DEFUN_DLD (rotate_scale, args, ,
+  "ROTATE_SCALE: arbitrary rotation and scaling of an image\n"
+  "              using fast bilinear interpolation\n"
+  "im1 = rotate_scale(im0, lm0, lm1, out_size)\n"
+  "  where:\n"
+  "im0 = input image\n"
+  "lm0 = landmarks of points in original image [ x1,x2;y1,y2 ]\n"
+  "im1 = output image, where size(im1) == out_size\n"
+  "lm1 = landmarks of points in output image [ x1,x2;y1,y2 ]\n"
+  "\n"
+  "   note1: two landmarks must be specified for lm0 and lm1\n"
+  "   note2: all images have a single component\n"
+  "   to use this for colour images, use:\n"
+  "  r_im1= rotate_scale( red_im0, lm0, lm1, out_size)\n"
+  "  g_im1= rotate_scale( grn_im0, lm0, lm1, out_size)\n"
+  "  b_im1= rotate_scale( blu_im0, lm0, lm1, out_size)\n"
+  "\n"
+  "   example:\n"
+  "  im0= zeros(100); im0(25:75,25:75)=1;\n"
+  "  im1= rotate_scale( im0, [40,60;50,50],[60,90;60,90],[120,120]);\n"
+) {
+   octave_value_list retval;
+   if (args.length() < 4 ||
+       !args(0).is_matrix_type() ||
+       !args(1).is_matrix_type() ||
+       !args(2).is_matrix_type() ||
+       !args(3).is_matrix_type()
+       ) {
+      print_usage ("rotate_scale");
+      return retval;
+   }
+
+   Matrix im0( args(0).matrix_value() );
+   const double * im0p = im0.data();
+   Matrix lm0( args(1).matrix_value() );
+   Matrix lm1( args(2).matrix_value() );
+   ColumnVector out_size( args(3).vector_value() );
+
+   int inp_hig= im0.rows();
+   int inp_wid= im0.cols();
+
+   int out_hig= (int) out_size(0);
+   int out_wid= (int) out_size(1);
+   Matrix im1( out_hig, out_wid);
+   double * im1p = im1.fortran_vec();
+
+   double Tx_x; double Ty_x;
+   double Tx_y; double Ty_y;
+   double Tx_1; double Ty_1;
+   calc_rotation_params(
+          lm0(0,0), lm0(1,0), lm0(0,1), lm0(1,1),
+          lm1(0,0), lm1(1,0), lm1(0,1), lm1(1,1),
+          & Tx_x, & Ty_x,
+          & Tx_y, & Ty_y,
+          & Tx_1, & Ty_1 );
+    
+   do_interpolation( Tx_x, Ty_x, Tx_y, Ty_y, Tx_1, Ty_1,
+                  inp_wid, inp_hig, out_wid, out_hig,
+                  im0p, im1p );
+
+   retval(0) = im1;
+   return retval;
+}
+
+#ifdef sqr
+#undef sqr
+#endif
+#define sqr(a) ((a)*(a))
+
+void
+calc_rotation_params(
+              double x1l,double y1l,double x1r,double y1r,
+              double x0l,double y0l,double x0r,double y0r,
+              double* Tx_x, double* Ty_x,
+              double* Tx_y, double* Ty_y,
+              double* Tx_1, double* Ty_1 
+              )
+{
+    double d0= sqrt( sqr(x0l-x0r) + sqr(y0l-y0r) );
+    double d1= sqrt( sqr(x1l-x1r) + sqr(y1l-y1r) );
+    double dr= d1/d0;
+
+    double a0= atan2( y0l-y0r , x0l-x0r );
+    double a1= atan2( y1l-y1r , x1l-x1r );
+    double ad= a1-a0;
+    double dr_cos_ad= dr*cos(ad);
+    double dr_sin_ad= dr*sin(ad);
+
+    double x0m= (x0l+x0r)/2;
+    double y0m= (y0l+y0r)/2;
+    double x1m= (x1l+x1r)/2;
+    double y1m= (y1l+y1r)/2;
+
+    *Tx_x=  dr_cos_ad;
+    *Ty_x=  dr_sin_ad;
+    *Tx_y= -dr_sin_ad;
+    *Ty_y=  dr_cos_ad;
+    *Tx_1=  x1m - dr_cos_ad*x0m + dr_sin_ad*y0m;
+    *Ty_1=  y1m - dr_sin_ad*x0m - dr_cos_ad*y0m;
+}    
+
+
+void
+do_interpolation (
+              double Tx_x, double Ty_x,
+              double Tx_y, double Ty_y,
+              double Tx_1, double Ty_1,
+              int x0max, int y0max,// initial size
+              int x1max, int y1max,// output size
+              const double * img0,
+              double       * img1 
+            )
+{
+
+    for (int i=0; i< x1max; i++) {
+        for (int j=0; j< y1max; j++) {
+            double x0i= Tx_x * i + Tx_y * j + Tx_1;
+            double y0i= Ty_x * i + Ty_y * j + Ty_1;
+
+            if ( x0i < 0       )    x0i= 0;
+            else
+            if (x0i >= x0max-1 )    x0i= x0max - 1.00001; 
+
+            if ( y0i < 0       )    y0i= 0;
+            else
+            if (y0i >= y0max-1 )    y0i= y0max - 1.00001; 
+
+            int x0idx= (int) x0i;
+            int y0idx= (int) y0i;
+
+            double frac_r= x0i- x0idx; 
+            double frac_l= 1 - frac_r;
+            double frac_d= y0i- y0idx; 
+            double frac_u= 1 - frac_d;
+
+            int pix_lu= (y0idx+0) + (x0idx+0) * y0max ;
+            int pix_ru= (y0idx+0) + (x0idx+1) * y0max ;
+            int pix_ld= (y0idx+1) + (x0idx+0) * y0max ;
+            int pix_rd= (y0idx+1) + (x0idx+1) * y0max ;
+               
+            img1[ i*y1max + j ]=
+               frac_l*frac_u* img0[ pix_lu ] +
+               frac_r*frac_u* img0[ pix_ru ] +
+               frac_l*frac_d* img0[ pix_ld ] +
+               frac_r*frac_d* img0[ pix_rd ];
+
+        }
+    }
+}
+