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-2017 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 
31 #include <cinttypes>
32 
34 
38 struct EXPORT_CORE combiner_type {
39  static const char *type_descr;
40 };
41 
45 struct EXPORT_CORE filter_type {
46  static const char *type_descr;
47 };
48 
49 #define DC(T, D) dynamic_cast<const T&>(D)
50 #define DV(T, D) dynamic_cast<T&>(D)
51 
53 
69 template <typename R>
70 struct TFilter {
72  typedef R result_type;
73 };
74 
85 template <class D>
86 class EXPORT_HANDLER TDataFilter: public TFilter< std::shared_ptr<D > >, public CProductBase {
87 public:
88 
90  typedef D plugin_data;
92  typedef filter_type plugin_type;
93 
95  typedef D Image;
96 
98  typedef std::shared_ptr<TDataFilter<D> > Pointer;
99 
102 
103  virtual ~TDataFilter();
104 
108  result_type filter(const Image& image) const;
109 
113  result_type filter(std::shared_ptr<D> pimage) const;
114 
115 
121  std::set<EPixelType> test_pixeltype_conversion(const std::set<EPixelType>& in_types) const;
122 private:
123  virtual result_type do_filter(const Image& image) const = 0;
124  virtual result_type do_filter(std::shared_ptr<D> image) const;
125 
126  virtual std::set<EPixelType> do_test_pixeltype_conversion(const std::set<EPixelType>& in_type) const;
127 
128 };
129 
130 template <class D>
132  typedef typename TDataFilter<D>::result_type result_type;
133 public:
134  typedef typename TDataFilter<D>::Pointer Pointer;
135 
136  void push_back(Pointer f) {
137  m_chain.push_back(f);
138  }
139 
140 private:
141  virtual result_type do_filter(const D& image) const {
142  assert(m_chain.size() > 0);
143 
144  cvdebug() << "Run chained filter '" << m_chain[0]->get_init_string() << "'\n";
145  result_type result = m_chain[0]->filter(image);
146  for(auto f = m_chain.begin() + 1; f != m_chain.end(); ++f) {
147  cvdebug() << "Run chained filter '" << (*f)->get_init_string() << "'\n";
148  result = (*f)->filter(*result);
149  }
150  return result;
151  }
152 
153  std::set<EPixelType> do_test_pixeltype_conversion(const std::set<EPixelType>& in_type) const
154  {
155  std::set<EPixelType> result = in_type;
156  for(auto f: m_chain) {
157  result = f->test_pixeltype_conversion(result);
158  }
159  return result;
160  }
161 
162  std::vector<Pointer> m_chain;
163 };
164 
165 
177 template <class Image>
178 class EXPORT_HANDLER TDataFilterPlugin: public TFactory<TDataFilter<Image> > {
179 public:
182  TDataFilterPlugin(char const * const name):
183  TFactory<TDataFilter<Image> >(name)
184  {}
185 };
186 
187 template <typename D>
189  static constexpr bool value = true;
191 };
192 
193 
199 template <template <class> class D>
200 struct __bind_all {
201  typedef D<bool> Dbool;
202  typedef D<int8_t> Dsc;
203  typedef D<uint8_t> Duc;
204  typedef D<int16_t> Dss;
205  typedef D<uint16_t> Dus;
206  typedef D<int32_t> Dsi;
207  typedef D<uint32_t> Dui;
208  typedef D<int64_t> Dsl;
209  typedef D<uint64_t> Dul;
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  case it_slong: return f(DC(typename D::Dsl,b));
262  case it_ulong: return f(DC(typename D::Dul,b));
263  case it_float: return f(DC(typename D::Dfloat,b));
264  case it_double:return f(DC(typename D::Ddouble,b));
265  default:
266  assert(!"unsupported pixel type in image");
267  throw std::invalid_argument("mia::filter: unsupported pixel type in image");
268  }
269 }
270 
283 template <typename F, typename B>
284 static typename F::result_type filter_inplace(const F& f, B& b)
285 {
286  typedef typename Binder<B>::Derived D;
287  switch (b.get_pixel_type()) {
288  case it_bit: return f(DV(typename D::Dbool,b));
289  case it_sbyte: return f(DV(typename D::Dsc,b));
290  case it_ubyte: return f(DV(typename D::Duc,b));
291  case it_sshort:return f(DV(typename D::Dss,b));
292  case it_ushort:return f(DV(typename D::Dus,b));
293  case it_sint: return f(DV(typename D::Dsi,b));
294  case it_uint: return f(DV(typename D::Dui,b));
295  case it_slong: return f(DV(typename D::Dsl,b));
296  case it_ulong: return f(DV(typename D::Dul,b));
297  case it_float: return f(DV(typename D::Dfloat,b));
298  case it_double:return f(DV(typename D::Ddouble,b));
299  default:
300  assert(!"unsupported pixel type in image");
301  throw std::invalid_argument("mia::filter: unsupported pixel type in image");
302  }
303 }
304 
316 template <typename F, typename B>
317 static typename F::result_type accumulate(F& f, const B& data)
318 {
319  typedef typename Binder<B>::Derived D;
320  switch (data.get_pixel_type()) {
321  case it_bit: return f(DC(typename D::Dbool,data));
322  case it_sbyte: return f(DC(typename D::Dsc,data));
323  case it_ubyte: return f(DC(typename D::Duc,data));
324  case it_sshort:return f(DC(typename D::Dss,data));
325  case it_ushort:return f(DC(typename D::Dus,data));
326  case it_sint: return f(DC(typename D::Dsi,data));
327  case it_uint: return f(DC(typename D::Dui,data));
328  case it_slong: return f(DC(typename D::Dsl,data));
329  case it_ulong: return f(DC(typename D::Dul,data));
330  case it_float: return f(DC(typename D::Dfloat,data));
331  case it_double:return f(DC(typename D::Ddouble,data));
332  default:
333  assert(!"unsupported pixel type in image");
334  throw std::invalid_argument("mia::filter: unsupported pixel type in image");
335  }
336 }
337 
338 template <typename F, typename INOUT, typename IN>
339 static typename F::result_type _combine_inplace(const F& f, INOUT& inout, const IN& in)
340 {
341  typedef typename Binder<IN>::Derived D;
342  switch (in.get_pixel_type()) {
343  case it_bit: return f(inout, DC(typename D::Dbool, in));
344  case it_sbyte: return f(inout, DC(typename D::Dsc, in));
345  case it_ubyte: return f(inout, DC(typename D::Duc, in));
346  case it_sshort:return f(inout, DC(typename D::Dss, in));
347  case it_ushort:return f(inout, DC(typename D::Dus, in));
348  case it_sint: return f(inout, DC(typename D::Dsi, in));
349  case it_uint: return f(inout, DC(typename D::Dui, in));
350  case it_slong: return f(inout, DC(typename D::Dsl, in));
351  case it_ulong: return f(inout, DC(typename D::Dul, in));
352  case it_float: return f(inout, DC(typename D::Dfloat, in));
353  case it_double:return f(inout, DC(typename D::Ddouble, in));
354  default:
355  assert(!"unsupported pixel type in image");
356  throw std::invalid_argument("mia::filter: unsupported pixel type in image");
357  }
358 }
359 
360 template <typename F, typename INOUT, typename IN>
361 static typename F::result_type combine_inplace(const F& f, INOUT& inout, const IN& in)
362 {
363  typedef typename Binder<INOUT
364 >::Derived D;
365  switch (inout.get_pixel_type()) {
366  case it_bit: return _combine_inplace(f, DV(typename D::Dbool, inout), in);
367  case it_sbyte: return _combine_inplace(f, DV(typename D::Dsc, inout), in);
368  case it_ubyte: return _combine_inplace(f, DV(typename D::Duc, inout), in);
369  case it_sshort:return _combine_inplace(f, DV(typename D::Dss, inout), in);
370  case it_ushort:return _combine_inplace(f, DV(typename D::Dus, inout), in);
371  case it_sint: return _combine_inplace(f, DV(typename D::Dsi, inout), in);
372  case it_uint: return _combine_inplace(f, DV(typename D::Dui, inout), in);
373  case it_slong: return _combine_inplace(f, DV(typename D::Dsl, inout), in);
374  case it_ulong: return _combine_inplace(f, DV(typename D::Dul, inout), in);
375  case it_float: return _combine_inplace(f, DV(typename D::Dfloat, inout), in);
376  case it_double:return _combine_inplace(f, DV(typename D::Ddouble, inout), in);
377  default:
378  assert(!"unsupported pixel type in image");
379  throw std::invalid_argument("mia::filter: unsupported pixel type in image");
380  }
381 
382 
383 }
384 
385 
398 template <typename F, typename B>
399 static typename F::result_type filter_equal(const F& f, const B& a, const B& b)
400 {
401  assert(a.get_pixel_type() == b.get_pixel_type());
402  typedef typename Binder<B>::Derived D;
403  switch (a.get_pixel_type()) {
404  case it_bit: return f(DC(typename D::Dbool, a), DC(typename D::Dbool,b));
405  case it_sbyte: return f( DC(typename D::Dsc, a), DC(typename D::Dsc,b));
406  case it_ubyte: return f( DC(typename D::Duc, a), DC(typename D::Duc,b));
407  case it_sshort:return f( DC(typename D::Dss, a), DC(typename D::Dss,b));
408  case it_ushort:return f( DC(typename D::Dus, a), DC(typename D::Dus,b));
409  case it_sint: return f( DC(typename D::Dsi, a), DC(typename D::Dsi,b));
410  case it_uint: return f( DC(typename D::Dui, a), DC(typename D::Dui,b));
411  case it_slong: return f( DC(typename D::Dsl, a), DC(typename D::Dsl,b));
412  case it_ulong: return f( DC(typename D::Dul, a), DC(typename D::Dul,b));
413  case it_float: return f( DC(typename D::Dfloat, a), DC(typename D::Dfloat,b));
414  case it_double:return f( DC(typename D::Ddouble, a), DC(typename D::Ddouble,b));
415  default:
416  assert(!"unsupported pixel type in image");
417  throw std::invalid_argument("mia::filter: unsupported pixel type in image");
418  }
419 }
420 
421 
433 template <typename F, typename B>
434 static void filter_equal_inplace(const F& f, const B& a, B& b)
435 {
436  assert(a.get_pixel_type() == b.get_pixel_type());
437  typedef typename Binder<B>::Derived D;
438  switch (a.get_pixel_type()) {
439  case it_bit: f(DC(typename D::Dbool, a), DV(typename D::Dbool,b));break;
440  case it_sbyte: f( DC(typename D::Dsc, a), DV(typename D::Dsc,b));break;
441  case it_ubyte: f( DC(typename D::Duc, a), DV(typename D::Duc,b));break;
442  case it_sshort: f( DC(typename D::Dss, a), DV(typename D::Dss,b));break;
443  case it_ushort: f( DC(typename D::Dus, a), DV(typename D::Dus,b));break;
444  case it_sint: f( DC(typename D::Dsi, a), DV(typename D::Dsi,b));break;
445  case it_uint: f( DC(typename D::Dui, a), DV(typename D::Dui,b));break;
446  case it_slong: f( DC(typename D::Dsl, a), DV(typename D::Dsl,b));break;
447  case it_ulong: f( DC(typename D::Dul, a), DV(typename D::Dul,b));break;
448  case it_float: f( DC(typename D::Dfloat, a), DV(typename D::Dfloat,b));break;
449  case it_double: f( DC(typename D::Ddouble, a), DV(typename D::Ddouble,b));break;
450  default:
451  assert(!"unsupported pixel type in image");
452  throw std::invalid_argument("mia::filter: unsupported pixel type in image");
453  }
454 }
455 
456 
468 template <typename F, typename B, typename O>
469 static typename F::result_type filter_and_output(const F& f, const B& a, O& b)
470 {
471  typedef typename Binder<B>::Derived D;
472  switch (a.get_pixel_type()) {
473  case it_bit: return f(DC(typename D::Dbool, a), b);break;
474  case it_sbyte: return f(DC(typename D::Dsc, a), b);break;
475  case it_ubyte: return f(DC(typename D::Duc, a), b);break;
476  case it_sshort: return f(DC(typename D::Dss, a), b);break;
477  case it_ushort: return f(DC(typename D::Dus, a), b);break;
478  case it_sint: return f(DC(typename D::Dsi, a), b);break;
479  case it_uint: return f(DC(typename D::Dui, a), b);break;
480  case it_slong: return f(DC(typename D::Dsl, a), b);break;
481  case it_ulong: return f(DC(typename D::Dul, a), b);break;
482  case it_float: return f(DC(typename D::Dfloat, a), b);break;
483  case it_double: return f(DC(typename D::Ddouble, a), b);break;
484  default:
485  assert(!"unsupported pixel type in image");
486  throw std::invalid_argument("mia::filter_and_output: unsupported pixel type in image");
487  }
488 }
489 
491 
492 template <typename F, typename A, typename B>
493 static typename F::result_type _filter(const F& f, const A& a, const B& b)
494 {
495  typedef typename Binder<A>::Derived D;
496  switch (a.get_pixel_type()) {
497  case it_bit: return f(DC(typename D::Dbool, a), b);
498  case it_sbyte: return f(DC(typename D::Dsc, a), b);
499  case it_ubyte: return f(DC(typename D::Duc, a), b);
500  case it_sshort:return f(DC(typename D::Dss, a), b);
501  case it_ushort:return f(DC(typename D::Dus, a), b);
502  case it_sint: return f(DC(typename D::Dsi, a), b);
503  case it_uint: return f(DC(typename D::Dui, a), b);
504  case it_slong: return f(DC(typename D::Dsl, a), b);
505  case it_ulong: return f(DC(typename D::Dul, a), b);
506  case it_float: return f(DC(typename D::Dfloat,a), b);
507  case it_double:return f(DC(typename D::Ddouble,a), b);
508  default:
509  assert(!"unsupported pixel type in image");
510  throw std::invalid_argument("mia::filter: unsupported pixel type in image");
511  }
512 }
514 
515 
528 template <typename F, typename A, typename B>
529 static typename F::result_type filter(const F& f, const A& a, const B& b)
530 {
531  typedef typename Binder<B>::Derived D;
532  switch (b.get_pixel_type()) {
533  case it_bit: return _filter(f, a, DC(typename D::Dbool, b));
534  case it_sbyte: return _filter(f, a, DC(typename D::Dsc, b));
535  case it_ubyte: return _filter(f, a, DC(typename D::Duc, b));
536  case it_sshort:return _filter(f, a, DC(typename D::Dss, b));
537  case it_ushort:return _filter(f, a, DC(typename D::Dus, b));
538  case it_sint: return _filter(f, a, DC(typename D::Dsi, b));
539  case it_uint: return _filter(f, a, DC(typename D::Dui, b));
540  case it_slong: return _filter(f, a, DC(typename D::Dsl, b));
541  case it_ulong: return _filter(f, a, DC(typename D::Dul, b));
542  case it_float: return _filter(f, a, DC(typename D::Dfloat, b));
543  case it_double:return _filter(f, a, DC(typename D::Ddouble,b));
544  default:
545  assert(!"unsupported pixel type in image");
546  throw std::invalid_argument("mia::filter: unsupported pixel type in image");
547  }
548 }
549 
550 
552 template <typename F, typename A, typename B>
553 static typename F::result_type _accumulate(F& f, const A& a, const B& b)
554 {
555  typedef typename Binder<A>::Derived D;
556  switch (a.get_pixel_type()) {
557  case it_bit: return f(DC(typename D::Dbool, a), b);
558  case it_sbyte: return f(DC(typename D::Dsc, a), b);
559  case it_ubyte: return f(DC(typename D::Duc, a), b);
560  case it_sshort:return f(DC(typename D::Dss, a), b);
561  case it_ushort:return f(DC(typename D::Dus, a), b);
562  case it_sint: return f(DC(typename D::Dsi, a), b);
563  case it_uint: return f(DC(typename D::Dui, a), b);
564  case it_slong: return f(DC(typename D::Dsl, a), b);
565  case it_ulong: return f(DC(typename D::Dul, a), b);
566  case it_float: return f(DC(typename D::Dfloat,a), b);
567  case it_double:return f(DC(typename D::Ddouble,a), b);
568  default:
569  assert(!"unsupported pixel type in image");
570  throw std::invalid_argument("mia::filter: unsupported pixel type in image");
571  }
572 }
574 
587 template <typename F, typename A, typename B>
588 static typename F::result_type accumulate(F& f, const A& a, const B& b)
589 {
590  typedef typename Binder<B>::Derived D;
591  switch (b.get_pixel_type()) {
592  case it_bit: return _accumulate(f, a, DC(typename D::Dbool, b));
593  case it_sbyte: return _accumulate(f, a, DC(typename D::Dsc, b));
594  case it_ubyte: return _accumulate(f, a, DC(typename D::Duc, b));
595  case it_sshort:return _accumulate(f, a, DC(typename D::Dss, b));
596  case it_ushort:return _accumulate(f, a, DC(typename D::Dus, b));
597  case it_sint: return _accumulate(f, a, DC(typename D::Dsi, b));
598  case it_uint: return _accumulate(f, a, DC(typename D::Dui, b));
599  case it_slong: return _accumulate(f, a, DC(typename D::Dsl, b));
600  case it_ulong: return _accumulate(f, a, DC(typename D::Dul, b));
601  case it_float: return _accumulate(f, a, DC(typename D::Dfloat, b));
602  case it_double:return _accumulate(f, a, DC(typename D::Ddouble,b));
603  default:
604  assert(!"unsupported pixel type in image");
605  throw std::invalid_argument("mia::accumulate: unsupported pixel type in image");
606  }
607 }
608 
609 
610 #undef DC
611 #undef DV
612 
613 
614 template <class D>
616 {
617 }
618 
619 template <class D>
621 TDataFilter<D>::filter(const D& image) const
622 {
623  return do_filter(image);
624 }
625 
626 template <class D>
628 TDataFilter<D>::filter(std::shared_ptr<D> pimage) const
629 {
630  return do_filter(pimage);
631 }
632 
633 template <class D>
635 TDataFilter<D>::do_filter(std::shared_ptr<D> pimage) const
636 {
637  return do_filter(*pimage);
638 }
639 
640 
641 template <class D>
642 std::set<EPixelType>
643 TDataFilter<D>::test_pixeltype_conversion(const std::set<EPixelType>& in_types) const
644 {
645  return do_test_pixeltype_conversion(in_types);
646 }
647 
648 template <class D>
649 std::set<EPixelType>
650 TDataFilter<D>::do_test_pixeltype_conversion(const std::set<EPixelType>& in_types) const
651 {
652  return in_types;
653 }
654 
655 
657 
658 #endif
CDebugSink & cvdebug()
Definition: msgstream.hh:216
D plugin_data
plugin handler helper type
Definition: core/filter.hh:90
static F::result_type filter_and_output(const F &f, const B &a, O &b)
Definition: core/filter.hh:469
static F::result_type combine_inplace(const F &f, INOUT &inout, const IN &in)
Definition: core/filter.hh:361
static F::result_type _combine_inplace(const F &f, INOUT &inout, const IN &in)
Definition: core/filter.hh:339
base class for all filer type functors.
Definition: core/filter.hh:70
TFactory< TDataFilter< Image > >::Product Product
Definition: core/filter.hh:180
result_type filter(const Image &image) const
Definition: core/filter.hh:621
static void filter_equal_inplace(const F &f, const B &a, B &b)
Definition: core/filter.hh:434
TDataFilterPlugin(char const *const name)
Constructor that sets the plug-in name.
Definition: core/filter.hh:182
#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:98
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:95
void push_back(Pointer f)
Definition: core/filter.hh:136
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:178
R result_type
defines the return type of the filter function
Definition: core/filter.hh:72
std::set< EPixelType > test_pixeltype_conversion(const std::set< EPixelType > &in_types) const
Definition: core/filter.hh:643
static F::result_type accumulate(F &f, const B &data)
Definition: core/filter.hh:317
TDataFilter< D >::Pointer Pointer
Definition: core/filter.hh:134
TFilter< std::shared_ptr< D > >::result_type result_type
result type of this filter
Definition: core/filter.hh:101
filter_type plugin_type
plugin handler helper type
Definition: core/filter.hh:92
#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:86
virtual ~TDataFilter()
Definition: core/filter.hh:615
static F::result_type filter_inplace(const F &f, B &b)
Definition: core/filter.hh:284
static F::result_type filter_equal(const F &f, const B &a, const B &b)
Definition: core/filter.hh:399
#define NS_MIA_END
conveniance define to end the mia namespace
Definition: defines.hh:36