1 #ifndef TIL_IMAGETOOLS_H 2 #define TIL_IMAGETOOLS_H 15 #include "boost/utility/enable_if.hpp" 35 template <
class TImage >
37 {
return im.isAllocated(); }
41 template <
class TImage >
46 throw std::invalid_argument(
"Unallocated image");
53 template <
class TImage1,
class TImage2 >
59 template <
class TImage1,
class TImage2 >
64 (im1.dim()[0] == im2.dim()[0]) &&
65 (im1.dim()[1] == im2.dim()[1]) &&
66 (im1.dim()[2] == im2.dim()[2]) &&
67 (im1.vdim()[0] == im2.vdim()[0]) &&
68 (im1.vdim()[1] == im2.vdim()[1]) &&
69 (im1.vdim()[2] == im2.vdim()[2]);
74 template <
class TImage1,
class TImage2 >
83 throw std::invalid_argument(
"Incompatible images");
89 template <
class TImage1,
class TImage2 >
93 template <
class TImage >
94 typename boost::enable_if<is_Image<TImage>,
bool>::type
103 template <
class TImage1,
class TImage2 >
104 typename boost::enable_if_c<
105 is_Image<TImage1>::value &&
106 is_Image<TImage2>::value
115 throw std::invalid_argument(
"Pointers point to the same image");
121 template <
class TImage >
124 std::cout <<
"Image Type : " <<
typeid(
typename TImage::value_type).name() << std::endl;
125 std::cout <<
"Image Size : " << im.dim()[0] <<
" "<< im.dim()[1] <<
" "<< im.dim()[2] << std::endl;
126 std::cout <<
"Image Voxel Size : " << im.vdim()[0] <<
" "<< im.vdim()[1] <<
" "<< im.vdim()[2] << std::endl;
132 template <
class TImage >
133 void copy(
const TImage &in, TImage &out)
149 template <
typename TImage >
153 double rx,
double ry,
double rz,
155 int sx,
int sy,
int sz,
156 typename TImage::value_type foreground,
157 typename TImage::value_type background
161 if (rx <=0 || ry <= 0 || rz <= 0)
163 throw std::invalid_argument(
"Invalid radii");
169 sx =2*(int)(ceil(2*rx))+1;
173 sy =2*(int)(ceil(2*ry))+1;
177 sz =2*(int)(ceil(2*rz))+1;
185 double cx = (sx-1.0)/2;
186 double cy = (sy-1.0)/2;
187 double cz = (sz-1.0)/2;
190 for (k = 0; k < im.dim()[2]; ++k)
192 for (j = 0; j < im.dim()[1]; ++j)
194 for (i = 0; i < im.dim()[0]; ++i)
200 foreground : background;
215 template <
typename TImage >
218 typename TImage::value_type amplitude,
222 typedef typename TImage::value_type value_type;
224 const double SIGMA_MIN = 0.0;
226 if (sigma[0] < SIGMA_MIN || sigma[1] < SIGMA_MIN || sigma[2] < SIGMA_MIN)
228 throw std::invalid_argument(
"Standard deviation is too small");
235 size[0] = 2*
max(1,castValue<double, int>(3.0*ceil((
double)sigma[0]))) + 1;
239 size[1] = 2*
max(1,castValue<double, int>(3.0*ceil((
double)sigma[1]))) + 1;
243 size[2] = 2*
max(1,castValue<double, int>(3.0*ceil((
double)sigma[2]))) + 1;
246 im.init(size, voxSize);
260 for (k = 0; k < im.dim()[2]; ++k)
262 for (j = 0; j < im.dim()[1]; ++j)
264 for (i = 0; i < im.dim()[0]; ++i)
277 template <
typename TImage >
279 double sigmaX,
double sigmaY,
double sigmaZ,
281 int sx,
int sy,
int sz)
291 template <
typename T1,
typename TImage2>
294 T1 sigmaX, sigmaY, sigmaZ;
300 hx = castValue<double, int>(3.0*ceil(sigmaX));
301 hy = castValue<double, int>(3.0*ceil(sigmaY));
302 hz = castValue<double, int>(3.0*ceil(sigmaZ));
307 template <
typename TImage >
314 throw std::invalid_argument(
"Point is outside image or on image border");
317 mat.
set(0,0, (im.getUnsafeValue(x+1,y,z) + im.getUnsafeValue(x-1,y,z) - 2*im.getUnsafeValue(x,y,z)) /
square(im.vdim()[0]));
318 mat.
set(1,1, (im.getUnsafeValue(x,y+1,z) + im.getUnsafeValue(x,y-1,z) - 2*im.getUnsafeValue(x,y,z)) /
square(im.vdim()[1]));
319 mat.
set(2,2, (im.getUnsafeValue(x,y,z+1) + im.getUnsafeValue(x,y,z-1) - 2*im.getUnsafeValue(x,y,z)) /
square(im.vdim()[2]));
321 mat.
set(0,1, (im.getUnsafeValue(x+1,y+1,z) + im.getUnsafeValue(x-1,y-1,z) - im.getUnsafeValue(x+1,y-1,z) - im.getUnsafeValue(x-1,y+1,z)) / ( im.vdim()[0] * im.vdim()[1] ));
322 mat.
set(0,2, (im.getUnsafeValue(x+1,y,z+1) + im.getUnsafeValue(x-1,y,z-1) - im.getUnsafeValue(x+1,y,z-1) - im.getUnsafeValue(x-1,y,z+1)) / ( im.vdim()[0] * im.vdim()[2] ));
323 mat.
set(1,2, (im.getUnsafeValue(x,y+1,z+1) + im.getUnsafeValue(z,y-1,z-1) - im.getUnsafeValue(x,y+1,z-1) - im.getUnsafeValue(x,y-1,z+1)) / ( im.vdim()[1] * im.vdim()[2] ));
328 template <
typename TImage >
339 template <
typename TImage >
342 if (!(im.dim()[0]%2 && im.dim()[1]%2 && im.dim()[2]%2))
344 throw std::invalid_argument(
"Even image size");
347 cx = im.dim()[0] / 2;
348 cy = im.dim()[1] / 2;
349 cz = im.dim()[2] / 2;
369 template <
typename TImage >
371 typename boost::enable_if<is_Image<TImage>,
bool>::type
374 return all_greater_equal(pos, 0) && all_less(pos, im.dim());
383 template <
typename TImage >
400 ( offset[0] == 0 || (pos[0] + offset[0] >= 0 && pos[0] + offset[0] < im.dim()[0])) &&
401 ( offset[1] == 0 || (pos[1] + offset[1] >= 0 && pos[1] + offset[1] < im.dim()[1])) &&
402 ( offset[2] == 0 || (pos[2] + offset[2] >= 0 && pos[2] + offset[2] < im.dim()[2]))
407 template <
typename TImage >
415 template <
typename TImage >
437 template <
typename TImage >
441 typename std::vector<typename TImage::value_type>::iterator iBar = bar.begin();
442 for (iIm.set_pos(pos); iBar != bar.end(); iIm.next(axis), ++iBar)
464 template <
typename TImage >
468 typename std::vector<typename TImage::value_type>::const_iterator iBar = bar.begin();
469 for (iIm.set_pos(pos); iBar != bar.end(); iIm.next(axis), ++iBar)
488 template <
typename TImage >
491 typedef typename TImage::value_type value_type;
493 if (std::numeric_limits<value_type>::is_integer)
495 throw std::domain_error(
"Defined for floating numbers only");
498 value_type nrm =
sum(im);
500 const value_type EPSILON = 128 * std::numeric_limits<value_type>::epsilon();
504 throw std::underflow_error(
"kernel norm too small");
507 mul(im, value_type(1.0/nrm));
513 template <
typename T >
516 if ( x<0 || y<0 || z<0)
518 throw std::invalid_argument(
"Image size < 0");
523 for (
int i=0; i < z; ++i)
525 res[i] = data + i * x * y;
532 template <
typename TImage >
540 template <
typename BoolFunctor,
typename TImage >
542 itlin(TImage &im,
const BoolFunctor &boolFunctor = BoolFunctor())
547 template <
typename TImage >
554 template <
typename BoolFunctor,
typename TImage >
556 itlin_const(
const TImage &im,
const BoolFunctor &boolFunctor = BoolFunctor())
561 template <
typename TImage >
568 template <
typename BoolFunctor,
typename TImage >
570 itvol(TImage &im,
const BoolFunctor &boolFunctor = BoolFunctor())
575 template <
typename TImage >
582 template <
typename BoolFunctor,
typename TImage >
584 itvol_const(
const TImage &im,
const BoolFunctor &boolFunctor = BoolFunctor())
592 template <
typename TImage >
596 typename TImage::value_type
min,
597 typename TImage::value_type
max 605 warning(
"til::rand: input max < min, setting max := min");
610 for (; !iIm.isAtEnd(); ++iIm)
612 *iIm =
rand(min, max);
619 template <
typename TImage >
623 typename TImage::value_type value
628 range.
set_bounds(axis, sliceNumber, sliceNumber);
631 for (; !iIm.isAtEnd(); ++iIm)
639 template <
typename TImage >
643 typename TImage::value_type background = 0
648 for (; !iIm.isAtEnd(); ++iIm)
651 (iIm.pos()[0] == 0) ||
652 (iIm.pos()[1] == 0) ||
653 (iIm.pos()[2] == 0) ||
654 (iIm.pos()[0] == im.dim()[0] - 1) ||
655 (iIm.pos()[1] == im.dim()[1] - 1) ||
656 (iIm.pos()[2] == im.dim()[2] - 1))
664 template <
int dx,
int dy,
int dz,
class VolumetricImageIterator>
668 (dx >= 0 || iIm.pos()[0] > 1+dx) &&
669 (dx <= 0 || iIm.pos()[0] < iIm.image().dim()[0]-dx) &&
671 (dy >= 0 || iIm.pos()[1] > 1+dy) &&
672 (dy <= 0 || iIm.pos()[1] < iIm.image().dim()[1]-dy) &&
674 (dz >= 0 || iIm.pos()[2] > 1+dz) &&
675 (dz <= 0 || iIm.pos()[2] < iIm.image().dim()[2]-dz));
679 template <
typename TImage,
typename T >
686 return mul<numeric_array<double,3> >(volumePos, im.vdim());
689 template <
typename TImage >
697 return div<numeric_array<double,3> >(worldPos, im.vdim());
A trait class to assign iterators to image types.
void setSlice(TImage &im, int sliceNumber, ImageAxis axis, typename TImage::value_type value)
Set a value to an image slice.
void convert(TTo &x, const TFrom &y)
boost::enable_if_c< is_Image< TImage1 >::value &&is_Image< TImage2 >::value >::type notSameImageCheck(const TImage1 &im1, const TImage2 &im2)
boost::enable_if< is_Image< TImage >, typename TImage::value_type >::type min(const TImage &im)
Iterator< TImage >::ConstLinear itlin_const(const TImage &im)
void set_bounds(const numeric_array< T, D > &minBounds, const numeric_array< T, D > &maxBounds)
Set min and max bounds.
void similarityCheck(const TImage1 &im1, const TImage2 &im2)
Check whether both images are allocated and have the same size and voxel size.
void getImageCenter(const TImage &im, int &cx, int &cy, int &cz)
Get coordinates of image center.
void getLocalHessian(const TImage &im, SymMatrix3< typename TImage::value_type > &mat, int x, int y, int z)
A class to store a 3*3 symetric matrix.
void clearBorder(TImage &im, typename TImage::value_type background=0)
Clear image borders.
Belongs to package Box Do not include directly, include til/Box.h instead.
numeric_array< int, 3 > getCenter(TImage &im)
Get coordinates of image center.
void printInfo(ConstVolumetricIterator< ImageNC< T > > &it)
void set(const std::pair< std::size_t, std::size_t > &i, T value)
Set a value to the matrix.
numeric_array< T, D > size(const Box< T, D > &box)
Return the size of a box.
General macros, definitions and functions.
void deduceImageSizeFromGaussianStandardDeviation(T1 sigma, const TImage2 &im, int &hx, int &hy, int &hz)
Iterator< TImage >::Volumetric itvol(TImage &im)
Conditional iterator for images.
Defines empty classes that serves as labels.
void generateEllipsoidImage(TImage &im, double rx, double ry, double rz, t_voxsize vx, t_voxsize vy, t_voxsize vz, int sx, int sy, int sz, typename TImage::value_type foreground, typename TImage::value_type background)
Creates an image with an ellipsoid centered on the image center.
void extractBar(const TImage &im, const numeric_array< int, 3 > &pos, ImageAxis axis, std::vector< typename TImage::value_type > &bar)
Extract the line starting from (x,y,z) in the direction of axis from im to bar.
void rand(TImage &im, typename TImage::value_type min, typename TImage::value_type max)
Fills the image with random numbers uniformly distributed on [min, max].
numeric_array< T, D > abs(const numeric_array< T, D > &a)
Absolute value, element-wise.
void generateGaussianImage(TImage &im, numeric_array< double, 3 > sigma, typename TImage::value_type amplitude, numeric_array< t_voxsize, 3 > voxSize, numeric_array< int, 3 > size)
Creates an image with a Gaussian around image center.
bool containsNeighbor(const VolumetricImageIterator &iIm)
INLINE void allocationCheck(const TImage &im)
Check whether smart pointer and image are allocated.
INLINE boost::enable_if< is_Image< TImage >, numeric_array< double, 3 > >::type vol2world(const TImage &im, const numeric_array< T, 3 > &volumePos)
Get the world coordinates of an image point.
t_bsprec sum(const TImage &im)
Computes the sum of the intensities of the input image.
void warning(const char *msg)
Library warning.
TImage::value_type max(const TImage &im)
Returns the maximum intensity of the input image.
void copy(const TImage &in, TImage &out)
Copy one image to another.
INLINE bool isAllocated(const TImage &im)
Check whether smart pointer and image are allocated.
bool areSameObject(const TImage1 &, const TImage2 &)
Check that inputs do not point to the same image.
boost::enable_if< is_numeric_container< TStorage >, bool >::type contains(const Box< T, D > &box, const TStorage &v)
Check whether a point lies within box.
Iterator< TImage >::ConstVolumetric itvol_const(const TImage &im)
Range< int, 3 > getRange(const TImage &im)
Get image range.
void setSumToOne(TImage &im)
Normalize the image so that the sum of its element is equal to one.
T modifySigmaAccordingToVoxelSize(T sigma, const numeric_array< float, 3 > &vdim, ImageAxis axis)
INLINE bool areSimilar(const TImage1 &im1, const TImage2 &im2)
void insertBar(TImage &im, const numeric_array< int, 3 > &pos, ImageAxis axis, const std::vector< typename TImage::value_type > &bar)
Insert the line starting from (x,y,z) in the direction of axis from bar to im.
Box< double, 3 > getBoundingBox(const TImage &im)
Get image bounding box.
A 3D box parallel to canonical axes.
INLINE boost::enable_if< is_Image< TImage >, numeric_array< double, 3 > >::type world2vol(const TImage &im, const numeric_array< double, 3 > &worldPos)
T ** simple2DoublePointer(T *data, int x, int y, int z)
Converts a contiguous memory buffer into a per-slice buffer.
void square(const TImage &in, TImage &out)
float t_voxsize
type of voxel size
void generateGaussianKernel(TImage &kernel, double sigmaX, double sigmaY, double sigmaZ, t_voxsize vx, t_voxsize vy, t_voxsize vz, int sx, int sy, int sz)
Iterator< TImage >::Linear itlin(TImage &im)