SegmentStatisticsProber.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 STATISTICS_PROBER_H
32 #define STATISTICS_PROBER_H
33 
34 #include <sstream>
35 #include <ostream>
36 #include <cmath>
37 //#include "ImageOp.h"
38 //#include "Coordinates.h"
39 //#include "FilePng.h"
40 #include "SegmentProber.h"
41 
42 namespace drain
43 {
44 namespace image
45 {
46 
48 
54 
55 public:
56 
58  clear();
59  };
60 
61  ~SegmentStatistics(){};
62 
64  virtual inline
65  void clear(){
66  size = 0;
67  sumX = 0;
68  sumY = 0;
69  sumXX = 0;
70  sumYY = 0;
71  sumXY = 0;
72  _updateNeeded = true;
73  };
74 
76  virtual inline
77  void add(const int &i, const int &j){
78  ++size;
79  sumX += i;
80  sumY += j;
81  sumXX += i*i;
82  sumYY += j*j;
83  sumXY += i*j;
84  }
85 
87 
93  inline
94  double getSize() const {
95  return static_cast<double>(size);
96  };
97 
99 
105  inline
106  double getMeanX() const {
107  updateStats();
108  return cx;
109  };
110 
112 
118  inline
119  double getMeanY() const {
120  updateStats();
121  return cy; ;
122  };
123 
125 
131  inline
132  double getHorizontality() const {
133  updateStats();
134  return cxx / (cxx + cyy);
135  //return sqrt(cxx) / sqrt(cxx + cyy);
136  };
137 
139  inline
140  double getVerticality() const {
141  updateStats();
142  return cyy / (cxx + cyy);
143  //return sqrt(cyy) / sqrt(cxx + cyy);
144  };
145 
146 
148 
153  inline
154  double getVariance() const {
155  updateStats();
156  return cxx + cyy;
157  //return getVarianceHorz() + getVarianceVert();
158  };
159 
160  inline
161  double getVarianceHorz() const {
162  updateStats();
163  return cxx;
164  };
165 
166  inline
167  double getVarianceVert() const {
168  updateStats();
169  return cyy;
170  };
171 
173 
205  inline
206  double getSlimness() const {
207  return 2.0*M_PI*getVariance()/sizeD - 1.0;
208  };
209 
211 
214  /*
215  inline
216  double getAnnularity() const {
217  updateStats();
218  return getSlimness() * 2.0 * eigenValue2 / (eigenValue1 + eigenValue2);
219  };
220  */
221 
222 
224 
230  inline
231  double getElongation() const {
232  updateStats();
233  return (eigenValue1 - eigenValue2) / (eigenValue1 + eigenValue2);
234  //return (eigenValue1 - eigenValue2) / eigenValue1;
235  };
236 
237  inline
238  double getEigenValue1() const {
239  updateStats();
240  return eigenValue1;
241  };
242 
243 
244  inline
245  double getEigenValue2() const {
246  updateStats();
247  return eigenValue2;
248  };
249 
250  inline
251  void toOstr(std::ostream & ostr) const {
252  ostr << '(' << getMeanX() << ',' << getMeanY() << ')' << ' ';
253  ostr << "s=" << getSize() << ',';
254  ostr << "h=" << getHorizontality() << ',';
255  ostr << "v=" << getVerticality() << ',';
256  ostr << "S=" << getVariance() << ',';
257  ostr << "C=" << '[' << cxx << ',' << cxy << ';' << cxy << ',' << cyy << ']' << ',';
258  ostr << "e12=" << getEigenValue1() << ',' << getEigenValue2() << ',';
259  //ostr << "TEMP=" << sqrt(cxxMcyy*cxxMcyy + 4.0*cxy2);
260  ostr << "e=" << getElongation() << ',';
261  ostr << "l=" << getSlimness() << ',';
262  }
263 
264 protected:
265 
266 
267  inline
268  void updateStats() const {
269 
270  if (!_updateNeeded)
271  return;
272 
273  sizeD = static_cast<double>(size);
274 
275  cx = static_cast<double>(sumX)/sizeD;
276  cy = static_cast<double>(sumY)/sizeD;
277 
278  if (size == 1){
279  cxx = 1.0;
280  cyy = 1.0;
281  cxy = 0.0;
282  }
283  else {
284  cxx = static_cast<double>(sumXX)/sizeD - cx*cx;
285  cxy = static_cast<double>(sumXY)/sizeD - cx*cy;
286  cyy = static_cast<double>(sumYY)/sizeD - cy*cy;
287  }
288 
289 
291  const double epsilon = 0.00001;
292  if ((cxy > -epsilon) && (cxy < epsilon)){
293  if (cxx > cyy){ // ensure eigenValue1 > eigenValue2
294  eigenValue1 = cxx;
295  eigenVector1x = 1.0;
296  eigenVector1y = 0.0;
297  eigenValue2 = cyy;
298  eigenVector2x = 0.0;
299  eigenVector2y = 1.0;
300  }
301  else {
302  eigenValue1 = cyy;
303  eigenVector1x = 0.0;
304  eigenVector1y = 1.0;
305  eigenValue2 = cxx;
306  eigenVector2x = 1.0;
307  eigenVector2y = 0.0;
308  }
309  }
310  else {
311 
312  /*
313  *
314  *
315  */
316 
317  double cxy2 = cxy*cxy;
318  double cxxPcyy = cxx+cyy;
319  double cxxMcyy = cxx-cyy;
320  double temp,scale;
321 
322  temp = sqrt(cxxMcyy*cxxMcyy + 4.0*cxy2);
323  eigenValue1 = (cxxPcyy + temp)/2.0;
324  eigenValue2 = (cxxPcyy - temp)/2.0;
325  // std::cerr << '(' << cx << ',' << cy << ')' << ' ';
326  // std::cerr << "E12,t=" << eigenValue1 << ',' << eigenValue2 << ',' << temp << '\n';
327 
328  temp = cxx-eigenValue1;
329  scale = sqrt(cxy2 + temp*temp);
330  eigenVector1x = temp/scale;
331  eigenVector1y = cxy/scale;
332 
333  temp = cxx-eigenValue2;
334  scale = sqrt(cxy2 + temp*temp);
335  eigenVector2x = temp/scale;
336  eigenVector2y = cxy/scale;
337  }
338 
339  //elongation = eigenValue2 / eigenValue1;
340  _updateNeeded = false;
341  }
342 
343  mutable bool _updateNeeded;
344 
346  long int size;
347 
349  long sumX, sumY;
350 
352  long sumXX, sumYY, sumXY;
353 
355  mutable double sizeD;
356 
358  mutable double cx;
359 
361  mutable double cy;
362 
364  mutable double cxx, cyy, cxy;
365 
366  mutable double eigenValue1;
367  mutable double eigenVector1x;
368  mutable double eigenVector1y;
369  mutable double eigenValue2;
370  mutable double eigenVector2x;
371  mutable double eigenVector2y;
372  mutable double elongation;
373 };
374 
375 
376 
377 inline
378 std::ostream & operator<<(std::ostream & ostr, const SegmentStatistics & s){
379  s.toOstr(ostr);
380  return ostr;
381 }
382 
383 
385 
391 template <class T, class D>
392 class SegmentStatisticsProber : public SegmentProber<T,D,SegmentProberConf<T,D> > {
393 
394 public:
395 
396  typedef T src_t;
397  typedef D dst_t;
398  //typedef SegmentProberConf<T,D> conf_t;
399 
400  SegmentStatisticsProber(const Channel &s, Channel & d, const std::string statistics="s") : SegmentProber<T,D,SegmentProberConf<T,D> >(s,d), stats(statistics) {
401  };
402 
403  virtual
405 
406  const std::string & stats;
407 
408  SegmentStatistics statistics;
409 
410  virtual inline
411  bool isValidSegment(int i, int j) const {
412  // this->src;
413  // this->conf;
414  // this->src.template get<src_t>(i,j);
415  // return this->conf.isValidIntensity(12345);
416  return this->conf.isValidIntensity(this->src.template get<src_t>(i,j));
417  }
418 
419 protected:
420 
421  virtual
422  inline
423  void clear(){
424  statistics.clear();
425  };
426 
427 
428  virtual
429  inline
430  void update(int i, int j){
431  this->statistics.add(i,j);
432  }
433 
434 
435 };
436 
437 
438 template <class T, class D>
439 std::ostream & operator<<(std::ostream & ostr, const SegmentStatisticsProber<T,D> & prober){
440  ostr << (const SegmentProber<T,D,SegmentProberConf<T,D> > &)prober << '\t';
441  ostr << prober.statistics;
442  return ostr;
443 }
444 
445 
446 
447 }
448 }
449 #endif /* SEGMENSTATS_H_ */
450 
451 
452 // Drain
Image with static geometry.
Definition: ImageChannel.h:60
bool isValidIntensity(S x) const
Criterion.
Definition: SegmentProber.h:81
A recursive method for visiting pixels of a segment in an image.
Definition: SegmentProber.h:100
A helper class applied by FloodFillOp and SegmentAreaOp.
Definition: SegmentStatisticsProber.h:392
virtual bool isValidSegment(int i, int j) const
Application dependent, to be redefined. Assumes checked coordinates.
Definition: SegmentStatisticsProber.h:411
virtual void update(int i, int j)
Application dependent operation performed in each segment location (i,j).
Definition: SegmentStatisticsProber.h:430
virtual void clear()
Called before processing each segment. Compare with init(), which is called once for each image.
Definition: SegmentStatisticsProber.h:423
A structure for accumulating coordinates and computing statistics thereof: area, centroid,...
Definition: SegmentStatisticsProber.h:53
double getSlimness() const
Returns the proportion in which the variance equals the variance of an annulus.
Definition: SegmentStatisticsProber.h:206
double getMeanY() const
Returns the horizontal coordinate of centre of mass.
Definition: SegmentStatisticsProber.h:119
void updateStats() const
Definition: SegmentStatisticsProber.h:268
double cy
Center of mass, y coordinate.
Definition: SegmentStatisticsProber.h:361
long sumXX
Sum of squared coordinates.
Definition: SegmentStatisticsProber.h:352
double getMeanX() const
Returns the horizontal coordinate of centre of mass.
Definition: SegmentStatisticsProber.h:106
double getElongation() const
Returns the proportion in which the variance equals the variance of an annulus.
Definition: SegmentStatisticsProber.h:231
double sizeD
Size in double precision.
Definition: SegmentStatisticsProber.h:355
double getSize() const
Returns the size of the segment.
Definition: SegmentStatisticsProber.h:94
virtual void clear()
Resets the statistics.
Definition: SegmentStatisticsProber.h:65
double getHorizontality() const
Returns the horizontal variance $\sigma_x$ scaled with total variance $\sigma_x + \sigma_y$....
Definition: SegmentStatisticsProber.h:132
double cx
Center of mass, x coordinate.
Definition: SegmentStatisticsProber.h:358
double getVariance() const
Returns the total variance of the pixel coordinates.
Definition: SegmentStatisticsProber.h:154
double getVerticality() const
Returns the vertical variance scaled with total variance. Takes values in [0,1].
Definition: SegmentStatisticsProber.h:140
virtual void add(const int &i, const int &j)
Accumulate location (i,j) in the statistics.
Definition: SegmentStatisticsProber.h:77
long sumX
Sum of coordinates.
Definition: SegmentStatisticsProber.h:349
long int size
Size of segment (area).
Definition: SegmentStatisticsProber.h:346
double cxx
Elements of covariance matrix.
Definition: SegmentStatisticsProber.h:364
Definition: DataSelector.cpp:1277