aimsalgo  5.1.2
Neuroimaging image processing
block_matching_d.h
Go to the documentation of this file.
1 /* Copyright (C) 2000-2013 CEA
2  *
3  * This software and supporting documentation were developed by
4  * bioPICSEL
5  * CEA/DSV/I²BM/MIRCen/LMN, Batiment 61,
6  * 18, route du Panorama
7  * 92265 Fontenay-aux-Roses
8  * France
9  */
10 
11 
12 #ifndef AIMS_REGISTRATION_BLOCK_MATCHING_D_H
13 #define AIMS_REGISTRATION_BLOCK_MATCHING_D_H
14 
17 #include <aims/math/math_g.h>
22 #include <cartobase/type/limits.h>
23 #include <vector>
24 
25 
26 template<typename T>
28 {
29  _done=false;
30  _initialisation=Motion();
31  _level_start=-1;
32  _level_stop=-1;
33  _transfo=1;
34  _tailleBloc=Point3d(4,4,4);
35  _cutVar=-1;
36  _stopVar=-1;
37  _Pkept=0.5;
38  _seuilCorrel=-1;
39  _seuils[0]=std::numeric_limits<T>::min();
40  _seuils[1]=std::numeric_limits<T>::max();
41  _seuils[2]=_seuils[0];
42  _seuils[3]=_seuils[1];
43  _itermax=3;
44  _info=false;
45 }
46 
47 
48 template<typename T>
51  const carto::rc_ptr<carto::Volume<T> >& test_orig )
52 {
53 
54 
55  carto::VolumeRef<T> test = carto::VolumeRef<T>( test_orig ).copy();
56 
57  // Mise de l'image test a la resolution de l'image de reference si besoin
58  if( ref->getVoxelSize() != test->getVoxelSize() )
59  {
60  Motion identity;
61  identity.setToIdentity();
63  reech.setRef( test );
64 
65  test = reech.doit( identity,
66  unsigned (test->getSizeX()*test->getVoxelSize()[0]/(1.0*ref->getVoxelSize()[0]) + .5),
67  unsigned (test->getSizeY()*test->getVoxelSize()[1]/(1.0*ref->getVoxelSize()[1]) + .5),
68  unsigned (test->getSizeZ()*test->getVoxelSize()[2]/(1.0*ref->getVoxelSize()[2]) + .5),
69  Point3df(ref->getVoxelSize()[0],ref->getVoxelSize()[1],ref->getVoxelSize()[2]));
70  }
71 
72 
73  // Instanciation des differentes classes externes
74  ScaleControl scaleControl; // Gere la pyramide
75  DisplacementField<T> displacementField; // Calcule le champ d'appariemment
76  Transformation transformation; // Gere le critere de changement d'echelle delta
77  Minimisation minimisation(_Pkept, _transfo); // Calcule la transformation a partir du champ
78 
79 
80  //declaration de l'image transformee a chaque etape
81  carto::VolumeRef<T> testtrans = carto::VolumeRef<T>( test ).copy();
82 
83 
84 
85  // Declaration des differents motions necessaires
86  // p transfo totale precedente, q transfo ponctuelle calculee, r nouvelle transfo totale composee
87  Motion p, q, r ;
88  p=_initialisation;
89  q.setToIdentity();
90  r.setToIdentity();
91 
92  {
94  reech.setRef( test );
95 
96  testtrans = reech.doit( p,
97  testtrans->getSizeX(),
98  testtrans->getSizeY(),
99  testtrans->getSizeZ(),
100  Point3df( testtrans->getVoxelSize() ) );
101  }
102 
103 
104  // Quelques initialisations en millimetres
105  transformation.setX(int(test->getSizeX()*test->getVoxelSize()[0]));
106  transformation.setY(int(test->getSizeY()*test->getVoxelSize()[1]));
107  transformation.setZ(int(test->getSizeZ()*test->getVoxelSize()[2]));
108  transformation.setiterMax(_itermax); //on fixe le nombre maxi d'iter par niveau
109  transformation.setcx(0);
110  transformation.setcy(0);
111  transformation.setcz(0);
112  if(ref->getSizeZ()==1) _tailleBloc[2] = 1;
113  scaleControl.init<T>( ref, _level_start, _level_stop, _cutVar, _stopVar, _seuilCorrel, _tailleBloc);
114  int count = 0 ;
115  // Initialisation de delta au carre de 4 fois un majorant de 2 fois la diagonale en mm...
116  float delta_init = 8*pow(test->getSizeX()*test->getVoxelSize()[0] + test->getSizeY()*test->getVoxelSize()[1] + test->getSizeZ()*test->getVoxelSize()[2], 2);
117 
118 
119  // Affichage de tous les parametres avant debut :
120  if(_info)
121  {
122  std::cout<<std::endl<<"PARAMETRES INITIAUX :"<<std::endl;
123  std::cout<<"Transfo initiale : "<<std::flush;
124  std::cout << p;
125 
126  std::cout<<"Transformation recherchee : ";
127  switch(_transfo){
128  case 1: std::cout<<"RIGIDE"<<std::endl; break;
129  case 2: std::cout<<"SIMILITUDE"<<std::endl; break;
130  case 3: std::cout<<"AFFINE"<<std::endl; break;}
131 
132  std::cout<<"Pyramide debut : "<<scaleControl.getScale()<<" fin : "<<scaleControl.getlevel_stop()<<std::endl;
133  std::cout<<"Taille des blocs : x = "<<_tailleBloc[0]<<" y = "<<_tailleBloc[1]<<" z = "<<_tailleBloc[2]<<std::endl;
134  std::cout<<"Pourcentage de blocs conserves par variance : %initial = "<<scaleControl.getcutVar()<<" %final ="<<scaleControl.getstopVar()<<std::endl;
135  std::cout<<"Seuil sur la mesure de similarite = "<<_seuilCorrel<<std::endl;
136  std::cout<<"Seuils sur les niveaux de gris : "<<std::endl;
137  std::cout<<" seuilBasRef = "<<_seuils[0]<<" seuilHautRef = "<<_seuils[1]<<std::endl;
138  std::cout<<" seuilBasTest = "<<_seuils[2]<<" seuilHautTest = "<<_seuils[3]<<std::endl;
139  std::cout<<"Nombre d'iterations par niveau de pyramide : "<<_itermax<<std::endl;
140  }
141 
142  // MISE DE p EN VOXELS !
143  p.matrix()(0, 3) /= test->getVoxelSize()[0];
144  p.matrix()(1, 3) /= test->getVoxelSize()[1];
145  p.matrix()(2, 3) /= test->getVoxelSize()[2];
146 
147 
148  do
149  {
150  // boucle echelle
151  std::cout << std::endl << std::endl << "PYRAMIDE NIVEAU : " << scaleControl.getScale() << std::endl;
152 
153  transformation.setdeltaprev(delta_init);
154  displacementField.init( ref, scaleControl, _seuils);
155 
156  count = 1; // count compte le nbre d'iterations sans changer d'echelle
157 
158 
159  do
160  {
161  // boucle delta
162  std::cout<<" ITERATION No "<<count<<std::endl;
163 
164  // mise a jour transfo ancienne a ancienne nouvelle...
165  p = q * p ;
166 
167  // Calcul effectif du champ
168  carto::VolumeRef< Point3d > df = displacementField.getField( testtrans);
169 
170  // Attention, le champ va de Ref a Test et non l'inverse !!!!!!!!!!!!!!!!!!!!!!!!
171 
172 
173  // Calcul de la transformation d'etape a partir du champ estime, rappel : q est un motion
174  q = minimisation.quaternion(displacementField); //transfo de test vers ref !!!!
175 
176 
177  // Rappel : r est la transformation totale actualisee, q la calculee courante et p l'ancienne totale
178  // On actualise effectivement r en composant q avec r
179  r = q * p ;
180 
181  // MISE DES TRANSLATIONS EN MILLIMETRES !
182  r.matrix()(0, 3) *= test->getVoxelSize()[0];
183  r.matrix()(1, 3) *= test->getVoxelSize()[1];
184  r.matrix()(2, 3) *= test->getVoxelSize()[2];
185 
186 
187  // Resampling de test en testtrans par r la transfo totale la plus recente
188  aims::LinearResampler<T> resampler;
189  resampler.setRef( test );
190  testtrans = resampler.doit( r, test->getSizeX(), test->getSizeY(), test->getSizeZ(),
191  Point3df(test->getVoxelSize()) );
192 
193 
194  // Compteur du nombre d'iterations a cette echelle
195  ++count ;
196 
197  } while ( count < (_itermax + 1) ); // On fait itermax iterations exactement a chaque niveau de pyramide
198 
199 
200  // On a fini d'iterer a cette echelle, on monte un niveau de pyramide
201  scaleControl.nextScale();
202 
203 
204  } while (scaleControl.goOn()); // test fin pyramide
205 
206 
207  _result = carto::VolumeRef<T>( test_orig ).copy();
209  linres.setRef( test_orig );
210  _result = linres.doit( r,
211  test_orig->getSizeX(),
212  test_orig->getSizeY(),
213  test_orig->getSizeZ(),
214  Point3df( test_orig->getVoxelSize() ) );
215 
216  _done=true;
217 
218 // std::cout<<"C'est fini!"<<std::endl<<"Le motion trouve est : "<<std::endl;
219 // std::cout << r << std::endl;
220  return(r);
221 }
222 
223 #endif
224 
aims::AffineTransformation3d doit(carto::rc_ptr< carto::Volume< T > > &ref, const carto::rc_ptr< carto::Volume< T > > &test_orig)
void init(carto::rc_ptr< carto::Volume< T > > ref, ScaleControl &scaleControl, T *seuils)
carto::VolumeRef< Point3d > getField(carto::rc_ptr< carto::Volume< T > > test)
Motion quaternion(DisplacementField< T > &displacementField)
void init(const carto::rc_ptr< carto::Volume< T > > ref, int level_start, int level_stop, double cutVar, double stopVar, double seuilCorrel, const Point3d &tailleBloc=Point3d(4, 4, 4))
double getstopVar()
Definition: scale_control.h:35
double getcutVar()
Definition: scale_control.h:34
void nextScale()
int getlevel_stop()
Definition: scale_control.h:31
void setY(int Y)
void setcx(float cx)
void setcy(float cy)
void setcz(float cz)
void setX(int X)
void setiterMax(int max)
void setdeltaprev(float d)
void setZ(int Z)
Volume resampler using linear (order 1) interpolation.
void setRef(const carto::rc_ptr< carto::Volume< T > > &ref)
Set the input data to be resampled by the doit() methods.
Definition: resampler_d.h:311
void doit(const aims::AffineTransformation3d &transform, carto::Volume< T > &output_data) const
Resample the input volume set with setRef() into an existing volume.
Definition: resampler_d.h:226
int getSizeZ() const
std::vector< float > getVoxelSize() const
int getSizeY() const
int getSizeX() const
VolumeRef< T > copy() const
reference_wrapper< T > ref(T &ref)
static _Tp min()
static _Tp max()