27#ifndef improc_imageUtils_hpp
28#define improc_imageUtils_hpp
44template <
typename realT =
double>
47 return 0.5 * ( 1.0 * rows_cols - 1 );
54template <
typename realT =
double,
typename imT>
57 return imCen<realT>( im.rows() );
64template <
typename realT =
double,
typename imT>
67 return imCen<realT>( im.cols() );
75constexpr T invalidNumber()
85 return ( ( ( ( *(uint32_t *)&value ) & 0x7fffffff ) > 0x7f800000 ) || ( value == invalidNumber<float>() ) ||
86 !std::isfinite( value ) );
92template <
typename realT>
101 x1 = xc - ( x0 - xc );
102 y1 = yc - ( y0 - yc );
115template <
class imageT,
typename valueT>
120 for(
int c = 0; c < im.cols(); ++c )
122 for(
int r = 0; r < im.rows(); ++r )
124 if(
IsNan( im( r, c ) ) )
136template <
class imageT>
139 typename imageT::Scalar zero = 0;
140 zeroNaNs<imageT, typename imageT::Scalar>( im, zero );
148template <
class cubeT,
class maskCubeT>
155 mask->resize( imc.rows(), imc.cols(), imc.planes() );
159 for(
int p = 0; p < imc.planes(); ++p )
161 for(
int c = 0; c < imc.cols(); ++c )
163 for(
int r = 0; r < imc.rows(); ++r )
165 if(
IsNan( imc.image( p )( r, c ) ) )
167 imc.image( p )( r, c ) = 0;
170 ( *mask ).image( p )( r, c ) = 1;
182template <
class cubeT>
185 return zeroNaNCube<cubeT, cubeT>( imc,
nullptr );
195template <
class calcT,
class imageT>
198 return static_cast<calcT
>( im.sum() ) / ( im.rows() * im.cols() );
207template <
class calcT,
class imageT,
class maskT>
211 return static_cast<calcT
>( ( im * mask ).sum() ) / ( mask.sum() );
221template <
typename calcT,
class imageT>
226 return ( im.template cast<calcT>() - mn ).square().sum() / ( im.rows() * im.cols() );
236template <
typename calcT,
class imageT,
class maskT>
242 return ( im.template cast<calcT>() * mask - mn ).square().sum() / ( mask.sum() );
257template <
typename imageT,
typename maskT = imageT>
258typename imageT::Scalar
261 std::vector<typename imageT::Scalar> *work = 0
266 typename imageT::Scalar med;
268 bool localWork =
false;
271 work =
new std::vector<typename imageT::Scalar>;
287 for(
int i = 0; i < mat.rows(); ++i )
289 for(
int j = 0; j < mat.cols(); ++j )
291 if( ( *mask )( i, j ) == 0 )
295 ( *work )[ii] = mat( i, j );
303 for(
int i = 0; i < mat.rows(); ++i )
305 for(
int j = 0; j < mat.cols(); ++j )
307 ( *work )[ii] = mat( i, j );
334template <
typename imageT>
336 std::vector<typename imageT::Scalar> *work = 0
340 return imageMedian( mat,
static_cast<Eigen::Array<typename imageT::Scalar, -1, -1
> *>(
nullptr), work );
348template <
typename imageT>
350 typename imageT::Scalar &y,
357 typename imageT::Scalar sum = im.sum();
361 x = 0.5 * ( im.rows() - 1.0 );
362 y = 0.5 * ( im.cols() - 1.0 );
366 for(
int j = 0; j < im.cols(); ++j )
368 for(
int i = 0; i < im.rows(); ++i )
370 x += ( i + 1 ) * im( i, j );
371 y += ( j + 1 ) * im( i, j );
388template <
typename floatT,
typename imageT,
typename magImageT,
typename transformT>
400 floatT magSize_x = ceil( ( im.rows() - 1.0 ) / scale_x ) + 1;
401 floatT magSize_y = ceil( ( im.cols() - 1.0 ) / scale_y ) + 1;
403 floatT mag_x = ( (floatT)magSize_x - 1.0 ) / ( (floatT)im.rows() - 1.0 );
404 floatT mag_y = ( (floatT)magSize_y - 1.0 ) / ( (floatT)im.cols() - 1.0 );
406 scale_x = 1.0 / mag_x;
407 scale_y = 1.0 / mag_y;
409 magIm.resize( magSize_x, magSize_y );
414 magIm.maxCoeff( &ix, &iy );
428template <
typename floatT,
typename imageT,
typename magImageT>
457template <
typename imageT,
typename imageT1,
typename imageT2,
typename imageT3,
typename imageT4>
460 const imageT2 &mask1,
465 combo.resize( im1.rows(), im2.cols() );
467 for(
int c = 0; c < combo.cols(); ++c )
469 for(
int r = 0; r < combo.rows(); ++r )
471 if( mask1( r, c ) == 1 && mask2( r, c ) == 0 )
472 combo( r, c ) = im1( r, c );
473 else if( mask2( r, c ) == 1 & mask1( r, c ) == 0 )
474 combo( r, c ) = im2( r, c );
475 else if( mask1( r, c ) == 1 && mask2( r, c ) == 1 )
476 combo( r, c ) = 0.5 * ( im1( r, c ) + im2( r, c ) );
487template <
typename eigenT,
typename eigenTin>
490 out.resize( in.rows() - w, in.cols() - w );
492 out.topLeftCorner( st, st ) = in.topLeftCorner( st, st );
494 out.bottomLeftCorner( in.rows() - ( st + w ), st ) = in.bottomLeftCorner( in.rows() - ( st + w ), st );
496 out.topRightCorner( st, in.cols() - ( st + w ) ) = in.topRightCorner( st, in.cols() - ( st + w ) );
498 out.bottomRightCorner( in.rows() - ( st + w ), in.cols() - ( st + w ) ) =
499 in.bottomRightCorner( in.rows() - ( st + w ), in.cols() - ( st + w ) );
506template <
typename eigenT,
typename eigenTin>
507void removeRows( eigenT &out,
const eigenTin &in,
int st,
int w )
509 out.resize( in.rows() - w, in.cols() );
511 out.topLeftCorner( st, in.cols() ) = in.topLeftCorner( st, in.cols() );
513 out.bottomLeftCorner( in.rows() - ( st + w ), in.cols() ) =
514 in.bottomLeftCorner( in.rows() - ( st + w ), in.cols() );
521template <
typename eigenT,
typename eigenTin>
522void removeCols( eigenT &out,
const eigenTin &in,
int st,
int w )
524 out.resize( in.rows(), in.cols() - w );
526 out.topLeftCorner( in.rows(), st ) = in.topLeftCorner( in.rows(), st );
528 out.topRightCorner( in.rows(), in.cols() - ( st + w ) ) = in.topRightCorner( in.rows(), in.cols() - ( st + w ) );
541void *
imcpy(
void *dest,
void removeCols(eigenT &out, const eigenTin &in, int st, int w)
Remove columns.
void removeRows(eigenT &out, const eigenTin &in, int st, int w)
Remove rows.
void removeRowsAndCols(eigenT &out, const eigenTin &in, int st, int w)
Remove rows and columns.
int imageMaxInterp(floatT &x, floatT &y, floatT &scale_x, floatT &scale_y, magImageT &magIm, const imageT &im, transformT trans)
Find the maximum in an image at sub-pixel resolution by interpolation.
imageT::Scalar imageMedian(const imageT &mat, const maskT *mask, std::vector< typename imageT::Scalar > *work=0)
Calculate the median of an Eigen-like array.
calcT imageVariance(imageT &im, calcT mn)
Calculate the variance of an image given its mean.
int imageCenterOfLight(typename imageT::Scalar &x, typename imageT::Scalar &y, const imageT &im)
Calculate the center of light of an image.
void combine2ImagesMasked(imageT &combo, const imageT1 &im1, const imageT2 &mask1, const imageT3 &im2, const imageT4 &mask2)
Combine two images, each with their own mask defining good pixels.
calcT imageMean(imageT &im)
Calculate the mean value of an image.
void zeroNaNs(imageT &im, valueT val)
Zero any NaNs in an image.
void zeroNaNCube(cubeT &imc, maskCubeT *mask)
Zero any NaNs in an image cube.
void * imcpy(void *dest, void *src, size_t width, size_t height, size_t szof)
Copy one image to another, with no transformation.
bool IsNan(float value)
Check if the number is nan, using several different methods.
void * imcpy_flipLR(void *dest, void *src, size_t width, size_t height, size_t szof)
Copy one image to another, flipping left-right.
void * imcpy_flipUDLR(void *dest, void *src, size_t width, size_t height, size_t szof)
Copy one image to another, flipping up-down and left-right.
void * imcpy_flipUD(void *dest, void *src, size_t width, size_t height, size_t szof)
Copy one image to another, flipping up-down.
int reflectImageCoords(int &x1, int &y1, int x0, int y0, realT xc, realT yc)
Reflect pixel coordinates across the given center pixel.
vectorT::value_type vectorMedianInPlace(vectorT &vec)
Calculate median of a vector in-place, altering the vector.
realT imCen(int rows_cols)
Get the mxlib standard center coordinate of an image.
realT imCenX(const imT &im)
Get the mxlib standard center x-coordinate of an image.
realT imCenY(const imT &im)
Get the mxlib standard center y-coordinate of an image.