00001
00008 #ifndef DERICHEFILTER_H
00009 #define DERICHEFILTER_H
00010
00011 #ifdef _USE_INTEL_COMPILER
00012 #include <omp.h>
00013 #endif
00014
00015 #include <Image.H>
00016
00017 using namespace Images;
00018
00019 namespace Images {
00020
00042 template<unsigned DIM, typename Pixel = float>
00043 class DericheFilter
00044 {
00045 public:
00046
00047 typedef BaseImage<DIM, Pixel> Image;
00048 typedef typename Image::Index Index;
00049 typedef BaseImage<DIM, float> ImageVariance;
00050 typedef blitz::RectDomain<DIM> RectDomain;
00051
00053
00055
00057 DericheFilter(float _sigma,
00058 int _order = 0,
00059 bool _border_cond = true
00060 );
00061
00063 DericheFilter(float _sigma[DIM],
00064 int _order = 0,
00065 bool _border_cond = true
00066 );
00067
00069 DericheFilter(ImageVariance& _sigma,
00070 int _order = 0,
00071 bool _border_cond = true
00072 );
00073
00075 ~DericheFilter();
00076
00078
00080
00082 void filter(Image& image);
00084 void filter_axis(Image& image, const int axis);
00085
00087
00089
00091 void set_filter_type(int _filter_type);
00093 void set_order(int _order);
00095 void set_border_cond(bool _border_cond);
00096
00098 void set_isotropic_sigma(float _sigma);
00100 void set_anisotropic_sigma(float _sigma[DIM]);
00102 void set_image_sigma(const ImageVariance& _sigma);
00103
00104 protected:
00105
00107
00109
00111 void _init_coefs();
00113 void _coefs_sigma(float sigma, float coefs[6], float border_coefs[4]);
00114
00116 void _deriche_map(Image line, const int axis, Pixel* tmp_buf, Index lbound, Index ubound);
00117
00118
00120
00122
00123 int m_filter_type;
00124 int m_order;
00125 bool m_border_cond;
00126
00127 float m_sigma[DIM];
00128 ImageVariance * m_sigma_image;
00129
00130 float m_coefs[6*DIM];
00131 ImageVariance * m_variant_coefs[6];
00132
00133 float m_border_coefs[4*DIM];
00134
00136
00137 };
00138
00139
00144
00145
00146
00147
00148 template<unsigned DIM, typename Pixel>
00149 DericheFilter<DIM, Pixel>::DericheFilter(float _sigma, int _order, bool _border_cond)
00150 :m_filter_type(0), m_order(_order), m_sigma_image(NULL), m_border_cond(_border_cond)
00151 {
00152 for (int i=0 ; i<DIM; i++)
00153 m_sigma[i] = _sigma;
00154
00155 for (int i=0 ; i<6; i++)
00156 m_variant_coefs[i] = NULL;
00157
00158 _init_coefs();
00159 }
00160
00161 template<unsigned DIM, typename Pixel>
00162 DericheFilter<DIM, Pixel>::DericheFilter(float _sigma[DIM], int _order, bool _border_cond)
00163 :m_filter_type(1), m_order(_order), m_sigma_image(NULL), m_border_cond(_border_cond)
00164 {
00165 for (int i=0 ; i<DIM; i++)
00166 m_sigma[i] = _sigma[i];
00167
00168 for (int i=0 ; i<6; i++)
00169 m_variant_coefs[i] = NULL;
00170
00171 _init_coefs();
00172 }
00173
00174 template<unsigned DIM, typename Pixel>
00175 DericheFilter<DIM, Pixel>::DericheFilter(ImageVariance& _sigma, int _order, bool _border_cond)
00176 :m_filter_type(2), m_order(_order), m_sigma_image(&_sigma), m_border_cond(_border_cond)
00177 {
00178 for (int i=0 ; i<DIM; i++)
00179 m_sigma[i] = 0.0;
00180
00181 for (int i=0 ; i<6; i++)
00182 m_variant_coefs[i] = NULL;
00183
00184 _init_coefs();
00185 }
00186
00187 template<unsigned DIM, typename Pixel>
00188 DericheFilter<DIM, Pixel>::~DericheFilter()
00189 {
00190 for (int i=0 ; i<6; i++)
00191 if (m_variant_coefs[i] != NULL)
00192 delete m_variant_coefs[i];
00193 }
00194
00195
00197
00198
00199
00200 template<unsigned DIM, typename Pixel>
00201 void DericheFilter<DIM, Pixel>::filter(Image& image)
00202 {
00203 for (int i=1 ; i<=DIM ; i++)
00204 filter_axis(image, i);
00205 }
00206
00207 template<unsigned DIM, typename Pixel>
00208 void DericheFilter<DIM, Pixel>::filter_axis(Image& image, const int axis)
00209 {
00210
00211 Index tl = image.lbound();
00212 Index br = image.ubound();
00213 tl(axis) = 0;
00214 br(axis) = 0;
00215
00216 blitz::RectDomain<DIM> rect_domain(tl, br);
00217 Image slice = image(rect_domain);
00218 int ubound = image.ubound(axis-1);
00219
00220 #if 0
00221
00222 Pixel* tmp_buf = new Pixel[image.extent(axis-1)];
00223
00224
00225 for (typename Image::template iterator<domain> i=slice.begin() ; i!=slice.end() ; ++i){
00226 rect_domain.lbound() = i.position();
00227 rect_domain.ubound() = i.position();
00228 rect_domain.ubound(axis-1) = ubound;
00229
00230 _deriche_map(image(rect_domain), axis, tmp_buf, rect_domain.lbound(), rect_domain.ubound());
00231 }
00232
00233 delete[] tmp_buf;
00234
00235 #else
00236
00237 Index tmp[slice.size()];
00238 int i = 0;
00239 for (typename Image::template iterator<domain> it=slice.begin() ; it!=slice.end() ; ++it)
00240 tmp[i++] = it.position();
00241
00242 #pragma omp parallel
00243 {
00244
00245 Pixel* tmp_buf = new Pixel[image.extent(axis-1)];
00246 #pragma omp for
00247 for (int i = 0 ; i < slice.size() ; i++){
00248 blitz::RectDomain<DIM> rect_domain(tmp[i],tmp[i]);
00249 rect_domain.ubound(axis-1) = ubound;
00250 _deriche_map(image(rect_domain), axis, tmp_buf, rect_domain.lbound(), rect_domain.ubound());
00251 }
00252 delete[] tmp_buf;
00253 }
00254 #endif
00255
00256 }
00257
00258
00260
00261
00262
00263 template<unsigned DIM, typename Pixel>
00264 void DericheFilter<DIM, Pixel>::set_filter_type(int _filter_type)
00265 {
00266 m_filter_type = _filter_type;
00267 }
00268
00269 template<unsigned DIM, typename Pixel>
00270 void DericheFilter<DIM, Pixel>::set_order(int _order)
00271 {
00272 m_order = _order;
00273 }
00274
00275 template<unsigned DIM, typename Pixel>
00276 void DericheFilter<DIM, Pixel>::set_border_cond(bool _border_cond)
00277 {
00278 m_border_cond = _border_cond;
00279 }
00280
00281 template<unsigned DIM, typename Pixel>
00282 void DericheFilter<DIM, Pixel>::set_isotropic_sigma(float _sigma)
00283 {
00284 m_filter_type = 0;
00285 for (int i=0 ; i<DIM; i++)
00286 m_sigma[i] = _sigma;
00287 _init_coefs();
00288 }
00289
00290 template<unsigned DIM, typename Pixel>
00291 void DericheFilter<DIM, Pixel>::set_anisotropic_sigma(float _sigma[DIM])
00292 {
00293 m_filter_type = 1;
00294 for (int i=0 ; i<DIM; i++)
00295 m_sigma[i] = _sigma[i];
00296 _init_coefs();
00297 }
00298
00299 template<unsigned DIM, typename Pixel>
00300 void DericheFilter<DIM, Pixel>::set_image_sigma(const ImageVariance& _sigma)
00301 {
00302 m_filter_type = 2;
00303 m_sigma_image = &_sigma;
00304 _init_coefs();
00305 }
00306
00307
00309
00310
00311
00312 template<unsigned DIM, typename Pixel>
00313 void DericheFilter<DIM, Pixel>::_init_coefs()
00314 {
00315
00316 float coefs[6];
00317 float border_coefs[4];
00318
00319 switch(m_filter_type){
00320
00321 case 0 :
00322 _coefs_sigma(m_sigma[0], coefs, border_coefs);
00323 for (int i = 0 ; i < 6*DIM ; i++)
00324 m_coefs[i] = coefs[i%6];
00325 for (int i = 0 ; i < 4*DIM ; i++)
00326 m_border_coefs[i] = border_coefs[i%4];
00327 break;
00328
00329 case 1 :
00330 for (int i = 0 ; i < DIM ; i++){
00331 _coefs_sigma(m_sigma[i], coefs, border_coefs);
00332 for (int j = 0 ; j < 6 ; j++)
00333 m_coefs[i*6 + j] = coefs[j];
00334 for (int j = 0 ; j < 4 ; j++)
00335 m_border_coefs[i*4 + j] = border_coefs[j];
00336 }
00337 break;
00338
00339 case 2 :
00340 for (int i=0 ; i<6 ; i++){
00341 if (m_variant_coefs[i] != NULL) delete m_variant_coefs[i];
00342 m_variant_coefs[i] = new ImageVariance(m_sigma_image->shape());
00343 }
00344 for (typename ImageVariance::template iterator<domain> i=m_sigma_image->begin() ; i!=m_sigma_image->end() ; ++i ){
00345 _coefs_sigma((*m_sigma_image)(i), coefs, border_coefs);
00346 for (int j = 0 ; j < 6 ; j++)
00347 (*m_variant_coefs[j])(i) = coefs[j];
00348 }
00349 break;
00350 }
00351 }
00352
00353 template<unsigned DIM, typename Pixel>
00354 void DericheFilter<DIM, Pixel>::_coefs_sigma(float sigma, float coefs[6], float border_coefs[4])
00355 {
00356
00357 float a1,a2,a3,a4,b1,b2;
00358 float parity, g0, sumg1, sumg0;
00359
00360
00361 g0 = sumg0 = sumg1 = 0;
00362
00363
00364 const float alpha=sigma>0?1.695f/sigma:0;
00365 const float ea=(float)exp(alpha);
00366 const float ema=(float)exp(-alpha);
00367 const float em2a=ema*ema;
00368
00369
00370 b1=2*ema;
00371 b2=-em2a;
00372
00373 float ek,ekn;
00374
00375
00376 switch(m_order)
00377 {
00378 case 1:
00379 ek = -(1-ema)*(1-ema)*(1-ema)/(2*(ema+1)*ema);
00380 a1 = 0;
00381 a2 = ek*ema;
00382 a3 = -ek*ema;
00383 a4 = 0;
00384 parity = 1;
00385 if (m_border_cond) {
00386 sumg1 = (ek*ea)/((ea-1)*(ea-1));
00387 g0 = 0;
00388 sumg0 = g0+sumg1;
00389 }
00390 break;
00391 case 2:
00392 ekn = ( -2*(-1+3*ea-3*ea*ea+ea*ea*ea)/(3*ea+1+3*ea*ea+ea*ea*ea) );
00393 ek = -(em2a-1)/(2*alpha*ema);
00394 a1 = ekn;
00395 a2 = -ekn*(1+ek*alpha)*ema;
00396 a3 = ekn*(1-ek*alpha)*ema;
00397 a4 = -ekn*em2a;
00398 parity = -1;
00399 if (m_border_cond) {
00400 sumg1 = ekn/2;
00401 g0 = ekn;
00402 sumg0 = g0+sumg1;
00403 }
00404 break;
00405 default:
00406 ek = (1-ema)*(1-ema) / (1+2*alpha*ema - em2a);
00407 a1 = ek;
00408 a2 = ek*ema*(alpha-1);
00409 a3 = ek*ema*(alpha+1);
00410 a4 = -ek*em2a;
00411 parity = 1;
00412 if (m_border_cond) {
00413 sumg1 = ek*(alpha*ea+ea-1)/((ea-1)*(ea-1));
00414 g0 = ek;
00415 sumg0 = g0+sumg1;
00416 }
00417 break;
00418 }
00419
00420 coefs[0] = a1;
00421 coefs[1] = a2;
00422 coefs[2] = a3;
00423 coefs[3] = a4;
00424 coefs[4] = b1;
00425 coefs[5] = b2;
00426
00427 border_coefs[0] = parity;
00428 border_coefs[1] = g0;
00429 border_coefs[2] = sumg1;
00430 border_coefs[3] = sumg0;
00431 }
00432
00433 template<unsigned DIM, typename Pixel>
00434 void DericheFilter<DIM, Pixel>::_deriche_map(Image line, const int axis, Pixel* temp_buf, Index lbound, Index ubound)
00435 {
00436 float b1, b2, a1, a2, a3, a4;
00437 float parity, g0, sumg1, sumg0;
00438
00439 if (m_filter_type != 2){
00440 a1 = m_coefs[(axis-1)*6];
00441 a2 = m_coefs[(axis-1)*6 + 1];
00442 a3 = m_coefs[(axis-1)*6 + 2];
00443 a4 = m_coefs[(axis-1)*6 + 3];
00444 b1 = m_coefs[(axis-1)*6 + 4];
00445 b2 = m_coefs[(axis-1)*6 + 5];
00446
00447 parity = m_border_coefs[(axis-1)*4];
00448 g0 = m_border_coefs[(axis-1)*4 + 1];
00449 sumg1 = m_border_coefs[(axis-1)*4 + 2];
00450 sumg0 = m_border_coefs[(axis-1)*4 + 3];
00451 }
00452
00453 typename Image::template iterator<domain> i = line.begin();
00454 Pixel Y0, I0, Y1, I1, Y2, I2;
00455
00456
00457
00458 if (m_filter_type != 2){
00459 I1 = line(i); ++i;
00460 I2 = line(i); ++i;
00461 Y2 = *(temp_buf++) = sumg0*I2;
00462 Y1 = *(temp_buf++) = g0*I1 + sumg1*I2;
00463 }
00464 else{
00465 I1 = line(i);
00466 I2 = I1;
00467 Y1 = I1/2.0;
00468 Y2 = I1/2.0;
00469 }
00470
00471
00472
00473 for (; i != line.end() ; ++i){
00474 if (m_filter_type == 2){
00475 a1 = (*m_variant_coefs[0])(i.position() + lbound);
00476 a2 = (*m_variant_coefs[1])(i.position() + lbound);
00477 b1 = (*m_variant_coefs[4])(i.position() + lbound);
00478 b2 = (*m_variant_coefs[5])(i.position() + lbound);
00479 }
00480 I1 = line(i);
00481 Y0 = *(temp_buf++) = a1*I1 + a2*I2 + b1*Y1 + b2*Y2;
00482 I2=I1;
00483 Y2=Y1;
00484 Y1=Y0;
00485 }
00486
00487
00488
00489 line.reverseSelf(axis-1);
00490 i = line.begin();
00491
00492 if (m_filter_type != 2){
00493 I2 = line(i);
00494 Y2 = Y1 = parity*sumg1*I2;
00495 line(i) = *(--temp_buf)+Y2; ++i;
00496 I0 = line(i);
00497 line(i) = *(--temp_buf)+Y1; ++i;
00498 }
00499 else{
00500 I1 = line(i);
00501 I2 = I1;
00502 Y1 = I1/2.0;
00503 Y2 = I1/2.0;
00504 }
00505
00506
00507
00508 for (; i != line.end() ; ++i){
00509 if (m_filter_type == 2){
00510 a3 = (*m_variant_coefs[2])(ubound - i.position());
00511 a4 = (*m_variant_coefs[3])(ubound - i.position());
00512 b1 = (*m_variant_coefs[4])(ubound - i.position());
00513 b2 = (*m_variant_coefs[5])(ubound - i.position());
00514 }
00515 Y0= a3*I1 + a4*I2 + b1*Y1 + b2*Y2;
00516 I2=I1;
00517 Y2=Y1;
00518 Y1=Y0;
00519 I1=line(i);
00520 line(i)= *(--temp_buf) + Y0;
00521 }
00522 }
00523 }
00524
00525 #endif // DERICHEFILTER_H