27#ifndef imagingUtils_hpp
28#define imagingUtils_hpp
32#include "../mxlib.hpp"
33#include "../improc/eigenImage.hpp"
34#include "../math/constants.hpp"
53template <
typename realT>
59 return ( lambda / metersPerPixel ) * ( 1. / pixels );
71template <
class arrayT>
73 typename arrayT::Scalar eps = 0,
74 typename arrayT::Scalar rad = 0,
76 typename arrayT::Scalar overscan = 0
96 typename arrayT::Scalar r;
97 typename arrayT::Scalar xc = 0.5 * ( l0 - 1 );
98 typename arrayT::Scalar yc = 0.5 * ( l1 - 1 );
101 rad = 0.5 * std::min( l0 - 1, l1 - 1 );
103 for(
size_t i = 0; i < l0; i++ )
105 for(
size_t j = 0; j < l1; j++ )
107 r = std::sqrt( std::pow( i - xc, 2 ) + std::pow( j - yc, 2 ) );
109 if( r <= rad + ( overscan ) && r >= eps * rad )
124template <
class arrayT>
125void drawLine( arrayT &im,
126 typename arrayT::Scalar x0,
127 typename arrayT::Scalar y0,
128 typename arrayT::Scalar x1,
129 typename arrayT::Scalar y1,
130 typename arrayT::Scalar halfWidth
137 typename arrayT::Scalar xc, yc;
139 xc = 0.5 * ( im.rows() - 1 );
140 yc = 0.5 * ( im.cols() - 1 );
142 typename arrayT::Scalar m = ( y1 - y0 ) / ( x1 - x0 );
147 for(
int x = x0; x <= x1; ++x )
149 y = y0 + ( x - x0 ) * m;
151 for(
int i = 0; i <= halfWidth; ++i )
153 if( x + xc >= 0 && x + xc < d1 && y + yc + i >= 0 && y + yc + i < d2 )
154 im( x + xc, y + yc + i ) = 0;
155 if( x + xc >= 0 && x + xc < d1 && y + yc - i >= 0 && y + yc - i < d2 )
156 im( x + xc, y + yc - i ) = 0;
162 for(
int x = x1; x <= x0; ++x )
164 y = y0 + ( x - x0 ) * m;
166 for(
int i = 0; i <= halfWidth; ++i )
168 if( x + xc >= 0 && x + xc < d1 && y + yc + i >= 0 && y + yc + i < d2 )
169 im( x + xc, y + yc + i ) = 0;
170 if( x + xc >= 0 && x + xc < d1 && y + yc - i >= 0 && y + yc - i < d2 )
171 im( x + xc, y + yc - i ) = 0;
186template <
typename arrayOutT,
typename arrayInT>
187void makeComplexPupil( arrayOutT &complexPupil,
const arrayInT &realPupil,
int wavefrontSizePixels )
190 complexPupil.resize( wavefrontSizePixels, wavefrontSizePixels );
191 complexPupil.setZero();
194 int bl = 0.5 * ( complexPupil.rows() - 1 ) - 0.5 * ( realPupil.rows() - 1. );
196 for(
int i = 0; i < realPupil.cols(); ++i )
198 for(
int j = 0; j < realPupil.rows(); ++j )
200 complexPupil( bl + i, bl + j ) =
201 typename arrayOutT::Scalar( realPupil( i, j ), 0 );
217template <
typename arrayOutT,
typename arrayInT>
219 const arrayInT &realAmplitude,
220 const arrayInT &realPhase,
221 int wavefrontSizePixels )
224 complexWavefront.resize( wavefrontSizePixels, wavefrontSizePixels );
225 complexWavefront.setConstant(
typename arrayOutT::Scalar( 0, 0 ) );
228 int bl = 0.5 * ( complexWavefront.rows() - 1 ) - 0.5 * ( realAmplitude.rows() - 1. );
230 for(
int i = 0; i < realAmplitude.cols(); ++i )
232 for(
int j = 0; j < realAmplitude.rows(); ++j )
234 complexWavefront( bl + j, bl + i ) =
235 realAmplitude( j, i ) * exp( (
typename arrayOutT::Scalar( 0, 1 ) ) * realPhase( j, i ) );
248template <
typename wavefrontT>
250 typename wavefrontT::Scalar::value_type xTilt,
251 typename wavefrontT::Scalar::value_type yTilt )
253 typedef typename wavefrontT::Scalar complexT;
254 typedef typename wavefrontT::Scalar::value_type realT;
258 int wfsSizeX = complexWavefront.cols();
259 int wfsSizeY = complexWavefront.rows();
261 realT xCen = 0.5 * ( wfsSizeX - 1 );
262 realT yCen = 0.5 * ( wfsSizeY - 1 );
264 realT argX = 2.0 * pi / ( wfsSizeX - 1.0 );
265 realT argY = 2.0 * pi / ( wfsSizeY - 1.0 );
267 for(
int ii = 0; ii < wfsSizeX; ++ii )
269 for(
int jj = 0; jj < wfsSizeY; ++jj )
271 complexWavefront( ii, jj ) =
272 complexWavefront( ii, jj ) *
273 exp( complexT( (realT)0., argX * xTilt * ( ii - xCen ) + argY * yTilt * ( jj - yCen ) ) );
279template <
typename imageT1,
290 int dest_cols = dest.cols();
292 int src_cols = src.cols();
294 typedef typename imageT1::Scalar dataT;
299 for(
int j = 0; j < imYsz; ++j )
301 dest_data = &dest.data()[imX0 + ( imY0 + j ) * dest_cols];
302 src_data = &src.data()[wfX0 + ( wfY0 + j ) * src_cols];
304 memcpy( dest_data, src_data,
sizeof( dataT ) * imXsz );
312template <
typename imageT1,
322 if( dest.rows() != src.rows() )
327 if( dest.cols() != src.cols() )
332 if( src.rows() != mask.rows() )
337 if( src.cols() != mask.cols() )
342 for(
int cc = 0; cc < dest.cols(); ++cc )
344 for(
int rr = 0; rr < dest.rows(); ++rr )
346 if( mask( rr, cc ) != 0 )
348 dest( rr, cc ) = src( rr, cc );
354template <
typename realImageT,
typename complexImageT>
355void extractIntensityImage(
356 realImageT &im,
int imX0,
int imXsz,
int imY0,
int imYsz, complexImageT &wf,
int wfX0,
int wfY0 )
358 int im_rows = im.cols();
360 int wf_rows = wf.cols();
362 typename realImageT::Scalar *im_data;
363 typename complexImageT::Scalar *wf_data;
365 for(
int j = 0; j < imXsz; ++j )
367 im_data = &im.data()[imX0 + ( imY0 + j ) * im_rows];
368 wf_data = &wf.data()[wfX0 + ( wfY0 + j ) * wf_rows];
369 for(
int i = 0; i < imYsz; ++i )
371 im_data[i] = norm( wf_data[i] );
380template <
typename realImageT,
typename complexImageT,
int cudaGPU = 0>
408void extractIntensityImageAccum<cuda::cudaPtr<float>, cuda::cudaPtr<std::complex<float>>, 1>(
409 cuda::cudaPtr<float> &im,
int imX0,
int imXsz,
int imY0,
int imYsz, cuda::cudaPtr<std::complex<float>> &wf,
int wfX0,
int wfY0 );
412void extractIntensityImageAccum<cuda::cudaPtr<double>, cuda::cudaPtr<std::complex<double>>, 1>(
413 cuda::cudaPtr<double> &im,
int imX0,
int imXsz,
int imY0,
int imYsz, cuda::cudaPtr<std::complex<double>> &wf,
int wfX0,
int wfY0 );
Augments an exception with the source file and line.
Eigen::Array< scalarT, -1, -1 > eigenImage
Definition of the eigenImage type, which is an alias for Eigen::Array.
@ sizeerr
A size was invalid or calculated incorrectly.
@ invalidarg
An argument was invalid.
error_t mxlib_error_report(const error_t &code, const std::string &expl, const std::source_location &loc=std::source_location::current())
Print a report to stderr given an mxlib error_t code and explanation and return the code.
constexpr floatT six_fifths()
Return 6/5 in the specified precision.
void tiltWavefront(wavefrontT &complexWavefront, typename wavefrontT::Scalar::value_type xTilt, typename wavefrontT::Scalar::value_type yTilt)
Apply a tilt to a wavefront.
void makeComplexPupil(arrayOutT &complexPupil, const arrayInT &realPupil, int wavefrontSizePixels)
Create a complex pupil plane wavefront from a real amplitude mask.
realT fftPlateScale(size_t pixels, realT metersPerPixel, realT lambda)
Calculate the angular plate scale (radians per pixel) of an image after propagation by FFT.
int circularPupil(arrayT &m, typename arrayT::Scalar eps=0, typename arrayT::Scalar rad=0, typename arrayT::Scalar overscan=0)
Fill in an Eigen-like array with a circular pupil mask.
Declares and defines a class for managing images.
void extractMaskedPixels(imageT1 &dest, const imageT2 &src, const imageT3 &mask)
Extract a pixels from one image and insert them into a second based on a mask.
void extractBlock(imageT1 &dest, int imX0, int imXsz, int imY0, int imYsz, imageT2 &src, int wfX0, int wfY0)
Extract a block from one image and insert it into a second.
void extractIntensityImageAccum(realImageT &im, int imX0, int imXsz, int imY0, int imYsz, complexImageT &wf, int wfX0, int wfY0)
Extract the intensity image from a complex wavefront and accumulate the result.