15#pragma GCC system_header
31template <
typename dataT>
35 typedef bool is_eigenCube;
38 typedef typename Eigen::Array<dataT, Eigen::Dynamic, Eigen::Dynamic>::Index Index;
40 typedef Eigen::Map<Eigen::Array<dataT, Eigen::Dynamic, Eigen::Dynamic>> imageRef;
42 typedef Eigen::Array<dataT, Eigen::Dynamic, Eigen::Dynamic> imageT;
49 dataT *m_data{
nullptr };
54 template <
typename eigenCubeT>
102 eigenCube<dataT> &
operator=(
const eigenCube<dataT> &ec );
105 eigenCube<dataT> &
operator=( eigenCube<dataT> &&ec )
noexcept;
107 void shallowCopy( eigenCube<dataT> &src,
bool takeOwner =
false );
112 void resize(
int r,
int c,
int p );
114 void resize(
int r,
int c );
118 const dataT *data()
const;
120 const Index rows()
const;
122 const Index cols()
const;
124 const Index planes()
const;
127 Eigen::Map<Eigen::Array<dataT, Eigen::Dynamic, Eigen::Dynamic>>
cube();
130 Eigen::Map<Eigen::Array<dataT, Eigen::Dynamic, Eigen::Dynamic>>
image( Index n );
133 const Eigen::Map<Eigen::Array<dataT, Eigen::Dynamic, Eigen::Dynamic>>
137 Eigen::Map<Eigen::Array<dataT, Eigen::Dynamic, Eigen::Dynamic>,
139 Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>>
143 Eigen::Map<Eigen::Array<dataT, Eigen::Dynamic, Eigen::Dynamic>>
asVectors();
146 void Covar( Eigen::Matrix<dataT, Eigen::Dynamic, Eigen::Dynamic> &cv );
152 template <
typename eigenT>
159 template <
typename eigenT>
173 template <
typename eigenT,
typename eigenCubeT>
177 double minGoodFract = 0.0
186 template <
typename eigenT>
188 std::vector<dataT> &weights
202 template <
typename eigenT,
typename eigenCubeT>
204 std::vector<dataT> &weights,
206 double minGoodFract = 0.0
213 template <
typename eigenT>
227 template <
typename eigenT,
typename eigenCubeT>
230 double minGoodFract = 0.0
237 template <
typename eigenT>
253 template <
typename eigenT,
typename eigenCubeT>
258 double minGoodFract = 0.0
267 template <
typename eigenT>
269 std::vector<dataT> &weights,
284 template <
typename eigenT,
typename eigenCubeT>
287 std::vector<dataT> &weights,
290 double minGoodFract = 0.0
294template <
typename dataT>
295template <
typename eigenCubeT>
298 if( mask.rows() != _rows || mask.cols() != _cols || mask.planes() != _planes )
303 if( !
math::isFinite( minGoodFract ) || minGoodFract < 0.0 || minGoodFract > 1.0 )
309template <
typename dataT>
312 if( weights.size() !=
static_cast<size_t>( _planes ) )
318template <
typename dataT>
321 return goodPixels > 0 &&
static_cast<double>( goodPixels ) >= minGoodFract *
static_cast<double>( _planes );
324template <
typename dataT>
325eigenCube<dataT>::eigenCube()
333template <
typename dataT>
334eigenCube<dataT>::eigenCube( Index nrows, Index ncols, Index nplanes )
340 m_data =
new dataT[_rows * _cols * _planes];
344template <
typename dataT>
345eigenCube<dataT>::eigenCube( dataT *ndata,
size_t nrows,
size_t ncols,
size_t nplanes )
355template <
typename dataT>
356eigenCube<dataT>::eigenCube(
const eigenCube<dataT> &ec ) : eigenCube()
361template <
typename dataT>
362eigenCube<dataT>::eigenCube( eigenCube<dataT> &&ec ) noexcept
363 : _rows( ec._rows ), _cols( ec._cols ), _planes( ec._planes ), m_data( ec.m_data ), _owner( ec._owner )
372template <
typename dataT>
373eigenCube<dataT>::~eigenCube()
375 if( _owner && m_data )
381template <
typename dataT>
382void eigenCube<dataT>::setZero()
384 int N = _rows * _cols * _planes;
386 for(
int i = 0; i < N; ++i )
387 m_data[i] = ( (dataT)0 );
390template <
typename dataT>
398 resize( ec.rows(), ec.cols(), ec.planes() );
400 int N = _rows * _cols * _planes;
402 for(
int i = 0; i < N; ++i )
403 m_data[i] = ec.m_data[i];
408template <
typename dataT>
420 _planes = ec._planes;
433template <
typename dataT>
445 _planes = src._planes;
448 if( takeOwner ==
true )
454 src.m_data =
nullptr;
463template <
typename dataT>
466 if( _owner && m_data )
478template <
typename dataT>
479void eigenCube<dataT>::resize(
int r,
int c,
int p )
487 m_data =
new dataT[_rows * _cols * _planes];
491template <
typename dataT>
492void eigenCube<dataT>::resize(
int r,
int c )
497template <
typename dataT>
498dataT *eigenCube<dataT>::data()
503template <
typename dataT>
504const dataT *eigenCube<dataT>::data()
const
509template <
typename dataT>
510const typename eigenCube<dataT>::Index eigenCube<dataT>::rows()
const
515template <
typename dataT>
516const typename eigenCube<dataT>::Index eigenCube<dataT>::cols()
const
521template <
typename dataT>
522const typename eigenCube<dataT>::Index eigenCube<dataT>::planes()
const
527template <
typename dataT>
530 return Eigen::Map<Eigen::Array<dataT, Eigen::Dynamic, Eigen::Dynamic>>( m_data, _rows * _cols, _planes );
533template <
typename dataT>
536 return Eigen::Map<Eigen::Array<dataT, Eigen::Dynamic, Eigen::Dynamic>>( m_data + n * _rows * _cols, _rows, _cols );
539template <
typename dataT>
542 return Eigen::Map<Eigen::Array<dataT, Eigen::Dynamic, Eigen::Dynamic>>( m_data + n * _rows * _cols, _rows, _cols );
545template <
typename dataT>
546Eigen::Map<Eigen::Array<dataT, Eigen::Dynamic, Eigen::Dynamic>,
548 Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>>
551 return Eigen::Map<Eigen::Array<dataT, Eigen::Dynamic, Eigen::Dynamic>,
553 Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>>(
554 m_data + j * _rows + i,
557 Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>( 0, _rows * _cols ) );
560template <
typename dataT>
563 return Eigen::Map<Eigen::Array<dataT, Eigen::Dynamic, Eigen::Dynamic>>( m_data, _rows * _cols, _planes );
566template <
typename dataT>
572template <
typename dataT>
573template <
typename eigenT>
576 mim.resize( _rows, _cols );
578#pragma omp parallel for schedule( static, 1 ) num_threads( Eigen::nbThreads() )
579 for( Index i = 0; i < _rows; ++i )
581 for( Index j = 0; j < _cols; ++j )
583 mim( i, j ) =
pixel( i, j ).sum();
588template <
typename dataT>
589template <
typename eigenT>
592 mim.resize( _rows, _cols );
594#pragma omp parallel for schedule( static, 1 ) num_threads( Eigen::nbThreads() )
595 for( Index i = 0; i < _rows; ++i )
597 for( Index j = 0; j < _cols; ++j )
599 mim( i, j ) =
pixel( i, j ).mean();
604template <
typename dataT>
605template <
typename eigenT,
typename eigenCubeT>
610 mim.resize( _rows, _cols );
614 std::vector<dataT> work;
617 for( Index i = 0; i < _rows; ++i )
619 for( Index j = 0; j < _cols; ++j )
624 for( Index k = 0; k < _planes; ++k )
626 if( ( mask.pixel( i, j ) )( k, 0 ) == 1 )
628 work.push_back( (
pixel( i, j ) )( k, 0 ) );
645template <
typename dataT>
646template <
typename eigenT>
651 mim.resize( _rows, _cols );
653#pragma omp parallel num_threads( Eigen::nbThreads() )
655 std::vector<Scalar> work;
657#pragma omp for schedule( static, 10 )
658 for( Index i = 0; i < _rows; ++i )
660 for( Index j = 0; j < _cols; ++j )
662 work.resize( _planes );
664 for(
int k = 0; k < _planes; ++k )
665 work[k] = (
pixel( i, j ) )( k, 0 );
673template <
typename dataT>
674template <
typename eigenT,
typename eigenCubeT>
680 mim.resize( _rows, _cols );
682#pragma omp parallel num_threads( Eigen::nbThreads() )
684 std::vector<Scalar> work, wwork;
686#pragma omp for schedule( static, 10 )
687 for( Index i = 0; i < _rows; ++i )
689 for( Index j = 0; j < _cols; ++j )
696 for( Index k = 0; k < _planes; ++k )
698 if( ( mask.pixel( i, j ) )( k, 0 ) == 1 )
700 work.push_back( (
pixel( i, j ) )( k, 0 ) );
701 wwork.push_back( weights[k] );
715template <
typename dataT>
716template <
typename eigenT>
719 mim.resize( _rows, _cols );
721#pragma omp parallel for schedule( static, 10 ) num_threads( Eigen::nbThreads() )
722 for( Index i = 0; i < _rows; ++i )
725 std::vector<Scalar> work;
726 for( Index j = 0; j < _cols; ++j )
733template <
typename dataT>
734template <
typename eigenT,
typename eigenCubeT>
739 mim.resize( _rows, _cols );
743 std::vector<Scalar> work;
746 for( Index i = 0; i < _rows; ++i )
748 for( Index j = 0; j < _cols; ++j )
752 for( Index k = 0; k < _planes; ++k )
754 if( ( mask.pixel( i, j ) )( k, 0 ) == 1 )
756 work.push_back( (
pixel( i, j ) )( k, 0 ) );
773template <
typename dataT>
774template <
typename eigenT>
777 mim.resize( _rows, _cols );
782 std::vector<Scalar> work;
786 for( Index i = 0; i < _rows; ++i )
788 for( Index j = 0; j < _cols; ++j )
790 work.resize( _planes );
791 for(
int k = 0; k < _planes; ++k )
793 work[k] = (
pixel( i, j ) )( k, 0 );
802template <
typename dataT>
803template <
typename eigenT,
typename eigenCubeT>
808 mim.resize( _rows, _cols );
812 std::vector<Scalar> work;
815 for( Index i = 0; i < _rows; ++i )
817 for( Index j = 0; j < _cols; ++j )
820 for( Index k = 0; k < _planes; ++k )
822 if( ( mask.pixel( i, j ) )( k, 0 ) == 1 )
824 work.push_back( (
pixel( i, j ) )( k, 0 ) );
841template <
typename dataT>
842template <
typename eigenT>
847 mim.resize( _rows, _cols );
849#pragma omp parallel num_threads( Eigen::nbThreads() )
851 std::vector<Scalar> work;
853#pragma omp for schedule( static, 10 )
854 for( Index i = 0; i < _rows; ++i )
856 for( Index j = 0; j < _cols; ++j )
858 work.resize( _planes );
859 for(
int k = 0; k < _planes; ++k )
860 work[k] = (
pixel( i, j ) )( k, 0 );
868template <
typename dataT>
869template <
typename eigenT,
typename eigenCubeT>
871 eigenT &mim, std::vector<dataT> &weights, eigenCubeT &mask, dataT sigma,
double minGoodFract )
876 mim.resize( _rows, _cols );
878#pragma omp parallel num_threads( Eigen::nbThreads() )
880 std::vector<Scalar> work, wwork;
882#pragma omp for schedule( static, 10 )
883 for( Index i = 0; i < _rows; ++i )
885 for( Index j = 0; j < _cols; ++j )
890 for( Index k = 0; k < _planes; ++k )
892 if( ( mask.pixel( i, j ) )( k, 0 ) == 1 )
894 work.push_back( (
pixel( i, j ) )( k, 0 ) );
895 wwork.push_back( weights[k] );
An image cube with an Eigen-like API.
void sigmaMean(eigenT &mim, std::vector< dataT > &weights, eigenCubeT &mask, Scalar sigma, double minGoodFract=0.0)
Calculate the sigma clipped weighted mean image of the cube, with a mask cube.
void Covar(Eigen::Matrix< dataT, Eigen::Dynamic, Eigen::Dynamic > &cv)
Calculate the covariance matrix of the images in the cube.
void sigmaMean(eigenT &mim, Scalar sigma)
Calculate the sigma clipped mean image of the cube.
void mean(eigenT &mim, std::vector< dataT > &weights, eigenCubeT &mask, double minGoodFract=0.0)
Calculate the weighted mean image of the cube, with a mask cube.
void validateMaskedCombination(const eigenCubeT &mask, double minGoodFract) const
Validate a mask and good-pixel threshold for a masked combination.
void clear()
De-allocate and set all sizes to 0.
const Eigen::Map< Eigen::Array< dataT, Eigen::Dynamic, Eigen::Dynamic > > image(Index n) const
Returns a 2D Eigen::Eigen::Map pointed at the specified image.
void sum(eigenT &mim)
Calculate the sum image of the cube.
void sigmaMean(eigenT &mim, std::vector< dataT > &weights, Scalar sigma)
Calculate the sigma clipped weighted mean image of the cube.
Eigen::Map< Eigen::Array< dataT, Eigen::Dynamic, Eigen::Dynamic >, Eigen::Unaligned, Eigen::Stride< Eigen::Dynamic, Eigen::Dynamic > > pixel(Index i, Index j)
Returns an Eigen::Eigen::Map-ed vector of the pixels at the given coordinate.
eigenCube< dataT > & operator=(const eigenCube< dataT > &ec)
Copy a cube into independently owned storage.
void median(eigenT &mim)
Calculate the median image of the cube.
void mean(eigenT &mim, std::vector< dataT > &weights)
Calculate the weighted mean image of the cube.
Eigen::Map< Eigen::Array< dataT, Eigen::Dynamic, Eigen::Dynamic > > cube()
Returns a 2D Eigen::Eigen::Map pointed at the entire cube.
eigenCube(eigenCube< dataT > &&ec) noexcept
Move a cube, transferring any owned storage.
void median(eigenT &mim, eigenCubeT &mask, double minGoodFract=0.0)
Calculate the median image of the cube with a mask.
void validateWeights(const std::vector< dataT > &weights) const
Validate the number of weights for a weighted combination.
eigenCube< dataT > & operator=(eigenCube< dataT > &&ec) noexcept
Move a cube, transferring any owned storage.
void mean(eigenT &mim, eigenCubeT &mask, double minGoodFract=0.0)
Calculate the mean image of the cube with a mask.
bool hasEnoughGoodPixels(size_t goodPixels, double minGoodFract) const
Test whether a nonempty set of good pixels meets the requested fraction.
void mean(eigenT &mim)
Calculate the mean image of the cube.
eigenCube(dataT *ndata, size_t nrows, size_t ncols, size_t nplanes)
C'tor taking an existing array as an argument.
void sigmaMean(eigenT &mim, eigenCubeT &mask, Scalar sigma, double minGoodFract=0.0)
Calculate the sigma clipped mean image of the cube, with a mask cube.
eigenCube(const eigenCube< dataT > &ec)
Copy a cube into independently owned storage.
eigenCube(Index nrows, Index ncols, Index nplanes)
C'tor which will allocate space..
Eigen::Map< Eigen::Array< dataT, Eigen::Dynamic, Eigen::Dynamic > > asVectors()
Return an Eigen::Eigen::Map of the cube where each image is a vector.
Eigen::Map< Eigen::Array< dataT, Eigen::Dynamic, Eigen::Dynamic > > image(Index n)
Returns a 2D Eigen::Eigen::Map pointed at the specified image.
Tools for using the eigen library for image processing.
The mxlib exception class.
imageT::Scalar imageMedian(const imageT &mat, const maskT *mask, std::vector< typename imageT::Scalar > *work=0)
Calculate the median of an Eigen-like array.
@ sizeerr
A size was invalid or calculated incorrectly.
@ exception
An exception was thrown.
@ invalidarg
An argument was invalid.
bool isFinite(realT value)
Test whether a floating-point value is finite, including under finite-math-only optimization.
constexpr realT invalidNumber()
Return the configured invalid image-pixel value.
vectorT::value_type vectorMedianInPlace(vectorT &vec)
Calculate median of a vector in-place, altering the vector.
vectorT::value_type vectorSigmaMean(const vectorT &vec, const vectorT *weights, const sigmaT &sigma, int &maxPasses)
Calculate the sigma-clipped mean of a vector.
valueT vectorMean(const valueT *vec, size_t sz)
Calculate the mean of a vector.
Header for the image processing utilities.
Header for the std::vector utilities.