SegmentAreaOp.h
1 /*
2 
3 MIT License
4 
5 Copyright (c) 2017 FMI Open Development / Markus Peura, first.last@fmi.fi
6 
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13 
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
16 
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 SOFTWARE.
24 
25 */
26 /*
27 Part of Rack development has been done in the BALTRAD projects part-financed
28 by the European Union (European Regional Development Fund and European
29 Neighbourhood Partnership Instrument, Baltic Sea Region Programme 2007-2013)
30 */
31 #ifndef SEGMENTAREAOP_H
32 #define SEGMENTAREAOP_H
33 
34 #include <math.h>
35 
36 #include "drain/util/FunctorBank.h"
37 #include "drain/image/SegmentProber.h"
38 
39 //#include "ImageOp.h"
40 //#include "FloodFillOp.h"
41 
42 #include "SegmentOp.h"
43 
44 namespace drain
45 {
46 namespace image
47 {
48 
49 /*
50  * Problem: --iSegmentArea 64:255,FuzzyStep:100:1
51  * actually is SegmentArea(64:255,FuzzyStep(100:100,1))
52  *
53  * Consider: FuzzyStep/100:100/1
54  *
55  * Or prefix cmd:
56  * --functor FuzzyStep,100:100,1
57  * --functor FuzzyStep|100:100,1
58  * --functor FuzzyStep[100:100,1]
59  *
60  * or last-arg-comma-support?
61  * a,b,1,2,3
62  * A=a,B=c,C=C,D,E
63  */
64 
65 
67 
95 template <class S, class D, class T=SizeProber>
96 class SegmentAreaOp: public SegmentOp
97 {
98 public:
99 
100  typedef S src_t;
101  typedef D dst_t;
109  inline // static_cast<double>(0xffff)
110  SegmentAreaOp(double min=1.0, double max=std::numeric_limits<double>::max()) :
111  //SegmentAreaOp(double min=1.0, double max=static_cast<double>(0xffff)) :
112  SegmentOp(__FUNCTION__, "Computes segment sizes.") {
113  parameters.link("intensity", this->intensity.tuple(), "min:max");
114  parameters.link("functor", this->functorStr); // eg. "FuzzyStep:params"
115  this->intensity.set(min, max);
116  };
117 
118  inline // double max=static_cast<double>(0xffff)
119  SegmentAreaOp(const drain::UnaryFunctor & ftor, double min=1.0, double max=std::numeric_limits<double>::max()) : //, const std::string & mapping="d", double scale=1.0, double offset=0.0) :
120  SegmentOp(__FUNCTION__, "Computes segment sizes", ftor) {
121  parameters.link("intensity", this->intensity.tuple(), "min:max");
122  this->intensity.set(min, max);
123  };
124 
125  SegmentAreaOp(const SegmentAreaOp & op) : SegmentOp(op){
126  parameters.copyStruct(op.getParameters(), op, *this);
127  }
128 
130  //void makeCompatible(const ImageFrame & src, Image & dst) const;
131  void getDstConf(const ImageConf & src, ImageConf & dst) const;
132 
133  inline
134  void traverseChannels(const ImageTray<const Channel> & src, ImageTray<Channel> & dst) const {
135  //drain::Logger mout(getImgLog(), __FILE__, __FUNCTION__); //REPL this->name+"[const ImageTray &, ImageTray &]", __FUNCTION__);
136  traverseChannelsSeparately(src, dst);
137  }
138 
139  virtual
140  void traverseChannel(const Channel & src, Channel & dst) const;
141 
142 
143 };
144 
145 
146 template <class S, class D, class T>
147 void SegmentAreaOp<S,D,T>::getDstConf(const ImageConf & src, ImageConf & dst) const {
148  // void SegmentAreaOp<S,D>::makeCompatible(const ImageFrame & src, Image & dst) const {
149 
150  drain::Logger mout(getImgLog(), __FUNCTION__, getName());
151 
152  const std::type_info & t = typeid(dst_t); // typeid(typename T::dst_t);
153 
154  /*if (!dst.typeIsSet()){
155  dst.setType(t);
156  }
157  else*/
158  if (Type::call<typeIsFloat>(dst.getType())){
159  dst.setType(t);
160  mout.warn("float valued destination data not supported, setting: " , Type::getTypeChar(t) );
161  //throw std::runtime_error("SegmentAreaOp: float valued destination image not supported.");
162  }
163 
164  dst.setArea(src.getGeometry());
165  dst.setChannelCount(std::max(src.getImageChannelCount(),dst.getImageChannelCount()), dst.getAlphaChannelCount());
166 
167  //if (clearDst)
168  // dst.clear();
169 
170 }
171 
172 template <class S, class D, class T>
173 void SegmentAreaOp<S,D,T>::traverseChannel(const Channel & src, Channel & dst) const {
174 
175  drain::Logger mout(getImgLog(), __FUNCTION__, getName());
176 
178  raw.min = src.getScaling().inv(this->intensity.min);
179  raw.max = (this->intensity.max == std::numeric_limits<double>::max()) ? src.getConf().getTypeMax<src_t>() : src.getScaling().inv(this->intensity.max);
180 
181  if (raw.min <= src.getConf().getTypeMin<src_t>()){
182  mout.warn("src scaling: " , src.getScaling() );
183  mout.warn("original range: " , intensity );
184  mout.warn("raw (code) range: " , raw );
185  mout.warn("min value=" , (double)raw.min , " less or smaller than storage type min=" , src.getConf().getTypeMin<src_t>() );
186  }
187 
188  mout.special("raw range: " , (double)raw.min , '-' , (double)raw.max );
189  mout.debug2("src: " , src );
190  mout.debug2("dst: " , dst );
191 
192  //SizeProber sizeProber(src, dst);
193  T sizeProber(src, dst);
194  sizeProber.conf.anchor.set(raw.min, raw.max);
195  mout.debug2("areaProber:" , sizeProber );
196 
197  FillProber floodFill(src, dst);
198  floodFill.conf.anchor.set(raw.min, raw.max); // Min = raw.min;
199  mout.debug2("Floodfill: " , floodFill );
200 
201  const double scale = drain::Type::call<typeNaturalMax>(dst.getType());
202  // const double scale = drain::Type::call<drain::typeIsSmallInt>(dst.getType()) ? dst.getEncoding().getTypeMax<double>() : 1.0;
203 
204  const UnaryFunctor & ftor = getFunctor(scale); // scale problematic, but needed for const Ftor
205 
206  mout.debug("Scale: " , scale );
207  mout.debug("Final functor: " , ftor.getName() , '(' , ftor.getParameters() , ')' );
208  /*
209  mout.warn("Functor: 1 =>" , ftor(1.0) );
210  mout.warn("Functor: 100 =>" , ftor(100.0) );
211  mout.warn("Functor: 10000 =>" , ftor(10000.0) );
212  */
213  //mout.debug2();
214 
215  const CoordinatePolicy & cp = src.getCoordinatePolicy();
216  const bool HORZ_MODE = ((cp.xUnderFlowPolicy != EdgePolicy::POLAR) && (cp.xOverFlowPolicy != EdgePolicy::POLAR));
217 
218  if (HORZ_MODE){
219  mout.attention("scan HORIZONTAL, coordPolicy=", cp);
220  }
221  else {
222  mout.attention("scan VERTICAL, coordPolicy=", cp);
223  }
224 
225  typedef drain::typeLimiter<dst_t> Limiter;
226  typename Limiter::value_t limit = dst.getConf().getLimiter<dst_t>();
227 
228  const size_t width = src.getWidth();
229  const size_t height = src.getHeight();
230 
231  size_t sizeMapped;
232  for (size_t i=0; i<width; i++){
233  for (size_t j=0; j<height; j++){
234 
235  // STAGE 1: detect size.
236  // Note: retries same locations again and again. Could return true in success, i.e. first pixel was univisited and accepted.
237  sizeProber.probe(i,j, HORZ_MODE);
238 
239  if (sizeProber.size > 0){
240 
241  // STAGE 2: mark the segment with size
242  sizeMapped = limit(ftor(sizeProber.size));
243  if (sizeMapped == 0)
244  sizeMapped = 1;
245 
246  // mout.warn() << "found segment at " << i << ',' << j << " f=" << src.get<float>(i,j);
247  // mout << " size=" << sizeProber.size << " => "<< sizeMapped << mout.endl;
248 
249  floodFill.conf.markerValue = sizeMapped;
250  floodFill.probe(i,j, HORZ_MODE);
251 
252  }
253  }
254  }
255 
256 
257 }
258 
259 
260 } // image
261 
262 } // drain
263 
264 #endif
265 
266 // Drain
virtual const std::string & getName() const
Return the name of an instance.
Definition: BeanLike.h:69
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition: Log.h:308
Logger & attention(const TT &... args)
Possible error, but execution can continue. Special type of Logger::warn().
Definition: Log.h:472
Logger & special(const TT &... args)
Other useful information.
Definition: Log.h:527
Logger & warn(const TT &... args)
Possible error, but execution can continue.
Definition: Log.h:426
Logger & debug(const TT &... args)
Public, yet typically used "internally", when TIMING=true.
Definition: Log.h:676
Logger & debug2(const TT &... args)
Debug information.
Definition: Log.h:686
Definition: Range.h:52
void copyStruct(const ReferenceMap &m, const T &src, T &dst, extLinkPolicy policy=RESERVE)
Experimental. Copies references and values of a structure to another.
Definition: ReferenceMap.h:399
double inv(double y) const
Inverse scaling: given physically meaningful value y, returns the corresponding code value.
Definition: ValueScaling.h:301
Image with static geometry.
Definition: ImageChannel.h:60
Policies for coordinate underflows and overflows.
Definition: CoordinatePolicy.h:106
const std::type_info & getType() const
Linear scaling.
Definition: ImageConf.h:110
void setType(const std::type_info &t)
Set storage type.
Definition: ImageConf.h:121
T getTypeMax() const
Returns the maximum value supported by the current storage type.
Definition: ImageConf.h:281
T getTypeMin() const
Returns the minimum value supported by the current storage type.
Definition: ImageConf.h:267
Definition: SegmentProber.h:490
Struct for image (excluding data)
Definition: ImageConf.h:333
const std::type_info & getType() const
Get the storage type.
Definition: ImageLike.h:100
const CoordinatePolicy & getCoordinatePolicy() const
Coord policy.
Definition: ImageLike.h:167
void traverseChannelsSeparately(const ImageTray< const Channel > &src, ImageTray< Channel > &dst) const
Process each (src,dst) channel pair independently. Raise error if their counts differ.
Definition: ImageOp.cpp:340
Computes sizes of connected pixel areas.
Definition: SegmentAreaOp.h:97
virtual void traverseChannel(const Channel &src, Channel &dst) const
Apply to single channel.
Definition: SegmentAreaOp.h:173
SegmentAreaOp(double min=1.0, double max=std::numeric_limits< double >::max())
Definition: SegmentAreaOp.h:110
void getDstConf(const ImageConf &src, ImageConf &dst) const
Resizes dst to width and height of src. Ensures integer type.
Definition: SegmentAreaOp.h:147
A base class for computing statistics of segments. As segment is an area of connected pixels.
Definition: SegmentOp.h:53
D markerValue
"fill value", also dynamically changing visit marker?
Definition: SegmentProber.h:77
void probe(int i, int j, bool HORIZONTAL)
Start probings.
Definition: SegmentProber.h:208
Class for ensuring that variable of type D remains within limits of type S.
Definition: TypeUtils.h:653
Definition: DataSelector.cpp:1277
UnaryFunctor & getFunctor(const std::string &nameAndParams, char separator)
Returns functor the parameters of which have been set.
Definition: FunctorBank.cpp:81
Definition: Functor.h:116