Xmipp  v3.23.11-Nereus
xmipp_polynomials.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Authors: Javier Vargas (jvargas@cnb.csic.es)
3  *
4  *
5  * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20  * 02111-1307 USA
21  *
22  * All comments concerning this program package may be sent to the
23  * e-mail address 'xmipp@cnb.csic.es'
24  ***************************************************************************/
25 
26 #include "xmipp_polynomials.h"
28 #include "core/numerical_recipes.h"
29 #include "core/xmipp_image.h"
30 
31 #define PR(x) std::cout << #x " = " << x << std::endl;
32 #define ZERNIKE_ORDER(n) ceil((-3+sqrt(9+8*(double)(n)))/2.);
33 
34 //This function generates the Zernike Polynomials. Please see: Efficient Cartesian representation of Zernike polynomials in computer memory
35 //SPIE Vol. 3190 pp. 382 to get more details about the implementation
37 {
38  Matrix2D<int> * fMatT;
39 
40  auto nMax=(int)VEC_XSIZE(coef);
41  for (int nZ = 0; nZ < nMax; ++nZ)
42  {
43  if (VEC_ELEM(coef,nZ) == 0)
44  {
45  fMatT = new Matrix2D<int>(1,1);
46  dMij(*fMatT,0,0)=0;
47  //*fMatT = 0;
48  }
49  else
50  {
51  // Note that the paper starts in n=1 and we start in n=0
52  int n = (size_t)ZERNIKE_ORDER(nZ);
53  int l = 2*nZ-n*(n+2);
54 
55  Matrix2D<int> testM(n+1,n+1);
56  fMatT = new Matrix2D<int>(n+1,n+1);
57 
58  int p = (l>0);
59  int q = ((n % 2 != 0) ? (abs(l)-1)/2 : (( l > 0 ) ? abs(l)/2-1 : abs(l)/2 ) );
60  l = abs(l); //We want the positive value of l
61  int m = (n-l)/2;
62 
63  for (int i = 0; i <= q; ++i)
64  {
65  int K1=binom(l,2*i+p);
66  for (int j = 0; j <= m; ++j)
67  {
68  int factor = ( (i+j)%2 ==0 ) ? 1 : -1 ;
69  int K2=factor * K1 * fact(n-j)/(fact(j)*fact(m-j)*fact(n-m-j));
70  for (int k = 0; k <= (m-j); ++k)
71  {
72  int ypow = 2 * (i+k) + p;
73  int xpow = n - 2 * (i+j+k) - p;
74  dMij(*fMatT,xpow,ypow) +=K2 * binom(m-j,k);
75  }
76  }
77  }
78  }
79 
80  fMatV.push_back(*fMatT);
81  delete fMatT;
82  }
83 }
84 
86  const MultidimArray<bool> & ROI, int verbose)
87 {
88  this->create(coef);
89 
90  size_t xdim = XSIZE(im);
91  size_t ydim = YSIZE(im);
92  //int numZer = (size_t)coef.sum();
93  int numZer = (size_t)coef.sum();
94 
95  //Actually polOrder corresponds to the polynomial order +1
96  auto polOrder=(int)ZERNIKE_ORDER(coef.size());
97 
98  im.setXmippOrigin();
99 
100  Matrix2D<double> polValue(polOrder,polOrder);
101 
102  //First argument means number of images
103  //Second argument means number of pixels
104  WeightedLeastSquaresHelper weightedLeastSquaresHelper;
105  Matrix2D<double>& zerMat=weightedLeastSquaresHelper.A;
106 
107  zerMat.resizeNoCopy((size_t)ROI.sum(), numZer);
108  double iMaxDim2 = 2./std::max(xdim,ydim);
109 
110  size_t pixel_idx=0;
111 
112  weightedLeastSquaresHelper.b.resizeNoCopy((size_t)ROI.sum());
113  weightedLeastSquaresHelper.w.resizeNoCopy(weightedLeastSquaresHelper.b);
114 
116  {
117  if (A2D_ELEM(ROI,i,j))
118  {
119  //For one i we swap the different j
120  double y=i*iMaxDim2;
121  double x=j*iMaxDim2;
122 
123  //polValue = [ 0 y y2 y3 ...
124  // x xy xy2 xy3 ...
125  // x2 x2y x2y2 x2y3 ]
126  //dMij(polValue,py,px) py es fila, px es columna
127 
128  for (int py = 0; py < polOrder; ++py)
129  {
130  double ypy=std::pow(y,py);
131  for (int px = 0; px < polOrder; ++px)
132  dMij(polValue,px,py) = ypy*std::pow(x,px);
133  }
134 
135  Matrix2D<int> *fMat;
136 
137  //We generate the representation of the Zernike polynomials
138  for (int k=0; k < numZer; ++k)
139  {
140  fMat = &fMatV[k];
141 
142  if (fMat == nullptr)
143  continue;
144 
145  double temp = 0;
146  for (size_t px = 0; px < (*fMat).Xdim(); ++px)
147  for (size_t py = 0; py < (*fMat).Ydim(); ++py)
148  temp += dMij(*fMat,py,px)*dMij(polValue,py,px);
149 
150  dMij(zerMat,pixel_idx,k) = temp;
151  }
152 
153  VEC_ELEM(weightedLeastSquaresHelper.b,pixel_idx)=A2D_ELEM(im,i,j);
154  VEC_ELEM(weightedLeastSquaresHelper.w,pixel_idx)=std::abs(A2D_ELEM(weight,i,j));
155  ++pixel_idx;
156  }
157  }
158 
159  Matrix1D<double> zernikeCoefficients;
160  weightedLeastSquares(weightedLeastSquaresHelper, zernikeCoefficients);
161  fittedCoeffs = zernikeCoefficients;
162 
163  // Pointer to the image to be fitted
164  MultidimArray<double> reconstructed;
165 
166  reconstructed.resizeNoCopy(im);
167  pixel_idx=0;
168 
170  if (A2D_ELEM(ROI,i,j))
171  {
172  double temp=0;
173  for (int k=0; k < numZer; ++k)
174  temp+=dMij(zerMat,pixel_idx,k)*VEC_ELEM(fittedCoeffs,k);
175 
176  A2D_ELEM(reconstructed,i,j)=temp;
177 
178  if ( fabs(A2D_ELEM(reconstructed,i,j)-A2D_ELEM(im,i,j)) > PI)
179  A2D_ELEM(ROI,i,j) = false;
180 
181  ++pixel_idx;
182  }
183 
184  if (verbose > 0)
185  {
186  Image<double> save;
187  save()=reconstructed;
188  save.write("reconstructedZernikes.xmp");
189  ROI.write("ROI.txt");
190  }
191 }
192 
194 {
195 
196  this->create(coef);
197 
198  auto polOrder=(int)ZERNIKE_ORDER(coef.size());
199  int numZer = coef.size();
200 
201  int xdim = XSIZE(im);
202  int ydim = YSIZE(im);
203 
204  im.setXmippOrigin();
205 
206  Matrix2D<double> polValue(polOrder,polOrder);
207  double iMaxDim2 = 2./std::max(xdim,ydim);
208 
209  double temp = 0;
211  {
212  if (A2D_ELEM(ROI,i,j))
213  {
214  //For one i we swap the different j
215  double y=i*iMaxDim2;
216  double x=j*iMaxDim2;
217 
218  //polValue = [ 0 y y2 y3 ...
219  // x xy xy2 xy3 ...
220  // x2 x2y x2y2 x2y3 ]
221  //dMij(polValue,py,px) py es fila, px es columna
222  for (int py = 0; py < polOrder; ++py)
223  {
224  double ypy=std::pow(y,py);
225  for (int px = 0; px < polOrder; ++px)
226  dMij(polValue,px,py) = ypy*std::pow(x,px);
227  }
228 
229  Matrix2D<int> *fMat;
230  //We generate the representation of the Zernike polynomials
231 
232  for (int k=0; k < numZer; ++k)
233  {
234  fMat = &fMatV[k];
235 
236  if ( (dMij(*fMat,0,0) == 0) && MAT_SIZE(*fMat) == 1 )
237  continue;
238 
239  for (size_t px = 0; px < (*fMat).Xdim(); ++px)
240  for (size_t py = 0; py < (*fMat).Ydim(); ++py)
241  temp += dMij(*fMat,py,px)*dMij(polValue,py,px)*VEC_ELEM(coef,k);
242  }
243 
244  A2D_ELEM(im,i,j) = temp;
245  temp = 0;
246  }
247  }
248 
249  STARTINGX(im)=STARTINGY(im)=0;
250 
251  if (verbose == 1)
252  {
253  Image<double> save;
254  save()=im;
255  save.write("PPP1.xmp");
256  }
257 }
#define YSIZE(v)
#define A2D_ELEM(v, i, j)
#define VEC_ELEM(v, i)
Definition: matrix1d.h:245
#define MAT_SIZE(m)
Definition: matrix2d.h:128
size_t size() const
Definition: matrix1d.h:508
#define VEC_XSIZE(m)
Definition: matrix1d.h:77
void resizeNoCopy(const MultidimArray< T1 > &v)
static double * y
void write(const FileName &name="", size_t select_img=ALL_IMAGES, bool isStack=false, int mode=WRITE_OVERWRITE, CastWriteMode castMode=CW_CAST, int _swapWrite=0)
#define ZERNIKE_ORDER(n)
void abs(Image< double > &op)
void zernikePols(const Matrix1D< int > coef, MultidimArray< double > &im, const MultidimArray< bool > &ROI, int verbose=0)
#define STARTINGX(v)
doublereal * x
#define i
ql0001_ & k(htemp+1),(cvec+1),(atemp+1),(bj+1),(bl+1),(bu+1),(x+1),(clamda+1), &iout, infoqp, &zero,(w+1), &lenw,(iw+1), &leniw, &glob_grd.epsmac
#define FOR_ALL_ELEMENTS_IN_ARRAY2D(m)
void resizeNoCopy(int Ydim, int Xdim)
Definition: matrix2d.h:534
#define STARTINGY(v)
Matrix1D< double > fittedCoeffs
Matrix1D< double > b
Matrix2D< double > A
#define dMij(m, i, j)
Definition: matrix2d.h:139
#define XSIZE(v)
void write(const FileName &fn) const
void max(Image< double > &op1, const Image< double > &op2)
double sum(bool average=false) const
Definition: matrix1d.cpp:652
#define j
int m
void create(const Matrix1D< int > &coef)
void resizeNoCopy(int Xdim)
Definition: matrix1d.h:458
void fit(const Matrix1D< int > &coef, MultidimArray< double > &im, const MultidimArray< double > &weight, const MultidimArray< bool > &ROI, int verbose=0)
#define PI
Definition: tools.h:43
void weightedLeastSquares(WeightedLeastSquaresHelper &h, Matrix1D< double > &result)
size_t fact(int num)
int * n
double sum() const
size_t binom(int n, int k)