Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.

Close

[07d29c]: rotate_scale.cc Maximize Restore History

Download this file

rotate_scale.cc    180 lines (154 with data), 5.4 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/*
* 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;
}
inline double sqr(double a) { return (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 ];
}
}
}