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.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
25 #define CCORRELATION_OPTICALFLOW_INTEGRATED
26 
27 
39 
40 
41 
42 template<typename T,typename Timg>
44 {
45 
46  public:
47 
48 
50  {// constructor
51 
52  this->class_name = "Correlation : Optical Flow Integrated";
53 
54  }
55 
56  virtual void init(CParameterNetCDF &fp)
57  {// init from parameter file
58 
64 
65  this->m_medianFilter = 0;
66 
68  this->m_ref.assign(3,-1);
69 
70  std::string attribute_name("refX");
71  int error = fp.loadAttribute(attribute_name,this->m_ref[0]);
72 
73  attribute_name = "refY";
74  error = fp.loadAttribute(attribute_name,this->m_ref[1]);
75 
76  attribute_name = "refZ";
77  error = fp.loadAttribute(attribute_name,this->m_ref[2]);
78 
79  if (this->m_verbose){printf("\tReference system computed by user: [%f,%f,%f]\n", this->m_ref[0], this->m_ref[1], this->m_ref[2]);}
80 
81  }
82 
83  virtual void assignG(const Cmesh<T,Timg> &oMesh, CImgList<T> &K, CImgList<T> &Ke)
84  {//assign approriate size for Ke and Fe tensors
85 
87 
88  K[0].assign(oMesh.num_mod(),oMesh.num_mod(),1,1, 0);
89  K[1].assign(1,oMesh.num_mod(),1,1, 0);
90 
91  Ke[0].assign(oMesh.num_mod(),oMesh.num_mod(),1,this->m_threadNB, 0);
92  Ke[1].assign(1,oMesh.num_mod(),1,this->m_threadNB, 0);
93 
94  }
95 
96  virtual void assignL(const Cmesh<T,Timg> &oMesh, CImgList<T> &Ve)
97  {//assign approriate size for Ve = Grad[dim].N[dim][mode] product at pix
98 
99  Ve.assign(1, oMesh.num_mod(),1,1,1, 0);
100 
101  }
102 
103  virtual void reset(const int &thread, CImgList<T> &Ke)
104  {//reset tensors
105 
106  cimglist_for(Ke, var)
107  {
108  Ke[var].fill(0);
109  }
110 
111  }
112 
113  virtual void evalGN(const std::vector<T> &grad,const CImgList<T> &N, CImgList<T> &Ve)
114  {//eval V[dim][mode] = grad[dim].N[dim][mode] product
115 
116  Ve[0].fill(0);
117  cimglist_for(N, dim)
118  {
119  cimg_forX(N[dim], mode)
120  {
121  Ve[0][mode] += grad[dim] * N[dim][mode];
122  }
123  }
124 
125  }
126 
127  virtual void e_ref(const Cimage<Timg> &oImage, const Cmesh<T,Timg> &oMesh, const int &elem, std::vector<T> &ref)
128  {// store position of upper left corner as element position reference "0"
129 
130  for (int dim=0; dim<oMesh.num_var(); dim++)
131  {// user reference or image centroid in physical unit
132  if (this->m_ref[dim] == -1)
133  {
134  ref[dim] = (oImage.cur_dim(dim)*oImage.m_pix[dim])/2.;
135  }
136  else
137  {//apply scaling to reference position provided by user.
138  ref[dim] = this->m_ref[dim]*oImage.m_Rpxmm;
139  }
140  }
141 
142  }
143 
144  virtual void evalU(const CImgList<T> &solution, const Cmesh<T,Timg> &oMesh, const int &elem, const CImgList<T> &N, std::vector<T> &U)
145  {//eval U[dim] at pix
146 
147  U[2] = 0;//init required if dimension is lower than 3
148  cimglist_for(N, dim)
149  {
150 
151  U[dim] = 0;
152 
153  cimg_forX(N[0], mode)
154  {
155  //for OFI (elem = 0) and OFIB (elem = centroid)
156  U[dim] += solution[mode][elem] * N[dim][mode];
157  }
158 
159  }
160 
161 
162  }
163 
164  virtual void gradient(const Cimage<Timg> &oImage, const std::vector<T> &x, std::vector<T> &grad)
165  {// image gradient calcul at "x, y, z" image location
166 
171  if (x[0] != 0 and x[0] != oImage.cur_dim(0)-1)
172  {
173  grad[0] = ((T)oImage.m_curImg[0](x[0]+1,x[1],x[2], 0) - (T)oImage.m_curImg[0](x[0]-1,x[1],x[2], 0))/(2.*oImage.m_pix[0]);
174  }
175  else{grad[0] = 0;}
176 
177  if (x[1] != 0 and x[1] != oImage.cur_dim(1)-1)
178  {
179  grad[1] = ((T)oImage.m_curImg[0](x[0],x[1]+1,x[2], 0) - (T)oImage.m_curImg[0](x[0],x[1]-1,x[2], 0))/(2.*oImage.m_pix[1]);
180  }
181  else{grad[1] = 0;}
182 
183  if (this->_3D)
184  {
185  if (x[2] != 0 and x[2] != oImage.cur_dim(2)-1)
186  {
187  grad[2] = ((T)oImage.m_curImg[0](x[0],x[1],x[2]+1, 0) - (T)oImage.m_curImg[0](x[0],x[1],x[2]-1, 0))/(2.*oImage.m_pix[2]);
188  }
189  else{grad[2] = 0;}
190  }
191 
192  }
193 
194  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)
195  {
196 
197  std::vector<T> coor;coor.assign(3,0);
198  for (int i=0; i<lCoor.size(); i++)
199  {
200  coor[i] = gCoor[i]*oImage.m_pix[i] - ref[i];
201  }
202 
203 
204 // std::cout<<"evalShape : "<<list.width()<<"; "<<list.height()<<", "<<list.depth()<<"\n";
205  (oField.m_pShape)->exec(list, coor, N);
206 
207  }
208 
209  virtual void assembly(const int &thread, const Cmesh<T,Timg> &oMesh, const int &elem, const CImgList<T> &Ke, CImgList<T> &K)
210  {//perform assembly of K and F
211 
212  //reduction
213  cimglist_for(Ke,var)
214  {
215  cimg_forXYC(Ke[var],x,y,c)
216  {
217  K[var](x,y) += Ke[var](x,y,0,c);
218  }
219 
220  }
221 
222  }
223 
224  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, CImgList<T> &K)
225  {//calcul K
226 
227  int thread(0), enter(1);
228 
229  #pragma omp single
230  {//init
231 
232  current_res.fill(0);
233  cimglist_for(K,var){K[var].fill(0);}
234 
235  //reset tensors
236  reset(thread,Ke);
237 
238  }
239 
240  //look for the reference system of the element
241  e_ref(oImage, oMesh, 0, ref);
242 
243  #pragma omp for schedule(runtime)
244  for (int pix=0; pix<oImage.m_curImg[0].size(); pix++)
245  {//eval Ke over pix
246 
247  //define global coordonates : find back "x,y,z" triplet
248  oImage.m_curImg[0].contains(oImage.m_curImg[0][pix],lCoor[0],lCoor[1],lCoor[2]);
249  for (int i=0; i<gCoor.size(); i++){gCoor[i]=lCoor[i];}
250 
251  enter = 1;
252  //if pix is unmasked
253  if (!oImage.m_mask.is_empty())
254  {enter = oImage.m_curMask(gCoor[0], gCoor[1], gCoor[2]);}
255 
256  if (enter!=0)
257  {//if pixels are unmasked and in bounds
258 
259  //check the thread number
260  thread = omp_get_thread_num();
261 
262  // Evaluates grad[dim] at (x,y,z) in physical unit
263  gradient(oImage, gCoor, grad);
264 
265  // Evaluates N[dim][mode] at (x,y,z) in physical unit
266 // std::cout<<"metric : "<<oImage.m_curImg[0].width()<<"; "<<oImage.m_curImg[0].height()<<", "<<oImage.m_curImg[0].depth()<<"\n";
267  evalShape(oImage.m_curImg[0], oImage, oField, ref, lCoor, gCoor, N);
268 
269  // Evaluates Ve[dim][mode] at (x,y,z) in physical unit
270  evalGN(grad,N, Ve);
271 
272  // Evaluates U[dim] in physical unit
273  evalU(solution, oMesh, 0, N, U);
274 
275  // Evaluates residue between ref and corrected deformed image at (x,y,z)
276  this->evalRes_loop(oImage, U, gCoor, residue, deformed);
277 
278  //sum of square residues over pixels and elements
279  current_res[thread] += std::pow(residue,2);
280 
281  //evaluate Ke
282  this->tensors(thread, Ve, residue, Ke);
283 
284  }//endif unmasked or out-of-bound
285 
286  }//for implied barrier
287 
288  #pragma omp single
289  {//sum of square residues over threads and normalization and store residue of previous increment
290  assembly(thread, oMesh, 0, Ke, K);
291  oField.m_meanRes.push_back(std::sqrt(current_res.sum())*100/oImage.m_res);
292  }
293 
294  }
295 
296  virtual void solve(CImgList<T> &K, const Cmesh<T,Timg> &oMesh, CImgList<T> &solution)
297  {// K.U = F
298 
299  K[1].solve(K[0]);
300 
301  cimg_forY(K[1],y){solution[y][0] += K[1][y];}
302 
303  if(this->m_verbose){for(int i=0; i<solution.size(); i++){std::cout<<solution[i][0]<<" ";}std::cout<<"\n";}
304 
305  }
306 
307  virtual void test(const CImgList<T> &solution, const double &epsilon, Cfield<T,Timg> &oField, T &previous_res, int &iter, int &converged)
308  {
309 
310  Ccorrelation_opticalFlow<T,Timg>::test(solution, epsilon, oField, previous_res, iter, converged);
311  if(converged)
312  {
313  std::cout<<"Solution vector : [ ";
314  for(int i=0; i<oField.m_mode.size(); i++){std::cout<<oField.m_mode[i][0]<<" ";}std::cout<<"]\n\n";
315  }
316 
317  }
318 
319  virtual void export_res(const Cimage<Timg> &oImage, const Cmesh<T,Timg> &oMesh, Cfield<T,Timg> &oField, CImgList<T> &N, std::vector<T> &ref, std::vector<T> &offset, std::vector<T> &lCoor, std::vector<T> &gCoor, std::vector<T> &U, T &residue, T &deformed, CImg<Timg> &list)
320  {//actualize residue
321 
322  int thread(0),enter(1);
323 
324  //look for the reference system of the element
325  e_ref(oImage, oMesh, 0, ref);
326 
327  #pragma omp for schedule(runtime)
328  for (int pix=0; pix<oImage.m_curImg[0].size(); pix++)
329  {//eval Ke over pix
330 
331  //define global coordonates : find back "x,y,z" triplet
332  oImage.m_curImg[0].contains(oImage.m_curImg[0][pix],lCoor[0],lCoor[1],lCoor[2]);
333  for (int i=0; i<gCoor.size(); i++){gCoor[i]=lCoor[i];}
334 
335  enter = 1;
336  //if pix is unmasked
337  if (!oImage.m_mask.is_empty()){enter = oImage.m_curMask(gCoor[0], gCoor[1], gCoor[2]);}
338 
339  if (enter!=0)
340  {//if pixels are unmasked and in bounds
341 
342  //check the thread number
343  thread = omp_get_thread_num();
344 
345  // Evaluates N[dim][mode] at (x,y,z) in physical unit
346  evalShape(oImage.m_curImg[0], oImage, oField, ref, lCoor, gCoor, N);
347 
348  // Evaluates U[dim] in physical unit
349  evalU(oField.m_mode, oMesh, 0, N, U);
350 
351  // Evaluates residue between ref and corrected deformed image at (x,y,z)
352  this->evalRes_final(oImage, U, gCoor, residue, deformed);
353 
354  //export data
355  store(oField,oImage,gCoor,U,deformed,residue);
356 
357  }//if
358 
359  }//for
360 
361  }
362 
363  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)
364  {//store output data
365 
366  if (oImage.m_storeField)
367  {//store field a iter - 1 to avoid storing the last diverging increment
368  cimglist_for(oField.m_field, dim)
369  {
370  oField.m_field(dim, gCoor[0],gCoor[1],gCoor[2]) = U[dim];
371  }
372  }
373 
374  if (oImage.m_storeDef)
375  {//store imDef a iter - 1
376  oField.m_def(gCoor[0],gCoor[1],gCoor[2]) = deformed;
377  }
378 
379  if (oImage.m_storeRes)
380  {//store imRes a iter - 1
381  oField.m_res(gCoor[0],gCoor[1],gCoor[2]) = residue;
382  }
383 
384  }
385 
386 
387 
388 };
389 
390 
391 #endif
void evalRes_final(const Cimage< Timg > &oImage, const std::vector< T > &U, const std::vector< T > &x, T &residue, T &deformed)
Definition: Ccorrelation_opticalFlow.h:230
virtual void gradient(const Cimage< Timg > &oImage, const std::vector< T > &x, std::vector< T > &grad)
Definition: Ccorrelation_opticalFlow_integrated.h:164
It implements optical flow strategy for FEM method.
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
Definition: Ccorrelation_opticalFlow_integrated.h:43
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
Definition: Ccorrelation_opticalFlow_fem.h:43
virtual void init(CParameterNetCDF &fp)
Definition: Ccorrelation_opticalFlow.h:69