21 #ifndef MIRTK_HashImage_HXX 22 #define MIRTK_HashImage_HXX 24 #include "mirtk/ImageConfig.h" 25 #include "mirtk/Math.h" 26 #include "mirtk/Memory.h" 27 #include "mirtk/Path.h" 28 #include "mirtk/Matrix3x3.h" 29 #include "mirtk/VoxelCast.h" 30 #include "mirtk/Vector3D.h" 31 #include "mirtk/Point.h" 33 #include "mirtk/ImageReader.h" 34 #include "mirtk/ImageWriter.h" 37 #if defined(HAVE_VTK) && MIRTK_Image_WITH_VTK 38 # include "vtkStructuredPoints.h" 44 #ifndef MIRTK_Image_DEFAULT_EXT 45 # define MIRTK_Image_DEFAULT_EXT ".gipl" 58 template <
class VoxelType>
62 if (_maskOwner)
Delete(_mask);
69 template <
class VoxelType>
73 template <
class VoxelType>
80 template <
class VoxelType>
93 template <
class VoxelType>
97 cerr <<
"HashImage::HashImage: 5D images not supported! Use 4D image with vector voxel type instead." << endl;
101 if (n > 1) t = n, attr.
_dt = .0;
111 template <
class VoxelType>
120 template <
class VoxelType>
133 template <
class VoxelType>
143 template <
class VoxelType>
template <
class VoxelType2>
153 template <
class VoxelType>
template <
class VoxelType2>
163 template <
class VoxelType>
184 template <
class VoxelType>
197 template <
class VoxelType>
218 template <
class VoxelType>
230 template <
class VoxelType>
237 template <
class VoxelType>
240 if (
this != &image) {
263 template <
class VoxelType>
template <
class VoxelType2>
270 Put(idx, voxel_cast<VoxelType>(image.
Get(idx)));
287 template <
class VoxelType>
template <
class VoxelType2>
291 _DefaultValue = voxel_cast<
VoxelType>(image.DefaultValue());
293 for (
auto it = image.Begin(); it != image.End(); ++it) {
294 Put(it->first, voxel_cast<VoxelType>(it->second));
312 template <
class VoxelType>
template <
class VoxelType2>
316 image = voxel_cast<VoxelType2>(_DefaultValue);
317 for (
auto it = Begin(); it != End(); ++it) {
318 image.
Put(it->first, voxel_cast<VoxelType2>(it->second));
323 template <
class VoxelType>
327 _DefaultValue=scalar;
332 template <
class VoxelType>
335 if (
this != &image) {
342 template <
class VoxelType>
template <
class VoxelType2>
351 template <
class VoxelType>
354 if (
this != &image) {
362 template <
class VoxelType>
template <
class VoxelType2>
370 template <
class VoxelType>
template <
class VoxelType2>
374 if (_DefaultValue != image.DefaultValue())
return false;
375 if (_Data.size() != image.NumberOfNonDefaultVoxels())
return false;
391 template <
class VoxelType>
396 double x1, y1, z1, t1, x2, y2, z2, t2;
399 Throw(ERR_InvalidArgument, __FUNCTION__,
"Parameter out of range");
427 image.
PutOrigin(x1 - x2, y1 - y2, z1 - z2, t1 - t2);
430 VoxelType value, empty=image.DefaultValue();
432 for (i = 0; i <
_attr.
_x; i++) {
434 if(value!=empty) image.
Put(i,j,0,0, value );
439 template <
class VoxelType>
449 template <
class VoxelType>
463 template <
class VoxelType>
466 int i2,
int j2,
int k2)
const 469 double x1, y1, z1, x2, y2, z2;
471 if ((i1 < 0) || (i1 >= i2) ||
472 (j1 < 0) || (j1 >= j2) ||
473 (k1 < 0) || (k1 >= k2) ||
475 Throw(ERR_InvalidArgument, __FUNCTION__,
"Parameter out of range");
501 image.
PutOrigin(x1 - x2, y1 - y2, z1 - z2);
504 VoxelType value, empty=image.DefaultValue();
506 for (k = k1; k < k2; k++)
507 for (j = j1; j < j2; j++)
508 for (i = i1; i < i2; i++) {
510 if(value!=empty) image.
Put(i-i1,j-j1,k-k1,l, value );
515 template <
class VoxelType>
520 this->
GetRegion(image, i1, j1, k1, i2, j2, k2);
525 template <
class VoxelType>
535 this->
GetRegion(*image, i1, j1, k1, i2, j2, k2);
539 template <
class VoxelType>
542 int i2,
int j2,
int k2,
int l2)
const 545 double x1, y1, z1, x2, y2, z2;
547 if ((i1 < 0) || (i1 >= i2) ||
548 (j1 < 0) || (j1 >= j2) ||
549 (k1 < 0) || (k1 >= k2) ||
550 (l1 < 0) || (l1 >= l2) ||
552 Throw(ERR_InvalidArgument, __FUNCTION__,
"Parameter out of range");
579 image.
PutOrigin(x1 - x2, y1 - y2, z1 - z2);
582 VoxelType value, empty=image.DefaultValue();
583 for (l = l1; l < l2; l++)
584 for (k = k1; k < k2; k++)
585 for (j = j1; j < j2; j++)
586 for (i = i1; i < i2; i++) {
588 if(value!=empty) image.
Put(i-i1,j-j1,k-k1,l-l1, value );
593 template <
class VoxelType>
595 ::GetRegion(
int i1,
int j1,
int k1,
int l1,
int i2,
int j2,
int k2,
int l2)
const 598 this->
GetRegion(image, i1, j1, k1, l1, i2, j2, k2, l2);
603 template <
class VoxelType>
613 this->
GetRegion(*image, i1, j1, k1, l1, i2, j2, k2, l2);
617 template <
class VoxelType>
622 if ((l2 < 0) || (l1 >=
_attr.
_t)) {
623 Throw(ERR_InvalidArgument, __FUNCTION__,
"Parameter out of range");
631 attr.
_t = l2 - l1 + 1;
636 VoxelType value, empty=image.DefaultValue();
637 for (
int l = l1; l <= l2; l++)
638 for (
int k = 0; k <
_attr.
_z; k++)
639 for (
int j = 0; j <
_attr.
_y; j++)
640 for (
int i = 0; i <
_attr.
_x; i++) {
642 if(value!=empty) image.
Put(i,j,k,l-l1, value );
647 template <
class VoxelType>
656 template <
class VoxelType>
674 template <
class VoxelType>
678 cerr <<
"HashImage::operator+=: Size mismatch in images" << endl;
692 template <
class VoxelType>
696 cerr <<
"HashImage::operator-=: Size mismatch in images" << endl;
710 template <
class VoxelType>
714 cerr <<
"HashImage::operator*=: Size mismatch in images" << endl;
728 template <
class VoxelType>
732 cerr <<
"HashImage::operator/=: Size mismatch in images" << endl;
741 value=image.
Get(idx);
743 value=
Get(idx)/value;
753 Throw(ERR_NotImplemented, __FUNCTION__,
"Not implemented for VoxelType=float3x3");
759 Throw(ERR_NotImplemented, __FUNCTION__,
"Not implemented for VoxelType=double3x3");
764 template <
class VoxelType>
767 _DefaultValue += scalar;
768 for (
auto it = Begin(); it != End(); ++it ){
770 _Data[it->first] +=scalar;
777 template <
class VoxelType>
780 _DefaultValue -= scalar;
781 for (
auto it = Begin(); it != End(); ++it ){
783 _Data[it->first] -=scalar;
790 template <
class VoxelType>
793 _DefaultValue *= scalar;
797 for (
auto it = Begin(); it != End(); ++it ){
799 _Data[it->first] *=scalar;
807 template <
class VoxelType>
811 _DefaultValue /= scalar;
812 for (
auto it = Begin(); it != End(); ++it ){
814 _Data[it->first] /=scalar;
818 cerr <<
"HashImage::operator/=: Division by zero" << endl;
825 template <
class VoxelType>
834 template <
class VoxelType>
843 template <
class VoxelType>
852 template <
class VoxelType>
860 template <
class VoxelType>
869 template <
class VoxelType>
878 template <
class VoxelType>
887 template <
class VoxelType>
901 template <
class VoxelType>
909 bool changedValue=
false;
910 if( _DefaultValue < bg){
916 for (
auto it = Begin(); it != End();){
917 modify=(it->second < bg);
918 if(modify && changedValue){
920 it = _Data.erase( it );
948 template <
class VoxelType>
951 min = max = _DefaultValue;
954 for (
auto it = Begin(); it != End(); ++it ){
957 if (value < min) min = value;
958 if (value > max) max = value;
965 Throw(ERR_NotImplemented, __FUNCTION__,
"Not implemented for VoxelType=float3x3");
970 Throw(ERR_NotImplemented, __FUNCTION__,
"Not implemented for VoxelType=double3x3");
974 template <
class VoxelType>
977 min = max = _DefaultValue;
979 for (
auto it = Begin(); it != End(); ++it ){
982 if (value < min) min = value;
983 if (value > max) max = value;
990 Throw(ERR_NotImplemented, __FUNCTION__,
"Not implemented for VoxelType=float3x3");
995 Throw(ERR_NotImplemented, __FUNCTION__,
"Not implemented for VoxelType=double3x3");
999 template <
class VoxelType>
1004 RealType slope = voxel_cast<RealType>(max - min) / voxel_cast<RealType>(max_val - min_val);
1005 RealType inter = voxel_cast<RealType>(min) - slope * voxel_cast<RealType>(min_val);
1007 _DefaultValue = inter + slope * _DefaultValue;
1008 for (
auto it = Begin(); it != End(); ++it ){
1010 _Data[it->first]=
static_cast<VoxelType>(inter + slope *it->second);
1017 Throw(ERR_NotImplemented, __FUNCTION__,
"Not implemented for VoxelType=float3x3");
1022 Throw(ERR_NotImplemented, __FUNCTION__,
"Not implemented for VoxelType=double3x3");
1031 template <
class VoxelType>
1035 for (
int t = 0; t <
_attr.
_t; ++t)
1036 for (
int z = 0; z <
_attr.
_z; ++z)
1037 for (
int y = 0; y <
_attr.
_y; ++y)
1038 for (
int x = 0; x <
_attr.
_x / 2; ++x) {
1052 template <
class VoxelType>
1056 for (
int t = 0; t <
_attr.
_t; ++t)
1057 for (
int z = 0; z <
_attr.
_z; ++z)
1058 for (
int y = 0; y <
_attr.
_y / 2; ++y)
1059 for (
int x = 0; x <
_attr.
_x; ++x) {
1073 template <
class VoxelType>
1077 for (
int t = 0; t <
_attr.
_t; ++t)
1078 for (
int z = 0; z <
_attr.
_z / 2; ++z)
1079 for (
int y = 0; y <
_attr.
_y; ++y)
1080 for (
int x = 0; x <
_attr.
_x; ++x) {
1094 template <
class VoxelType>
1098 for (
int t = 0; t <
_attr.
_t / 2; ++t)
1099 for (
int z = 0; z <
_attr.
_z; ++z)
1100 for (
int y = 0; y <
_attr.
_y; ++y)
1101 for (
int x = 0; x <
_attr.
_x; ++x) {
1113 template <
class VoxelType>
1116 Throw(ERR_NotImplemented, __FUNCTION__,
"Not implemented");
1120 template <
class VoxelType>
1123 Throw(ERR_NotImplemented, __FUNCTION__,
"Not implemented");
1127 template <
class VoxelType>
1130 Throw(ERR_NotImplemented, __FUNCTION__,
"Not implemented");
1134 template <
class VoxelType>
1137 Throw(ERR_NotImplemented, __FUNCTION__,
"Not implemented");
1141 template <
class VoxelType>
1144 Throw(ERR_NotImplemented, __FUNCTION__,
"Not implemented");
1148 template <
class VoxelType>
1151 Throw(ERR_NotImplemented, __FUNCTION__,
"Not implemented");
1156 template <
class VoxelType>
1159 Throw(ERR_NotImplemented, __FUNCTION__,
"Not implemented");
1163 template <
class VoxelType>
1166 Throw(ERR_NotImplemented, __FUNCTION__,
"Not implemented");
1170 template <
class VoxelType>
1173 Throw(ERR_NotImplemented, __FUNCTION__,
"Not implemented");
1177 template <
class VoxelType>
1180 Throw(ERR_NotImplemented, __FUNCTION__,
"Not implemented");
1184 template <
class VoxelType>
1187 Throw(ERR_NotImplemented, __FUNCTION__,
"Not implemented");
1191 template <
class VoxelType>
1194 Throw(ERR_NotImplemented, __FUNCTION__,
"Not implemented");
1200 #if defined(HAVE_VTK) && MIRTK_Image_WITH_VTK 1203 template <
class VoxelType>
1206 if (this->ImageToVTKScalarType() == VTK_VOID) {
1207 Throw(ERR_LogicError, __FUNCTION__,
"Cannot convert image with this VoxelType to VTK structured points");
1209 double x = 0, y = 0, z = 0;
1211 vtk->SetOrigin (x, y, z);
1214 #if VTK_MAJOR_VERSION >= 6 1215 vtk->AllocateScalars(this->ImageToVTKScalarType(), 1);
1217 vtk->SetScalarType(this->ImageToVTKScalarType());
1218 vtk->AllocateScalars();
1222 for (
int i = 0; i < nvox; ++i) {
1223 for (
int l = 0; l <
_attr.
_t; ++l, ++ptr2) *ptr2 =
Get(l * nvox);
1230 Throw(ERR_NotImplemented, __FUNCTION__,
"Not implemented");
1234 template <
class Type>
1237 Throw(ERR_NotImplemented, __FUNCTION__,
"Not implemented");
1240 #endif // defined(HAVE_VTK) && MIRTK_Image_WITH_VTK 1246 template <
class VoxelType>
1257 Throw(ERR_NotImplemented, __FUNCTION__,
"Not implemented for VoxelType=float3x3");
1262 Throw(ERR_NotImplemented, __FUNCTION__,
"Not implemented for VoxelType=double3x3");
1266 template <
class VoxelType>
1270 if (
Extension(fname).empty()) name += MIRTK_Image_DEFAULT_EXT;
1273 writer->Input(&img);
1279 Throw(ERR_NotImplemented, __FUNCTION__,
"Not implemented for VoxelType=float3x3");
1284 Throw(ERR_NotImplemented, __FUNCTION__,
"Not implemented for VoxelType=double3x3");
1288 template <
class VoxelType>
1292 this->
CopyTo(dense_image);
1297 template <
class VoxelType>
template <
class VoxelType2>
1306 #endif // MIRTK_HashImage_HXX double _dt
Voxel t-dimensions (in ms)
int _NumberOfVoxels
Total number of voxels.
double _xaxis[3]
Direction of x-axis.
bool HasBackgroundValue() const
Whether a background value has been set.
void Print(ostream &, Indent=0) const
Print attributes.
double GetBackgroundValueAsDouble() const
Get background value.
HashImage & operator/=(ScalarType)
Divide by scalar.
BinaryImage * _mask
Foreground mask.
virtual void ReflectZ(bool modify_axes=false)
Reflect image along z.
void PutBackgroundValueAsDouble(double)
Put background value.
static ImageWriter * New(const char *)
virtual void SwapYT(bool modify_axes=true)
Swap y and t axis.
void CopyFrom(const BaseImage &)
Copy image data from other image of same size.
const ImageAttributes & Attributes() const
Gets the image attributes.
void Put(int, VoxelType)
Function for pixel put access.
void PutAttributes(const ImageAttributes &)
Puts attributes of image.
virtual void FlipYT(bool modify_origin=false)
Flip y and t axis, always also swaps voxel size.
HashImage operator+(const HashImage &) const
Add images.
void Put(int, VoxelType)
Function for pixel put access.
HashImage operator*(const HashImage &) const
Multiply images voxel-wise.
BaseImage()
Default constructor.
void PutMinMax(VoxelType, VoxelType)
Linearly rescale intensities.
double _torigin
Image t-origin (in ms)
virtual void FlipZT(bool modify_origin=false)
Flip z and t axis, always also swaps voxel size.
int _y
Image y-dimension (in voxels)
virtual void GetAsVector(Vector &, int) const
Function for pixel get access as double.
void Clear()
Clear an image.
HashImage GetFrame(int, int=-1) const
Get time instance (i.e., frame) or channel of image.
const ImageAttributes & GetImageAttributes() const
virtual void ReflectX(bool modify_axes=false)
Reflect image along x.
BinaryImage * GetMask(bool=false)
Get foreground mask (optionally, take over ownership)
double _xorigin
Image x-origin (in mm)
double _bg
Background value - may also be NaN for floating point images.
bool IsForeground(int) const
Whether voxel is within foreground without index-out-of-bounds check.
void PutOrigin(const Point &)
Image origin put access.
HashImage & operator*=(ScalarType)
Multiply by scalar.
virtual void SwapYZ(bool modify_axes=true)
Swap y and z axis.
virtual void FlipXY(bool modify_origin=false)
Flip x and y axis, always also swaps voxel size.
virtual void SwapXT(bool modify_axes=true)
Swap x and t axis.
HashImage operator/(const HashImage &) const
Divide images voxel-wise.
void Delete(Type *&p)
Delete object.
ImageAttributes _attr
Image attributes.
HashImage()
Default constructor.
void AllocateImage()
Allocate image memory.
VoxelType Get(int) const
Function for pixel get access.
void GetMinMax(VoxelType &, VoxelType &) const
Minimum and maximum pixel values get accessor.
virtual void SwapXZ(bool modify_axes=true)
Swap x and z axis.
virtual void FlipXT(bool modify_origin=false)
Flip x and t axis, always also swaps voxel size.
void ImageToWorld(double &, double &) const
Image to world coordinate conversion with two doubles.
int _z
Image z-dimension (in voxels)
double _dz
Voxel z-dimensions (in mm)
HashImage & operator-=(ScalarType)
Subtract scalar.
virtual void Read(const char *)
Read image from file.
int _t
Image t-dimension (in voxels)
virtual void ReflectY(bool modify_axes=false)
Reflect image along y.
void UpdateMatrix()
Update coordinate transformation.
double _zorigin
Image z-origin (in mm)
virtual void FlipXZ(bool modify_origin=false)
Flip x and z axis, always also swaps voxel size.
HashImage GetRegion(int, int) const
Get image consisting of specified 2D slice.
virtual void FlipYZ(bool modify_origin=false)
Flip y and z axis, always also swaps voxel size.
double ImageToTime(double) const
Image to time coordinate conversion.
bool operator==(const HashImage< TVoxel2 > &) const
double _zaxis[3]
Direction of z-axis.
HashImage & operator+=(ScalarType)
Add scalar.
void Throw(ErrorType err, const char *func, Args... args) const
double _yorigin
Image y-origin (in mm)
GenericImage< BinaryPixel > BinaryImage
Binary image as used for masks (0: off, otherwise: on)
double _dy
Voxel y-dimensions (in mm)
void CopyTo(GenericImage< TVoxel2 > &) const
Copy image data to GenericImage.
virtual void ReflectT(bool modify_axes=false)
Reflect image along t.
virtual void PutBackgroundValueAsDouble(double, bool)
Put background value.
string Extension(const char *, ExtensionMode=EXT_Default)
Get file name extension in lower case incl. leading dot ('.')
virtual void Initialize()
Initialize a previously allocated image.
virtual void SwapZT(bool modify_axes=true)
Swap z and t axis.
VoxelType Get(int) const
Function for pixel get access.
virtual void Initialize()
Initialize a previously allocated image.
HashImage & operator=(VoxelType)
Assign constant value to each voxel.
virtual void SwapXY(bool modify_axes=true)
Swap x and y axis.
int _x
Image x-dimension (in voxels)
bool _bgSet
Whether a background value was set.
HashImage operator-(const HashImage &) const
Subtract images.
TVoxel VoxelType
Voxel type.
double _dx
Voxel x-dimensions (in mm)
virtual void Write(const char *) const
Write image to file.
virtual BaseImage * Copy() const
Create copy of this image.
double _yaxis[3]
Direction of y-axis.