uLib-0.2
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
VoxImage.h
Go to the documentation of this file.
1 /*//////////////////////////////////////////////////////////////////////////////
2 // CMT Cosmic Muon Tomography project //////////////////////////////////////////
4 
5  Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova
6  All rights reserved
7 
8  Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it >
9 
10  ------------------------------------------------------------------
11  This library is free software; you can redistribute it and/or
12  modify it under the terms of the GNU Lesser General Public
13  License as published by the Free Software Foundation; either
14  version 3.0 of the License, or (at your option) any later version.
15 
16  This library is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public
22  License along with this library.
23 
25 
26 
27 
28 #ifndef U_MATH_VOXIMAGE_H
29 #define U_MATH_VOXIMAGE_H
30 
31 #include "Core/StaticInterface.h"
32 #include "Math/Dense.h"
33 #include "Math/StructuredGrid.h"
34 
35 #include <iostream>
36 #include <stdlib.h>
37 #include <vector>
38 
39 namespace uLib {
40 
42 // ABSTRACT VOX IMAGE //////////////////////////////////////////////////////
44 
45 namespace Abstract {
46 
47 class VoxImage : public uLib::StructuredGrid {
48 public:
49  typedef uLib::StructuredGrid BaseClass;
50 
51  virtual float GetValue(const Vector3i &id) const = 0;
52  virtual float GetValue(const int id) const = 0;
53  virtual void SetValue(const Vector3i &id, float value) = 0;
54  virtual void SetValue(const int id, float value) = 0;
55 
56  virtual void SetDims(const Vector3i &size) = 0;
57 
58  void ExportToVtk(const char *file, bool density_type = 0);
59  void ExportToVtkXml(const char *file, bool density_type = 0);
60  int ImportFromVtk(const char *file);
61 
62 protected:
63 
64  virtual ~VoxImage() {}
65  VoxImage(const Vector3i &size) : BaseClass(size) {}
66 };
67 
68 }
69 
71 // VOXEL ////////////////////////////////////////////////////////////////////
73 
74 namespace Interface {
75 struct Voxel {
76  template<class Self> void check_structural() {
77  uLibCheckMember(Self,Value, Scalarf);
78  }
79 };
80 }
81 
82 struct Voxel {
83  Scalarf Value;
84 };
85 
86 
88 // VOX IMAGE /////////////////////////////////////////////////////////////////
90 
91 
92 template< typename T >
93 class VoxImage : public Abstract::VoxImage {
94 public:
95  typedef Abstract::VoxImage BaseClass;
96 
97  VoxImage();
98 
99  VoxImage(const Vector3i &size);
100 
101  VoxImage(const VoxImage<T> &copy) :
102  BaseClass(copy)
103  {
104  this->m_Data = copy.m_Data;
105  }
106 
107  inline std::vector<T> & Data() { return this->m_Data; }
108  inline const std::vector<T>& ConstData() const { return m_Data; }
109 
110  inline const T& At(int i) const { return m_Data.at(i); }
111  inline const T& At(const Vector3i &id) const { return m_Data.at(Map(id)); }
112  inline T& operator[](unsigned int i) { return m_Data[i]; }
113  inline T& operator[](const Vector3i &id) { return m_Data[Map(id)]; }
114 
115  // this implements Abstract interface //
116  inline Scalarf GetValue(const Vector3i &id) const {
117  return this->At(id).Value;
118  }
119  inline Scalarf GetValue(const int id) const {
120  return this->At(id).Value;
121  }
122 
123  inline void SetValue(const Vector3i &id, Scalarf value) {
124  this->operator [](id).Value = value;
125  }
126  inline void SetValue(const int id, float value) {
127  this->operator [](id).Value = value;
128  }
129 
130  inline void SetDims(const Vector3i &size) {
131  this->m_Data.resize(size.prod());
132  BaseClass::BaseClass::SetDims(size); // FIX horrible coding style !
133  }
134 
135  inline VoxImage<T> clipImage(const Vector3i begin, const Vector3i end) const;
136  inline VoxImage<T> clipImage(const HPoint3f begin, const HPoint3f end) const;
137  inline VoxImage<T> clipImage(const float density) const;
138  inline VoxImage<T> clipImage(const float densityMin, const float densityMax) const;
139 
140  inline VoxImage<T> maskImage(const HPoint3f begin, const HPoint3f end, float value) const;
141  inline VoxImage<T> maskImage(const float threshold, float belowValue=0, float aboveValue=0) const;
142  inline VoxImage<T> fixVoxels(const float threshold, float tolerance) const;
143  inline VoxImage<T> fixVoxels(const float threshold, float tolerance, const HPoint3f begin, const HPoint3f end) const;
144  inline VoxImage<T> fixVoxelsAroundPlane(const float threshold, float tolerance, const HPoint3f begin, const HPoint3f end, bool aboveAir) const;
145  inline VoxImage<T> fixVoxels(const HPoint3f begin, const HPoint3f end) const;
146  inline VoxImage<T> Abs() const;
147 
148  inline void SelectScalarfComponent(T &element, Scalarf *scalar);
149 
150  inline void InitVoxels(T t);
151 
152  // MATH OPERATORS //
153  inline void operator *=(Scalarf scalar) {
154  for(unsigned int i = 0; i < m_Data.size(); ++i)
155  m_Data[i].Value *= scalar;
156  }
157  inline void operator +=(Scalarf scalar) {
158  for(unsigned int i = 0; i < m_Data.size(); ++i)
159  m_Data[i].Value += scalar;
160  }
161  inline void operator /=(Scalarf scalar) {
162  for(unsigned int i = 0; i < m_Data.size(); ++i)
163  m_Data[i].Value /= scalar;
164  }
165  inline void operator -=(Scalarf scalar) {
166  for(unsigned int i = 0; i < m_Data.size(); ++i)
167  m_Data[i].Value -= scalar;
168  }
169 
170  // MATH VoxImage Operators //
171  template <typename S>
172  void operator +=(VoxImage<S> &sibling) {
173  if (this->GetDims() != sibling.GetDims()) {
174  //printf("Warning when adding VoxImages: I'm NOT doing it!\n");
175  return;
176  }// WARNING! You must Warn the user!
177  for(unsigned int i = 0; i < m_Data.size(); ++i) {
178  m_Data[i].Value += sibling.At(i).Value;
179  }
180  }
181 
182  template <typename S>
183  void operator -=(VoxImage<S> &sibling) {
184  if (this->GetDims() != sibling.GetDims()) {
185  //printf("Warning when subtracting VoxImages: I'm NOT doing it!\n");
186  return;
187  }// WARNING! You must Warn the user!
188  for(unsigned int i = 0; i < m_Data.size(); ++i) {
189  m_Data[i].Value -= sibling.At(i).Value;
190  }
191  }
192 
193  template <typename S>
194  void operator *=(VoxImage<S> &sibling) {
195  if (this->GetDims() != sibling.GetDims()) {
196  //printf("Warning when multiplying VoxImages: I'm NOT doing it!\n");
197  return;
198  }// WARNING! You must Warn the user!
199  for(unsigned int i = 0; i < m_Data.size(); ++i) {
200  m_Data[i].Value *= sibling.At(i).Value;
201  }
202  }
203 
204  template <typename S>
205  void operator /=(VoxImage<S> &sibling) {
206  if (this->GetDims() != sibling.GetDims()) {
207  //printf("Warning when dividing VoxImages: I'm NOT doing it!\n");
208  return;
209  }// WARNING! You must Warn the user!
210  for(unsigned int i = 0; i < m_Data.size(); ++i) {
211  m_Data[i].Value /= sibling.At(i).Value;
212  }
213  }
214 
215 private:
216  std::vector<T> m_Data;
217 };
218 
219 
220 template<typename T>
221 VoxImage<T>::VoxImage() :
222  m_Data(0),
223  BaseClass(Vector3i(0,0,0))
224 { Interface::IsA <T,Interface::Voxel>(); /* structural check for T */ }
225 
226 template<typename T>
228  m_Data(size.prod()),
229  BaseClass(size)
230 { Interface::IsA <T,Interface::Voxel>(); /* structural check for T */ }
231 
232 
233 template <typename T>
235 {
236  Vector3i dim = (end-begin)+Vector3i(1,1,1);
237  VoxImage<T> out(*this);
238  out.SetDims(dim);
239  out.SetPosition(this->GetPosition() + this->GetSpacing().cwiseProduct(begin.cast<float>()) );
240 
241  for(uint x = 0; x<dim(0); ++x )
242  for(uint y = 0; y<dim(1); ++y )
243  for(uint z = 0; z<dim(2); ++z )
244  {
245  Vector3i id = Vector3i(x,y,z);
246  out[id] = this->At(begin + id);
247  }
248  return out;
249 }
250 
251 template <typename T>
253 {
254  Vector3i v1 = this->Find(begin);
255  Vector3i v2 = this->Find(end);
256  return this->clipImage(v1,v2);
257 }
258 
259 template <typename T>
260 VoxImage<T> VoxImage<T>::clipImage(const float density) const
261 {
262  Vector3i v1 = this->GetDims();
263  Vector3i v2 = Vector3i(0,0,0);
264  for(uint i=0; i< this->m_Data.size(); ++i) {
265  if( this->GetValue(i) >= density ) {
266  Vector3i id = this->UnMap(i);
267  v1 = v1.array().min(id.array());
268  v2 = v2.array().max(id.array());
269  }
270  }
271  return this->clipImage(v1,v2);
272 }
273 
274 template <typename T>
275 VoxImage<T> VoxImage<T>::clipImage(const float densityMin, const float densityMax) const
276 {
277  Vector3i v1 = this->GetDims();
278  Vector3i v2 = Vector3i(0,0,0);
279  for(uint i=0; i< this->m_Data.size(); ++i) {
280  if( this->GetValue(i) >= densityMin && this->GetValue(i) <= densityMax) {
281  Vector3i id = this->UnMap(i);
282  v1 = v1.array().min(id.array());
283  v2 = v2.array().max(id.array());
284  }
285  }
286  return this->clipImage(v1,v2);
287 }
288 
289 template <typename T>
290 VoxImage<T> VoxImage<T>::maskImage(const HPoint3f begin, const HPoint3f end, float value) const
291 {
292  VoxImage<T> out(*this);
293  out.SetDims(this->GetDims());
294  out.SetPosition(this->GetPosition());
295 
296  Vector3i voxB = this->Find(begin);
297  Vector3i voxE = this->Find(end);
298 
299  Vector3i ID;
300 
301  for(int ix=voxB(0); ix<voxE(0); ix++)
302  for(int iy=voxB(1); iy<voxE(1); iy++)
303  for(int iz=voxB(2); iz<voxE(2); iz++){
304  ID << ix,iy,iz;
305  out.SetValue(ID,value*1.E-6);
306  }
307 
308  return out;
309 }
310 
311 template <typename T>
312 VoxImage<T> VoxImage<T>::maskImage(const float threshold, float belowValue, float aboveValue) const
313 {
314  std::cout << "VoxImage: maskImage, fixing voxels under threshold " << threshold;
315  if(belowValue)
316  std::cout << " at value " << belowValue;
317  else
318  std::cout << " at -value";
319  std::cout << ", voxels above threshold at value ";
320  if(aboveValue)
321  std::cout << aboveValue;
322  else
323  std::cout << "found";
324 
325 
326  VoxImage<T> out(*this);
327  out.SetDims(this->GetDims());
328  out.SetPosition(this->GetPosition());
329 
330  for(uint i=0; i< this->m_Data.size(); ++i) {
331  // skip negative voxels: they are already frozen
332  if( this->GetValue(i) >= 0 ){
333  // voxels under threshold
334  if( this->GetValue(i) <= threshold*1.E-6 ){
335  if(belowValue){
336  // std::cout << "vox " << i << ", " << this->GetValue(i);
337  // std::cout << " ----> set to " << -1.*belowValue*1.E-6 << std::endl;
338  out.SetValue(i,-1.*belowValue*1.E-6);}
339  else
340  out.SetValue(i,-1.*this->GetValue(i));
341  }
342  // voxels over threshold
343  else{
344  if(aboveValue)
345  out.SetValue(i,aboveValue*1.E-6);
346  else
347  out.SetValue(i,this->GetValue(i));
348  }
349  }
350  }
351  return out;
352 }
353 
354 template <typename T>
355 VoxImage<T> VoxImage<T>::fixVoxels(const float threshold, float tolerance) const
356 {
357  std::cout << "VoxImage: fixing voxels with value " << threshold << std::endl;
358 
359  VoxImage<T> out(*this);
360  out.SetDims(this->GetDims());
361  out.SetPosition(this->GetPosition());
362 
363  for(uint i=0; i< this->m_Data.size(); ++i) {
364  // voxels around threshold
365  if( fabs(this->GetValue(i) - threshold*1.E-6) < tolerance* 1.E-6 ){
366 // std::cout << "vox " << i << ", " << this->GetValue(i);
367 // std::cout << " ----> set to " << -1.*this->GetValue(i) << std::endl;
368  out.SetValue(i,-1.*this->GetValue(i));
369  }
370  }
371  return out;
372 }
373 
374 template <typename T>
376 {
377  std::cout << "VoxImage: set abs voxels value " << std::endl;
378 
379  VoxImage<T> out(*this);
380  out.SetDims(this->GetDims());
381  out.SetPosition(this->GetPosition());
382 
383  for(uint i=0; i< this->m_Data.size(); ++i)
384  out.SetValue(i,fabs(this->GetValue(i)));
385 
386  return out;
387 }
388 
389 template <typename T>
390 VoxImage<T> VoxImage<T>::fixVoxels( const float threshold, float tolerance, const HPoint3f begin, const HPoint3f end) const
391 {
392  VoxImage<T> out(*this);
393  out.SetDims(this->GetDims());
394  out.SetPosition(this->GetPosition());
395 
396  Vector3i voxB = this->Find(begin);
397  Vector3i voxE = this->Find(end);
398 
399  Vector3i ID;
400 
401  for(int ix=voxB(0); ix<voxE(0); ix++)
402  for(int iy=voxB(1); iy<voxE(1); iy++)
403  for(int iz=voxB(2); iz<voxE(2); iz++){
404  ID << ix,iy,iz;
405  // voxels around threshold
406  if( fabs(this->GetValue(ID) - threshold*1.E-6) < tolerance*1.E-6 ){
407  out.SetValue(ID,-1.*this->GetValue(ID));
408  }
409  }
410 
411  return out;
412 }
413 
414 template <typename T>
416 {
417  VoxImage<T> out(*this);
418  out.SetDims(this->GetDims());
419  out.SetPosition(this->GetPosition());
420 
421  Vector3i voxB = this->Find(begin);
422  Vector3i voxE = this->Find(end);
423 
424  Vector3i ID;
425 
426  for(int ix=voxB(0); ix<voxE(0); ix++)
427  for(int iy=voxB(1); iy<voxE(1); iy++)
428  for(int iz=voxB(2); iz<voxE(2); iz++){
429  ID << ix,iy,iz;
430  // voxels around threshold
431  out.SetValue(ID,-1.*this->GetValue(ID));
432  }
433  return out;
434 }
435 
436 
437 template <typename T>
438 VoxImage<T> VoxImage<T>::fixVoxelsAroundPlane( const float threshold, float tolerance, const HPoint3f B, const HPoint3f E, bool aboveAir) const
439 {
440  VoxImage<T> out(*this);
441  Vector3i dim = this->GetDims();
442  out.SetDims(dim);
443  out.SetPosition(this->GetPosition());
444 
445  HPoint3f Bcoll = this->GetPosition().homogeneous();
446 
447  Vector3i ID;
448  for(int ix=0; ix<dim(0); ix++)
449  for(int iy=0; iy<dim(1); iy++)
450  for(int iz=0; iz<dim(2); iz++){
451  ID << ix,iy,iz;
452 
453  // B, E voxel position
454  Vector3i iv(ix,iy,iz);
455  Vector3f v = Vector3f(iv.cast<float>().cwiseProduct(this->GetSpacing()));
456  HPoint3f Bvox = Bcoll + HPoint3f(v);
457  HPoint3f Evox = Bvox + this->GetSpacing().homogeneous();
458  HPoint3f V = Bvox + 0.5*(this->GetSpacing().homogeneous());
459 
460  // if distance point (x0,y0) from line by points (x1,y1) and (x2,y2) is less than tolerance
461  float x1 = B[1];
462  float y1 = B[2];
463  float x2 = E[1];
464  float y2 = E[2];
465  float x0 = V[1];
466  float y0 = V[2];
467  float dist = fabs( (x2-x1)*(y1-y0) - ((x1-x0)*(y2-y1))) / sqrt( (x2-x1)*(x2-x1)+((y2-y1)*(y2-y1)));
468  float distSign = (x2-x1)*(y1-y0) - ((x1-x0)*(y2-y1));
469 
470  // set voxel air value
471  if(dist < tolerance){
472  //std::cout << "voxel " << iv << ", line " << dist << ", tolerance " << tolerance << std::endl;
473  out.SetValue(ID,threshold*1.E-6);
474  }
475  else
476  out.SetValue(ID,this->GetValue(ID));
477 
478  if((distSign>0 && aboveAir) || (distSign<0 && !aboveAir) )
479  out.SetValue(ID,threshold*1.E-6);
480  }
481  return out;
482 }
483 
484 
485 template<typename T>
487 {
488  std::fill( m_Data.begin(), m_Data.end(), t ); // warning... stl function //
489 }
490 
491 }
492 
493 #endif // VOXIMAGE_H
void SetValue(const Vector3i &id, Scalarf value)
Definition: VoxImage.h:123
Definition: ContainerBox.h:38
Eigen::Vector3i Vector3i
Definition: Dense.h:134
VoxImage< T > maskImage(const HPoint3f begin, const HPoint3f end, float value) const
Definition: VoxImage.h:290
Eigen::Vector3f Vector3f
Definition: Dense.h:139
VoxImage< T > fixVoxels(const float threshold, float tolerance) const
Definition: VoxImage.h:355
VoxImage< T > fixVoxelsAroundPlane(const float threshold, float tolerance, const HPoint3f begin, const HPoint3f end, bool aboveAir) const
Definition: VoxImage.h:438
void SetPosition(const Vector3f &v)
Definition: Transform.h:96
VoxImage< T > Abs() const
Definition: VoxImage.h:375
void SetDims(const Vector3i &size)
Definition: VoxImage.h:130
_HPoint3f< true > HPoint3f
Definition: Dense.h:219
VoxImage< T > clipImage(const Vector3i begin, const Vector3i end) const
Definition: VoxImage.h:234
void InitVoxels(T t)
Definition: VoxImage.h:486
Definition: VoxImage.h:93