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 );
90template <
typename _arithT>
95 static const size_t width = 4;
96 static const size_t lbuff = 1;
125 return (
cubic + 2. ) * d * d * d - (
cubic + 3. ) * d * d + 1.;
137 template <
typename arrT,
typename arithT>
140 arithT km2x, km1x, kp1x, kp2x;
141 arithT km2y, km1y, kp1y, kp2y;
153 kern( 0, 0 ) = km2x * km2y;
154 kern( 0, 1 ) = km2x * km1y;
155 kern( 0, 2 ) = km2x * kp1y;
156 kern( 0, 3 ) = km2x * kp2y;
158 kern( 1, 0 ) = km1x * km2y;
159 kern( 1, 1 ) = km1x * km1y;
160 kern( 1, 2 ) = km1x * kp1y;
161 kern( 1, 3 ) = km1x * kp2y;
163 kern( 2, 0 ) = kp1x * km2y;
164 kern( 2, 1 ) = kp1x * km1y;
165 kern( 2, 2 ) = kp1x * kp1y;
166 kern( 2, 3 ) = kp1x * kp2y;
168 kern( 3, 0 ) = kp2x * km2y;
169 kern( 3, 1 ) = kp2x * km1y;
170 kern( 3, 2 ) = kp2x * kp1y;
171 kern( 3, 3 ) = kp2x * kp2y;
198template <
typename transformT,
typename arrT,
typename arrT2,
typename floatT>
205 typedef typename transformT::arithT arithT;
214 const int lbuff = transformT::lbuff;
215 const int width = transformT::width;
223 transim.resize( Nrows, Ncols );
226 xcen = 0.5 * ( Nrows - 1. );
227 ycen = 0.5 * ( Ncols - 1. );
229 int xulim = Nrows - width + lbuff;
230 int yulim = Ncols - width + lbuff;
232 arithT xc_x_cosq = xcen * cosq;
233 arithT xc_x_sinq = xcen * sinq;
234 arithT yc_x_cosq = ycen * cosq;
235 arithT yc_x_sinq = ycen * sinq;
237 xc_x_cosq += yc_x_sinq;
238 xc_x_sinq -= yc_x_cosq;
242 #pragma omp parallel private( x0, y0, i0, j0, x, y )
245 arithT i_x_cosq, i_x_sinq;
247 kern.resize( width, width );
251 #pragma omp for schedule( static, 1 )
253 for(
int i = 0; i < Nrows; ++i )
255 i_x_cosq = i * cosq - xc_x_cosq;
256 i_x_sinq = -( i * sinq - xc_x_sinq );
258 for(
int j = 0; j < Ncols; ++j )
264 x0 = i_x_cosq + j * sinq;
265 y0 = i_x_sinq + j * cosq;
271 if( i0 <= lbuff || i0 >= xulim || j0 <= lbuff || j0 >= yulim )
282 transim( i, j ) = ( im.block( i0 - lbuff, j0 - lbuff, width, width ) * kern ).sum();
299template <
typename outputArrT,
typename inputArrT>
311 int outr = out.rows();
312 int outc = out.cols();
329 for(
int cc = 0; cc < outc; ++cc )
338 for(
int rr = 0; rr < outr; ++rr )
347 out( rr, cc ) = in( x, y );
357 for(
int cc = 0; cc < outc; ++cc )
361 if( y < 0 || y >= inc )
363 for(
int rr = 0; rr < outr; ++rr )
371 for(
int rr = 0; rr < outr; ++rr )
375 if( x < 0 || x >= inr )
381 out( rr, cc ) = in( x, y );
400template <
typename outputArrT,
typename inputArrT,
typename scaleArrT>
413 int outr = out.rows();
414 int outc = out.cols();
429 for(
int cc = 0; cc < outc; ++cc )
438 for(
int rr = 0; rr < outr; ++rr )
447 out( rr, cc ) = in( x, y ) * scale( rr, cc );
472template <
typename arrOutT,
typename arrInT,
typename floatT1,
typename floatT2,
typename transformT>
480 typedef typename transformT::arithT arithT;
484 const int lbuff = transformT::lbuff;
485 const int width = transformT::width;
488 if( dx == floor( dx ) && dy == floor( dy ) )
494 int xulim = Nrows - width + lbuff;
495 int yulim = Ncols - width + lbuff;
497 transim.resize( Nrows, Ncols );
505 arithT rx = 1 - ( dx - floor( dx ) );
506 arithT ry = 1 - ( dy - floor( dy ) );
509 kern.resize( width, width );
510 trans( kern, rx, ry );
515 for(
int i = 0; i < Nrows; ++i )
522 if( i0 <= lbuff || i0 >= xulim )
524 for(
int j = 0; j < Ncols; ++j )
531 for(
int j = 0; j < Ncols; ++j )
535 if( j0 <= lbuff || j0 >= yulim )
541 transim( i, j ) = ( im.block( i0 - lbuff, j0 - lbuff, width, width ) * kern ).sum();
581template <
typename arrOutT,
typename arrInT,
typename transformT>
587 typedef typename transformT::arithT arithT;
595 const int lbuff = transformT::lbuff;
596 const int width = transformT::width;
598 Nrows = transim.rows();
599 Ncols = transim.cols();
601 int xulim = im.rows() - lbuff - 1;
602 int yulim = im.cols() - lbuff - 1;
604 arithT x_scale = ( (arithT)im.rows() - 1.0 ) / ( transim.rows() - 1.0 );
605 arithT y_scale = ( (arithT)im.cols() - 1.0 ) / ( transim.cols() - 1.0 );
607 arithT xcen = 0.5 * ( (arithT)transim.rows() - 1.0 );
608 arithT ycen = 0.5 * ( (arithT)transim.cols() - 1.0 );
610 arithT xcen0 = 0.5 * ( (arithT)im.rows() - 1.0 );
611 arithT ycen0 = 0.5 * ( (arithT)im.cols() - 1.0 );
616 kern.resize( width, width );
618 for(
int j = 0; j < Ncols; ++j )
625 y0 = ycen0 + ( j - ycen ) * y_scale;
628 if( j0 < lbuff || j0 >= yulim )
630 for(
int i = 0; i < Nrows; ++i )
638 for(
int i = 0; i < Nrows; ++i )
640 x0 = xcen0 + ( i - xcen ) * x_scale;
643 if( i0 < lbuff || i0 >= xulim )
654 transim( i, j ) = ( im.block( i0 - lbuff, j0 - lbuff, width, width ) * kern ).sum();
670template <
typename arrOutT,
typename arrInT>
681template <
typename imageOutT,
typename imageInT>
684 const imageInT &imin,
688 int rebin = imin.rows() / imout.rows();
689 if( imin.cols() / imout.cols() != rebin )
695 for(
int i = 0; i < imout.rows(); ++i )
697 for(
int j = 0; j < imout.cols(); ++j )
699 imout( i, j ) = imin.block( i * rebin, j * rebin, rebin, rebin ).sum() / N;
712template <
typename imageOutT,
typename imageInT>
717 typename imageOutT::Scalar &pMax,
718 const imageInT &imin,
722 int rebin = imin.rows() / imout.rows();
723 if( imin.cols() / imout.cols() != rebin )
732 pMax = std::numeric_limits<typename imageOutT::Scalar>::lowest();
734 for(
int i = 0; i < imout.rows(); ++i )
736 for(
int j = 0; j < imout.cols(); ++j )
738 imout( i, j ) = imin.block( i * rebin, j * rebin, rebin, rebin ).sum() / N;
739 if( imout( i, j ) > pMax )
741 pMax = imout( i, j );
754template <
typename imageOutT,
typename imageInT>
768template <
typename imageOutT,
typename imageInT>
773 typename imageOutT::Scalar &pMax,
774 const imageInT &imin,
784template <
typename imageOutT,
typename imageInT>
790 int rebin = imin.rows() / imout.rows();
791 if( imin.cols() / imout.cols() != rebin )
794 int N = rebin * rebin - 2;
796 for(
int i = 0; i < imout.rows(); ++i )
798 for(
int j = 0; j < imout.cols(); ++j )
800 typename imageOutT::Scalar sum = 0;
801 typename imageOutT::Scalar max = imin( i * rebin, j * rebin );
802 typename imageOutT::Scalar min = imin( i * rebin, j * rebin );
803 for(
int k = 0; k < rebin; ++k )
805 for(
int l = 0; l < rebin; ++l )
807 sum += imin( i * rebin + k, j * rebin + l );
808 if( imin( i * rebin + k, j * rebin + l ) > max )
809 max = imin( i * rebin + k, j * rebin + l );
810 if( imin( i * rebin + k, j * rebin + l ) < min )
811 min = imin( i * rebin + k, j * rebin + l );
814 imout( i, j ) = ( sum - max - min ) / N;
827template <
typename imageOutT,
typename imageInT>
832 typename imageOutT::Scalar &pMax,
836 int rebin = imin.rows() / imout.rows();
837 if( imin.cols() / imout.cols() != rebin )
840 int N = rebin * rebin - 2;
844 pMax = std::numeric_limits<typename imageOutT::Scalar>::lowest();
846 for(
int i = 0; i < imout.rows(); ++i )
848 for(
int j = 0; j < imout.cols(); ++j )
850 typename imageOutT::Scalar sum = 0;
851 typename imageOutT::Scalar max = imin( i * rebin, j * rebin );
852 typename imageOutT::Scalar min = imin( i * rebin, j * rebin );
853 for(
int k = 0; k < rebin; ++k )
855 for(
int l = 0; l < rebin; ++l )
857 sum += imin( i * rebin + k, j * rebin + l );
858 if( imin( i * rebin + k, j * rebin + l ) > max )
859 max = imin( i * rebin + k, j * rebin + l );
860 if( imin( i * rebin + k, j * rebin + l ) < min )
861 min = imin( i * rebin + k, j * rebin + l );
864 imout( i, j ) = ( sum - max - min ) / N;
866 if( imout( i, j ) > pMax )
868 pMax = imout( i, j );
884template <
typename imageOutT,
typename imageInT>
887 typedef typename imageOutT::Scalar Scalar;
890 Scalar inputTotal = fabs( imin.sum() );
893 int closestRebin = imin.rows() / imout.rows();
895 float sample = ( (float)imin.rows() ) / closestRebin;
897 while( sample != floor( sample ) )
900 if( closestRebin == 1 )
902 sample = ( (float)imin.rows() ) / closestRebin;
907 temp.resize( imin.rows() / closestRebin, imin.cols() / closestRebin );
909 for(
int i = 0; i < temp.rows(); ++i )
911 for(
int j = 0; j < temp.cols(); ++j )
913 temp( i, j ) = imin.block( i * closestRebin, j * closestRebin, closestRebin, closestRebin ).sum();
918 if( temp.rows() == imout.rows() && temp.cols() == imout.cols() )
930 const int lbuff = transformT::lbuff;
931 const int width = transformT::width;
933 for(
int i = 0; i < imout.rows(); ++i )
935 for(
int j = 0; j < imout.cols(); ++j )
937 double x = ( (double)i / imout.rows() ) * temp.rows();
938 double y = ( (double)j / imout.cols() ) * temp.cols();
940 trans( kern, x - floor( x ), y - floor( y ) );
942 imout( i, j ) = ( temp.block( floor( x ) - lbuff, floor( y ) - lbuff, width, width ) * kern ).sum();
947 Scalar outputTotal = fabs( imout.sum() );
948 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.