27#ifndef improc_imageTransforms_hpp
28#define improc_imageTransforms_hpp
46template <
typename _arithT>
49 typedef _arithT arithT;
51 static const size_t width = 2;
52 static const size_t lbuff = 0;
54 template <
typename arrT,
typename arithT>
55 void operator()( arrT &kern, arithT x, arithT y )
57 kern.resize( width, width );
59 kern( 0, 0 ) = ( 1. - x ) * ( 1. - y );
60 kern( 0, 1 ) = ( 1. - x ) * y;
61 kern( 1, 0 ) = x * ( 1. - y );
91template <
typename _arithT>
96 static const size_t width = 4;
97 static const size_t lbuff = 1;
126 return (
cubic + 2. ) * d * d * d - (
cubic + 3. ) * d * d + 1.;
138 template <
typename arrT,
typename arithT>
141 arithT km2x, km1x, kp1x, kp2x;
142 arithT km2y, km1y, kp1y, kp2y;
154 kern( 0, 0 ) = km2x * km2y;
155 kern( 0, 1 ) = km2x * km1y;
156 kern( 0, 2 ) = km2x * kp1y;
157 kern( 0, 3 ) = km2x * kp2y;
159 kern( 1, 0 ) = km1x * km2y;
160 kern( 1, 1 ) = km1x * km1y;
161 kern( 1, 2 ) = km1x * kp1y;
162 kern( 1, 3 ) = km1x * kp2y;
164 kern( 2, 0 ) = kp1x * km2y;
165 kern( 2, 1 ) = kp1x * km1y;
166 kern( 2, 2 ) = kp1x * kp1y;
167 kern( 2, 3 ) = kp1x * kp2y;
169 kern( 3, 0 ) = kp2x * km2y;
170 kern( 3, 1 ) = kp2x * km1y;
171 kern( 3, 2 ) = kp2x * kp1y;
172 kern( 3, 3 ) = kp2x * kp2y;
199template <
typename transformT,
typename arrT,
typename arrT2,
typename floatT>
206 typedef typename transformT::arithT arithT;
215 const int lbuff = transformT::lbuff;
216 const int width = transformT::width;
224 transim.resize( Nrows, Ncols );
227 xcen = 0.5 * ( Nrows - 1. );
228 ycen = 0.5 * ( Ncols - 1. );
230 int xulim = Nrows - width + lbuff;
231 int yulim = Ncols - width + lbuff;
233 arithT xc_x_cosq = xcen * cosq;
234 arithT xc_x_sinq = xcen * sinq;
235 arithT yc_x_cosq = ycen * cosq;
236 arithT yc_x_sinq = ycen * sinq;
238 xc_x_cosq += yc_x_sinq;
239 xc_x_sinq -= yc_x_cosq;
243 #pragma omp parallel private( x0, y0, i0, j0, x, y )
246 arithT i_x_cosq, i_x_sinq;
248 kern.resize( width, width );
252 #pragma omp for schedule( static, 1 )
254 for(
int i = 0; i < Nrows; ++i )
256 i_x_cosq = i * cosq - xc_x_cosq;
257 i_x_sinq = -( i * sinq - xc_x_sinq );
259 for(
int j = 0; j < Ncols; ++j )
265 x0 = i_x_cosq + j * sinq;
266 y0 = i_x_sinq + j * cosq;
272 if( i0 <= lbuff || i0 >= xulim || j0 <= lbuff || j0 >= yulim )
283 transim( i, j ) = ( im.block( i0 - lbuff, j0 - lbuff, width, width ) * kern ).sum();
301template <
typename outputArrT,
typename inputArrT>
313 int outr = out.rows();
314 int outc = out.cols();
331 for(
int cc = 0; cc < outc; ++cc )
340 for(
int rr = 0; rr < outr; ++rr )
349 out( rr, cc ) = in( x, y );
359 for(
int cc = 0; cc < outc; ++cc )
363 if( y < 0 || y >= inc )
365 for(
int rr = 0; rr < outr; ++rr )
373 for(
int rr = 0; rr < outr; ++rr )
377 if( x < 0 || x >= inr )
383 out( rr, cc ) = in( x, y );
402template <
typename outputArrT,
typename inputArrT,
typename scaleArrT>
415 int outr = out.rows();
416 int outc = out.cols();
431 for(
int cc = 0; cc < outc; ++cc )
440 for(
int rr = 0; rr < outr; ++rr )
449 out( rr, cc ) = in( x, y ) * scale( rr, cc );
475template <
typename arrOutT,
typename arrInT,
typename floatT1,
typename floatT2,
typename transformT>
483 typedef typename transformT::arithT arithT;
487 const int lbuff = transformT::lbuff;
488 const int width = transformT::width;
491 if( dx == floor( dx ) && dy == floor( dy ) )
497 int xulim = Nrows - width + lbuff;
498 int yulim = Ncols - width + lbuff;
500 transim.resize( Nrows, Ncols );
508 arithT rx = 1 - ( dx - floor( dx ) );
509 arithT ry = 1 - ( dy - floor( dy ) );
512 kern.resize( width, width );
513 trans( kern, rx, ry );
518 for(
int i = 0; i < Nrows; ++i )
525 if( i0 <= lbuff || i0 >= xulim )
527 for(
int j = 0; j < Ncols; ++j )
534 for(
int j = 0; j < Ncols; ++j )
538 if( j0 <= lbuff || j0 >= yulim )
544 transim( i, j ) = ( im.block( i0 - lbuff, j0 - lbuff, width, width ) * kern ).sum();
584template <
typename arrOutT,
typename arrInT,
typename transformT>
590 typedef typename transformT::arithT arithT;
598 const int lbuff = transformT::lbuff;
599 const int width = transformT::width;
601 Nrows = transim.rows();
602 Ncols = transim.cols();
604 int xulim = im.rows() - lbuff - 1;
605 int yulim = im.cols() - lbuff - 1;
607 arithT x_scale = ( (arithT)im.rows() - 1.0 ) / ( transim.rows() - 1.0 );
608 arithT y_scale = ( (arithT)im.cols() - 1.0 ) / ( transim.cols() - 1.0 );
610 arithT xcen = 0.5 * ( (arithT)transim.rows() - 1.0 );
611 arithT ycen = 0.5 * ( (arithT)transim.cols() - 1.0 );
613 arithT xcen0 = 0.5 * ( (arithT)im.rows() - 1.0 );
614 arithT ycen0 = 0.5 * ( (arithT)im.cols() - 1.0 );
619 kern.resize( width, width );
621 for(
int j = 0; j < Ncols; ++j )
628 y0 = ycen0 + ( j - ycen ) * y_scale;
631 if( j0 < lbuff || j0 >= yulim )
633 for(
int i = 0; i < Nrows; ++i )
641 for(
int i = 0; i < Nrows; ++i )
643 x0 = xcen0 + ( i - xcen ) * x_scale;
646 if( i0 < lbuff || i0 >= xulim )
657 transim( i, j ) = ( im.block( i0 - lbuff, j0 - lbuff, width, width ) * kern ).sum();
673template <
typename arrOutT,
typename arrInT>
684template <
typename imageOutT,
typename imageInT>
687 const imageInT &imin,
691 int rebin = imin.rows() / imout.rows();
692 if( imin.cols() / imout.cols() != rebin )
698 for(
int i = 0; i < imout.rows(); ++i )
700 for(
int j = 0; j < imout.cols(); ++j )
702 imout( i, j ) = imin.block( i * rebin, j * rebin, rebin, rebin ).sum() / N;
715template <
typename imageOutT,
typename imageInT>
720 typename imageOutT::Scalar &pMax,
721 const imageInT &imin,
725 int rebin = imin.rows() / imout.rows();
726 if( imin.cols() / imout.cols() != rebin )
735 pMax = std::numeric_limits<typename imageOutT::Scalar>::lowest();
737 for(
int i = 0; i < imout.rows(); ++i )
739 for(
int j = 0; j < imout.cols(); ++j )
741 imout( i, j ) = imin.block( i * rebin, j * rebin, rebin, rebin ).sum() / N;
742 if( imout( i, j ) > pMax )
744 pMax = imout( i, j );
757template <
typename imageOutT,
typename imageInT>
771template <
typename imageOutT,
typename imageInT>
776 typename imageOutT::Scalar &pMax,
777 const imageInT &imin,
787template <
typename imageOutT,
typename imageInT>
793 int rebin = imin.rows() / imout.rows();
794 if( imin.cols() / imout.cols() != rebin )
797 int N = rebin * rebin - 2;
799 for(
int i = 0; i < imout.rows(); ++i )
801 for(
int j = 0; j < imout.cols(); ++j )
803 typename imageOutT::Scalar sum = 0;
804 typename imageOutT::Scalar max = imin( i * rebin, j * rebin );
805 typename imageOutT::Scalar min = imin( i * rebin, j * rebin );
806 for(
int k = 0; k < rebin; ++k )
808 for(
int l = 0; l < rebin; ++l )
810 sum += imin( i * rebin + k, j * rebin + l );
811 if( imin( i * rebin + k, j * rebin + l ) > max )
812 max = imin( i * rebin + k, j * rebin + l );
813 if( imin( i * rebin + k, j * rebin + l ) < min )
814 min = imin( i * rebin + k, j * rebin + l );
817 imout( i, j ) = ( sum - max - min ) / N;
830template <
typename imageOutT,
typename imageInT>
835 typename imageOutT::Scalar &pMax,
839 int rebin = imin.rows() / imout.rows();
840 if( imin.cols() / imout.cols() != rebin )
843 int N = rebin * rebin - 2;
847 pMax = std::numeric_limits<typename imageOutT::Scalar>::lowest();
849 for(
int i = 0; i < imout.rows(); ++i )
851 for(
int j = 0; j < imout.cols(); ++j )
853 typename imageOutT::Scalar sum = 0;
854 typename imageOutT::Scalar max = imin( i * rebin, j * rebin );
855 typename imageOutT::Scalar min = imin( i * rebin, j * rebin );
856 for(
int k = 0; k < rebin; ++k )
858 for(
int l = 0; l < rebin; ++l )
860 sum += imin( i * rebin + k, j * rebin + l );
861 if( imin( i * rebin + k, j * rebin + l ) > max )
862 max = imin( i * rebin + k, j * rebin + l );
863 if( imin( i * rebin + k, j * rebin + l ) < min )
864 min = imin( i * rebin + k, j * rebin + l );
867 imout( i, j ) = ( sum - max - min ) / N;
869 if( imout( i, j ) > pMax )
871 pMax = imout( i, j );
887template <
typename imageOutT,
typename imageInT>
890 typedef typename imageOutT::Scalar Scalar;
893 Scalar inputTotal = fabs( imin.sum() );
896 int closestRebin = imin.rows() / imout.rows();
898 float sample = ( (float)imin.rows() ) / closestRebin;
900 while( sample != floor( sample ) )
903 if( closestRebin == 1 )
905 sample = ( (float)imin.rows() ) / closestRebin;
910 temp.resize( imin.rows() / closestRebin, imin.cols() / closestRebin );
912 for(
int i = 0; i < temp.rows(); ++i )
914 for(
int j = 0; j < temp.cols(); ++j )
916 temp( i, j ) = imin.block( i * closestRebin, j * closestRebin, closestRebin, closestRebin ).sum();
921 if( temp.rows() == imout.rows() && temp.cols() == imout.cols() )
933 const int lbuff = transformT::lbuff;
934 const int width = transformT::width;
936 for(
int i = 0; i < imout.rows(); ++i )
938 for(
int j = 0; j < imout.cols(); ++j )
940 double x = ( (double)i / imout.rows() ) * temp.rows();
941 double y = ( (double)j / imout.cols() ) * temp.cols();
943 trans( kern, x - floor( x ), y - floor( y ) );
945 imout( i, j ) = ( temp.block( floor( x ) - lbuff, floor( y ) - lbuff, width, width ) * kern ).sum();
950 Scalar outputTotal = fabs( imout.sum() );
951 imout *= inputTotal / outputTotal;
Tools for using the eigen library for image processing.
Eigen::Array< scalarT, -1, -1 > eigenImage
Definition of the eigenImage type, which is an alias for Eigen::Array.