ODIN
filter_morph.h
1 /***************************************************************************
2  filter_morph.h - description
3  -------------------
4  begin : Fr Nov 29 2019
5  copyright : (C) 2019-2021 by Thies Jochimsen
6  email : thies@jochimsen.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #ifndef FILTER_MORPH_H
19 #define FILTER_MORPH_H
20 
21 #include <odindata/filter_step.h>
22 #include <odindata/utils.h> // for on_grid(...)
23 
24 
25 enum morphOp { erode=0, dilate };
26 
27 
28 template <morphOp morphop>
29 class FilterMorph: public FilterStep {
30 
31  LDRfloat radius;
32 
33  STD_string label() const {if(morphop==erode) return "erode"; else return "dilate";}
34  STD_string description() const {return label()+" image using spherical kernel as structuring element";}
35  bool process(Data<float,4>& data, Protocol& prot) const {
36 
37  Log<Filter> odinlog(c_label(),"process");
38 
39  Range all=Range::all();
40 
41  TinyVector<int,4> shape=data.shape();
42  TinyVector<int,3> spatshape(shape(sliceDim), shape(phaseDim), shape(readDim));
43 
44 
45 
46  TinyVector<float,3> voxel_spacing;
47  voxel_spacing(0)=FileFormat::voxel_extent(prot.geometry, sliceDirection, data.extent(sliceDim));
48  voxel_spacing(1)=FileFormat::voxel_extent(prot.geometry, phaseDirection, data.extent(phaseDim));
49  voxel_spacing(2)=FileFormat::voxel_extent(prot.geometry, readDirection, data.extent(readDim));
50  ODINLOG(odinlog,normalDebug) << "voxel_spacing=" << voxel_spacing << STD_endl;
51 
52 
53  TinyVector<int,3> enclbox;
54  enclbox=radius/voxel_spacing+1;
55 
56  ODINLOG(odinlog,normalDebug) << "enclbox=" << enclbox << STD_endl;
57 
58 
59  STD_vector<TinyVector<int,3> > neighboffset;
60 
61  for(int k=-enclbox(0); k<=enclbox(0); k++) {
62  for(int j=-enclbox(1); j<=enclbox(1); j++) {
63  for(int i=-enclbox(2); i<=enclbox(2); i++) {
64  TinyVector<float,3> distvec(voxel_spacing(0)*k, voxel_spacing(1)*j, voxel_spacing(2)*i);
65 
66  float dist=sqrt(sum(distvec*distvec));
67  if(dist<=radius) {
68  neighboffset.push_back(TinyVector<int,3>( k, j, i));
69  }
70  }
71  }
72  }
73 
74  unsigned int numof_neigb=neighboffset.size();
75  ODINLOG(odinlog,normalDebug) << "numof_neigb=" << numof_neigb << STD_endl;
76  for(unsigned int i=0; i<numof_neigb; i++) {
77  ODINLOG(odinlog,normalDebug) << "neighboffset[" << i << "]=" << neighboffset[i] << STD_endl;
78  }
79 
80 
81  Data<float,3> involdata(spatshape);
82  Data<unsigned int,3> neighbcount(spatshape); neighbcount=0;
83  Data<float,3> outmask(spatshape); outmask=0.0;
84  TinyVector<int,3> index, neighbindex;
85 
86  for(int irep=0; irep<shape(timeDim); irep++) {
87 
88  involdata(all,all,all)=data(irep,all,all,all);
89 
90  for(unsigned int i=0; i<involdata.size(); i++) {
91  index=involdata.create_index(i);
92 
93  if(involdata(index)!=0.0) {
94  for(unsigned int j=0; j<numof_neigb; j++) {
95  neighbindex=index+neighboffset[j];
96 
97  if(on_grid<3>(spatshape, neighbindex)) {
98  neighbcount(neighbindex)++;
99  }
100  }
101  }
102  }
103 
104  for(unsigned int i=0; i<involdata.size(); i++) {
105  index=involdata.create_index(i);
106  unsigned int count=neighbcount(index);
107  if(morphop==erode && count==numof_neigb) outmask(index)=1.0;
108  if(morphop==dilate && count>0) outmask(index)=1.0;
109  }
110 
111  data(irep,all,all,all)=outmask(all,all,all);
112 
113  }
114 
115 
116  return true;
117  }
118  FilterStep* allocate() const {return new FilterMorph<morphop>();}
119  void init() {
120  radius.set_unit(ODIN_SPAT_UNIT).set_description("radius of kernel");
121  append_arg(radius,"radius");
122  }
123 
124 };
125 
126 
128 
129 #endif
static float voxel_extent(const Geometry &geometry, direction direction, int size)
virtual bool process(Data< float, 4 > &data, Protocol &prot) const
LDRbase & set_description(const STD_string &descr)
Definition: ldrbase.h:382
LDRbase & set_unit(const STD_string &un)
Definition: ldrbase.h:401
Definition: tjlog.h:218
Protocol proxy.
Definition: protocol.h:33
Geometry geometry
Definition: protocol.h:83
virtual FilterStep * allocate() const=0
void append_arg(LDRbase &arg, const STD_string &arglabel)
Definition: step_code.h:76
virtual STD_string description() const=0
virtual void init()=0
virtual STD_string label() const=0