YaDICs  V04.14.a
Yet another Digital Image Correlation software: platform dedicated to 2/3D Fluid and Solid kinematics field measurements.
 All Classes Files Functions Variables Pages
Ccorrelation_opticalFlow_integrated_block.h
Go to the documentation of this file.
1 /**********************************************************************
2  * Copyright (C) 2012, The YaDICs Project Developers.
3  * See the COPYRIGHT file at the top-level directory of this distribution ./COPYRIGHT.
4  * See ./COPYING file for copying and redistribution conditions.
5  *
6  * This file is part of YaDICs.
7  * YaDICs 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 3 of the License, or
10  * (at your option) any later version.
11  *
12  * YaDICs 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 YaDICs. If not, see <http://www.gnu.org/licenses/>.
19  *
20  * Information about how to use the software are provided at http://yadic.univ-lille1.fr/
21  **********************************************************************/
22 
23 
24 #ifndef CCORRELATION_OPTICALFLOW_INTEGRATED_BLOCK
25 #define CCORRELATION_OPTICALFLOW_INTEGRATED_BLOCK
26 
27 
28 
39 
42 template<typename T,typename Timg>
44 {
45 
46  public:
47 
49  {// constructor
50 
51  this->class_name = "Correlation : Optical Flow Integrated per Block";
52 
53  }
54 
55  virtual void init(CParameterNetCDF &fp)
56  {// init from parameter file
57 
63 
64  std::string attribute_name = "median_filter";
65  int error = fp.loadAttribute(attribute_name,this->m_medianFilter);
66  if (this->m_verbose){printf("\t\t median filter over following domain -> %i\n",this->m_medianFilter);}
67 
68  }
69 
70  virtual void assignG(const Cmesh<T,Timg> &oMesh, CImgList<T> &Ke)
71  {//assign approriate size for Ke and Fe tensors
72 
73  Ke.assign(2);
74  Ke[0].assign(oMesh.num_mod(),oMesh.num_mod(),1,1, 0);
75  Ke[1].assign(1,oMesh.num_mod(),1,1, 0);
76 
77  }
78 
79  virtual void reset(const int &thread, CImgList<T> &Ke)
80  {//reset tensors
81 
82  cimglist_for(Ke, var)
83  {
84  Ke[var].fill(0);
85  }
86 
87  }
88 
89  virtual void e_ref(const Cimage<Timg> &oImage, const Cmesh<T,Timg> &oMesh, const int &elem, std::vector<T> &ref)
90  {// omp_get_num_threads()store position of the centroid as element position reference "0"
91 
92 
93  for (int dim=0; dim<oMesh.num_var(); dim++)
94  {// user reference or image centroid in physical unit
95 
96  if (this->m_ref[dim] == -1)
97  {
98  //centroid coordonates in physical unit
99  ref[dim] = oMesh.m_node[dim][oMesh.m_connect[elem].front()]*oImage.m_pix[dim] ;
100  }
101  else
102  {//apply scaling to reference position provided by user.
103  ref[dim] = this->m_ref[dim]*oImage.m_Rpxmm;
104  }
105 
106  }
107 
108  }
109 
110  virtual void evalShape(const CImg<Timg> &list, const Cimage<Timg> &oImage, const Cfield<T,Timg> &oField, const std::vector<T> &ref, const std::vector<T> &lCoor, const std::vector<T> &gCoor, CImgList<T> &N)
111  {//evaluate the shape function at pix (x, y, z)
112 
113  std::vector<T> coor;coor.assign(3,0);
114  for (int i=0; i<gCoor.size(); i++)
115  {
116  coor[i] = gCoor[i]*oImage.m_pix[i] - ref[i];
117  }
118 
119  (oField.m_pShape)->exec(list, coor, N);
120 
121  }
122 
123  virtual void tensors(const int &thread, const CImgList<T> &Ve, const T &residue, CImgList<T> &Ke)
124  {//eval stiffness matrix & force vector at element
125 
126  cimg_forZ(Ke[0], dim)
127  {//in the case of OFI dim = 0
128  cimg_forX(Ke[0],modi)
129  {//for every modes or nodes
130  cimg_forY(Ke[0],modj)
131  {
132  Ke[0](modi,modj,dim) += Ve[dim][modi] * Ve[dim][modj];//Ke
133  }
134  Ke[1](0, modi,dim) += Ve[dim][modi] * residue;//Fe
135  }
136  }
137 
138  }
139 
140  virtual void metric(const Cimage<Timg> &oImage, const Cmesh<T,Timg> &oMesh, CImgList<T> &solution, Cfield<T,Timg> &oField, CImgList<T> &N, CImgList<T> &Ve, CImgList<T> &Ke, std::vector<T> &ref, std::vector<T> &offset, std::vector<T> &lCoor, std::vector<T> &gCoor, std::vector<T> &U, std::vector<T> &grad, T &residue, T &deformed, CImg<Timg> &list, CImg<int> &p, CImg<T> &current_res)
141  {//calcul K
142 
143  #pragma omp single
144  {//init
145  current_res.fill(0);
146  p.fill(0);
147  }
148 
149  int thread(0), enter(1);
150 
151  #pragma omp for schedule(runtime)
152  cimglist_for(oMesh.m_connect, elem)
153  {//for every elements
154 
155  if (oMesh.cropList(oImage, elem, list, offset))
156  {//if the list is not entirely masked
157 
158  //check the thread number
159  thread = omp_get_thread_num();
160 
161  //look for the reference system of the element
162  e_ref(oImage, oMesh, elem, ref);
163 
164  //reset tensors
165  reset(thread,Ke);
166 
167  for (int pix=0; pix<list.size(); pix++)
168  {//eval Ke over pix
169 
170  //define global coordonates : find back "x,y,z" triplet
171  list.contains(list[pix],lCoor[0],lCoor[1],lCoor[2]);
172  for (int i=0; i<gCoor.size(); i++){gCoor[i]=lCoor[i]+offset[i];}
173 
174  //if pix is in img bounds
175  enter = oImage.m_img[0].contains(oImage.m_img[0](gCoor[0],gCoor[1],gCoor[2]));
176  //if pix is unmasked
177  if (!oImage.m_mask.is_empty() and enter){enter = oImage.m_curMask(gCoor[0], gCoor[1], gCoor[2]);}
178 
179  p[thread]++;
180 
181  if (enter!=0)
182  {//if pixels are unmasked and in bounds
183 
184  // Evaluates grad[dim] at (x,y,z) in physical unit
185  Ccorrelation_opticalFlow<T,Timg>::gradient(oImage, gCoor, grad);
186 
187  // Evaluates N[dim][mode] at (x,y,z) in physical unit
188  evalShape(list, oImage, oField, ref, lCoor, gCoor, N);
189 
190  // Evaluates Ve[dim][mode] at (x,y,z) in physical unit
191  this->evalGN(grad,N, Ve);
192 
193  // Evaluates U[dim] in physical unit
194  this->evalU(solution, oMesh, elem, N, U);
195 
196  // Evaluates residue between ref and corrected deformed image at (x,y,z)
197  this->evalRes_loop(oImage, U, gCoor, residue, deformed);
198 
199  //sum of square residues over pixels and elements
200  current_res[thread] += std::pow(residue,2);
201 
202  //evaluate Ke
203  tensors(thread, Ve, residue, Ke);
204 
205  }//endif unmasked or out-of-bound
206 
207  }//for implied barrier
208 
209  Ke[1].solve(Ke[0]);
210  cimg_forY(Ke[1],y){solution[y][elem] += Ke[1][y];}
211 
212  }
213 
214  }
215 
216  #pragma omp single
217  {//sum of square residues over threads and normalization and store residue of previous increment
218  oField.m_meanRes.push_back(std::sqrt(current_res.sum())/p.sum()*oImage.m_curImg[0].size()*100/oImage.m_res);
219  }
220 
221  }
222 
223  virtual void exec(const Cimage<Timg> &oImage, const Cmesh<T,Timg> &oMesh, Cfield<T,Timg> &oField)
224  {// exec optical flow correlation
225 
226  //-----------------------------------------------------------------------
227  //monoprocessing asignments
228  this->_3D = oMesh._3D;
229 
230  int iter(0); //number of iterations
231  int converged(0); //convergence parameter
232  T previous_res(1e10); //residue at previous step
233 
234  CImg<int> p(this->m_threadNB,1,1,1,0);
235  CImgList<T> solution(oField.m_mode);//intermediate solution vector
236  CImg<T> current_res(this->m_threadNB,1,1,1,0);//global mean residue
237  //-----------------------------------------------------------------------
238 
239  #pragma omp parallel
240  {//beginning of parallel section
241 
242  //-----------------------------------------------------------------------
243  //multithread initializations
244  //for elements
245  CImgList<T> Ke;//global and local tensors for linear system K[0].U=K[1] with K[0] = sum_(V.Vt) and K[1] = sum_((Img1(X)-Img2(X-U)).V)
246  assignG(oMesh, Ke);//global assignments
247  CImg<Timg> list; //elementary pixel list
248 
249  //for pixels
250  CImgList<T> Ve; //shape function to image gradient product at pix
251  CImgList<T> N(oMesh.num_var(), oMesh.num_mod(),1,1,1, 0);//Shape function at pix
252  T residue(0), deformed(0); //residue and corrected GL at pix
253  std::vector<T> ref, offset, lCoor, gCoor, grad, U;
254  ref.assign(3,0);offset.assign(3,0);lCoor.assign(3,0); gCoor.assign(3,0); U.assign(3,0); grad.assign(oMesh.num_var(),0);
255 
256  this->assignL(oMesh, Ve);
257  //-----------------------------------------------------------------------
258 
259  do
260  {//while the convergency velocity is higher than a certain level
261 
262  metric(oImage,oMesh,solution,oField,N,Ve,Ke,ref,offset,lCoor,gCoor,U,grad,residue,deformed,list, p,current_res);
263 
264  #pragma omp single
265  {
266  if (this->m_medianFilter){this->regularize(oMesh, oImage, solution);}
267  test(solution, this->m_epsilon, oField, previous_res, iter, converged);
268  }
269 
270  }
271  while(!converged);
272 
273  if (oImage.m_storeActiv)
274  {Ccorrelation_opticalFlow<T,Timg>::export_res(oImage,oMesh,oField, N,ref,offset,lCoor,gCoor,U,residue,deformed,list);}
275 
276  }// pragma omp parallel
277 
278  }
279 
280 
281  virtual void store(Cfield<T,Timg> &oField, const Cimage<Timg> &oImage, const std::vector<T> gCoor, const std::vector<T> &U,const T &deformed,const T &residue)
282  {//store output data
283 
284  if (oImage.m_storeField)
285  {//store field a iter - 1 to avoid storing the last diverging increment
286  cimglist_for(oField.m_field, dim)
287  {
288  #pragma omp critical
289  {
290  oField.m_field(dim, gCoor[0],gCoor[1],gCoor[2]) = U[dim];
291  }
292  }
293  }
294 
295  if (oImage.m_storeDef)
296  {//store imDef a iter - 1
297  #pragma omp critical
298  {
299  oField.m_def(gCoor[0],gCoor[1],gCoor[2]) = deformed;
300  }
301  }
302 
303  if (oImage.m_storeRes)
304  {//store imRes a iter - 1
305  #pragma omp critical
306  {
307  oField.m_res(gCoor[0],gCoor[1],gCoor[2]) = residue;
308  }
309  }
310 
311  }
312 
313  virtual void test(const CImgList<T> &solution, const double &epsilon, Cfield<T,Timg> &oField, T &previous_res, int &iter, int &converged)
314  {
315 
316  Ccorrelation_opticalFlow<T,Timg>::test(solution, epsilon, oField, previous_res, iter, converged);
317 
318  }
319 
320 };
321 
322 #endif
virtual void regularize(const Cmesh< T, Timg > &oMesh, const Cimage< Timg > &oImage, CImgList< T > &solution)
Definition: Ccorrelation.h:96
virtual void init(CParameterNetCDF &fp)
Definition: Ccorrelation_opticalFlow_integrated.h:56
void evalRes_loop(const Cimage< Timg > &oImage, const std::vector< T > &U, const std::vector< T > &x, T &residue, T &deformed)
Definition: Ccorrelation_opticalFlow.h:209
It implements the Optical Flow with Integrated kinematics within independant block such as Block-matc...
Definition: Ccorrelation_opticalFlow_integrated_block.h:43
Definition: Ccorrelation_opticalFlow_integrated.h:43
It implements optical flow strategy for global shape functions.
This is the mother class of Optical Flow strategies: It implements different steps required for the i...
Definition: Ccorrelation_opticalFlow.h:53
Definition: Cmesh.h:61
Definition: Cfield.h:51
Definition: Cimage.h:57
virtual void gradient(const Cimage< Timg > &oImage, const std::vector< T > &x, std::vector< T > &grad)
Definition: Ccorrelation_opticalFlow.h:194
virtual void init(CParameterNetCDF &fp)
Definition: Ccorrelation_opticalFlow_integrated_block.h:55