core/filter.hh
Go to the documentation of this file.
1 /* -*- mia-c++ -*-
2  *
3  * This file is part of MIA - a toolbox for medical image analysis
4  * Copyright (c) Leipzig, Madrid 1999-2016 Gert Wollny
5  *
6  * MIA is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with MIA; if not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #ifndef mia_core_filter_hh
22 #define mia_core_filter_hh
23 
24 #include <cassert>
25 #include <stdexcept>
26 #include <mia/core/pixeltype.hh>
27 #include <mia/core/product_base.hh>
28 #include <mia/core/factory.hh>
30 
32 
36 struct EXPORT_CORE combiner_type {
37  static const char *type_descr;
38 };
39 
43 struct EXPORT_CORE filter_type {
44  static const char *type_descr;
45 };
46 
47 #define DC(T, D) dynamic_cast<const T&>(D)
48 #define DV(T, D) dynamic_cast<T&>(D)
49 
51 
67 template <typename R>
68 struct TFilter {
70  typedef R result_type;
71 };
72 
83 template <class D>
84 class EXPORT_HANDLER TDataFilter: public TFilter< std::shared_ptr<D > >, public CProductBase {
85 public:
86 
88  typedef D plugin_data;
90  typedef filter_type plugin_type;
91 
93  typedef D Image;
94 
96  typedef std::shared_ptr<TDataFilter<D> > Pointer;
97 
100 
101  virtual ~TDataFilter();
102 
106  result_type filter(const Image& image) const;
107 
111  result_type filter(std::shared_ptr<D> pimage) const;
112 
113 
119  std::set<EPixelType> test_pixeltype_conversion(const std::set<EPixelType>& in_types) const;
120 private:
121  virtual result_type do_filter(const Image& image) const = 0;
122  virtual result_type do_filter(std::shared_ptr<D> image) const;
123 
124  virtual std::set<EPixelType> do_test_pixeltype_conversion(const std::set<EPixelType>& in_type) const;
125 
126 };
127 
128 template <class D>
130  typedef typename TDataFilter<D>::result_type result_type;
131 public:
132  typedef typename TDataFilter<D>::Pointer Pointer;
133 
134  void push_back(Pointer f) {
135  m_chain.push_back(f);
136  }
137 
138 private:
139  virtual result_type do_filter(const D& image) const {
140  assert(m_chain.size() > 0);
141 
142  cvdebug() << "Run chained filter '" << m_chain[0]->get_init_string() << "'\n";
143  result_type result = m_chain[0]->filter(image);
144  for(auto f = m_chain.begin() + 1; f != m_chain.end(); ++f) {
145  cvdebug() << "Run chained filter '" << (*f)->get_init_string() << "'\n";
146  result = (*f)->filter(*result);
147  }
148  return result;
149  }
150 
151  std::set<EPixelType> do_test_pixeltype_conversion(const std::set<EPixelType>& in_type) const
152  {
153  std::set<EPixelType> result = in_type;
154  for(auto f: m_chain) {
155  result = f->test_pixeltype_conversion(result);
156  }
157  return result;
158  }
159 
160  std::vector<Pointer> m_chain;
161 };
162 
163 
175 template <class Image>
176 class EXPORT_HANDLER TDataFilterPlugin: public TFactory<TDataFilter<Image> > {
177 public:
180  TDataFilterPlugin(char const * const name):
181  TFactory<TDataFilter<Image> >(name)
182  {}
183 };
184 
185 template <typename D>
187  static constexpr bool value = true;
189 };
190 
191 
197 template <template <class> class D>
198 struct __bind_all {
199  typedef D<bool> Dbool;
200  typedef D<signed char> Dsc;
201  typedef D<unsigned char> Duc;
202  typedef D<signed short> Dss;
203  typedef D<unsigned short> Dus;
204  typedef D<signed int> Dsi;
205  typedef D<unsigned int> Dui;
206 #ifdef LONG_64BIT
207  typedef D<signed long> Dsl;
208  typedef D<unsigned long> Dul;
209 #endif
210  typedef D<float> Dfloat;
211  typedef D<double> Ddouble;
212 };
213 
225 template <typename B>
226 struct Binder {
227 };
229 
230 
249 template <typename F, typename B>
250 static typename F::result_type filter(const F& f, const B& b)
251 {
252  typedef typename Binder<B>::Derived D;
253  switch (b.get_pixel_type()) {
254  case it_bit: return f(DC(typename D::Dbool,b));
255  case it_sbyte: return f(DC(typename D::Dsc,b));
256  case it_ubyte: return f(DC(typename D::Duc,b));
257  case it_sshort:return f(DC(typename D::Dss,b));
258  case it_ushort:return f(DC(typename D::Dus,b));
259  case it_sint: return f(DC(typename D::Dsi,b));
260  case it_uint: return f(DC(typename D::Dui,b));
261 #ifdef LONG_64BIT
262  case it_slong: return f(DC(typename D::Dsl,b));
263  case it_ulong: return f(DC(typename D::Dul,b));
264 #endif
265  case it_float: return f(DC(typename D::Dfloat,b));
266  case it_double:return f(DC(typename D::Ddouble,b));
267  default:
268  assert(!"unsupported pixel type in image");
269  throw std::invalid_argument("mia::filter: unsupported pixel type in image");
270  }
271 }
272 
285 template <typename F, typename B>
286 static typename F::result_type filter_inplace(const F& f, B& b)
287 {
288  typedef typename Binder<B>::Derived D;
289  switch (b.get_pixel_type()) {
290  case it_bit: return f(DV(typename D::Dbool,b));
291  case it_sbyte: return f(DV(typename D::Dsc,b));
292  case it_ubyte: return f(DV(typename D::Duc,b));
293  case it_sshort:return f(DV(typename D::Dss,b));
294  case it_ushort:return f(DV(typename D::Dus,b));
295  case it_sint: return f(DV(typename D::Dsi,b));
296  case it_uint: return f(DV(typename D::Dui,b));
297 #ifdef LONG_64BIT
298  case it_slong: return f(DV(typename D::Dsl,b));
299  case it_ulong: return f(DV(typename D::Dul,b));
300 #endif
301  case it_float: return f(DV(typename D::Dfloat,b));
302  case it_double:return f(DV(typename D::Ddouble,b));
303  default:
304  assert(!"unsupported pixel type in image");
305  throw std::invalid_argument("mia::filter: unsupported pixel type in image");
306  }
307 }
308 
320 template <typename F, typename B>
321 static typename F::result_type accumulate(F& f, const B& data)
322 {
323  typedef typename Binder<B>::Derived D;
324  switch (data.get_pixel_type()) {
325  case it_bit: return f(DC(typename D::Dbool,data));
326  case it_sbyte: return f(DC(typename D::Dsc,data));
327  case it_ubyte: return f(DC(typename D::Duc,data));
328  case it_sshort:return f(DC(typename D::Dss,data));
329  case it_ushort:return f(DC(typename D::Dus,data));
330  case it_sint: return f(DC(typename D::Dsi,data));
331  case it_uint: return f(DC(typename D::Dui,data));
332 #ifdef LONG_64BIT
333  case it_slong: return f(DC(typename D::Dsl,data));
334  case it_ulong: return f(DC(typename D::Dul,data));
335 #endif
336  case it_float: return f(DC(typename D::Dfloat,data));
337  case it_double:return f(DC(typename D::Ddouble,data));
338  default:
339  assert(!"unsupported pixel type in image");
340  throw std::invalid_argument("mia::filter: unsupported pixel type in image");
341  }
342 }
343 
344 template <typename F, typename INOUT, typename IN>
345 static typename F::result_type _combine_inplace(const F& f, INOUT& inout, const IN& in)
346 {
347  typedef typename Binder<IN>::Derived D;
348  switch (in.get_pixel_type()) {
349  case it_bit: return f(inout, DC(typename D::Dbool, in));
350  case it_sbyte: return f(inout, DC(typename D::Dsc, in));
351  case it_ubyte: return f(inout, DC(typename D::Duc, in));
352  case it_sshort:return f(inout, DC(typename D::Dss, in));
353  case it_ushort:return f(inout, DC(typename D::Dus, in));
354  case it_sint: return f(inout, DC(typename D::Dsi, in));
355  case it_uint: return f(inout, DC(typename D::Dui, in));
356 #ifdef LONG_64BIT
357  case it_slong: return f(inout, DC(typename D::Dsl, in));
358  case it_ulong: return f(inout, DC(typename D::Dul, in));
359 #endif
360  case it_float: return f(inout, DC(typename D::Dfloat, in));
361  case it_double:return f(inout, DC(typename D::Ddouble, in));
362  default:
363  assert(!"unsupported pixel type in image");
364  throw std::invalid_argument("mia::filter: unsupported pixel type in image");
365  }
366 }
367 
368 template <typename F, typename INOUT, typename IN>
369 static typename F::result_type combine_inplace(const F& f, INOUT& inout, const IN& in)
370 {
371  typedef typename Binder<INOUT
372 >::Derived D;
373  switch (inout.get_pixel_type()) {
374  case it_bit: return _combine_inplace(f, DV(typename D::Dbool, inout), in);
375  case it_sbyte: return _combine_inplace(f, DV(typename D::Dsc, inout), in);
376  case it_ubyte: return _combine_inplace(f, DV(typename D::Duc, inout), in);
377  case it_sshort:return _combine_inplace(f, DV(typename D::Dss, inout), in);
378  case it_ushort:return _combine_inplace(f, DV(typename D::Dus, inout), in);
379  case it_sint: return _combine_inplace(f, DV(typename D::Dsi, inout), in);
380  case it_uint: return _combine_inplace(f, DV(typename D::Dui, inout), in);
381 #ifdef LONG_64BIT
382  case it_slong: return _combine_inplace(f, DV(typename D::Dsl, inout), in);
383  case it_ulong: return _combine_inplace(f, DV(typename D::Dul, inout), in);
384 #endif
385  case it_float: return _combine_inplace(f, DV(typename D::Dfloat, inout), in);
386  case it_double:return _combine_inplace(f, DV(typename D::Ddouble, inout), in);
387  default:
388  assert(!"unsupported pixel type in image");
389  throw std::invalid_argument("mia::filter: unsupported pixel type in image");
390  }
391 
392 
393 }
394 
395 
408 template <typename F, typename B>
409 static typename F::result_type filter_equal(const F& f, const B& a, const B& b)
410 {
411  assert(a.get_pixel_type() == b.get_pixel_type());
412  typedef typename Binder<B>::Derived D;
413  switch (a.get_pixel_type()) {
414  case it_bit: return f(DC(typename D::Dbool, a), DC(typename D::Dbool,b));
415  case it_sbyte: return f( DC(typename D::Dsc, a), DC(typename D::Dsc,b));
416  case it_ubyte: return f( DC(typename D::Duc, a), DC(typename D::Duc,b));
417  case it_sshort:return f( DC(typename D::Dss, a), DC(typename D::Dss,b));
418  case it_ushort:return f( DC(typename D::Dus, a), DC(typename D::Dus,b));
419  case it_sint: return f( DC(typename D::Dsi, a), DC(typename D::Dsi,b));
420  case it_uint: return f( DC(typename D::Dui, a), DC(typename D::Dui,b));
421 #ifdef LONG_64BIT
422  case it_slong: return f( DC(typename D::Dsl, a), DC(typename D::Dsl,b));
423  case it_ulong: return f( DC(typename D::Dul, a), DC(typename D::Dul,b));
424 #endif
425  case it_float: return f( DC(typename D::Dfloat, a), DC(typename D::Dfloat,b));
426  case it_double:return f( DC(typename D::Ddouble, a), DC(typename D::Ddouble,b));
427  default:
428  assert(!"unsupported pixel type in image");
429  throw std::invalid_argument("mia::filter: unsupported pixel type in image");
430  }
431 }
432 
433 
445 template <typename F, typename B>
446 static void filter_equal_inplace(const F& f, const B& a, B& b)
447 {
448  assert(a.get_pixel_type() == b.get_pixel_type());
449  typedef typename Binder<B>::Derived D;
450  switch (a.get_pixel_type()) {
451  case it_bit: f(DC(typename D::Dbool, a), DV(typename D::Dbool,b));break;
452  case it_sbyte: f( DC(typename D::Dsc, a), DV(typename D::Dsc,b));break;
453  case it_ubyte: f( DC(typename D::Duc, a), DV(typename D::Duc,b));break;
454  case it_sshort: f( DC(typename D::Dss, a), DV(typename D::Dss,b));break;
455  case it_ushort: f( DC(typename D::Dus, a), DV(typename D::Dus,b));break;
456  case it_sint: f( DC(typename D::Dsi, a), DV(typename D::Dsi,b));break;
457  case it_uint: f( DC(typename D::Dui, a), DV(typename D::Dui,b));break;
458 #ifdef LONG_64BIT
459  case it_slong: f( DC(typename D::Dsl, a), DV(typename D::Dsl,b));break;
460  case it_ulong: f( DC(typename D::Dul, a), DV(typename D::Dul,b));break;
461 #endif
462  case it_float: f( DC(typename D::Dfloat, a), DV(typename D::Dfloat,b));break;
463  case it_double: f( DC(typename D::Ddouble, a), DV(typename D::Ddouble,b));break;
464  default:
465  assert(!"unsupported pixel type in image");
466  throw std::invalid_argument("mia::filter: unsupported pixel type in image");
467  }
468 }
469 
470 
482 template <typename F, typename B, typename O>
483 static typename F::result_type filter_and_output(const F& f, const B& a, O& b)
484 {
485  typedef typename Binder<B>::Derived D;
486  switch (a.get_pixel_type()) {
487  case it_bit: return f(DC(typename D::Dbool, a), b);break;
488  case it_sbyte: return f(DC(typename D::Dsc, a), b);break;
489  case it_ubyte: return f(DC(typename D::Duc, a), b);break;
490  case it_sshort: return f(DC(typename D::Dss, a), b);break;
491  case it_ushort: return f(DC(typename D::Dus, a), b);break;
492  case it_sint: return f(DC(typename D::Dsi, a), b);break;
493  case it_uint: return f(DC(typename D::Dui, a), b);break;
494 #ifdef HAVE_INT64
495  case it_slong: return f(DC(typename D::Dsl, a), b);break;
496  case it_ulong: return f(DC(typename D::Dul, a), b);break;
497 #endif
498  case it_float: return f(DC(typename D::Dfloat, a), b);break;
499  case it_double: return f(DC(typename D::Ddouble, a), b);break;
500  default:
501  assert(!"unsupported pixel type in image");
502  throw std::invalid_argument("mia::filter_and_output: unsupported pixel type in image");
503  }
504 }
505 
507 
508 template <typename F, typename A, typename B>
509 static typename F::result_type _filter(const F& f, const A& a, const B& b)
510 {
511  typedef typename Binder<A>::Derived D;
512  switch (a.get_pixel_type()) {
513  case it_bit: return f(DC(typename D::Dbool, a), b);
514  case it_sbyte: return f(DC(typename D::Dsc, a), b);
515  case it_ubyte: return f(DC(typename D::Duc, a), b);
516  case it_sshort:return f(DC(typename D::Dss, a), b);
517  case it_ushort:return f(DC(typename D::Dus, a), b);
518  case it_sint: return f(DC(typename D::Dsi, a), b);
519  case it_uint: return f(DC(typename D::Dui, a), b);
520 #ifdef LONG_64BIT
521  case it_slong: return f(DC(typename D::Dsl, a), b);
522  case it_ulong: return f(DC(typename D::Dul, a), b);
523 #endif
524  case it_float: return f(DC(typename D::Dfloat,a), b);
525  case it_double:return f(DC(typename D::Ddouble,a), b);
526  default:
527  assert(!"unsupported pixel type in image");
528  throw std::invalid_argument("mia::filter: unsupported pixel type in image");
529  }
530 }
532 
533 
546 template <typename F, typename A, typename B>
547 static typename F::result_type filter(const F& f, const A& a, const B& b)
548 {
549  typedef typename Binder<B>::Derived D;
550  switch (b.get_pixel_type()) {
551  case it_bit: return _filter(f, a, DC(typename D::Dbool, b));
552  case it_sbyte: return _filter(f, a, DC(typename D::Dsc, b));
553  case it_ubyte: return _filter(f, a, DC(typename D::Duc, b));
554  case it_sshort:return _filter(f, a, DC(typename D::Dss, b));
555  case it_ushort:return _filter(f, a, DC(typename D::Dus, b));
556  case it_sint: return _filter(f, a, DC(typename D::Dsi, b));
557  case it_uint: return _filter(f, a, DC(typename D::Dui, b));
558 #ifdef LONG_64BIT
559  case it_slong: return _filter(f, a, DC(typename D::Dsl, b));
560  case it_ulong: return _filter(f, a, DC(typename D::Dul, b));
561 #endif
562  case it_float: return _filter(f, a, DC(typename D::Dfloat, b));
563  case it_double:return _filter(f, a, DC(typename D::Ddouble,b));
564  default:
565  assert(!"unsupported pixel type in image");
566  throw std::invalid_argument("mia::filter: unsupported pixel type in image");
567  }
568 }
569 
570 
572 template <typename F, typename A, typename B>
573 static typename F::result_type _accumulate(F& f, const A& a, const B& b)
574 {
575  typedef typename Binder<A>::Derived D;
576  switch (a.get_pixel_type()) {
577  case it_bit: return f(DC(typename D::Dbool, a), b);
578  case it_sbyte: return f(DC(typename D::Dsc, a), b);
579  case it_ubyte: return f(DC(typename D::Duc, a), b);
580  case it_sshort:return f(DC(typename D::Dss, a), b);
581  case it_ushort:return f(DC(typename D::Dus, a), b);
582  case it_sint: return f(DC(typename D::Dsi, a), b);
583  case it_uint: return f(DC(typename D::Dui, a), b);
584 #ifdef LONG_64BIT
585  case it_slong: return f(DC(typename D::Dsl, a), b);
586  case it_ulong: return f(DC(typename D::Dul, a), b);
587 #endif
588  case it_float: return f(DC(typename D::Dfloat,a), b);
589  case it_double:return f(DC(typename D::Ddouble,a), b);
590  default:
591  assert(!"unsupported pixel type in image");
592  throw std::invalid_argument("mia::filter: unsupported pixel type in image");
593  }
594 }
596 
609 template <typename F, typename A, typename B>
610 static typename F::result_type accumulate(F& f, const A& a, const B& b)
611 {
612  typedef typename Binder<B>::Derived D;
613  switch (b.get_pixel_type()) {
614  case it_bit: return _accumulate(f, a, DC(typename D::Dbool, b));
615  case it_sbyte: return _accumulate(f, a, DC(typename D::Dsc, b));
616  case it_ubyte: return _accumulate(f, a, DC(typename D::Duc, b));
617  case it_sshort:return _accumulate(f, a, DC(typename D::Dss, b));
618  case it_ushort:return _accumulate(f, a, DC(typename D::Dus, b));
619  case it_sint: return _accumulate(f, a, DC(typename D::Dsi, b));
620  case it_uint: return _accumulate(f, a, DC(typename D::Dui, b));
621 #ifdef LONG_64BIT
622  case it_slong: return _accumulate(f, a, DC(typename D::Dsl, b));
623  case it_ulong: return _accumulate(f, a, DC(typename D::Dul, b));
624 #endif
625  case it_float: return _accumulate(f, a, DC(typename D::Dfloat, b));
626  case it_double:return _accumulate(f, a, DC(typename D::Ddouble,b));
627  default:
628  assert(!"unsupported pixel type in image");
629  throw std::invalid_argument("mia::accumulate: unsupported pixel type in image");
630  }
631 }
632 
633 
634 #undef DC
635 #undef DV
636 
637 
638 template <class D>
640 {
641 }
642 
643 template <class D>
645 TDataFilter<D>::filter(const D& image) const
646 {
647  return do_filter(image);
648 }
649 
650 template <class D>
652 TDataFilter<D>::filter(std::shared_ptr<D> pimage) const
653 {
654  return do_filter(pimage);
655 }
656 
657 template <class D>
659 TDataFilter<D>::do_filter(std::shared_ptr<D> pimage) const
660 {
661  return do_filter(*pimage);
662 }
663 
664 
665 template <class D>
666 std::set<EPixelType>
667 TDataFilter<D>::test_pixeltype_conversion(const std::set<EPixelType>& in_types) const
668 {
669  return do_test_pixeltype_conversion(in_types);
670 }
671 
672 template <class D>
673 std::set<EPixelType>
674 TDataFilter<D>::do_test_pixeltype_conversion(const std::set<EPixelType>& in_types) const
675 {
676  return in_types;
677 }
678 
679 
681 
682 #endif
CDebugSink & cvdebug()
Definition: msgstream.hh:216
result_type filter(const Image &image) const
Definition: core/filter.hh:645
std::set< EPixelType > test_pixeltype_conversion(const std::set< EPixelType > &in_types) const
Definition: core/filter.hh:667
D plugin_data
plugin handler helper type
Definition: core/filter.hh:88
static F::result_type filter_and_output(const F &f, const B &a, O &b)
Definition: core/filter.hh:483
static F::result_type combine_inplace(const F &f, INOUT &inout, const IN &in)
Definition: core/filter.hh:369
static F::result_type _combine_inplace(const F &f, INOUT &inout, const IN &in)
Definition: core/filter.hh:345
base class for all filer type functors.
Definition: core/filter.hh:68
TFactory< TDataFilter< Image > >::Product Product
Definition: core/filter.hh:178
static void filter_equal_inplace(const F &f, const B &a, B &b)
Definition: core/filter.hh:446
TDataFilterPlugin(char const *const name)
Constructor that sets the plug-in name.
Definition: core/filter.hh:180
#define NS_MIA_BEGIN
conveniance define to start the mia namespace
Definition: defines.hh:33
std::shared_ptr< TDataFilter< D > > Pointer
pointer type of the data filtered by this filter
Definition: core/filter.hh:96
static F::result_type filter(const F &f, const B &b)
Definition: core/filter.hh:250
#define EXPORT_HANDLER
Definition: core/cost.hh:32
D Image
defines the image type handled by the image filter
Definition: core/filter.hh:93
void push_back(Pointer f)
Definition: core/filter.hh:134
This is tha base of all plugins that create "things", like filters, cost functions time step operator...
Definition: factory.hh:49
Generic image filter plugin base.
Definition: core/filter.hh:176
R result_type
defines the return type of the filter function
Definition: core/filter.hh:70
static F::result_type accumulate(F &f, const B &data)
Definition: core/filter.hh:321
TDataFilter< D >::Pointer Pointer
Definition: core/filter.hh:132
TFilter< std::shared_ptr< D > >::result_type result_type
result type of this filter
Definition: core/filter.hh:99
filter_type plugin_type
plugin handler helper type
Definition: core/filter.hh:90
#define EXPORT_CORE
Macro to manage Visual C++ style dllimport/dllexport.
Definition: defines.hh:101
The base class for all plug-in created object.
Definition: product_base.hh:40
Generic interface class to data filters.
Definition: core/filter.hh:84
virtual ~TDataFilter()
Definition: core/filter.hh:639
static F::result_type filter_inplace(const F &f, B &b)
Definition: core/filter.hh:286
static F::result_type filter_equal(const F &f, const B &a, const B &b)
Definition: core/filter.hh:409
#define NS_MIA_END
conveniance define to end the mia namespace
Definition: defines.hh:36