My Project
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>
28#include <mia/core/factory.hh>
30
31#include <cinttypes>
32
34
38struct EXPORT_CORE combiner_type {
39 static const char *type_descr;
40};
41
45struct 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
69template <typename R>
70struct TFilter {
72 typedef R result_type;
73};
74
85template <class D>
86class EXPORT_HANDLER TDataFilter: public TFilter< std::shared_ptr<D >>, public CProductBase
87{
88public:
89
91 typedef D plugin_data;
93 typedef filter_type plugin_type;
94
96 typedef D Image;
97
99 typedef std::shared_ptr<TDataFilter<D>> Pointer;
100
102 typedef typename TFilter< std::shared_ptr<D >>::result_type result_type;
103
104 virtual ~TDataFilter();
105
109 result_type filter(const Image& image) const;
110
114 result_type filter(std::shared_ptr<D> pimage) const;
115
116
122 std::set<EPixelType> test_pixeltype_conversion(const std::set<EPixelType>& in_types) const;
123private:
124 virtual result_type do_filter(const Image& image) const = 0;
125 virtual result_type do_filter(std::shared_ptr<D> image) const;
126
127 virtual std::set<EPixelType> do_test_pixeltype_conversion(const std::set<EPixelType>& in_type) const;
128
129};
130
131template <class D>
133{
135public:
137
139 {
140 m_chain.push_back(f);
141 }
142
143private:
144 virtual result_type do_filter(const D& image) const
145 {
146 assert(m_chain.size() > 0);
147 cvdebug() << "Run chained filter '" << m_chain[0]->get_init_string() << "'\n";
148 result_type result = m_chain[0]->filter(image);
149
150 for (auto f = m_chain.begin() + 1; f != m_chain.end(); ++f) {
151 cvdebug() << "Run chained filter '" << (*f)->get_init_string() << "'\n";
152 result = (*f)->filter(*result);
153 }
154
155 return result;
156 }
157
158 std::set<EPixelType> do_test_pixeltype_conversion(const std::set<EPixelType>& in_type) const
159 {
160 std::set<EPixelType> result = in_type;
161
162 for (auto f : m_chain) {
163 result = f->test_pixeltype_conversion(result);
164 }
165
166 return result;
167 }
168
169 std::vector<Pointer> m_chain;
170};
171
172
184template <class Image>
185class EXPORT_HANDLER TDataFilterPlugin: public TFactory<TDataFilter<Image>>
186{
187public:
188 typedef typename TFactory<TDataFilter<Image>>::Product Product;
190 TDataFilterPlugin(char const *const name):
191 TFactory<TDataFilter<Image>>(name)
192 {}
193};
194
195template <typename D>
197 static constexpr bool value = true;
199};
200
201
207template <template <class> class D>
208struct __bind_all {
209 typedef D<bool> Dbool;
210 typedef D<int8_t> Dsc;
211 typedef D<uint8_t> Duc;
212 typedef D<int16_t> Dss;
213 typedef D<uint16_t> Dus;
214 typedef D<int32_t> Dsi;
215 typedef D<uint32_t> Dui;
216 typedef D<int64_t> Dsl;
217 typedef D<uint64_t> Dul;
218 typedef D<float> Dfloat;
219 typedef D<double> Ddouble;
220};
221
233template <typename B>
234struct Binder {
235};
237
238
257template <typename F, typename B>
258static typename F::result_type filter(const F& f, const B& b)
259{
260 typedef typename Binder<B>::Derived D;
261
262 switch (b.get_pixel_type()) {
263 case it_bit:
264 return f(DC(typename D::Dbool, b));
265
266 case it_sbyte:
267 return f(DC(typename D::Dsc, b));
268
269 case it_ubyte:
270 return f(DC(typename D::Duc, b));
271
272 case it_sshort:
273 return f(DC(typename D::Dss, b));
274
275 case it_ushort:
276 return f(DC(typename D::Dus, b));
277
278 case it_sint:
279 return f(DC(typename D::Dsi, b));
280
281 case it_uint:
282 return f(DC(typename D::Dui, b));
283
284 case it_slong:
285 return f(DC(typename D::Dsl, b));
286
287 case it_ulong:
288 return f(DC(typename D::Dul, b));
289
290 case it_float:
291 return f(DC(typename D::Dfloat, b));
292
293 case it_double:
294 return f(DC(typename D::Ddouble, b));
295
296 default:
297 assert(!"unsupported pixel type in image");
298 throw std::invalid_argument("mia::filter: unsupported pixel type in image");
299 }
300}
301
314template <typename F, typename B>
315static typename F::result_type filter_inplace(const F& f, B& b)
316{
317 typedef typename Binder<B>::Derived D;
318
319 switch (b.get_pixel_type()) {
320 case it_bit:
321 return f(DV(typename D::Dbool, b));
322
323 case it_sbyte:
324 return f(DV(typename D::Dsc, b));
325
326 case it_ubyte:
327 return f(DV(typename D::Duc, b));
328
329 case it_sshort:
330 return f(DV(typename D::Dss, b));
331
332 case it_ushort:
333 return f(DV(typename D::Dus, b));
334
335 case it_sint:
336 return f(DV(typename D::Dsi, b));
337
338 case it_uint:
339 return f(DV(typename D::Dui, b));
340
341 case it_slong:
342 return f(DV(typename D::Dsl, b));
343
344 case it_ulong:
345 return f(DV(typename D::Dul, b));
346
347 case it_float:
348 return f(DV(typename D::Dfloat, b));
349
350 case it_double:
351 return f(DV(typename D::Ddouble, b));
352
353 default:
354 assert(!"unsupported pixel type in image");
355 throw std::invalid_argument("mia::filter: unsupported pixel type in image");
356 }
357}
358
370template <typename F, typename B>
371static typename F::result_type accumulate(F& f, const B& data)
372{
373 typedef typename Binder<B>::Derived D;
374
375 switch (data.get_pixel_type()) {
376 case it_bit:
377 return f(DC(typename D::Dbool, data));
378
379 case it_sbyte:
380 return f(DC(typename D::Dsc, data));
381
382 case it_ubyte:
383 return f(DC(typename D::Duc, data));
384
385 case it_sshort:
386 return f(DC(typename D::Dss, data));
387
388 case it_ushort:
389 return f(DC(typename D::Dus, data));
390
391 case it_sint:
392 return f(DC(typename D::Dsi, data));
393
394 case it_uint:
395 return f(DC(typename D::Dui, data));
396
397 case it_slong:
398 return f(DC(typename D::Dsl, data));
399
400 case it_ulong:
401 return f(DC(typename D::Dul, data));
402
403 case it_float:
404 return f(DC(typename D::Dfloat, data));
405
406 case it_double:
407 return f(DC(typename D::Ddouble, data));
408
409 default:
410 assert(!"unsupported pixel type in image");
411 throw std::invalid_argument("mia::filter: unsupported pixel type in image");
412 }
413}
414
415template <typename F, typename INOUT, typename IN>
416static typename F::result_type _combine_inplace(const F& f, INOUT& inout, const IN& in)
417{
418 typedef typename Binder<IN>::Derived D;
419
420 switch (in.get_pixel_type()) {
421 case it_bit:
422 return f(inout, DC(typename D::Dbool, in));
423
424 case it_sbyte:
425 return f(inout, DC(typename D::Dsc, in));
426
427 case it_ubyte:
428 return f(inout, DC(typename D::Duc, in));
429
430 case it_sshort:
431 return f(inout, DC(typename D::Dss, in));
432
433 case it_ushort:
434 return f(inout, DC(typename D::Dus, in));
435
436 case it_sint:
437 return f(inout, DC(typename D::Dsi, in));
438
439 case it_uint:
440 return f(inout, DC(typename D::Dui, in));
441
442 case it_slong:
443 return f(inout, DC(typename D::Dsl, in));
444
445 case it_ulong:
446 return f(inout, DC(typename D::Dul, in));
447
448 case it_float:
449 return f(inout, DC(typename D::Dfloat, in));
450
451 case it_double:
452 return f(inout, DC(typename D::Ddouble, in));
453
454 default:
455 assert(!"unsupported pixel type in image");
456 throw std::invalid_argument("mia::filter: unsupported pixel type in image");
457 }
458}
459
460template <typename F, typename INOUT, typename IN>
461static typename F::result_type combine_inplace(const F& f, INOUT& inout, const IN& in)
462{
463 typedef typename Binder<INOUT
464 >::Derived D;
465
466 switch (inout.get_pixel_type()) {
467 case it_bit:
468 return _combine_inplace(f, DV(typename D::Dbool, inout), in);
469
470 case it_sbyte:
471 return _combine_inplace(f, DV(typename D::Dsc, inout), in);
472
473 case it_ubyte:
474 return _combine_inplace(f, DV(typename D::Duc, inout), in);
475
476 case it_sshort:
477 return _combine_inplace(f, DV(typename D::Dss, inout), in);
478
479 case it_ushort:
480 return _combine_inplace(f, DV(typename D::Dus, inout), in);
481
482 case it_sint:
483 return _combine_inplace(f, DV(typename D::Dsi, inout), in);
484
485 case it_uint:
486 return _combine_inplace(f, DV(typename D::Dui, inout), in);
487
488 case it_slong:
489 return _combine_inplace(f, DV(typename D::Dsl, inout), in);
490
491 case it_ulong:
492 return _combine_inplace(f, DV(typename D::Dul, inout), in);
493
494 case it_float:
495 return _combine_inplace(f, DV(typename D::Dfloat, inout), in);
496
497 case it_double:
498 return _combine_inplace(f, DV(typename D::Ddouble, inout), in);
499
500 default:
501 assert(!"unsupported pixel type in image");
502 throw std::invalid_argument("mia::filter: unsupported pixel type in image");
503 }
504}
505
506
519template <typename F, typename B>
520static typename F::result_type filter_equal(const F& f, const B& a, const B& b)
521{
522 assert(a.get_pixel_type() == b.get_pixel_type());
523 typedef typename Binder<B>::Derived D;
524
525 switch (a.get_pixel_type()) {
526 case it_bit:
527 return f(DC(typename D::Dbool, a), DC(typename D::Dbool, b));
528
529 case it_sbyte:
530 return f( DC(typename D::Dsc, a), DC(typename D::Dsc, b));
531
532 case it_ubyte:
533 return f( DC(typename D::Duc, a), DC(typename D::Duc, b));
534
535 case it_sshort:
536 return f( DC(typename D::Dss, a), DC(typename D::Dss, b));
537
538 case it_ushort:
539 return f( DC(typename D::Dus, a), DC(typename D::Dus, b));
540
541 case it_sint:
542 return f( DC(typename D::Dsi, a), DC(typename D::Dsi, b));
543
544 case it_uint:
545 return f( DC(typename D::Dui, a), DC(typename D::Dui, b));
546
547 case it_slong:
548 return f( DC(typename D::Dsl, a), DC(typename D::Dsl, b));
549
550 case it_ulong:
551 return f( DC(typename D::Dul, a), DC(typename D::Dul, b));
552
553 case it_float:
554 return f( DC(typename D::Dfloat, a), DC(typename D::Dfloat, b));
555
556 case it_double:
557 return f( DC(typename D::Ddouble, a), DC(typename D::Ddouble, b));
558
559 default:
560 assert(!"unsupported pixel type in image");
561 throw std::invalid_argument("mia::filter: unsupported pixel type in image");
562 }
563}
564
565
577template <typename F, typename B>
578static void filter_equal_inplace(const F& f, const B& a, B& b)
579{
580 assert(a.get_pixel_type() == b.get_pixel_type());
581 typedef typename Binder<B>::Derived D;
582
583 switch (a.get_pixel_type()) {
584 case it_bit:
585 f(DC(typename D::Dbool, a), DV(typename D::Dbool, b));
586 break;
587
588 case it_sbyte:
589 f( DC(typename D::Dsc, a), DV(typename D::Dsc, b));
590 break;
591
592 case it_ubyte:
593 f( DC(typename D::Duc, a), DV(typename D::Duc, b));
594 break;
595
596 case it_sshort:
597 f( DC(typename D::Dss, a), DV(typename D::Dss, b));
598 break;
599
600 case it_ushort:
601 f( DC(typename D::Dus, a), DV(typename D::Dus, b));
602 break;
603
604 case it_sint:
605 f( DC(typename D::Dsi, a), DV(typename D::Dsi, b));
606 break;
607
608 case it_uint:
609 f( DC(typename D::Dui, a), DV(typename D::Dui, b));
610 break;
611
612 case it_slong:
613 f( DC(typename D::Dsl, a), DV(typename D::Dsl, b));
614 break;
615
616 case it_ulong:
617 f( DC(typename D::Dul, a), DV(typename D::Dul, b));
618 break;
619
620 case it_float:
621 f( DC(typename D::Dfloat, a), DV(typename D::Dfloat, b));
622 break;
623
624 case it_double:
625 f( DC(typename D::Ddouble, a), DV(typename D::Ddouble, b));
626 break;
627
628 default:
629 assert(!"unsupported pixel type in image");
630 throw std::invalid_argument("mia::filter: unsupported pixel type in image");
631 }
632}
633
634
646template <typename F, typename B, typename O>
647static typename F::result_type filter_and_output(const F& f, const B& a, O& b)
648{
649 typedef typename Binder<B>::Derived D;
650
651 switch (a.get_pixel_type()) {
652 case it_bit:
653 return f(DC(typename D::Dbool, a), b);
654 break;
655
656 case it_sbyte:
657 return f(DC(typename D::Dsc, a), b);
658 break;
659
660 case it_ubyte:
661 return f(DC(typename D::Duc, a), b);
662 break;
663
664 case it_sshort:
665 return f(DC(typename D::Dss, a), b);
666 break;
667
668 case it_ushort:
669 return f(DC(typename D::Dus, a), b);
670 break;
671
672 case it_sint:
673 return f(DC(typename D::Dsi, a), b);
674 break;
675
676 case it_uint:
677 return f(DC(typename D::Dui, a), b);
678 break;
679
680 case it_slong:
681 return f(DC(typename D::Dsl, a), b);
682 break;
683
684 case it_ulong:
685 return f(DC(typename D::Dul, a), b);
686 break;
687
688 case it_float:
689 return f(DC(typename D::Dfloat, a), b);
690 break;
691
692 case it_double:
693 return f(DC(typename D::Ddouble, a), b);
694 break;
695
696 default:
697 assert(!"unsupported pixel type in image");
698 throw std::invalid_argument("mia::filter_and_output: unsupported pixel type in image");
699 }
700}
701
703
704template <typename F, typename A, typename B>
705static typename F::result_type _filter(const F& f, const A& a, const B& b)
706{
707 typedef typename Binder<A>::Derived D;
708
709 switch (a.get_pixel_type()) {
710 case it_bit:
711 return f(DC(typename D::Dbool, a), b);
712
713 case it_sbyte:
714 return f(DC(typename D::Dsc, a), b);
715
716 case it_ubyte:
717 return f(DC(typename D::Duc, a), b);
718
719 case it_sshort:
720 return f(DC(typename D::Dss, a), b);
721
722 case it_ushort:
723 return f(DC(typename D::Dus, a), b);
724
725 case it_sint:
726 return f(DC(typename D::Dsi, a), b);
727
728 case it_uint:
729 return f(DC(typename D::Dui, a), b);
730
731 case it_slong:
732 return f(DC(typename D::Dsl, a), b);
733
734 case it_ulong:
735 return f(DC(typename D::Dul, a), b);
736
737 case it_float:
738 return f(DC(typename D::Dfloat, a), b);
739
740 case it_double:
741 return f(DC(typename D::Ddouble, a), b);
742
743 default:
744 assert(!"unsupported pixel type in image");
745 throw std::invalid_argument("mia::filter: unsupported pixel type in image");
746 }
747}
749
750
763template <typename F, typename A, typename B>
764static typename F::result_type filter(const F& f, const A& a, const B& b)
765{
766 typedef typename Binder<B>::Derived D;
767
768 switch (b.get_pixel_type()) {
769 case it_bit:
770 return _filter(f, a, DC(typename D::Dbool, b));
771
772 case it_sbyte:
773 return _filter(f, a, DC(typename D::Dsc, b));
774
775 case it_ubyte:
776 return _filter(f, a, DC(typename D::Duc, b));
777
778 case it_sshort:
779 return _filter(f, a, DC(typename D::Dss, b));
780
781 case it_ushort:
782 return _filter(f, a, DC(typename D::Dus, b));
783
784 case it_sint:
785 return _filter(f, a, DC(typename D::Dsi, b));
786
787 case it_uint:
788 return _filter(f, a, DC(typename D::Dui, b));
789
790 case it_slong:
791 return _filter(f, a, DC(typename D::Dsl, b));
792
793 case it_ulong:
794 return _filter(f, a, DC(typename D::Dul, b));
795
796 case it_float:
797 return _filter(f, a, DC(typename D::Dfloat, b));
798
799 case it_double:
800 return _filter(f, a, DC(typename D::Ddouble, b));
801
802 default:
803 assert(!"unsupported pixel type in image");
804 throw std::invalid_argument("mia::filter: unsupported pixel type in image");
805 }
806}
807
808
810template <typename F, typename A, typename B>
811static typename F::result_type _accumulate(F& f, const A& a, const B& b)
812{
813 typedef typename Binder<A>::Derived D;
814
815 switch (a.get_pixel_type()) {
816 case it_bit:
817 return f(DC(typename D::Dbool, a), b);
818
819 case it_sbyte:
820 return f(DC(typename D::Dsc, a), b);
821
822 case it_ubyte:
823 return f(DC(typename D::Duc, a), b);
824
825 case it_sshort:
826 return f(DC(typename D::Dss, a), b);
827
828 case it_ushort:
829 return f(DC(typename D::Dus, a), b);
830
831 case it_sint:
832 return f(DC(typename D::Dsi, a), b);
833
834 case it_uint:
835 return f(DC(typename D::Dui, a), b);
836
837 case it_slong:
838 return f(DC(typename D::Dsl, a), b);
839
840 case it_ulong:
841 return f(DC(typename D::Dul, a), b);
842
843 case it_float:
844 return f(DC(typename D::Dfloat, a), b);
845
846 case it_double:
847 return f(DC(typename D::Ddouble, a), b);
848
849 default:
850 assert(!"unsupported pixel type in image");
851 throw std::invalid_argument("mia::filter: unsupported pixel type in image");
852 }
853}
855
868template <typename F, typename A, typename B>
869static typename F::result_type accumulate(F& f, const A& a, const B& b)
870{
871 typedef typename Binder<B>::Derived D;
872
873 switch (b.get_pixel_type()) {
874 case it_bit:
875 return _accumulate(f, a, DC(typename D::Dbool, b));
876
877 case it_sbyte:
878 return _accumulate(f, a, DC(typename D::Dsc, b));
879
880 case it_ubyte:
881 return _accumulate(f, a, DC(typename D::Duc, b));
882
883 case it_sshort:
884 return _accumulate(f, a, DC(typename D::Dss, b));
885
886 case it_ushort:
887 return _accumulate(f, a, DC(typename D::Dus, b));
888
889 case it_sint:
890 return _accumulate(f, a, DC(typename D::Dsi, b));
891
892 case it_uint:
893 return _accumulate(f, a, DC(typename D::Dui, b));
894
895 case it_slong:
896 return _accumulate(f, a, DC(typename D::Dsl, b));
897
898 case it_ulong:
899 return _accumulate(f, a, DC(typename D::Dul, b));
900
901 case it_float:
902 return _accumulate(f, a, DC(typename D::Dfloat, b));
903
904 case it_double:
905 return _accumulate(f, a, DC(typename D::Ddouble, b));
906
907 default:
908 assert(!"unsupported pixel type in image");
909 throw std::invalid_argument("mia::accumulate: unsupported pixel type in image");
910 }
911}
912
913
914#undef DC
915#undef DV
916
917
918template <class D>
922
923template <class D>
925TDataFilter<D>::filter(const D& image) const
926{
927 return do_filter(image);
928}
929
930template <class D>
932TDataFilter<D>::filter(std::shared_ptr<D> pimage) const
933{
934 return do_filter(pimage);
935}
936
937template <class D>
939TDataFilter<D>::do_filter(std::shared_ptr<D> pimage) const
940{
941 return do_filter(*pimage);
942}
943
944
945template <class D>
946std::set<EPixelType>
947TDataFilter<D>::test_pixeltype_conversion(const std::set<EPixelType>& in_types) const
948{
949 return do_test_pixeltype_conversion(in_types);
950}
951
952template <class D>
953std::set<EPixelType>
954TDataFilter<D>::do_test_pixeltype_conversion(const std::set<EPixelType>& in_types) const
955{
956 return in_types;
957}
958
959
961
962#endif
The base class for all plug-in created object.
void push_back(Pointer f)
TDataFilter< D >::Pointer Pointer
Generic image filter plugin base.
TDataFilterPlugin(char const *const name)
Constructor that sets the plug-in name.
TFactory< TDataFilter< Image > >::Product Product
Generic interface class to data filters.
result_type filter(const Image &image) const
virtual ~TDataFilter()
result_type filter(std::shared_ptr< D > pimage) const
filter_type plugin_type
plugin handler helper type
D plugin_data
plugin handler helper type
std::shared_ptr< TDataFilter< D > > Pointer
pointer type of the data filtered by this filter
std::set< EPixelType > test_pixeltype_conversion(const std::set< EPixelType > &in_types) const
TFilter< std::shared_ptr< D > >::result_type result_type
result type of this filter
D Image
defines the image type handled by the image filter
This is tha base of all plugins that create "things", like filters, cost functions time step operator...
Definition factory.hh:51
#define EXPORT_HANDLER
Definition core/cost.hh:32
static F::result_type _combine_inplace(const F &f, INOUT &inout, const IN &in)
static F::result_type combine_inplace(const F &f, INOUT &inout, const IN &in)
#define NS_MIA_BEGIN
conveniance define to start the mia namespace
Definition defines.hh:33
#define EXPORT_CORE
Macro to manage Visual C++ style dllimport/dllexport.
Definition defines.hh:101
#define NS_MIA_END
conveniance define to end the mia namespace
Definition defines.hh:36
static void filter_equal_inplace(const F &f, const B &a, B &b)
static F::result_type filter_and_output(const F &f, const B &a, O &b)
static F::result_type filter(const F &f, const B &b)
static F::result_type filter_equal(const F &f, const B &a, const B &b)
static F::result_type filter_inplace(const F &f, B &b)
static F::result_type accumulate(F &f, const B &data)
CDebugSink & cvdebug()
Definition msgstream.hh:226
@ it_slong
Definition pixeltype.hh:40
@ it_ushort
Definition pixeltype.hh:37
@ it_float
Definition pixeltype.hh:42
@ it_ubyte
Definition pixeltype.hh:35
@ it_uint
Definition pixeltype.hh:39
@ it_double
Definition pixeltype.hh:43
@ it_ulong
Definition pixeltype.hh:41
@ it_sbyte
Definition pixeltype.hh:34
@ it_sshort
Definition pixeltype.hh:36
@ it_sint
Definition pixeltype.hh:38
@ it_bit
Definition pixeltype.hh:33
base class for all filer type functors.
R result_type
defines the return type of the filter function
static constexpr bool value