00001
00002 #ifndef vil_gauss_reduce_txx_
00003 #define vil_gauss_reduce_txx_
00004
00005
00006
00007
00008
00009 #include "vil_gauss_reduce.h"
00010 #include <vcl_cassert.h>
00011 #include <vil/vil_bilin_interp.h>
00012 #include <vil/vil_plane.h>
00013 #include <vil/vil_convert.h>
00014
00015
00016
00017
00018 template<class T>
00019 void vil_gauss_reduce(const vil_image_view<T>& src_im,
00020 vil_image_view<T>& dest_im,
00021 vil_image_view<T>& work_im)
00022 {
00023 unsigned ni = src_im.ni();
00024 unsigned nj = src_im.nj();
00025 unsigned n_planes = src_im.nplanes();
00026
00027
00028 unsigned ni2 = (ni+1)/2;
00029 unsigned nj2 = (nj+1)/2;
00030
00031 dest_im.set_size(ni2,nj2,n_planes);
00032
00033 if (work_im.ni()<ni2 || work_im.nj()<nj)
00034 work_im.set_size(ni2,nj);
00035
00036
00037 for (unsigned int i=0;i<n_planes;++i)
00038 {
00039
00040 vil_gauss_reduce_1plane(src_im.top_left_ptr()+i*src_im.planestep(),ni,nj,
00041 src_im.istep(),src_im.jstep(),
00042 work_im.top_left_ptr(),
00043 work_im.istep(),work_im.jstep());
00044
00045
00046 vil_gauss_reduce_1plane(work_im.top_left_ptr(),nj,ni2,
00047 work_im.jstep(),work_im.istep(),
00048 dest_im.top_left_ptr()+i*dest_im.planestep(),
00049 dest_im.jstep(),dest_im.istep());
00050 }
00051 }
00052
00053
00054
00055
00056 template<class T>
00057 void vil_gauss_reduce_2_3(const vil_image_view<T>& src_im,
00058 vil_image_view<T>& dest_im,
00059 vil_image_view<T>& work_im)
00060 {
00061 unsigned ni = src_im.ni();
00062 unsigned nj = src_im.nj();
00063 unsigned n_planes = src_im.nplanes();
00064
00065
00066 unsigned ni2 = (2*ni+1)/3;
00067 unsigned nj2 = (2*nj+1)/3;
00068
00069 dest_im.set_size(ni2,nj2,n_planes);
00070
00071 if (work_im.ni()<ni2 || work_im.nj()<nj)
00072 work_im.set_size(ni2,nj);
00073
00074
00075 for (unsigned int i=0;i<n_planes;++i)
00076 {
00077
00078 vil_gauss_reduce_2_3_1plane(src_im.top_left_ptr()+i*src_im.planestep(),ni,nj,
00079 src_im.istep(),src_im.jstep(),
00080 work_im.top_left_ptr(),
00081 work_im.istep(),work_im.jstep());
00082
00083
00084 vil_gauss_reduce_2_3_1plane(work_im.top_left_ptr(),nj,ni2,
00085 work_im.jstep(),work_im.istep(),
00086 dest_im.top_left_ptr()+i*dest_im.planestep(),
00087 dest_im.jstep(),dest_im.istep());
00088 }
00089 }
00090
00091
00092
00093 template<class T>
00094 void vil_gauss_reduce_121(const vil_image_view<T>& src_im,
00095 vil_image_view<T>& dest_im)
00096 {
00097 unsigned int ni = src_im.ni();
00098 unsigned int nj = src_im.nj();
00099 unsigned int n_planes = src_im.nplanes();
00100
00101
00102 unsigned int ni2 = (ni+1)/2;
00103 unsigned int nj2 = (nj+1)/2;
00104
00105 dest_im.set_size(ni2,nj2,n_planes);
00106
00107
00108 for (unsigned int i=0;i<n_planes;++i)
00109 {
00110 vil_gauss_reduce_121_1plane(src_im.top_left_ptr() + i*src_im.planestep(),
00111 ni, nj,
00112 src_im.istep(),src_im.jstep(),
00113 dest_im.top_left_ptr() + i*dest_im.planestep(),
00114 dest_im.istep(), dest_im.jstep());
00115 }
00116 }
00117
00118
00119
00120 inline unsigned char rl_round(double x, unsigned char )
00121 { return (unsigned char) (x+0.5);}
00122
00123 inline signed char rl_round(double x, signed char )
00124 { return (signed char) (x+0.5);}
00125
00126 inline unsigned short rl_round(double x, unsigned short )
00127 { return (unsigned short) (x+0.5);}
00128
00129 inline signed short rl_round(double x, signed short )
00130 { return (signed short) (x+0.5);}
00131
00132 inline unsigned int rl_round(double x, unsigned int )
00133 { return (unsigned int) (x+0.5);}
00134
00135 inline signed int rl_round(double x, signed int )
00136 { return (signed int) (x+0.5);}
00137
00138 inline unsigned long rl_round(double x, unsigned long )
00139 { return (unsigned long) (x+0.5);}
00140
00141 inline signed long rl_round(double x, signed long )
00142 { return (signed long) (x+0.5);}
00143
00144 inline double rl_round (double x, double )
00145 { return x; }
00146
00147 inline float rl_round (double x, float )
00148 { return (float) x; }
00149
00150
00151
00152
00153
00154
00155
00156 template <class T>
00157 void vil_gauss_reduce_general_plane(const vil_image_view<T>& src,
00158 vil_image_view<T>& dest,
00159 vil_image_view<T>& worka,
00160 vil_image_view<T>& workb,
00161 const vil_gauss_reduce_params ¶ms)
00162 {
00163 assert(src.ni() >= 5 && src.nj() >= 5);
00164
00165
00166
00167
00168 for (unsigned y=0;y<src.nj();y++)
00169 {
00170 unsigned ni2 = src.ni()-2;
00171 for (unsigned x=2;x<ni2;++x)
00172 worka(x,y) = rl_round( params.filt2() * (src(x-2,y) + src(x+2,y))
00173 + params.filt1() * (src(x-1,y) + src(x+1,y))
00174 + params.filt0() * src(x ,y),
00175 T(0));
00176
00177
00178 worka(0,y) = rl_round( params.filt_edge0() * src(0,y)
00179 + params.filt_edge1() * src(1,y)
00180 + params.filt_edge2() * src(2,y), (T)0);
00181
00182 worka(1,y) = rl_round( params.filt_pen_edge_n1() * src(0,y)
00183 + params.filt_pen_edge0() * src(1,y)
00184 + params.filt_pen_edge1() * src(2,y)
00185 + params.filt_pen_edge2() * src(3,y), (T)0);
00186
00187 worka(src.ni()-2,y) = rl_round( params.filt_pen_edge2() * src(src.ni()-4,y)
00188 + params.filt_pen_edge1() * src(src.ni()-3,y)
00189 + params.filt_pen_edge0() * src(src.ni()-2,y)
00190 + params.filt_pen_edge_n1() * src(src.ni()-1,y), (T)0);
00191
00192 worka(src.ni()-1,y) = rl_round( params.filt_edge2() * src(src.ni()-3,y)
00193 + params.filt_edge1() * src(src.ni()-2,y)
00194 + params.filt_edge0() * src(src.ni()-1,y), (T)0);
00195 }
00196
00197
00198
00199 for (unsigned int y=2;y+2<src.nj();++y)
00200 {
00201 for (unsigned int x=0; x<src.ni(); x++)
00202 workb(x,y) = rl_round( params.filt2() *(worka(x,y-2) + worka(x,y+2))
00203 + params.filt1() *(worka(x,y-1) + worka(x,y+1))
00204 + params.filt0() * worka(x, y),
00205 (T)0);
00206 }
00207
00208
00209
00210 for (unsigned x=0;x<src.ni();x++)
00211 {
00212 workb(x,src.nj()-1) = rl_round( params.filt_edge0() * worka(x,src.nj()-1)
00213 + params.filt_edge1() * worka(x,src.nj()-2)
00214 + params.filt_edge2() * worka(x,src.nj()-3), (T)0);
00215
00216 workb(x,src.nj()-2) = rl_round( params.filt_pen_edge2() * worka(x,src.nj()-4)
00217 + params.filt_pen_edge1() * worka(x,src.nj()-3)
00218 + params.filt_pen_edge0() * worka(x,src.nj()-2)
00219 + params.filt_pen_edge_n1() * worka(x,src.nj()-1), (T)0);
00220
00221 workb(x,1) = rl_round( params.filt_pen_edge2() * worka(x,3)
00222 + params.filt_pen_edge1() * worka(x,2)
00223 + params.filt_pen_edge0() * worka(x,1)
00224 + params.filt_pen_edge_n1() * worka(x,0), (T)0);
00225
00226 workb(x,0) = rl_round( params.filt_edge2() * worka(x,2)
00227 + params.filt_edge1() * worka(x,1)
00228 + params.filt_edge0() * worka(x,0), (T)0);
00229 }
00230
00231
00232
00233
00234
00235
00236 const double init_x = 0.5 * (src.ni()-1 - (dest.ni()-1)*params.scale_step());
00237 double yd = 0.5 * (src.nj() -1 - (dest.nj()-1)*params.scale_step());
00238 for (unsigned int yi=0; yi<dest.nj(); yi++)
00239 {
00240 double xd=init_x;
00241 for (unsigned int xi=0; xi<dest.ni(); xi++)
00242 {
00243 dest(xi,yi) = rl_round (vil_bilin_interp_safe_extend(workb, xd, yd), T(0));
00244 xd += params.scale_step();
00245 }
00246 yd+= params.scale_step();
00247 }
00248 }
00249
00250
00251 template <class T>
00252 void vil_gauss_reduce_general(const vil_image_view<T>& src,
00253 vil_image_view<T>& dest,
00254 vil_image_view<T>& worka,
00255 vil_image_view<T>& workb,
00256 const vil_gauss_reduce_params ¶ms)
00257 {
00258 if (worka.ni() < src.ni() || worka.nj() < src.nj())
00259 worka.set_size(src.ni(), src.nj());
00260 if (workb.ni() < src.ni() || workb.nj() < src.nj())
00261 workb.set_size(src.ni(), src.nj());
00262 dest.set_size((unsigned) (src.ni()/params.scale_step()+0.5),
00263 (unsigned) (src.nj()/params.scale_step()+0.5), src.nplanes());
00264
00265
00266 for (unsigned p=0;p<src.nplanes();++p) {
00267 vil_image_view<T> src_plane = vil_plane(src,p);
00268 vil_image_view<T> dest_plane = vil_plane(dest,p);
00269 vil_gauss_reduce_general_plane(src_plane, dest_plane, worka, workb, params);
00270 }
00271 #if 0
00272 vsl_indent_inc(vcl_cout);
00273 vcl_cout << vsl_indent() << "Work image B\n";
00274 workb_.print_all(vcl_cout);
00275 vsl_indent_dec(vcl_cout);
00276 #endif
00277 }
00278
00279
00280 template <class T>
00281 void vil_gauss_reduce_1plane(const T* src_im,
00282 unsigned src_ni, unsigned src_nj,
00283 vcl_ptrdiff_t s_x_step, vcl_ptrdiff_t s_y_step,
00284 T* dest_im,
00285 vcl_ptrdiff_t d_x_step, vcl_ptrdiff_t d_y_step)
00286 {
00287 T* d_row = dest_im;
00288 const T* s_row = src_im;
00289 vcl_ptrdiff_t sxs2 = s_x_step*2;
00290 unsigned ni2 = (src_ni-3)/2;
00291 vil_convert_round_pixel<double,T> rounder;
00292
00293 for (unsigned y=0;y<src_nj;++y)
00294 {
00295
00296 double dsum = 0.071 * static_cast<double>(s_row[sxs2]) +
00297 0.357 * static_cast<double>(s_row[s_x_step]) +
00298 0.572 * static_cast<double>(s_row[0]);
00299 rounder(dsum, *d_row);
00300
00301 T* d = d_row + d_x_step;
00302 const T* s = s_row + sxs2;
00303 for (unsigned x=0;x<ni2;++x)
00304 {
00305 dsum = 0.05*static_cast<double>(s[-sxs2]) + 0.25*static_cast<double>(s[-s_x_step]) +
00306 0.05*static_cast<double>(s[ sxs2]) + 0.25*static_cast<double>(s[ s_x_step]) +
00307 0.4 *static_cast<double>(s[0]);
00308 rounder(dsum, *d);
00309
00310 d += d_x_step;
00311 s += sxs2;
00312 }
00313
00314 dsum = 0.071 * static_cast<double>(s[-sxs2]) +
00315 0.357 * static_cast<double>(s[-s_x_step]) +
00316 0.572 * static_cast<double>(s[0]);
00317 rounder(dsum, *d);
00318
00319 d_row += d_y_step;
00320 s_row += s_y_step;
00321 }
00322 }
00323
00324
00325
00326
00327 template <class T>
00328 void vil_gauss_reduce_121_1plane(const T* src_im,
00329 unsigned src_ni, unsigned src_nj,
00330 vcl_ptrdiff_t s_x_step, vcl_ptrdiff_t s_y_step,
00331 T* dest_im,
00332 vcl_ptrdiff_t d_x_step, vcl_ptrdiff_t d_y_step)
00333 {
00334 vcl_ptrdiff_t sxs2 = s_x_step*2;
00335 vcl_ptrdiff_t sys2 = s_y_step*2;
00336 T* d_row = dest_im+d_y_step;
00337 const T* s_row1 = src_im + s_y_step;
00338 const T* s_row2 = s_row1 + s_y_step;
00339 const T* s_row3 = s_row2 + s_y_step;
00340 unsigned ni2 = (src_ni-2)/2;
00341 unsigned nj2 = (src_nj-2)/2;
00342 vil_convert_round_pixel<double,T> rounder;
00343
00344 for (unsigned y=0;y<nj2;++y)
00345 {
00346
00347 *d_row = *s_row2;
00348 T * d = d_row + d_x_step;
00349 const T* s1 = s_row1 + sxs2;
00350 const T* s2 = s_row2 + sxs2;
00351 const T* s3 = s_row3 + sxs2;
00352 for (unsigned x=0;x<ni2;++x)
00353 {
00354
00355 double ds1 = 0.0625 * static_cast<double>(s1[-s_x_step])
00356 + 0.125 * static_cast<double>(s1[0])
00357 + 0.0625 * static_cast<double>(s1[s_x_step]),
00358 ds2 = 0.1250 * static_cast<double>(s2[-s_x_step])
00359 + 0.250 * static_cast<double>(s2[0])
00360 + 0.1250 * static_cast<double>(s2[s_x_step]),
00361 ds3 = 0.0625 * static_cast<double>(s3[-s_x_step])
00362 + 0.125 * static_cast<double>(s3[0])
00363 + 0.0625 * static_cast<double>(s3[s_x_step]);
00364 rounder(ds1 + ds2 + ds3, *d);
00365
00366 d += d_x_step;
00367 s1 += sxs2;
00368 s2 += sxs2;
00369 s3 += sxs2;
00370 }
00371
00372 if (src_ni&1)
00373 *d = *s2;
00374
00375 d_row += d_y_step;
00376 s_row1 += sys2;
00377 s_row2 += sys2;
00378 s_row3 += sys2;
00379 }
00380
00381
00382
00383
00384 const T* s0 = src_im;
00385 unsigned ni=(src_ni+1)/2;
00386 for (unsigned i=0;i<ni;++i)
00387 {
00388 dest_im[i]= *s0;
00389 s0+=sxs2;
00390 }
00391
00392 if (src_nj&1)
00393 {
00394 unsigned yhi = (src_nj-1)/2;
00395 T* dest_last_row = dest_im + yhi*d_y_step;
00396 const T* s_last = src_im + yhi*sys2;
00397 for (unsigned i=0;i<ni;++i)
00398 {
00399 dest_last_row[i]= *s_last;
00400 s_last+=sxs2;
00401 }
00402 }
00403 }
00404
00405
00406 template <class T>
00407 void vil_gauss_reduce_2_3_1plane(const T* src_im,
00408 unsigned src_ni, unsigned src_nj,
00409 vcl_ptrdiff_t s_x_step, vcl_ptrdiff_t s_y_step,
00410 T* dest_im, vcl_ptrdiff_t d_x_step, vcl_ptrdiff_t d_y_step)
00411 {
00412 T* d_row = dest_im;
00413 const T* s_row = src_im;
00414 vcl_ptrdiff_t sxs2 = s_x_step*2,sxs3 = s_x_step*3;
00415 unsigned d_ni = (2*src_ni+1)/3;
00416 unsigned d_ni2 = d_ni/2;
00417 vil_convert_round_pixel<double,T> rounder;
00418
00419 for (unsigned y=0;y<src_nj;++y)
00420 {
00421
00422
00423 double drow0=0.75*static_cast<double>(s_row[0]) + 0.25*static_cast<double>(s_row[s_x_step]);
00424 double drow_xs=0.5*static_cast<double>(s_row[s_x_step]) + 0.5*static_cast<double>(s_row[sxs2]);
00425 rounder(drow0,d_row[0]);
00426 rounder(drow_xs,d_row[d_x_step]);
00427
00428 T* d = d_row + 2*d_x_step;
00429 const T* s = s_row + sxs3;
00430 for (unsigned x=1;x<d_ni2;++x)
00431 {
00432 double df= 0.2 * ( static_cast<double>(s[-s_x_step]) + static_cast<double>(s[s_x_step]) )
00433 + 0.6 * static_cast<double>(s[0]) ;
00434 rounder(df,*d);
00435
00436 d += d_x_step;
00437
00438 df = 0.5*(static_cast<double>(s[s_x_step]) + static_cast<double>(s[sxs2]) );
00439 rounder(df,*d);
00440
00441 d += d_x_step;
00442 s += sxs3;
00443 }
00444
00445 if (src_ni%3==1)
00446 {
00447 double df=0.75*static_cast<double>(s[-s_x_step]) + 0.25*static_cast<double>(s[0]);
00448 rounder(df,*d);
00449 }
00450 else if (src_ni%3==2)
00451 {
00452 double df = 0.2 * (static_cast<double>(s[-s_x_step]) + static_cast<double>(s[s_x_step]) )
00453 + 0.6 * static_cast<double>(s[0]);
00454 rounder(df,*d);
00455 }
00456 d_row += d_y_step;
00457 s_row += s_y_step;
00458 }
00459 }
00460
00461
00462 #undef VIL_GAUSS_REDUCE_INSTANTIATE
00463 #define VIL_GAUSS_REDUCE_INSTANTIATE(T) \
00464 template void vil_gauss_reduce(const vil_image_view<T >& src, \
00465 vil_image_view<T >& dest, \
00466 vil_image_view<T >& work_im); \
00467 template void vil_gauss_reduce_2_3(const vil_image_view<T >& src, \
00468 vil_image_view<T >& dest, \
00469 vil_image_view<T >& work_im); \
00470 template void vil_gauss_reduce_121(const vil_image_view<T >& src, \
00471 vil_image_view<T >& dest); \
00472 template void vil_gauss_reduce_general(const vil_image_view<T >& src_im, \
00473 vil_image_view<T >& dest_im, \
00474 vil_image_view<T >& worka, \
00475 vil_image_view<T >& workb, \
00476 const vil_gauss_reduce_params& params)
00477
00478 #endif // vil_gauss_reduce_txx_