PCL
MorphologicalOperator.h
Go to the documentation of this file.
1 // ____ ______ __
2 // / __ \ / ____// /
3 // / /_/ // / / /
4 // / ____// /___ / /___ PixInsight Class Library
5 // /_/ \____//_____/ PCL 2.7.0
6 // ----------------------------------------------------------------------------
7 // pcl/MorphologicalOperator.h - Released 2024-06-18T15:48:54Z
8 // ----------------------------------------------------------------------------
9 // This file is part of the PixInsight Class Library (PCL).
10 // PCL is a multiplatform C++ framework for development of PixInsight modules.
11 //
12 // Copyright (c) 2003-2024 Pleiades Astrophoto S.L. All Rights Reserved.
13 //
14 // Redistribution and use in both source and binary forms, with or without
15 // modification, is permitted provided that the following conditions are met:
16 //
17 // 1. All redistributions of source code must retain the above copyright
18 // notice, this list of conditions and the following disclaimer.
19 //
20 // 2. All redistributions in binary form must reproduce the above copyright
21 // notice, this list of conditions and the following disclaimer in the
22 // documentation and/or other materials provided with the distribution.
23 //
24 // 3. Neither the names "PixInsight" and "Pleiades Astrophoto", nor the names
25 // of their contributors, may be used to endorse or promote products derived
26 // from this software without specific prior written permission. For written
27 // permission, please contact info@pixinsight.com.
28 //
29 // 4. All products derived from this software, in any form whatsoever, must
30 // reproduce the following acknowledgment in the end-user documentation
31 // and/or other materials provided with the product:
32 //
33 // "This product is based on software from the PixInsight project, developed
34 // by Pleiades Astrophoto and its contributors (https://pixinsight.com/)."
35 //
36 // Alternatively, if that is where third-party acknowledgments normally
37 // appear, this acknowledgment must be reproduced in the product itself.
38 //
39 // THIS SOFTWARE IS PROVIDED BY PLEIADES ASTROPHOTO AND ITS CONTRIBUTORS
40 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
41 // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PLEIADES ASTROPHOTO OR ITS
43 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
44 // EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, BUSINESS
45 // INTERRUPTION; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; AND LOSS OF USE,
46 // DATA OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
49 // POSSIBILITY OF SUCH DAMAGE.
50 // ----------------------------------------------------------------------------
51 
52 #ifndef __PCL_MorphologicalOperator_h
53 #define __PCL_MorphologicalOperator_h
54 
56 
57 #include <pcl/Defs.h>
58 #include <pcl/Diagnostics.h>
59 
60 #include <pcl/Exception.h>
61 #include <pcl/Math.h>
62 #include <pcl/PixelTraits.h>
63 #include <pcl/Selection.h>
64 #include <pcl/Sort.h>
65 #include <pcl/String.h>
66 #include <pcl/Utility.h>
67 
68 namespace pcl
69 {
70 
71 // ----------------------------------------------------------------------------
72 
80 class PCL_CLASS MorphologicalOperator
81 {
82 public:
83 
87  MorphologicalOperator() = default;
88 
93 
98  {
99  }
100 
105  virtual MorphologicalOperator* Clone() const = 0;
106 
110  virtual String Description() const
111  {
112  return String();
113  }
114 
121  virtual bool IsDilation() const
122  {
123  return false;
124  }
125 
131  {
132  throw NotImplemented( *this, "Apply to 32-bit floating-point images" );
133  }
134 
140  {
141  throw NotImplemented( *this, "Apply to 64-bit floating-point images" );
142  }
143 
149  {
150  throw NotImplemented( *this, "Apply to 32-bit complex images" );
151  }
152 
158  {
159  throw NotImplemented( *this, "Apply to 64-bit complex images" );
160  }
161 
167  {
168  throw NotImplemented( *this, "Apply to 8-bit integer images" );
169  }
170 
176  {
177  throw NotImplemented( *this, "Apply to 16-bit integer images" );
178  }
179 
185  {
186  throw NotImplemented( *this, "Apply to 32-bit integer images" );
187  }
188 };
189 
190 // ----------------------------------------------------------------------------
191 
199 class PCL_CLASS ErosionFilter : public MorphologicalOperator
200 {
201 public:
202 
205  MorphologicalOperator* Clone() const override
206  {
207  return new ErosionFilter( *this );
208  }
209 
212  String Description() const override
213  {
214  return "Erosion";
215  }
216 
221  FloatPixelTraits::sample operator ()( FloatPixelTraits::sample* f, size_type n ) const override
222  {
223  return Operate( f, n );
224  }
225 
231  {
232  return Operate( f, n );
233  }
234 
239  UInt8PixelTraits::sample operator ()( UInt8PixelTraits::sample* f, size_type n ) const override
240  {
241  return Operate( f, n );
242  }
243 
249  {
250  return Operate( f, n );
251  }
252 
258  {
259  return Operate( f, n );
260  }
261 
262 private:
263 
264  template <typename T>
265  static T Operate( T* __restrict__ f, size_type n )
266  {
267  T x = *f++;
268  for ( ; --n > 0; ++f )
269  if ( *f < x )
270  x = *f;
271  return x;
272  }
273 };
274 
275 // ----------------------------------------------------------------------------
276 
284 class PCL_CLASS DilationFilter : public MorphologicalOperator
285 {
286 public:
287 
290  MorphologicalOperator* Clone() const override
291  {
292  return new DilationFilter( *this );
293  }
294 
297  String Description() const override
298  {
299  return "Dilation";
300  }
301 
304  bool IsDilation() const override
305  {
306  return true;
307  }
308 
313  FloatPixelTraits::sample operator ()( FloatPixelTraits::sample* f, size_type n ) const override
314  {
315  return Operate( f, n );
316  }
317 
323  {
324  return Operate( f, n );
325  }
326 
331  UInt8PixelTraits::sample operator ()( UInt8PixelTraits::sample* f, size_type n ) const override
332  {
333  return Operate( f, n );
334  }
335 
341  {
342  return Operate( f, n );
343  }
344 
350  {
351  return Operate( f, n );
352  }
353 
354 private:
355 
356  template <typename T>
357  static T Operate( T* __restrict__ f, size_type n )
358  {
359  T x = *f++;
360  for ( ; --n > 0; ++f )
361  if ( x < *f )
362  x = *f;
363  return x;
364  }
365 };
366 
367 // ----------------------------------------------------------------------------
368 
376 class PCL_CLASS MedianFilter : public MorphologicalOperator
377 {
378 public:
379 
382  MorphologicalOperator* Clone() const override
383  {
384  return new MedianFilter( *this );
385  }
386 
389  String Description() const override
390  {
391  return "Median";
392  }
393 
398  FloatPixelTraits::sample operator ()( FloatPixelTraits::sample* f, size_type n ) const override
399  {
400  return Operate( f, n, (FloatPixelTraits*)0 );
401  }
402 
408  {
409  return Operate( f, n, (DoublePixelTraits*)0 );
410  }
411 
416  UInt8PixelTraits::sample operator ()( UInt8PixelTraits::sample* f, size_type n ) const override
417  {
418  return Operate( f, n, (UInt8PixelTraits*)0 );
419  }
420 
426  {
427  return Operate( f, n, (UInt16PixelTraits*)0 );
428  }
429 
435  {
436  return Operate( f, n, (UInt32PixelTraits*)0 );
437  }
438 
439 private:
440 
441 #define CMPXCHG( a, b ) \
442  if ( f[b] < f[a] ) pcl::Swap( f[a], f[b] )
443 
444 #define MEAN( a, b ) \
445  P::FloatToSample( (double( a ) + double( b ))/2 )
446 
447  template <typename T, class P>
448  static T Operate( T* __restrict__ f, size_type n, P* )
449  {
450  /*
451  * Use fast, hard-coded selection networks for n <= 24:
452  *
453  * Knuth, D. E., The Art of Computer Programming, volume 3: Sorting and
454  * Searching, Addison Wesley, 1973.
455  *
456  * Hillis, W. D., Co-evolving parasites improve simulated evolution as an
457  * optimization procedure.</em> Langton, C. et al. (Eds.), Artificial
458  * Life II. Addison Wesley, 1992.
459  *
460  * Hugues Juille, Evolution of Non-Deterministic Incremental Algorithms
461  * as a New Approach for Search in State Spaces, 1995.
462  *
463  * Use a quick selection algorithm for n > 24:
464  *
465  * William H. Press et al., Numerical Recipes 3rd Edition: The Art of
466  * Scientific Computing, Cambridge University Press, 2007, Section 8.5.
467  *
468  * Robert Sedgewick, Kevin Wayne, Algorithms, 4th Edition, Addison-Wesley
469  * Professional, 2011, pp 345-347.
470  */
471  switch ( n )
472  {
473  case 0: // ?!
474  return 0;
475  case 1: // !?
476  return f[0];
477  case 2:
478  return MEAN( f[0], f[1] );
479  case 3:
480  CMPXCHG( 0, 1 ); CMPXCHG( 1, 2 );
481  return pcl::Max( f[0], f[1] );
482  case 4:
483  CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 0, 2 );
484  CMPXCHG( 1, 3 );
485  return MEAN( f[1], f[2] );
486  case 5:
487  CMPXCHG( 0, 1 ); CMPXCHG( 3, 4 ); CMPXCHG( 0, 3 );
488  CMPXCHG( 1, 4 ); CMPXCHG( 1, 2 ); CMPXCHG( 2, 3 );
489  return pcl::Max( f[1], f[2] );
490  case 6:
491  CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 0, 2 );
492  CMPXCHG( 1, 3 ); CMPXCHG( 1, 2 ); CMPXCHG( 4, 5 );
493  CMPXCHG( 0, 4 ); CMPXCHG( 1, 5 ); CMPXCHG( 1, 4 );
494  CMPXCHG( 2, 4 ); CMPXCHG( 3, 5 ); CMPXCHG( 3, 4 );
495  return MEAN( f[2], f[3] );
496  case 7:
497  CMPXCHG( 0, 5 ); CMPXCHG( 0, 3 ); CMPXCHG( 1, 6 );
498  CMPXCHG( 2, 4 ); CMPXCHG( 0, 1 ); CMPXCHG( 3, 5 );
499  CMPXCHG( 2, 6 ); CMPXCHG( 2, 3 ); CMPXCHG( 3, 6 );
500  CMPXCHG( 4, 5 ); CMPXCHG( 1, 4 ); CMPXCHG( 1, 3 );
501  return pcl::Min( f[3], f[4] );
502  case 8:
503  CMPXCHG( 0, 4 ); CMPXCHG( 1, 5 ); CMPXCHG( 2, 6 );
504  CMPXCHG( 3, 7 ); CMPXCHG( 0, 2 ); CMPXCHG( 1, 3 );
505  CMPXCHG( 4, 6 ); CMPXCHG( 5, 7 ); CMPXCHG( 2, 4 );
506  CMPXCHG( 3, 5 ); CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 );
507  CMPXCHG( 4, 5 ); CMPXCHG( 6, 7 ); CMPXCHG( 1, 4 );
508  CMPXCHG( 3, 6 );
509  return MEAN( f[3], f[4] );
510  case 9:
511  CMPXCHG( 1, 2 ); CMPXCHG( 4, 5 ); CMPXCHG( 7, 8 );
512  CMPXCHG( 0, 1 ); CMPXCHG( 3, 4 ); CMPXCHG( 6, 7 );
513  CMPXCHG( 1, 2 ); CMPXCHG( 4, 5 ); CMPXCHG( 7, 8 );
514  CMPXCHG( 0, 3 ); CMPXCHG( 5, 8 ); CMPXCHG( 4, 7 );
515  CMPXCHG( 3, 6 ); CMPXCHG( 1, 4 ); CMPXCHG( 2, 5 );
516  CMPXCHG( 4, 7 ); CMPXCHG( 4, 2 ); CMPXCHG( 6, 4 );
517  return pcl::Min( f[2], f[4] );
518  case 10:
519  CMPXCHG( 4, 9 ); CMPXCHG( 3, 8 ); CMPXCHG( 2, 7 );
520  CMPXCHG( 1, 6 ); CMPXCHG( 0, 5 ); CMPXCHG( 1, 4 );
521  CMPXCHG( 6, 9 ); CMPXCHG( 0, 3 ); CMPXCHG( 5, 8 );
522  CMPXCHG( 0, 2 ); CMPXCHG( 3, 6 ); CMPXCHG( 7, 9 );
523  CMPXCHG( 0, 1 ); CMPXCHG( 2, 4 ); CMPXCHG( 5, 7 );
524  CMPXCHG( 8, 9 ); CMPXCHG( 1, 2 ); CMPXCHG( 4, 6 );
525  CMPXCHG( 7, 8 ); CMPXCHG( 3, 5 ); CMPXCHG( 2, 5 );
526  CMPXCHG( 6, 8 ); CMPXCHG( 1, 3 ); CMPXCHG( 4, 7 );
527  CMPXCHG( 2, 3 ); CMPXCHG( 6, 7 ); CMPXCHG( 3, 4 );
528  CMPXCHG( 5, 6 );
529  return MEAN( f[4], f[5] );
530  case 11:
531  CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 );
532  CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 ); CMPXCHG( 1, 3 );
533  CMPXCHG( 5, 7 ); CMPXCHG( 0, 2 ); CMPXCHG( 4, 6 );
534  CMPXCHG( 8, 10 ); CMPXCHG( 1, 2 ); CMPXCHG( 5, 6 );
535  CMPXCHG( 9, 10 ); CMPXCHG( 1, 5 ); CMPXCHG( 6, 10 );
536  CMPXCHG( 5, 9 ); CMPXCHG( 2, 6 ); CMPXCHG( 1, 5 );
537  CMPXCHG( 6, 10 ); CMPXCHG( 0, 4 ); CMPXCHG( 3, 7 );
538  CMPXCHG( 4, 8 ); CMPXCHG( 0, 4 ); CMPXCHG( 1, 4 );
539  CMPXCHG( 7, 10 ); CMPXCHG( 3, 8 ); CMPXCHG( 2, 3 );
540  CMPXCHG( 8, 9 ); CMPXCHG( 3, 5 ); CMPXCHG( 6, 8 );
541  return pcl::Min( f[5], f[6] );
542  case 12:
543  CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 );
544  CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 );
545  CMPXCHG( 1, 3 ); CMPXCHG( 5, 7 ); CMPXCHG( 9, 11 );
546  CMPXCHG( 0, 2 ); CMPXCHG( 4, 6 ); CMPXCHG( 8, 10 );
547  CMPXCHG( 1, 2 ); CMPXCHG( 5, 6 ); CMPXCHG( 9, 10 );
548  CMPXCHG( 1, 5 ); CMPXCHG( 6, 10 ); CMPXCHG( 5, 9 );
549  CMPXCHG( 2, 6 ); CMPXCHG( 1, 5 ); CMPXCHG( 6, 10 );
550  CMPXCHG( 0, 4 ); CMPXCHG( 7, 11 ); CMPXCHG( 3, 7 );
551  CMPXCHG( 4, 8 ); CMPXCHG( 0, 4 ); CMPXCHG( 7, 11 );
552  CMPXCHG( 1, 4 ); CMPXCHG( 7, 10 ); CMPXCHG( 3, 8 );
553  CMPXCHG( 2, 3 ); CMPXCHG( 8, 9 ); CMPXCHG( 3, 5 );
554  CMPXCHG( 6, 8 );
555  return MEAN( f[5], f[6] );
556  case 13:
557  CMPXCHG( 0, 8 ); CMPXCHG( 1, 9 ); CMPXCHG( 2, 10 );
558  CMPXCHG( 3, 11 ); CMPXCHG( 4, 12 ); CMPXCHG( 0, 4 );
559  CMPXCHG( 1, 5 ); CMPXCHG( 2, 6 ); CMPXCHG( 3, 7 );
560  CMPXCHG( 8, 12 ); CMPXCHG( 4, 8 ); CMPXCHG( 5, 9 );
561  CMPXCHG( 6, 10 ); CMPXCHG( 7, 11 ); CMPXCHG( 0, 2 );
562  CMPXCHG( 1, 3 ); CMPXCHG( 4, 6 ); CMPXCHG( 5, 7 );
563  CMPXCHG( 8, 10 ); CMPXCHG( 9, 11 ); CMPXCHG( 2, 8 );
564  CMPXCHG( 3, 9 ); CMPXCHG( 6, 12 ); CMPXCHG( 2, 4 );
565  CMPXCHG( 3, 5 ); CMPXCHG( 6, 8 ); CMPXCHG( 7, 9 );
566  CMPXCHG( 10, 12 ); CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 );
567  CMPXCHG( 4, 5 ); CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 );
568  CMPXCHG( 10, 11 ); CMPXCHG( 1, 8 ); CMPXCHG( 3, 10 );
569  CMPXCHG( 5, 12 ); CMPXCHG( 3, 6 ); CMPXCHG( 5, 8 );
570  return pcl::Max( f[5], f[6] );
571  case 14:
572  CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 );
573  CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 );
574  CMPXCHG( 12, 13 ); CMPXCHG( 0, 2 ); CMPXCHG( 4, 6 );
575  CMPXCHG( 8, 10 ); CMPXCHG( 1, 3 ); CMPXCHG( 5, 7 );
576  CMPXCHG( 9, 11 ); CMPXCHG( 0, 4 ); CMPXCHG( 8, 12 );
577  CMPXCHG( 1, 5 ); CMPXCHG( 9, 13 ); CMPXCHG( 2, 6 );
578  CMPXCHG( 3, 7 ); CMPXCHG( 0, 8 ); CMPXCHG( 1, 9 );
579  CMPXCHG( 2, 10 ); CMPXCHG( 3, 11 ); CMPXCHG( 4, 12 );
580  CMPXCHG( 5, 13 ); CMPXCHG( 5, 10 ); CMPXCHG( 6, 9 );
581  CMPXCHG( 3, 12 ); CMPXCHG( 7, 11 ); CMPXCHG( 1, 2 );
582  CMPXCHG( 4, 8 ); CMPXCHG( 7, 13 ); CMPXCHG( 2, 8 );
583  CMPXCHG( 5, 6 ); CMPXCHG( 9, 10 ); CMPXCHG( 3, 8 );
584  CMPXCHG( 7, 12 ); CMPXCHG( 6, 8 ); CMPXCHG( 3, 5 );
585  CMPXCHG( 7, 9 ); CMPXCHG( 5, 6 ); CMPXCHG( 7, 8 );
586  return MEAN( f[6], f[7] );
587  case 15:
588  CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 );
589  CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 );
590  CMPXCHG( 12, 13 ); CMPXCHG( 0, 2 ); CMPXCHG( 4, 6 );
591  CMPXCHG( 8, 10 ); CMPXCHG( 12, 14 ); CMPXCHG( 1, 3 );
592  CMPXCHG( 5, 7 ); CMPXCHG( 9, 11 ); CMPXCHG( 0, 4 );
593  CMPXCHG( 8, 12 ); CMPXCHG( 1, 5 ); CMPXCHG( 9, 13 );
594  CMPXCHG( 2, 6 ); CMPXCHG( 10, 14 ); CMPXCHG( 3, 7 );
595  CMPXCHG( 0, 8 ); CMPXCHG( 1, 9 ); CMPXCHG( 2, 10 );
596  CMPXCHG( 3, 11 ); CMPXCHG( 4, 12 ); CMPXCHG( 5, 13 );
597  CMPXCHG( 6, 14 ); CMPXCHG( 5, 10 ); CMPXCHG( 6, 9 );
598  CMPXCHG( 3, 12 ); CMPXCHG( 13, 14 ); CMPXCHG( 7, 11 );
599  CMPXCHG( 1, 2 ); CMPXCHG( 4, 8 ); CMPXCHG( 7, 13 );
600  CMPXCHG( 2, 8 ); CMPXCHG( 5, 6 ); CMPXCHG( 9, 10 );
601  CMPXCHG( 3, 8 ); CMPXCHG( 7, 12 ); CMPXCHG( 6, 8 );
602  CMPXCHG( 3, 5 ); CMPXCHG( 7, 9 ); CMPXCHG( 5, 6 );
603  CMPXCHG( 7, 8 );
604  return pcl::Max( f[6], f[7] );
605  case 16:
606  CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 );
607  CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 );
608  CMPXCHG( 12, 13 ); CMPXCHG( 14, 15 ); CMPXCHG( 0, 2 );
609  CMPXCHG( 4, 6 ); CMPXCHG( 8, 10 ); CMPXCHG( 12, 14 );
610  CMPXCHG( 1, 3 ); CMPXCHG( 5, 7 ); CMPXCHG( 9, 11 );
611  CMPXCHG( 13, 15 ); CMPXCHG( 0, 4 ); CMPXCHG( 8, 12 );
612  CMPXCHG( 1, 5 ); CMPXCHG( 9, 13 ); CMPXCHG( 2, 6 );
613  CMPXCHG( 10, 14 ); CMPXCHG( 3, 7 ); CMPXCHG( 11, 15 );
614  CMPXCHG( 0, 8 ); CMPXCHG( 1, 9 ); CMPXCHG( 2, 10 );
615  CMPXCHG( 3, 11 ); CMPXCHG( 4, 12 ); CMPXCHG( 5, 13 );
616  CMPXCHG( 6, 14 ); CMPXCHG( 7, 15 ); CMPXCHG( 5, 10 );
617  CMPXCHG( 6, 9 ); CMPXCHG( 3, 12 ); CMPXCHG( 13, 14 );
618  CMPXCHG( 7, 11 ); CMPXCHG( 1, 2 ); CMPXCHG( 4, 8 );
619  CMPXCHG( 7, 13 ); CMPXCHG( 2, 8 ); CMPXCHG( 5, 6 );
620  CMPXCHG( 9, 10 ); CMPXCHG( 3, 8 ); CMPXCHG( 7, 12 );
621  CMPXCHG( 6, 8 ); CMPXCHG( 10, 12 ); CMPXCHG( 3, 5 );
622  CMPXCHG( 7, 9 ); CMPXCHG( 5, 6 ); CMPXCHG( 7, 8 );
623  CMPXCHG( 9, 10 ); CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 );
624  return MEAN( f[7], f[8] );
625  case 17:
626  CMPXCHG( 0, 16 ); CMPXCHG( 0, 8 ); CMPXCHG( 1, 9 );
627  CMPXCHG( 2, 10 ); CMPXCHG( 3, 11 ); CMPXCHG( 4, 12 );
628  CMPXCHG( 5, 13 ); CMPXCHG( 6, 14 ); CMPXCHG( 7, 15 );
629  CMPXCHG( 8, 16 ); CMPXCHG( 0, 4 ); CMPXCHG( 1, 5 );
630  CMPXCHG( 2, 6 ); CMPXCHG( 3, 7 ); CMPXCHG( 8, 12 );
631  CMPXCHG( 9, 13 ); CMPXCHG( 10, 14 ); CMPXCHG( 11, 15 );
632  CMPXCHG( 4, 16 ); CMPXCHG( 4, 8 ); CMPXCHG( 5, 9 );
633  CMPXCHG( 6, 10 ); CMPXCHG( 7, 11 ); CMPXCHG( 12, 16 );
634  CMPXCHG( 0, 2 ); CMPXCHG( 1, 3 ); CMPXCHG( 4, 6 );
635  CMPXCHG( 5, 7 ); CMPXCHG( 8, 10 ); CMPXCHG( 9, 11 );
636  CMPXCHG( 12, 14 ); CMPXCHG( 13, 15 ); CMPXCHG( 2, 16 );
637  CMPXCHG( 2, 8 ); CMPXCHG( 3, 9 ); CMPXCHG( 6, 12 );
638  CMPXCHG( 7, 13 ); CMPXCHG( 10, 16 ); CMPXCHG( 2, 4 );
639  CMPXCHG( 3, 5 ); CMPXCHG( 6, 8 ); CMPXCHG( 7, 9 );
640  CMPXCHG( 10, 12 ); CMPXCHG( 11, 13 ); CMPXCHG( 14, 16 );
641  CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 );
642  CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 );
643  CMPXCHG( 12, 13 ); CMPXCHG( 14, 15 ); CMPXCHG( 1, 16 );
644  CMPXCHG( 1, 8 ); CMPXCHG( 3, 10 ); CMPXCHG( 5, 12 );
645  CMPXCHG( 7, 14 ); CMPXCHG( 5, 8 ); CMPXCHG( 7, 10 );
646  return pcl::Max( f[7], f[8] );
647  case 18:
648  CMPXCHG( 0, 16 ); CMPXCHG( 1, 17 ); CMPXCHG( 0, 8 );
649  CMPXCHG( 1, 9 ); CMPXCHG( 2, 10 ); CMPXCHG( 3, 11 );
650  CMPXCHG( 4, 12 ); CMPXCHG( 5, 13 ); CMPXCHG( 6, 14 );
651  CMPXCHG( 7, 15 ); CMPXCHG( 8, 16 ); CMPXCHG( 9, 17 );
652  CMPXCHG( 0, 4 ); CMPXCHG( 1, 5 ); CMPXCHG( 2, 6 );
653  CMPXCHG( 3, 7 ); CMPXCHG( 8, 12 ); CMPXCHG( 9, 13 );
654  CMPXCHG( 10, 14 ); CMPXCHG( 11, 15 ); CMPXCHG( 4, 16 );
655  CMPXCHG( 5, 17 ); CMPXCHG( 4, 8 ); CMPXCHG( 5, 9 );
656  CMPXCHG( 6, 10 ); CMPXCHG( 7, 11 ); CMPXCHG( 12, 16 );
657  CMPXCHG( 13, 17 ); CMPXCHG( 0, 2 ); CMPXCHG( 1, 3 );
658  CMPXCHG( 4, 6 ); CMPXCHG( 5, 7 ); CMPXCHG( 8, 10 );
659  CMPXCHG( 9, 11 ); CMPXCHG( 12, 14 ); CMPXCHG( 13, 15 );
660  CMPXCHG( 2, 16 ); CMPXCHG( 3, 17 ); CMPXCHG( 2, 8 );
661  CMPXCHG( 3, 9 ); CMPXCHG( 6, 12 ); CMPXCHG( 7, 13 );
662  CMPXCHG( 10, 16 ); CMPXCHG( 11, 17 ); CMPXCHG( 2, 4 );
663  CMPXCHG( 3, 5 ); CMPXCHG( 6, 8 ); CMPXCHG( 7, 9 );
664  CMPXCHG( 10, 12 ); CMPXCHG( 11, 13 ); CMPXCHG( 14, 16 );
665  CMPXCHG( 15, 17 ); CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 );
666  CMPXCHG( 4, 5 ); CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 );
667  CMPXCHG( 10, 11 ); CMPXCHG( 12, 13 ); CMPXCHG( 14, 15 );
668  CMPXCHG( 16, 17 ); CMPXCHG( 1, 16 ); CMPXCHG( 1, 8 );
669  CMPXCHG( 3, 10 ); CMPXCHG( 5, 12 ); CMPXCHG( 7, 14 );
670  CMPXCHG( 9, 16 ); CMPXCHG( 5, 8 ); CMPXCHG( 7, 10 );
671  CMPXCHG( 9, 12 ); CMPXCHG( 7, 8 ); CMPXCHG( 9, 10 );
672  return MEAN( f[8], f[9] );
673  case 19:
674  CMPXCHG( 0, 16 ); CMPXCHG( 1, 17 ); CMPXCHG( 2, 18 );
675  CMPXCHG( 0, 8 ); CMPXCHG( 1, 9 ); CMPXCHG( 2, 10 );
676  CMPXCHG( 3, 11 ); CMPXCHG( 4, 12 ); CMPXCHG( 5, 13 );
677  CMPXCHG( 6, 14 ); CMPXCHG( 7, 15 ); CMPXCHG( 8, 16 );
678  CMPXCHG( 9, 17 ); CMPXCHG( 10, 18 ); CMPXCHG( 0, 4 );
679  CMPXCHG( 1, 5 ); CMPXCHG( 2, 6 ); CMPXCHG( 3, 7 );
680  CMPXCHG( 8, 12 ); CMPXCHG( 9, 13 ); CMPXCHG( 10, 14 );
681  CMPXCHG( 11, 15 ); CMPXCHG( 4, 16 ); CMPXCHG( 5, 17 );
682  CMPXCHG( 6, 18 ); CMPXCHG( 4, 8 ); CMPXCHG( 5, 9 );
683  CMPXCHG( 6, 10 ); CMPXCHG( 7, 11 ); CMPXCHG( 12, 16 );
684  CMPXCHG( 13, 17 ); CMPXCHG( 14, 18 ); CMPXCHG( 0, 2 );
685  CMPXCHG( 1, 3 ); CMPXCHG( 4, 6 ); CMPXCHG( 5, 7 );
686  CMPXCHG( 8, 10 ); CMPXCHG( 9, 11 ); CMPXCHG( 12, 14 );
687  CMPXCHG( 13, 15 ); CMPXCHG( 16, 18 ); CMPXCHG( 2, 16 );
688  CMPXCHG( 3, 17 ); CMPXCHG( 2, 8 ); CMPXCHG( 3, 9 );
689  CMPXCHG( 6, 12 ); CMPXCHG( 7, 13 ); CMPXCHG( 10, 16 );
690  CMPXCHG( 11, 17 ); CMPXCHG( 2, 4 ); CMPXCHG( 3, 5 );
691  CMPXCHG( 6, 8 ); CMPXCHG( 7, 9 ); CMPXCHG( 10, 12 );
692  CMPXCHG( 11, 13 ); CMPXCHG( 14, 16 ); CMPXCHG( 15, 17 );
693  CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 );
694  CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 );
695  CMPXCHG( 12, 13 ); CMPXCHG( 14, 15 ); CMPXCHG( 16, 17 );
696  CMPXCHG( 1, 16 ); CMPXCHG( 3, 18 ); CMPXCHG( 3, 10 );
697  CMPXCHG( 5, 12 ); CMPXCHG( 7, 14 ); CMPXCHG( 9, 16 );
698  CMPXCHG( 7, 10 ); CMPXCHG( 9, 12 );
699  return pcl::Min( f[9], f[10] );
700  case 20:
701  CMPXCHG( 0, 16 ); CMPXCHG( 1, 17 ); CMPXCHG( 2, 18 );
702  CMPXCHG( 3, 19 ); CMPXCHG( 0, 8 ); CMPXCHG( 1, 9 );
703  CMPXCHG( 2, 10 ); CMPXCHG( 3, 11 ); CMPXCHG( 4, 12 );
704  CMPXCHG( 5, 13 ); CMPXCHG( 6, 14 ); CMPXCHG( 7, 15 );
705  CMPXCHG( 8, 16 ); CMPXCHG( 9, 17 ); CMPXCHG( 10, 18 );
706  CMPXCHG( 11, 19 ); CMPXCHG( 0, 4 ); CMPXCHG( 1, 5 );
707  CMPXCHG( 2, 6 ); CMPXCHG( 3, 7 ); CMPXCHG( 8, 12 );
708  CMPXCHG( 9, 13 ); CMPXCHG( 10, 14 ); CMPXCHG( 11, 15 );
709  CMPXCHG( 4, 16 ); CMPXCHG( 5, 17 ); CMPXCHG( 6, 18 );
710  CMPXCHG( 7, 19 ); CMPXCHG( 4, 8 ); CMPXCHG( 5, 9 );
711  CMPXCHG( 6, 10 ); CMPXCHG( 7, 11 ); CMPXCHG( 12, 16 );
712  CMPXCHG( 13, 17 ); CMPXCHG( 14, 18 ); CMPXCHG( 15, 19 );
713  CMPXCHG( 0, 2 ); CMPXCHG( 1, 3 ); CMPXCHG( 4, 6 );
714  CMPXCHG( 5, 7 ); CMPXCHG( 8, 10 ); CMPXCHG( 9, 11 );
715  CMPXCHG( 12, 14 ); CMPXCHG( 13, 15 ); CMPXCHG( 16, 18 );
716  CMPXCHG( 17, 19 ); CMPXCHG( 2, 16 ); CMPXCHG( 3, 17 );
717  CMPXCHG( 2, 8 ); CMPXCHG( 3, 9 ); CMPXCHG( 6, 12 );
718  CMPXCHG( 7, 13 ); CMPXCHG( 10, 16 ); CMPXCHG( 11, 17 );
719  CMPXCHG( 2, 4 ); CMPXCHG( 3, 5 ); CMPXCHG( 6, 8 );
720  CMPXCHG( 7, 9 ); CMPXCHG( 10, 12 ); CMPXCHG( 11, 13 );
721  CMPXCHG( 14, 16 ); CMPXCHG( 15, 17 ); CMPXCHG( 0, 1 );
722  CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 ); CMPXCHG( 6, 7 );
723  CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 ); CMPXCHG( 12, 13 );
724  CMPXCHG( 14, 15 ); CMPXCHG( 16, 17 ); CMPXCHG( 18, 19 );
725  CMPXCHG( 1, 16 ); CMPXCHG( 3, 18 ); CMPXCHG( 3, 10 );
726  CMPXCHG( 5, 12 ); CMPXCHG( 7, 14 ); CMPXCHG( 9, 16 );
727  CMPXCHG( 7, 10 ); CMPXCHG( 9, 12 );
728  return MEAN( f[9], f[10] );
729  case 21:
730  CMPXCHG( 0, 16 ); CMPXCHG( 1, 17 ); CMPXCHG( 2, 18 );
731  CMPXCHG( 3, 19 ); CMPXCHG( 4, 20 ); CMPXCHG( 0, 8 );
732  CMPXCHG( 1, 9 ); CMPXCHG( 2, 10 ); CMPXCHG( 3, 11 );
733  CMPXCHG( 4, 12 ); CMPXCHG( 5, 13 ); CMPXCHG( 6, 14 );
734  CMPXCHG( 7, 15 ); CMPXCHG( 8, 16 ); CMPXCHG( 9, 17 );
735  CMPXCHG( 10, 18 ); CMPXCHG( 11, 19 ); CMPXCHG( 12, 20 );
736  CMPXCHG( 0, 4 ); CMPXCHG( 1, 5 ); CMPXCHG( 2, 6 );
737  CMPXCHG( 3, 7 ); CMPXCHG( 8, 12 ); CMPXCHG( 9, 13 );
738  CMPXCHG( 10, 14 ); CMPXCHG( 11, 15 ); CMPXCHG( 16, 20 );
739  CMPXCHG( 4, 16 ); CMPXCHG( 5, 17 ); CMPXCHG( 6, 18 );
740  CMPXCHG( 7, 19 ); CMPXCHG( 4, 8 ); CMPXCHG( 5, 9 );
741  CMPXCHG( 6, 10 ); CMPXCHG( 7, 11 ); CMPXCHG( 12, 16 );
742  CMPXCHG( 13, 17 ); CMPXCHG( 14, 18 ); CMPXCHG( 15, 19 );
743  CMPXCHG( 0, 2 ); CMPXCHG( 1, 3 ); CMPXCHG( 4, 6 );
744  CMPXCHG( 5, 7 ); CMPXCHG( 8, 10 ); CMPXCHG( 9, 11 );
745  CMPXCHG( 12, 14 ); CMPXCHG( 13, 15 ); CMPXCHG( 16, 18 );
746  CMPXCHG( 17, 19 ); CMPXCHG( 2, 16 ); CMPXCHG( 3, 17 );
747  CMPXCHG( 6, 20 ); CMPXCHG( 2, 8 ); CMPXCHG( 3, 9 );
748  CMPXCHG( 6, 12 ); CMPXCHG( 7, 13 ); CMPXCHG( 10, 16 );
749  CMPXCHG( 11, 17 ); CMPXCHG( 14, 20 ); CMPXCHG( 2, 4 );
750  CMPXCHG( 3, 5 ); CMPXCHG( 6, 8 ); CMPXCHG( 7, 9 );
751  CMPXCHG( 10, 12 ); CMPXCHG( 11, 13 ); CMPXCHG( 14, 16 );
752  CMPXCHG( 15, 17 ); CMPXCHG( 18, 20 ); CMPXCHG( 0, 1 );
753  CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 ); CMPXCHG( 6, 7 );
754  CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 ); CMPXCHG( 12, 13 );
755  CMPXCHG( 14, 15 ); CMPXCHG( 16, 17 ); CMPXCHG( 18, 19 );
756  CMPXCHG( 1, 16 ); CMPXCHG( 3, 18 ); CMPXCHG( 5, 20 );
757  CMPXCHG( 3, 10 ); CMPXCHG( 5, 12 ); CMPXCHG( 7, 14 );
758  CMPXCHG( 9, 16 ); CMPXCHG( 7, 10 ); CMPXCHG( 9, 12 );
759  return pcl::Max( f[9], f[10] );
760  case 22:
761  CMPXCHG( 0, 16 ); CMPXCHG( 1, 17 ); CMPXCHG( 2, 18 );
762  CMPXCHG( 3, 19 ); CMPXCHG( 4, 20 ); CMPXCHG( 5, 21 );
763  CMPXCHG( 0, 8 ); CMPXCHG( 1, 9 ); CMPXCHG( 2, 10 );
764  CMPXCHG( 3, 11 ); CMPXCHG( 4, 12 ); CMPXCHG( 5, 13 );
765  CMPXCHG( 6, 14 ); CMPXCHG( 7, 15 ); CMPXCHG( 8, 16 );
766  CMPXCHG( 9, 17 ); CMPXCHG( 10, 18 ); CMPXCHG( 11, 19 );
767  CMPXCHG( 12, 20 ); CMPXCHG( 13, 21 ); CMPXCHG( 0, 4 );
768  CMPXCHG( 1, 5 ); CMPXCHG( 2, 6 ); CMPXCHG( 3, 7 );
769  CMPXCHG( 8, 12 ); CMPXCHG( 9, 13 ); CMPXCHG( 10, 14 );
770  CMPXCHG( 11, 15 ); CMPXCHG( 16, 20 ); CMPXCHG( 17, 21 );
771  CMPXCHG( 4, 16 ); CMPXCHG( 5, 17 ); CMPXCHG( 6, 18 );
772  CMPXCHG( 7, 19 ); CMPXCHG( 4, 8 ); CMPXCHG( 5, 9 );
773  CMPXCHG( 6, 10 ); CMPXCHG( 7, 11 ); CMPXCHG( 12, 16 );
774  CMPXCHG( 13, 17 ); CMPXCHG( 14, 18 ); CMPXCHG( 15, 19 );
775  CMPXCHG( 0, 2 ); CMPXCHG( 1, 3 ); CMPXCHG( 4, 6 );
776  CMPXCHG( 5, 7 ); CMPXCHG( 8, 10 ); CMPXCHG( 9, 11 );
777  CMPXCHG( 12, 14 ); CMPXCHG( 13, 15 ); CMPXCHG( 16, 18 );
778  CMPXCHG( 17, 19 ); CMPXCHG( 2, 16 ); CMPXCHG( 3, 17 );
779  CMPXCHG( 6, 20 ); CMPXCHG( 7, 21 ); CMPXCHG( 2, 8 );
780  CMPXCHG( 3, 9 ); CMPXCHG( 6, 12 ); CMPXCHG( 7, 13 );
781  CMPXCHG( 10, 16 ); CMPXCHG( 11, 17 ); CMPXCHG( 14, 20 );
782  CMPXCHG( 15, 21 ); CMPXCHG( 2, 4 ); CMPXCHG( 3, 5 );
783  CMPXCHG( 6, 8 ); CMPXCHG( 7, 9 ); CMPXCHG( 10, 12 );
784  CMPXCHG( 11, 13 ); CMPXCHG( 14, 16 ); CMPXCHG( 15, 17 );
785  CMPXCHG( 18, 20 ); CMPXCHG( 19, 21 ); CMPXCHG( 0, 1 );
786  CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 ); CMPXCHG( 6, 7 );
787  CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 ); CMPXCHG( 12, 13 );
788  CMPXCHG( 14, 15 ); CMPXCHG( 16, 17 ); CMPXCHG( 18, 19 );
789  CMPXCHG( 20, 21 ); CMPXCHG( 1, 16 ); CMPXCHG( 3, 18 );
790  CMPXCHG( 5, 20 ); CMPXCHG( 3, 10 ); CMPXCHG( 5, 12 );
791  CMPXCHG( 7, 14 ); CMPXCHG( 9, 16 ); CMPXCHG( 11, 18 );
792  CMPXCHG( 7, 10 ); CMPXCHG( 9, 12 ); CMPXCHG( 11, 14 );
793  CMPXCHG( 9, 10 ); CMPXCHG( 11, 12 );
794  return MEAN( f[10], f[11] );
795  case 23:
796  CMPXCHG( 0, 16 ); CMPXCHG( 1, 17 ); CMPXCHG( 2, 18 );
797  CMPXCHG( 3, 19 ); CMPXCHG( 4, 20 ); CMPXCHG( 5, 21 );
798  CMPXCHG( 6, 22 ); CMPXCHG( 0, 8 ); CMPXCHG( 1, 9 );
799  CMPXCHG( 2, 10 ); CMPXCHG( 3, 11 ); CMPXCHG( 4, 12 );
800  CMPXCHG( 5, 13 ); CMPXCHG( 6, 14 ); CMPXCHG( 7, 15 );
801  CMPXCHG( 8, 16 ); CMPXCHG( 9, 17 ); CMPXCHG( 10, 18 );
802  CMPXCHG( 11, 19 ); CMPXCHG( 12, 20 ); CMPXCHG( 13, 21 );
803  CMPXCHG( 14, 22 ); CMPXCHG( 0, 4 ); CMPXCHG( 1, 5 );
804  CMPXCHG( 2, 6 ); CMPXCHG( 3, 7 ); CMPXCHG( 8, 12 );
805  CMPXCHG( 9, 13 ); CMPXCHG( 10, 14 ); CMPXCHG( 11, 15 );
806  CMPXCHG( 16, 20 ); CMPXCHG( 17, 21 ); CMPXCHG( 18, 22 );
807  CMPXCHG( 4, 16 ); CMPXCHG( 5, 17 ); CMPXCHG( 6, 18 );
808  CMPXCHG( 7, 19 ); CMPXCHG( 4, 8 ); CMPXCHG( 5, 9 );
809  CMPXCHG( 6, 10 ); CMPXCHG( 7, 11 ); CMPXCHG( 12, 16 );
810  CMPXCHG( 13, 17 ); CMPXCHG( 14, 18 ); CMPXCHG( 15, 19 );
811  CMPXCHG( 0, 2 ); CMPXCHG( 1, 3 ); CMPXCHG( 4, 6 );
812  CMPXCHG( 5, 7 ); CMPXCHG( 8, 10 ); CMPXCHG( 9, 11 );
813  CMPXCHG( 12, 14 ); CMPXCHG( 13, 15 ); CMPXCHG( 16, 18 );
814  CMPXCHG( 17, 19 ); CMPXCHG( 20, 22 ); CMPXCHG( 2, 16 );
815  CMPXCHG( 3, 17 ); CMPXCHG( 6, 20 ); CMPXCHG( 7, 21 );
816  CMPXCHG( 2, 8 ); CMPXCHG( 3, 9 ); CMPXCHG( 6, 12 );
817  CMPXCHG( 7, 13 ); CMPXCHG( 10, 16 ); CMPXCHG( 11, 17 );
818  CMPXCHG( 14, 20 ); CMPXCHG( 15, 21 ); CMPXCHG( 2, 4 );
819  CMPXCHG( 3, 5 ); CMPXCHG( 6, 8 ); CMPXCHG( 7, 9 );
820  CMPXCHG( 10, 12 ); CMPXCHG( 11, 13 ); CMPXCHG( 14, 16 );
821  CMPXCHG( 15, 17 ); CMPXCHG( 18, 20 ); CMPXCHG( 19, 21 );
822  CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 );
823  CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 );
824  CMPXCHG( 12, 13 ); CMPXCHG( 14, 15 ); CMPXCHG( 16, 17 );
825  CMPXCHG( 18, 19 ); CMPXCHG( 20, 21 ); CMPXCHG( 1, 16 );
826  CMPXCHG( 3, 18 ); CMPXCHG( 5, 20 ); CMPXCHG( 7, 22 );
827  CMPXCHG( 5, 12 ); CMPXCHG( 7, 14 ); CMPXCHG( 9, 16 );
828  CMPXCHG( 11, 18 ); CMPXCHG( 9, 12 ); CMPXCHG( 11, 14 );
829  return pcl::Min( f[11], f[12] );
830  case 24:
831  CMPXCHG( 0, 16 ); CMPXCHG( 1, 17 ); CMPXCHG( 2, 18 );
832  CMPXCHG( 3, 19 ); CMPXCHG( 4, 20 ); CMPXCHG( 5, 21 );
833  CMPXCHG( 6, 22 ); CMPXCHG( 7, 23 ); CMPXCHG( 0, 8 );
834  CMPXCHG( 1, 9 ); CMPXCHG( 2, 10 ); CMPXCHG( 3, 11 );
835  CMPXCHG( 4, 12 ); CMPXCHG( 5, 13 ); CMPXCHG( 6, 14 );
836  CMPXCHG( 7, 15 ); CMPXCHG( 8, 16 ); CMPXCHG( 9, 17 );
837  CMPXCHG( 10, 18 ); CMPXCHG( 11, 19 ); CMPXCHG( 12, 20 );
838  CMPXCHG( 13, 21 ); CMPXCHG( 14, 22 ); CMPXCHG( 15, 23 );
839  CMPXCHG( 0, 4 ); CMPXCHG( 1, 5 ); CMPXCHG( 2, 6 );
840  CMPXCHG( 3, 7 ); CMPXCHG( 8, 12 ); CMPXCHG( 9, 13 );
841  CMPXCHG( 10, 14 ); CMPXCHG( 11, 15 ); CMPXCHG( 16, 20 );
842  CMPXCHG( 17, 21 ); CMPXCHG( 18, 22 ); CMPXCHG( 19, 23 );
843  CMPXCHG( 4, 16 ); CMPXCHG( 5, 17 ); CMPXCHG( 6, 18 );
844  CMPXCHG( 7, 19 ); CMPXCHG( 4, 8 ); CMPXCHG( 5, 9 );
845  CMPXCHG( 6, 10 ); CMPXCHG( 7, 11 ); CMPXCHG( 12, 16 );
846  CMPXCHG( 13, 17 ); CMPXCHG( 14, 18 ); CMPXCHG( 15, 19 );
847  CMPXCHG( 0, 2 ); CMPXCHG( 1, 3 ); CMPXCHG( 4, 6 );
848  CMPXCHG( 5, 7 ); CMPXCHG( 8, 10 ); CMPXCHG( 9, 11 );
849  CMPXCHG( 12, 14 ); CMPXCHG( 13, 15 ); CMPXCHG( 16, 18 );
850  CMPXCHG( 17, 19 ); CMPXCHG( 20, 22 ); CMPXCHG( 21, 23 );
851  CMPXCHG( 2, 16 ); CMPXCHG( 3, 17 ); CMPXCHG( 6, 20 );
852  CMPXCHG( 7, 21 ); CMPXCHG( 2, 8 ); CMPXCHG( 3, 9 );
853  CMPXCHG( 6, 12 ); CMPXCHG( 7, 13 ); CMPXCHG( 10, 16 );
854  CMPXCHG( 11, 17 ); CMPXCHG( 14, 20 ); CMPXCHG( 15, 21 );
855  CMPXCHG( 2, 4 ); CMPXCHG( 3, 5 ); CMPXCHG( 6, 8 );
856  CMPXCHG( 7, 9 ); CMPXCHG( 10, 12 ); CMPXCHG( 11, 13 );
857  CMPXCHG( 14, 16 ); CMPXCHG( 15, 17 ); CMPXCHG( 18, 20 );
858  CMPXCHG( 19, 21 ); CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 );
859  CMPXCHG( 4, 5 ); CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 );
860  CMPXCHG( 10, 11 ); CMPXCHG( 12, 13 ); CMPXCHG( 14, 15 );
861  CMPXCHG( 16, 17 ); CMPXCHG( 18, 19 ); CMPXCHG( 20, 21 );
862  CMPXCHG( 22, 23 ); CMPXCHG( 1, 16 ); CMPXCHG( 3, 18 );
863  CMPXCHG( 5, 20 ); CMPXCHG( 7, 22 ); CMPXCHG( 5, 12 );
864  CMPXCHG( 7, 14 ); CMPXCHG( 9, 16 ); CMPXCHG( 11, 18 );
865  CMPXCHG( 9, 12 ); CMPXCHG( 11, 14 );
866  return MEAN( f[11], f[12] );
867  default:
868  {
869  distance_type n2 = distance_type( n >> 1 );
870  if ( n & 1 )
871  return *pcl::Select( f, f+n, n2 );
872  return P::FloatToSample( (double( *pcl::Select( f, f+n, n2 ) )
873  + double( *pcl::Select( f, f+n, n2-1 ) ))/2 );
874  }
875  }
876  }
877 
878 #undef CMPXCHG
879 #undef MEAN
880 };
881 
882 // ----------------------------------------------------------------------------
883 
897 class PCL_CLASS SelectionFilter : public MorphologicalOperator
898 {
899 public:
900 
905  SelectionFilter() = default;
906 
910  SelectionFilter( float p )
911  : k( pcl::Range( p, float( 0 ), float( 1 ) ) )
912  {
913  PCL_PRECONDITION( 0 <= p && p <= 1 )
914  PCL_CHECK( 0 <= k && k <= 1 )
915  }
916 
920  SelectionFilter( const SelectionFilter& ) = default;
921 
924  MorphologicalOperator* Clone() const override
925  {
926  return new SelectionFilter( *this );
927  }
928 
932  float SelectionPoint() const
933  {
934  return k;
935  }
936 
940  void SetSelectionPoint( float _k )
941  {
942  PCL_PRECONDITION( 0 <= _k && _k <= 1 )
943  k = pcl::Range( _k, float( 0 ), float( 1 ) );
944  }
945 
948  String Description() const override
949  {
950  return String().Format( "Selection, k=%.5f", k );
951  }
952 
957  FloatPixelTraits::sample operator ()( FloatPixelTraits::sample* f, size_type n ) const override
958  {
959  return Operate( f, n );
960  }
961 
967  {
968  return Operate( f, n );
969  }
970 
975  UInt8PixelTraits::sample operator ()( UInt8PixelTraits::sample* f, size_type n ) const override
976  {
977  return Operate( f, n );
978  }
979 
985  {
986  return Operate( f, n );
987  }
988 
994  {
995  return Operate( f, n );
996  }
997 
998 private:
999 
1000  float k = 0.5F;
1001 
1002  template <typename T>
1003  T Operate( T* f, size_type n ) const
1004  {
1005  return *pcl::Select( f, f+n, distance_type( pcl::RoundInt( k*(n-1) ) ) );
1006  }
1007 };
1008 
1009 // ----------------------------------------------------------------------------
1010 
1018 class PCL_CLASS MidpointFilter : public MorphologicalOperator
1019 {
1020 public:
1021 
1024  MorphologicalOperator* Clone() const override
1025  {
1026  return new MidpointFilter( *this );
1027  }
1028 
1031  String Description() const override
1032  {
1033  return "Midpoint";
1034  }
1035 
1041  {
1042  return Operate( f, n, (FloatPixelTraits*)0 );
1043  }
1044 
1050  {
1051  return Operate( f, n, (DoublePixelTraits*)0 );
1052  }
1053 
1059  {
1060  return Operate( f, n, (UInt8PixelTraits*)0 );
1061  }
1062 
1068  {
1069  return Operate( f, n, (UInt16PixelTraits*)0 );
1070  }
1071 
1077  {
1078  return Operate( f, n, (UInt32PixelTraits*)0 );
1079  }
1080 
1081 private:
1082 
1083  template <typename T, class P>
1084  static T Operate( T* f, size_type n, P* )
1085  {
1086  T* min, * max;
1087  pcl::FindExtremeItems( min, max, f, f+n );
1088  return P::FloatToSample( (double( *min ) + double( *max ))/2 );
1089  }
1090 };
1091 
1092 // ----------------------------------------------------------------------------
1093 
1110 {
1111 public:
1112 
1120 
1126  : d( pcl::Range( t, float( 0 ), float( 1 ) ) )
1127  {
1128  PCL_PRECONDITION( 0 <= t && t <= 1 )
1129  PCL_CHECK( 0 <= d && d <= 1 )
1130  }
1131 
1136 
1139  MorphologicalOperator* Clone() const override
1140  {
1141  return new AlphaTrimmedMeanFilter( *this );
1142  }
1143 
1147  float TrimmingFactor() const
1148  {
1149  return d;
1150  }
1151 
1155  void SetTrimmingFactor( float t )
1156  {
1157  PCL_PRECONDITION( 0 <= t && t <= 1 )
1158  d = pcl::Range( t, float( 0 ), float( 1 ) );
1159  }
1160 
1163  String Description() const override
1164  {
1165  return String().Format( "Alpha-trimmed mean, d=%.5f", d );
1166  }
1167 
1173  {
1174  return Operate( f, n, (FloatPixelTraits*)0 );
1175  }
1176 
1182  {
1183  return Operate( f, n, (DoublePixelTraits*)0 );
1184  }
1185 
1191  {
1192  return Operate( f, n, (UInt8PixelTraits*)0 );
1193  }
1194 
1200  {
1201  return Operate( f, n, (UInt16PixelTraits*)0 );
1202  }
1203 
1209  {
1210  return Operate( f, n, (UInt32PixelTraits*)0 );
1211  }
1212 
1213 private:
1214 
1215  float d = 0.2F;
1216 
1217  template <typename T, class P>
1218  T Operate( T* f, size_type n, P* ) const
1219  {
1220  pcl::Sort( f, f+n );
1221  double s = 0;
1222  size_type i1 = RoundInt( d*((n - 1) >> 1) );
1223  size_type i2 = n-i1;
1224  for ( size_type i = i1; i < i2; ++i )
1225  s += f[i];
1226  return P::FloatToSample( s/(i2 - i1) );
1227  }
1228 };
1229 
1230 // ----------------------------------------------------------------------------
1231 
1232 } // pcl
1233 
1234 #endif // __PCL_MorphologicalOperator_h
1235 
1236 // ----------------------------------------------------------------------------
1237 // EOF pcl/MorphologicalOperator.h - Released 2024-06-18T15:48:54Z
Alpha-trimmed mean operator.
AlphaTrimmedMeanFilter(const AlphaTrimmedMeanFilter &)=default
String Description() const override
MorphologicalOperator * Clone() const override
Generic complex number.
Definition: Complex.h:84
Dilation morphological operator.
String Description() const override
MorphologicalOperator * Clone() const override
64-bit IEEE 754 normalized floating point real pixel traits.
Definition: PixelTraits.h:963
traits_type::sample sample
Definition: PixelTraits.h:974
Erosion morphological operator.
MorphologicalOperator * Clone() const override
String Description() const override
32-bit IEEE 754 normalized floating point real pixel traits.
Definition: PixelTraits.h:369
traits_type::sample sample
Definition: PixelTraits.h:380
Morphological median operator.
MorphologicalOperator * Clone() const override
String Description() const override
String Description() const override
MorphologicalOperator * Clone() const override
Abstract base class of all PCL morphological operators.
virtual String Description() const
virtual MorphologicalOperator * Clone() const =0
MorphologicalOperator(const MorphologicalOperator &)=default
An exception that indicates an unsupported feature.
Definition: Exception.h:344
Morphological selection operator.
String Description() const override
SelectionFilter(const SelectionFilter &)=default
MorphologicalOperator * Clone() const override
SelectionFilter()=default
void SetSelectionPoint(float _k)
Unicode (UTF-16) string.
Definition: String.h:8113
String & Format(const_c_string8 fmt,...)
Definition: String.h:11081
16-bit unsigned integer pixel traits.
Definition: PixelTraits.h:3934
traits_type::sample sample
Definition: PixelTraits.h:3945
32-bit unsigned integer pixel traits.
Definition: PixelTraits.h:4798
traits_type::sample sample
Definition: PixelTraits.h:4809
8-bit unsigned integer pixel traits.
Definition: PixelTraits.h:3070
traits_type::sample sample
Definition: PixelTraits.h:3081
int RoundInt(T x) noexcept
Definition: Math.h:1503
RI Select(RI i, RI j, distance_type k)
Definition: Selection.h:165
ptrdiff_t distance_type
Definition: Defs.h:615
size_t size_type
Definition: Defs.h:609
void Sort(BI i, BI j)
Definition: Sort.h:520
constexpr const T & Min(const T &a, const T &b) noexcept
Definition: Utility.h:90
void FindExtremeItems(FI &kmin, FI &kmax, FI i, FI j) noexcept
Definition: Utility.h:517
constexpr const T & Range(const T &x, const T &a, const T &b) noexcept
Definition: Utility.h:190
constexpr const T & Max(const T &a, const T &b) noexcept
Definition: Utility.h:119
PCL root namespace.
Definition: AbstractImage.h:77