aimsalgo 6.0.0
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
26template<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
48template<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()
double getcutVar()
void nextScale()
int getlevel_stop()
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.
void doit(const aims::AffineTransformation3d &transform, carto::Volume< T > &output_data) const
Resample the input volume set with setRef() into an existing volume.
int getSizeZ() const
std::vector< float > getVoxelSize() const
int getSizeY() const
VolumeRef< T > copy() const
int getSizeX() const
aims::AffineTransformation3d Motion
static _Tp min()
static _Tp max()
AimsVector< float, 3 > Point3df
AimsVector< int16_t, 3 > Point3d