SlidingWindow.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 DRAIN_SLIDING_WINDOW
32 #define DRAIN_SLIDING_WINDOW
33 
34 #include "Window.h"
35 
36 namespace drain
37 {
38 
39 namespace image
40 {
41 
43 
48 template <class C = WindowConfig, class R = WindowCore>
49 class SlidingWindow : public Window<C,R>
50 {
51 
52 public:
53 
58  SlidingWindow(int width=0, int height=0, bool horzMultiple=true, bool vertMultiple=true) : Window<C,R>(width,height){
59  setSlidingMode(horzMultiple, vertMultiple);
60  };
61 
62  SlidingWindow(const C & conf, bool horzMultiple=true, bool vertMultiple=true) : Window<C,R>(conf){
63  setSlidingMode(horzMultiple, vertMultiple);
64  };
65 
66  virtual ~SlidingWindow(){};
67 
68  void setSlidingMode(bool horzMultiple, bool vertMultiple){
69 
70  modeStr = "??";
71  modeStr.at(0) = horzMultiple?'H':'h';
72  modeStr.at(1) = vertMultiple?'V':'v';
73 
74  updateHorz = horzMultiple ? &SlidingWindow<C,R>::updateHorzMultiple : &SlidingWindow<C,R>::updateHorzSingle;
76 
77  if (horzMultiple && vertMultiple)
79  else if (horzMultiple)
81  else if (vertMultiple)
83  else {
84  drain::Logger mout(getImgLog(), __FILE__, __FUNCTION__);
85  mout << "illegal sliding mode single-horz, single-vert" << mout.endl;
87  }
88 
89  }
90 
92 
95  void run(){
96 
97  drain::Logger mout(getImgLog(), __FILE__, __FUNCTION__);
98 
99  // CONSIDER: why runHorz and runVert, separately? If must be, this function could go:
109  mout.debug3("SCALE=" , (int)this->SCALE );
110  mout.debug3("calling initialize" );
111  initialize();
112 
113  //this->myFunctor.updateBean();
114  mout.debug2((*this) );
115  //mout.warn("final functor:" , this->myFunctor );
116  /*
117  for (int i=0; i<50; ++i){
118  std::cerr << __FUNCTION__ << i << '\t' << this->myFunctor(i) << '\n';
119  }
120  */
121 
122  (this->*fill)();
123  write();
124 
125  if (this->isHorizontal()){
126  mout.debug2("start slideHorz" );
127  slideHorz();
128  mout.debug2("end slideHorz" );
129  }
130  else {
131  mout.debug2("start slideVert" );
132  slideVert();
133  }
134  }
135 
137 
140  void runHorz(){
141 
142  drain::Logger mout(getImgLog(), __FILE__, __FUNCTION__);
143  mout.debug3("start" );
144  mout.debug3("SCALE=" , (int)this->SCALE );
145  mout.debug3("initialize" );
146  initialize();
147 
148  mout.debug3((*this) );
149 
150  fill();
151  write();
152 
153  mout.debug3("slideHorz");
154  slideHorz();
155  }
156 
158 
161  void runVert(){
162 
163  drain::Logger mout(getImgLog(), __FILE__, __FUNCTION__);
164  mout.debug3("start" );
165  mout.debug3("SCALE=" , (int)this->SCALE );
166  mout.debug3("initialize" );
167  initialize();
168 
169  mout.debug3((*this) );
170 
171  fill();
172  write();
173 
174  mout.debug3("slideVert");
175  slideVert();
176  }
177 
178 
179 
180  virtual
181  void debug(){
182  drain::Logger mout(getImgLog(), __FILE__, __FUNCTION__);
183  mout.warn("Using apply() recommended for debugging only." );
185  }
186 
188 
191  virtual
192  void write() = 0; //{dst.at(location) = value;};
193 
194  inline
195  const std::string & getModeStr(){
196  return modeStr;
197  }
198 
199 protected:
200 
201 
203 
207  virtual
208  void initialize() = 0;
209 
211  virtual inline
212  bool reset(){
213  (this->*fill)();
214  return true;
215  };
216 
218  inline
219  void slideHorz(){
220 
221  while (true){
222 
223  while (moveRight())
224  write();
225 
226  if (!moveDown())
227  return;
228 
229  write();
230 
231  while (moveLeft())
232  write();
233 
234  if (!moveDown())
235  return;
236 
237  write();
238 
239  // For 1) cleaning numerical residues and 2) updating window parameters
240  if (this->resetAtEdges){
241  if (!this->reset())
242  return;
243  }
244 
245  }
246 
247  }
248 
250  inline
251  void slideVert(){
252 
253  while (true){
254 
255  while (moveDown())
256  write();
257 
258  if (!moveRight())
259  return;
260 
261  write();
262 
263  while (moveUp())
264  write();
265 
266  if (!moveRight())
267  return;
268 
269  write();
270 
271  // For 1) cleaning numerical residues and 2) updating window parameters
272  if (this->resetAtEdges){
273  if (!this->reset())
274  return;
275  }
276 
277 
278  }
279 
280  }
281 
282 
283 
284 protected:
285 
286  Point2D<int> locationLead;
287  Point2D<int> locationTrail;
288 
289 
291 
297  inline // FINAL
298  bool moveDown(){
299 
300  ++this->location.y;
301  if (this->location.y <= this->coordinateHandler.getYRange().max){ // < this->srcHeight){
302  locationLead.y = this->location.y + this->jRange.max;
303  locationTrail.y = this->location.y + this->jRange.min - 1;
304  (this->*updateVert)();
305  return true;
306  }
307  else { // step back
308  --this->location.y;
309  return false;
310  }
311  }
312 
314 
319  inline // FINAL
320  bool moveUp(){
321 
322  --this->location.y;
323  if (this->location.y >= 0){
324  locationLead.y = this->location.y + this->jRange.min;
325  locationTrail.y = this->location.y + this->jRange.max + 1;
326  (this->*updateVert)();
327  return true;
328  }
329  else { // step back
330  ++this->location.y;
331  return false;
332  }
333  }
334 
336 
341  inline // FINAL
342  bool moveRight(){
343 
344  ++this->location.x;
345  if (this->location.x <= this->coordinateHandler.getXRange().max){ // this->srcWidth){
346  locationLead.x = this->location.x + this->iRange.max;
347  locationTrail.x = this->location.x + this->iRange.min-1;
348  (this->*updateHorz)();
349  return true;
350  }
351  else { // step back
352  --this->location.x;
353  return false;
354  }
355 
356  }
357 
359 
364  inline // FINAL
365  bool moveLeft(){
366 
367  --this->location.x;
368  if (this->location.x >= 0){
369  locationLead.x = this->location.x + this->iRange.min;
370  locationTrail.x = this->location.x + this->iRange.max+1;
371  (this->*updateHorz)();
372  return true;
373  }
374  else { // step back
375  ++this->location.x;
376  return false;
377  }
378  }
379 
380 
381 
383  virtual
384  void clear(){
385  std::cerr << __FUNCTION__ << " (plain) " << std::endl;
386  };
387 
388 
390 
394  virtual // ?
395  inline
396  void fillBoth(){
397  //drain::Logger mout(getImgLog(), "SlidingWindow", __FUNCTION__);
398  this->clear();
399  //mout.warn("init window" );
400  for (int i = this->iRange.min; i <= this->iRange.max; i++) {
401  for (int j = this->jRange.min; j <= this->jRange.max; j++) {
402  this->locationTmp.setLocation(this->location.x+i, this->location.y+j);
403  this->addPixel(this->locationTmp);
404  }
405  }
406  }
407 
409 
413  inline
414  void fillHorz(){
415  this->clear();
416  for (int i = this->iRange.min; i <= this->iRange.max; i++) {
417  this->locationTmp.setLocation(this->location.x+i, this->location.y);
418  this->addPixel(this->locationTmp);
419  }
420  }
421 
423 
427  inline
428  void fillVert(){
429  this->clear();
430  for (int j = this->jRange.min; j <= this->jRange.max; j++) {
431  this->locationTmp.setLocation(this->location.x, this->location.y+j);
432  this->addPixel(this->locationTmp);
433  }
434  }
435 
437 
440  void (SlidingWindow<C,R>::* fill)(); //
441 
443 
449  void (SlidingWindow<C,R>::* updateHorz)(); // initially
450 
452 
459 
460 
463 
464  for (int j = this->jRange.min; j <= this->jRange.max; j++) {
465 
466  locationTmp.setLocation(locationTrail.x, this->location.y + j);
467  this->removePixel(locationTmp);
468 
469  locationTmp.setLocation(locationLead.x, this->location.y + j);
470  this->addPixel(locationTmp);
471 
472  }
473  }
474 
475  void updateHorzSingle(){
476 
477  this->locationTmp.setLocation(this->locationTrail.x, this->location.y);
478  this->removePixel(this->locationTmp);
479 
480  this->locationTmp.setLocation(this->locationLead.x, this->location.y);
481  this->addPixel(this->locationTmp);
482 
483  }
484 
487 
488  for (int i=this->iRange.min; i<=this->iRange.max; i++) {
489 
490  locationTmp.setLocation(this->location.x + i, locationTrail.y);
491  this->removePixel(locationTmp);
492 
493  locationTmp.setLocation(this->location.x + i, locationLead.y);
494  this->addPixel(locationTmp);
495 
496  }
497 
498  }
499 
501  // virtual inline
503 
504  this->locationTmp.setLocation(this->location.x, this->locationTrail.y);
505  this->removePixel(this->locationTmp);
506 
507  this->locationTmp.setLocation(this->location.x, this->locationLead.y);
508  this->addPixel(this->locationTmp);
509 
510  }
511 
513 
521  virtual
522  void addPixel(Point2D<int> &p) = 0; // consider addPixel(Point2D<int> &p, int index/double weight)
523 
525 
536  virtual
537  void removePixel(Point2D<int> &p) = 0; // consider addPixel(Point2D<int> &p, int index/double weight)
538 
539 
540  // private:
541  // protected:
542 
543  mutable Point2D<int> locationTmp;
544 
545 private:
546 
547  std::string modeStr;
548 
549 
550 };
551 
552 
553 
554 
555 
556 
558 
563 template <class C = WindowConfig, class R = WindowCore, bool DIR=true>
564 class SlidingStripe : public SlidingWindow<C,R> {
565 public:
566 
567  SlidingStripe(size_t n=1) : SlidingWindow<C,R>(DIR?n:1, DIR?1:n, !DIR, DIR) {
568  };
569 
570  virtual
571  ~SlidingStripe(){};
572 
573  void setSize(size_t width = 1){
574  this->SlidingWindow<C,R>::setSize(width, 1);
575  }
576 
577 protected:
578 
579  virtual
580  void setSize(size_t width, size_t height){
581 
582  drain::Logger mout(getImgLog(), "SlidingStripe", __FUNCTION__);
583  //if (height > 1)
584  // mout.warn("horz stripe, height(" , height , ") discarded" );
585  //SlidingWindow<C,R>::setSize(width, 1);
586  if (DIR){
587  if (height > 1)
588  mout.warn("horz stripe, height(" , height , ") discarded" );
589  SlidingWindow<C,R>::setSize(width, 1);
590  }
591  else {
592  if (width > 1)
593  mout.warn("vert stripe, width(" , width , ") discarded" );
594  SlidingWindow<C,R>::setSize(1, height);
595  }
596 
597  }
598 
599 };
600 
601 
602 
603 
605 
613 
622 }
623 
624 }
625 
626 #endif /*SLIDINGWINDOWOP_H_*/
627 
628 // Drain
LogSourc e is the means for a function or any program segment to "connect" to a Log.
Definition: Log.h:308
Logger & warn(const TT &... args)
Possible error, but execution can continue.
Definition: Log.h:426
Logger & debug2(const TT &... args)
Debug information.
Definition: Log.h:686
A horizontal, one-dimensional SlidingWindow (Nx1).
Definition: SlidingWindow.h:564
virtual void setSize(size_t width, size_t height)
Sets the window size.
Definition: SlidingWindow.h:580
Window implementation that uses incremental update of state.
Definition: SlidingWindow.h:50
virtual void removePixel(Point2D< int > &p)=0
Removes a pixel from window statistics. Unvalidated location.
SlidingWindow(int width=0, int height=0, bool horzMultiple=true, bool vertMultiple=true)
Definition: SlidingWindow.h:58
void updateVertSingle()
For 1 x n sized windows.
Definition: SlidingWindow.h:502
void updateHorzMultiple()
In moving horizontally, updates the window centered at current location. Calls removePixel() and addP...
Definition: SlidingWindow.h:462
void run()
Sets coord handler, calls initialise, sets pos(0,0), fills, writes and slides.
Definition: SlidingWindow.h:95
void(SlidingWindow< C, R >::* updateVert)()
Pointer to update function invoked at each vertical move.
Definition: SlidingWindow.h:458
void runHorz()
Sets coord handler, calls initialise, sets pos(0,0), fills, writes and slides.
Definition: SlidingWindow.h:140
void fillVert()
Clears and computes the statistics for the current location. FINAL.
Definition: SlidingWindow.h:428
bool moveDown()
Moves one pixel down. Stops at the edge, and returns false.
Definition: SlidingWindow.h:298
virtual void write()=0
Write the result in the target image.
void(SlidingWindow< C, R >::* fill)()
Pointer to fill operation preformed at initial location (0,0)
Definition: SlidingWindow.h:440
void slideHorz()
High-level functionality of a sliding window. FINAL.
Definition: SlidingWindow.h:219
virtual void initialize()=0
Sets class-specific initial values. Does not change general window state (e.g. location)....
bool moveLeft()
Moves one pixel left. Stops at the edge, and returns false.
Definition: SlidingWindow.h:365
void updateVertMultiple()
In moving vertically, updates the window centered at current location. Calls removePixel() and addPix...
Definition: SlidingWindow.h:486
virtual void clear()
Clears the applied statistics. Redefined in derived classes.
Definition: SlidingWindow.h:384
void slideVert()
High-level functionality of a sliding window. FINAL.
Definition: SlidingWindow.h:251
virtual bool reset()
Returns false, if traversal should be ended.
Definition: SlidingWindow.h:212
virtual void addPixel(Point2D< int > &p)=0
Adds a pixel to window statistics. Unvalidated location.
void fillHorz()
Clears and computes the statistics for the current location. FINAL.
Definition: SlidingWindow.h:414
virtual void fillBoth()
Clears and computes the statistics for the current location.
Definition: SlidingWindow.h:396
bool moveRight()
Moves one pixel right. Stops at the edge, and returns false.
Definition: SlidingWindow.h:342
bool moveUp()
Moves one pixel up. Stops at the edge, and returns false.
Definition: SlidingWindow.h:320
void(SlidingWindow< C, R >::* updateHorz)()
Pointer to update function invoked at each horizontal move.
Definition: SlidingWindow.h:449
void runVert()
Sets coord handler, calls initialise, sets pos(0,0), fills, writes and slides.
Definition: SlidingWindow.h:161
Base class for windows applied by WindowOp's.
Definition: Window.h:404
bool resetAtEdges
To avoid accumulated numerical errors esp. with floats, reset the statistics at row/cols ends....
Definition: Window.h:529
virtual void run()
Main loop: traverses the source image and writes result to dst image.
Definition: Window.h:642
Point2D< int > location
Current location of this window.
Definition: Window.h:520
virtual void setSize(size_t width, size_t height)
Sets the window size.
Definition: Window.h:479
virtual bool isHorizontal() const
Tells if the window should be moved (traversed of slided) row-by-row (horizontally) or column-by-colu...
Definition: Window.h:520
Range< int > iRange
Studies source and destination images and decides whether scaling (SCALE=true) should be set.
Definition: Window.h:572
bool SCALE
If set, scaling is applied, potentially slowering the computation.
Definition: Window.h:532
Definition: DataSelector.cpp:1277