mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
eigenImage.hpp
Go to the documentation of this file.
1 /** \file eigenImage.hpp
2  * \brief Tools for using the eigen library for image processing
3  * \ingroup image_processing_files
4  * \author Jared R. Males (jaredmales@gmail.com)
5  *
6  */
7 
8 //***********************************************************************//
9 // Copyright 2015, 2016, 2017 Jared R. Males (jaredmales@gmail.com)
10 //
11 // This file is part of mxlib.
12 //
13 // mxlib is free software: you can redistribute it and/or modify
14 // it under the terms of the GNU General Public License as published by
15 // the Free Software Foundation, either version 3 of the License, or
16 // (at your option) any later version.
17 //
18 // mxlib is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 // GNU General Public License for more details.
22 //
23 // You should have received a copy of the GNU General Public License
24 // along with mxlib. If not, see <http://www.gnu.org/licenses/>.
25 //***********************************************************************//
26 
27 #ifndef improc_eigenImage_hpp
28 #define improc_eigenImage_hpp
29 
30 #pragma GCC system_header
31 #include <Eigen/Dense>
32 
33 #include "../math/vectorUtils.hpp"
34 
35 namespace mx
36 {
37 namespace improc
38 {
39 
40 ///Definition of the eigenImage type, which is an alias for Eigen::Array.
41 /** \ingroup eigen_image_processing
42  */
43 template<typename scalarT>
44 using eigenImage = Eigen::Array<scalarT, -1, -1>;
45 
46 ///Definition of the eigenMap type, which is an alias for Eigen::Map<Array>.
47 /** \ingroup eigen_image_processing
48  */
49 template<typename scalarT>
50 using eigenMap = Eigen::Map<Eigen::Array<scalarT, -1, -1>>;
51 
52 ///Test whether a type is an eigenCube by testing whether it has a typedef of "is_eigenCube"
53 /** Used for compile-time determination of type
54  * Example usage:
55  * \code
56  * bool is_eC = is_eigenCube<eigenCube<float> >; //Evaluates to true
57  * bool is_not_eC = is_eigenCube<eigenImagef>; //Evaluates to false
58  * \endcode
59  *
60  * This was taken directly from the example at http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error
61  *
62  * \ingroup eigen_image_processing
63  */
64 template <typename T>
65 struct is_eigenCube
66 {
67  // Types "yes" and "no" are guaranteed to have different sizes,
68  // specifically sizeof(yes) == 1 and sizeof(no) == 2.
69  typedef char yes[1];
70  typedef char no[2];
71 
72  template <typename imageT>
73  static yes& test(typename imageT::is_eigenCube*);
74 
75  template <typename>
76  static no& test(...);
77 
78  // If the "sizeof" of the result of calling test<T>(0) would be equal to sizeof(yes),
79  // the first overload worked and T has a nested type named "is_eigenCube".
80  static const bool value = sizeof(test<T>(0)) == sizeof(yes);
81 };
82 
83 
84 ///Function object to return the number of planes for any Eigen like object, whether 2D or a 3D cube.
85 /** Uses SFINAE to check for 3D eigenCube.
86  *
87  * \ingroup eigen_image_processing
88  */
89 template<typename arrT, bool isCube=is_eigenCube<arrT>::value>
91 {
92  //If it's an eigenCube, call planes planes()
93  int operator()(const arrT & arr)
94  {
95  return arr.planes();
96  }
97 };
98 
99 template<typename arrT>
100 struct eigenArrPlanes<arrT, false>
101 {
102  //If it's not an eigenCube, never call planes()
103  int operator()(const arrT & arr)
104  {
105  return 1;
106  }
107 };
108 
109 /// Calculate the median of an Eigen-like array.
110 /** Calculates the median of the entire array, allowing for some pixels to be ignored using a mask.
111  * Working memory can be retained between calls.
112  *
113  * \tparam imageT is an Eigen-like type
114  * \tparam maskT is an Eigen-like type
115  *
116  * \returns the median of the unmasked pixels of mat, using \ref vectorMedianInPlace().
117  *
118  * \ingroup eigen_image_processing
119  *
120  */
121 template<typename imageT, typename maskT=imageT>
122 typename imageT::Scalar imageMedian( const imageT & mat, ///< [in] the image to take the median of
123  const maskT * mask, ///< [in] if non-0, a 1/0 mask where 0 pixels are ignored.
124  std::vector<typename imageT::Scalar> * work =0 ///< [in] [optional] working memory can be retained and re-passed. Is resized.
125  )
126 {
127  typename imageT::Scalar med;
128 
129  bool localWork = false;
130  if(work == 0)
131  {
132  work = new std::vector<typename imageT::Scalar>;
133  localWork = true;
134  }
135 
136  int sz = mat.size();
137 
138  if(mask)
139  {
140  sz = mask->sum();
141  }
142 
143  work->resize(sz);
144 
145  int ii = 0;
146  for(int i=0;i<mat.rows();++i)
147  {
148  for(int j=0; j<mat.cols();++j)
149  {
150  if(mask)
151  {
152  if( (*mask)(i,j) == 0) continue;
153  }
154 
155  (*work)[ii] = mat(i,j);
156  ++ii;
157  }
158  }
159 
160 
161  med = math::vectorMedianInPlace(*work);
162 
163  if(localWork) delete work;
164 
165  return med;
166 }
167 
168 /// Calculate the median of an Eigen-like array.
169 /** Calculates the median of the entire array.
170  * Working memory can be retained between calls.
171  *
172  * \tparam imageT is an Eigen-like type
173  *
174  * \returns the median of the unmasked pixels of mat, using \ref vectorMedianInPlace().
175  *
176  * \ingroup eigen_image_processing
177  *
178  */
179 template<typename imageT>
180 typename imageT::Scalar imageMedian( const imageT & mat, ///< [in] the image to take the median of
181  std::vector<typename imageT::Scalar> * work =0 ///< [in] [optional] working memory can be retained and re-passed.
182  )
183 {
184  return imageMedian( mat, (Eigen::Array<typename imageT::Scalar,-1,-1> *) 0, work);
185 }
186 
187 
188 } //namespace improc
189 } //namespace mx
190 
191 #endif //improc_eigenImage_hpp
192 
Eigen::Array< scalarT, -1, -1 > eigenImage
Definition of the eigenImage type, which is an alias for Eigen::Array.
Definition: eigenImage.hpp:44
Eigen::Map< Eigen::Array< scalarT, -1, -1 > > eigenMap
Definition of the eigenMap type, which is an alias for Eigen::Map<Array>.
Definition: eigenImage.hpp:50
imageT::Scalar imageMedian(const imageT &mat, std::vector< typename imageT::Scalar > *work=0)
Calculate the median of an Eigen-like array.
Definition: eigenImage.hpp:180
vectorT::value_type vectorMedianInPlace(vectorT &vec)
Calculate median of a vector in-place, altering the vector.
The mxlib c++ namespace.
Definition: mxError.hpp:107
Function object to return the number of planes for any Eigen like object, whether 2D or a 3D cube.
Definition: eigenImage.hpp:91
Test whether a type is an eigenCube by testing whether it has a typedef of "is_eigenCube".
Definition: eigenImage.hpp:66