Fraxinus  2023.01.05-dev+develop.0da12
An IGT application
cxImageAlgorithms.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
11 
12 #include "cxImageAlgorithms.h"
13 
14 #include <vtkImageData.h>
15 #include <vtkImageReslice.h>
16 #include <vtkMatrix4x4.h>
17 
18 #include <vtkImageResample.h>
19 #include <vtkImageClip.h>
20 #include <vtkImageChangeInformation.h>
21 
22 #include "cxImage.h"
23 #include "cxPatientModelService.h"
24 #include "cxUtilHelpers.h"
25 #include "cxImageTF3D.h"
26 #include "cxImageLUT2D.h"
28 
29 #include "cxTime.h"
30 #include "cxVolumeHelpers.h"
31 
32 #include "cxSlicedImageProxy.h"
33 #include "cxSliceProxy.h"
34 #include "cxLogger.h"
35 #include "cxEnumConversion.h"
36 
37 
38 namespace cx
39 {
40 
45 {
46  //TODO: fix error:
47  // There is an error in the transfer functions of the returned image from this function
48 
49  // provide a resampled volume for algorithms requiring that (such as PickerRep)
50  vtkMatrix4x4Ptr orientatorMatrix = vtkMatrix4x4Ptr::New();
51  vtkImageReslicePtr orientator = vtkImageReslicePtr::New();
52  orientator->SetInputData(image->getBaseVtkImageData());
53  orientator->SetInterpolationModeToLinear();
54  orientator->SetOutputDimensionality(3);
55  orientator->SetResliceAxes(qMd.inv().getVtkMatrix());
56  orientator->AutoCropOutputOn();
57  orientator->Update();
58  vtkImageDataPtr rawResult = orientator->GetOutput();
59 
60 // rawResult->Update();
61 
62  QString uid = image->getUid() + "_or%1";
63  QString name = image->getName()+" or%1";
64 // ImagePtr oriented = dataManager->createDerivedImage(rawResult, uid, name, image);
65 
66  ImagePtr oriented = createDerivedImage(dataManager,
67  uid, name,
68  rawResult, image);
69 
70  oriented->get_rMd_History()->setRegistration(image->get_rMd() * qMd.inv());
71  oriented->mergevtkSettingsIntosscTransform();
72 
73  return oriented;
74 }
75 
79 ImagePtr resampleImage(PatientModelServicePtr dataManager, ImagePtr image, const Vector3D spacing, QString uid, QString name)
80 {
81  vtkImageResamplePtr resampler = vtkImageResamplePtr::New();
82  resampler->SetInputData(image->getBaseVtkImageData());
83  resampler->SetAxisOutputSpacing(0, spacing[0]);
84  resampler->SetAxisOutputSpacing(1, spacing[1]);
85  resampler->SetAxisOutputSpacing(2, spacing[2]);
86  resampler->Update();
87  vtkImageDataPtr rawResult = resampler->GetOutput();
88 
89  if (uid.isEmpty())
90  {
91  uid = image->getUid() + "_res%1";
92  name = image->getName()+" res%1";
93  }
94 
95  ImagePtr retval = createDerivedImage(dataManager,
96  uid, name,
97  rawResult, image);
98  return retval;
99 }
100 
105 {
106  Vector3D spacing(image->getBaseVtkImageData()->GetSpacing());
107  return resampleImage(dataManager, image, spacing, image->getUid()+"_copy%1", image->getName()+" copy%1");
108 }
109 
114 {
115  vtkImageClipPtr clip = vtkImageClipPtr::New();
116  clip->SetInputData(input);
117  clip->SetOutputWholeExtent(cropbox.begin());
118  clip->ClipDataOn();
119  clip->Update();
120  vtkImageDataPtr rawResult = clip->GetOutput();
121 
122 // rawResult->Update();
123 // rawResult->UpdateInformation();
124  rawResult->ComputeBounds();
125  return rawResult;
126 }
127 
132 {
133  DoubleBoundingBox3D bb = image->getCroppingBox();
134  double* sp = image->getBaseVtkImageData()->GetSpacing();
135  IntBoundingBox3D cropbox(
136  static_cast<int>(bb[0]/sp[0]+0.5), static_cast<int>(bb[1]/sp[0]+0.5),
137  static_cast<int>(bb[2]/sp[1]+0.5), static_cast<int>(bb[3]/sp[1]+0.5),
138  static_cast<int>(bb[4]/sp[2]+0.5), static_cast<int>(bb[5]/sp[2]+0.5));
139  vtkImageDataPtr rawResult = cropImage(image->getBaseVtkImageData(), cropbox);
140 
141  QString uid = image->getUid() + "_crop%1";
142  QString name = image->getName()+" crop%1";
143  ImagePtr result = createDerivedImage(dataManager,
144  uid, name,
145  rawResult, image);
146  result->mergevtkSettingsIntosscTransform();
147 
148  return result;
149 }
150 
153 QDateTime extractTimestamp(QString text)
154 {
155  // retrieve timestamp as
156  QRegExp tsReg("[0-9]{8}T[0-9]{6}");
157  if (tsReg.indexIn(text)>0)
158  {
159  QDateTime datetime = QDateTime::fromString(tsReg.cap(0), timestampSecondsFormat());
160  return datetime;
161  }
162  return QDateTime();
163 }
164 
165 //From https://www.vtk.org/Wiki/VTK/Examples/Cxx/Qt/ImageDataToQImage
166 QImage vtkImageDataToQImage(vtkImageDataPtr imageData, bool overlay, QColor overlayColor)
167 {
168  if ( !imageData ) { return QImage(); }
169 
170  int width = imageData->GetDimensions()[0];
171  int height = imageData->GetDimensions()[1];
172 
173  QImage image( width, height, QImage::Format_ARGB32 ); //32 bit
174  QRgb *rgbPtr = reinterpret_cast<QRgb *>( image.bits() ) + width * ( height - 1 );
175  unsigned char *colorsPtr = reinterpret_cast<unsigned char *>( imageData->GetScalarPointer() );
176 
177  // Loop over the vtkImageData contents.
178  for ( int row = 0; row < height; row++ )
179  {
180  for ( int col = 0; col < width; col++ )
181  {
182  // Swap the vtkImageData RGB values with an equivalent QColor
183  *( rgbPtr++ ) = convertToQColor(colorsPtr, overlay, overlayColor);
184 
185  colorsPtr += imageData->GetNumberOfScalarComponents();
186  }
187 
188  rgbPtr -= width * 2;
189  }
190 
191  return image;
192 }
193 
194 QRgb convertToQColor(unsigned char *colorsPtr, bool overlay, QColor overlayColor)
195 {
196  if(overlay)
197  return modifyOverlayColor(colorsPtr, overlayColor);
198 
199  //32 bit
200  QRgb rgb;
201  rgb = QColor(colorsPtr[0], colorsPtr[1], colorsPtr[2], colorsPtr[3] ).rgba();
202  // rgb = QColor(colorsPtr[0], colorsPtr[1], colorsPtr[2], opacity ).rgba(); //Don't use alpha for now
203 
204  return rgb;
205 }
206 
207 bool isDark(unsigned char *colorsPtr)
208 {
209  unsigned char threshold = 10;
210  if (colorsPtr[0] < threshold &&
211  colorsPtr[1] < threshold &&
212  colorsPtr[2] < threshold)
213  return true;
214  return false;
215 }
216 
217 QRgb modifyOverlayColor(unsigned char *colorsPtr, QColor overlayColor)
218 {
219  if(isDark(colorsPtr))
220  overlayColor.setAlpha(0);
221 
222  QRgb retval = overlayColor.rgba();
223  return retval;
224 }
225 
226 vtkImageDataPtr createSlice(ImagePtr image, PLANE_TYPE planeType, Vector3D outputSpacing, Eigen::Array3i outputDimensions, ToolPtr sliceTool, PatientModelServicePtr patientModel, bool applyLUT)
227 {
228  vtkImageDataPtr retval = vtkImageDataPtr::New();
229 
230  if(!image || !patientModel)
231  {
232  return retval;
233  }
234 
235  cx::SliceProxyPtr proxy = cx::SliceProxy::create(patientModel);
236  SlicedImageProxyPtr imageSlicer(new SlicedImageProxy);
237 
238  proxy->setTool(sliceTool);
239 
240  imageSlicer->setSliceProxy(proxy);
241  imageSlicer->setImage(image);
242 
243  proxy->initializeFromPlane(planeType, false, false, 1, 0);
244  proxy->setClinicalApplicationToFixedValue(mdRADIOLOGICAL);//Always create slices in radiological view
245 
246  // Using these values centers image in view, but seems to lock the manual image movement in some directions.
247  double screenX = outputDimensions[0]*outputSpacing[0] / 2;
248  double screenY = outputDimensions[1]*outputSpacing[1] / 2;
249 
250  imageSlicer->setOutputFormat(Vector3D(-screenX,-screenY,0), outputDimensions, outputSpacing);
251 
252  imageSlicer->update();
253  if (applyLUT)
254  {
255  imageSlicer->getOutputPort()->Update();
256  retval->DeepCopy(imageSlicer->getOutput());
257  }
258  else //Don't use LUT
259  {
260  imageSlicer->getOutputPortWithoutLUT()->Update();
261  retval->DeepCopy(imageSlicer->getOutputWithoutLUT());
262 
263  }
264 
265  return retval;
266 }
267 
268 vtkImageDataPtr createSlice(ImagePtr image, PLANE_TYPE planeType, Vector3D position_r, Vector3D target_r, double offset, bool applyLUT)
269 {
270  vtkImageDataPtr slicedImage = vtkImageDataPtr::New();
271 
272  vtkImageReslicePtr imageReslicer = vtkImageReslicePtr::New();
273 
274  imageReslicer->SetInputData(image->getBaseVtkImageData());
275  imageReslicer->SetBackgroundLevel(image->getMin());
276 
277  imageReslicer->SetInterpolationModeToLinear();
278  imageReslicer->SetOutputDimensionality(2);
279 
280 
281  Eigen::Array3d inputSpacing = image->getSpacing();
282 
283  //imageReslicer->SetOutputOrigin(image->getBaseVtkImageData()->GetOrigin()); // set to [0, 0, 0] ??
284 // double origin[3];
285 // image->getBaseVtkImageData()->GetOrigin(origin);
286 
287 // Eigen::Array3d spacing = image->getSpacing();
288  int extent[6];
289  image->getBaseVtkImageData()->GetExtent(extent);
290 
291  Transform3D rMd = image->get_rMd();
292 
293  //Eigen::Array3i dim(image->getBaseVtkImageData()->GetDimensions());
294 
295  Transform3D positionTransform_d = rMd.inv() * createTransformTranslate(position_r);
296  vtkSmartPointer<vtkMatrix4x4> resliceAxes = vtkSmartPointer<vtkMatrix4x4>::New();
297 
298  Transform3D targetTransform_d;
299  Vector3D direction;
300  Vector3D up(0, -1, 0);
301  Vector3D xAxis;
302  Vector3D yAxis;
303 
304 
305  switch (planeType)
306  {
307  case ptAXIAL:
308  resliceAxes->SetElement(0, 0, 1);
309  resliceAxes->SetElement(0, 1, 0);
310  resliceAxes->SetElement(0, 2, 0);
311  resliceAxes->SetElement(0, 3, 0);
312  resliceAxes->SetElement(1, 0, 0);
313  resliceAxes->SetElement(1, 1, -1);
314  resliceAxes->SetElement(1, 2, 0);
315  resliceAxes->SetElement(1, 3, 0);
316  resliceAxes->SetElement(2, 0, 0);
317  resliceAxes->SetElement(2, 1, 0);
318  resliceAxes->SetElement(2, 2, 1);
319  resliceAxes->SetElement(2, 3, positionTransform_d(2,3) + offset);
320  resliceAxes->SetElement(3, 0, 0);
321  resliceAxes->SetElement(3, 1, 0);
322  resliceAxes->SetElement(3, 2, 0);
323  resliceAxes->SetElement(3, 3, 1);
324  imageReslicer->SetResliceAxes(resliceAxes);
325  imageReslicer->SetOutputExtent(extent[0], extent[1], extent[2], extent[3], 0, 0);
326  imageReslicer->SetOutputSpacing(inputSpacing[0], inputSpacing[1], 0);
327  break;
328  case ptCORONAL:
329  resliceAxes->SetElement(0, 0, 1);
330  resliceAxes->SetElement(0, 1, 0);
331  resliceAxes->SetElement(0, 2, 0);
332  resliceAxes->SetElement(0, 3, 0);
333  resliceAxes->SetElement(1, 0, 0);
334  resliceAxes->SetElement(1, 1, 0);
335  resliceAxes->SetElement(1, 2, 1);
336  resliceAxes->SetElement(1, 3, positionTransform_d(1,3) + offset);
337  resliceAxes->SetElement(2, 0, 0);
338  resliceAxes->SetElement(2, 1, 1);
339  resliceAxes->SetElement(2, 2, 0);
340  resliceAxes->SetElement(2, 3, 0);
341  resliceAxes->SetElement(3, 0, 0);
342  resliceAxes->SetElement(3, 1, 0);
343  resliceAxes->SetElement(3, 2, 0);
344  resliceAxes->SetElement(3, 3, 1);
345  imageReslicer->SetResliceAxes(resliceAxes);
346  imageReslicer->SetOutputExtent(extent[0], extent[1], extent[4], extent[5], 0, 0);
347  imageReslicer->SetOutputSpacing(inputSpacing[0], inputSpacing[2], 0);
348  break;
349  case ptSAGITTAL:
350  resliceAxes->SetElement(0, 0, 0);
351  resliceAxes->SetElement(0, 1, 0);
352  resliceAxes->SetElement(0, 2, -1);
353  resliceAxes->SetElement(0, 3, positionTransform_d(0,3));
354  resliceAxes->SetElement(1, 0, 1);
355  resliceAxes->SetElement(1, 1, 0);
356  resliceAxes->SetElement(1, 2, 0);
357  resliceAxes->SetElement(1, 3, 0);
358  resliceAxes->SetElement(2, 0, 0);
359  resliceAxes->SetElement(2, 1, 1);
360  resliceAxes->SetElement(2, 2, 0);
361  resliceAxes->SetElement(2, 3, 0);
362  resliceAxes->SetElement(3, 0, 0);
363  resliceAxes->SetElement(3, 1, 0);
364  resliceAxes->SetElement(3, 2, 0);
365  resliceAxes->SetElement(3, 3, 1);
366  imageReslicer->SetResliceAxes(resliceAxes);
367  imageReslicer->SetOutputExtent(extent[2], extent[3], extent[4], extent[5], 0, 0);
368  imageReslicer->SetOutputSpacing(inputSpacing[1], inputSpacing[2], 0);
369  break;
370  case ptRADIALPLANE:
371  targetTransform_d = rMd.inv() * createTransformTranslate(target_r);
372  direction(0) = targetTransform_d(0,3) - positionTransform_d(0,3);
373  direction(1) = targetTransform_d(1,3) - positionTransform_d(1,3);
374  direction(2) = targetTransform_d(2,3) - positionTransform_d(2,3);
375  direction = direction.normalized();
376  xAxis = up.cross(direction).normalized();
377  yAxis = direction.cross(xAxis).normalized();
378 
379  resliceAxes->SetElement(0, 0, xAxis(0));
380  resliceAxes->SetElement(0, 1, yAxis(0));
381  resliceAxes->SetElement(0, 2, direction(0));
382  resliceAxes->SetElement(0, 3, positionTransform_d(0,3) + offset*direction(0));
383  resliceAxes->SetElement(1, 0, xAxis(1));
384  resliceAxes->SetElement(1, 1, yAxis(1));
385  resliceAxes->SetElement(1, 2, direction(1));
386  resliceAxes->SetElement(1, 3, positionTransform_d(1,3) + offset*direction(1));
387  resliceAxes->SetElement(2, 0, xAxis(2));
388  resliceAxes->SetElement(2, 1, yAxis(2));
389  resliceAxes->SetElement(2, 2, direction(2));
390  resliceAxes->SetElement(2, 3, positionTransform_d(2,3) + offset*direction(2));
391  resliceAxes->SetElement(3, 0, 0);
392  resliceAxes->SetElement(3, 1, 0);
393  resliceAxes->SetElement(3, 2, 0);
394  resliceAxes->SetElement(3, 3, 1);
395  imageReslicer->SetResliceAxes(resliceAxes);
396  imageReslicer->SetOutputExtent(extent[0], extent[1], extent[2], extent[3], 0, 0);
397  imageReslicer->SetOutputSpacing(inputSpacing[0], inputSpacing[1], 0);
398  break;
399  default:
400  CX_LOG_WARNING() << "Not a valid plane type." << enum2string(planeType);
401  }
402 
403  imageReslicer->Update();
404 
405  if (applyLUT)
406  {
408  vtkImageChangeInformationPtr redirecterPtr = vtkImageChangeInformationPtr::New();
409  redirecterPtr->SetInputConnection(imageReslicer->GetOutputPort());
410 
411  imageWithLUTProxyPtr->setInput(redirecterPtr, image->getLookupTable2D()->getOutputLookupTable());
412 
413  imageWithLUTProxyPtr->getOutputPort()->Update();
414  slicedImage->DeepCopy(imageWithLUTProxyPtr->getOutput());
415  }
416  else
417  slicedImage = imageReslicer->GetOutput();
418 
419  return slicedImage;
420 }
421 
422 std::vector<int> getSliceVoxelFrom3Dposition(ImagePtr image, PLANE_TYPE planeType, Vector3D position_r)
423 {
424  std::vector<int> voxel(2,0);
425 
426  Transform3D rMd = image->get_rMd();
427  Eigen::Array3d spacing = image->getSpacing();
428  Transform3D positionTransform_d = rMd.inv() * createTransformTranslate(position_r);
429  int xVoxel = std::round( positionTransform_d(0,3) / spacing(0) );
430  int yVoxel = std::round( positionTransform_d(1,3) / spacing(1) );
431  int zVoxel = std::round( positionTransform_d(2,3) / spacing(2) );
432 
433  switch (planeType)
434  {
435  case ptAXIAL:
436  voxel[0] = xVoxel;
437  voxel[1] = yVoxel;
438  break;
439  case ptCORONAL:
440  voxel[0] = xVoxel;
441  voxel[1] = zVoxel;
442  break;
443  case ptSAGITTAL:
444  voxel[0] = yVoxel;
445  voxel[1] = zVoxel;
446  break;
447  default:
448  CX_LOG_WARNING() << "Not a valid plane type." << enum2string(planeType);
449  }
450  return voxel;
451 }
452 
453 int getSliceNumberFrom3Dposition(ImagePtr image, PLANE_TYPE planeType, Vector3D position_r)
454 {
455  int sliceNumber;
456 
457  Transform3D rMd = image->get_rMd();
458  Eigen::Array3d spacing = image->getSpacing();
459  Transform3D positionTransform_d = rMd.inv() * createTransformTranslate(position_r);
460 
461  switch (planeType)
462  {
463  case ptAXIAL:
464  sliceNumber = std::round( positionTransform_d(2,3) / spacing(2) );
465  break;
466  case ptCORONAL:
467  sliceNumber = std::round( positionTransform_d(1,3) / spacing(1) );
468  break;
469  case ptSAGITTAL:
470  sliceNumber = std::round( positionTransform_d(0,3) / spacing(0) );
471  break;
472  default:
473  CX_LOG_WARNING() << "Not a valid plane type." << enum2string(planeType);
474  }
475  return sliceNumber;
476 }
477 
478 Vector3D get3DpositionFromSliceVoxel(ImagePtr image, PLANE_TYPE planeType, std::vector<int> voxel, int sliceNumber)
479 {
480  Vector3D position_r;
481 
482  Transform3D rMd = image->get_rMd();
483  Eigen::Array3d spacing = image->getSpacing();
484  Vector3D position_d;
485 
486  switch (planeType)
487  {
488  case ptAXIAL:
489  position_d(0) = voxel[0]*spacing(0);
490  position_d(1) = voxel[1]*spacing(1);
491  position_d(2) = sliceNumber*spacing(2);
492  break;
493  case ptCORONAL:
494  position_d(0) = voxel[0]*spacing(0);
495  position_d(1) = sliceNumber*spacing(1);
496  position_d(2) = voxel[1]*spacing(2);
497  break;
498  case ptSAGITTAL:
499  position_d(0) = sliceNumber*spacing(0);
500  position_d(1) = voxel[0]*spacing(1);
501  position_d(2) = voxel[1]*spacing(2);
502  break;
503  default:
504  CX_LOG_WARNING() << "Not a valid plane type." << enum2string(planeType);
505  return position_r;
506  }
507 
508  Transform3D positionTransform_r = rMd * createTransformTranslate(position_d);
509  position_r(0) = positionTransform_r(0,3);
510  position_r(1) = positionTransform_r(1,3);
511  position_r(2) = positionTransform_r(2,3);
512 
513  return position_r;
514 }
515 
516 } // namespace cx
vtkSmartPointer< class vtkMatrix4x4 > vtkMatrix4x4Ptr
Definition: cxMathBase.h:37
int getSliceNumberFrom3Dposition(ImagePtr image, PLANE_TYPE planeType, Vector3D position_r)
QRgb modifyOverlayColor(unsigned char *colorsPtr, QColor overlayColor)
ImagePtr resampleImage(PatientModelServicePtr dataManager, ImagePtr image, Transform3D qMd)
ptCORONAL
a slice seen from the front of the patient
Definition: cxDefinitions.h:39
static SliceProxyPtr create(PatientModelServicePtr dataManager)
mdRADIOLOGICAL
Definition: cxDefinitions.h:60
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
boost::shared_ptr< class SliceProxy > SliceProxyPtr
QRgb convertToQColor(unsigned char *colorsPtr, bool overlay, QColor overlayColor)
vtkImageDataPtr cropImage(vtkImageDataPtr input, IntBoundingBox3D cropbox)
boost::shared_ptr< class Image > ImagePtr
Definition: cxDicomWidget.h:27
vtkSmartPointer< vtkImageChangeInformation > vtkImageChangeInformationPtr
Definition: cxImage.cpp:46
boost::shared_ptr< class SlicedImageProxy > SlicedImageProxyPtr
ptAXIAL
a slice seen from the top of the patient
Definition: cxDefinitions.h:39
QString timestampSecondsFormat()
Definition: cxTime.cpp:18
Helper class for slicing an image given a SliceProxy and an image.
boost::shared_ptr< class ApplyLUTToImage2DProxy > ApplyLUTToImage2DProxyPtr
vtkImageDataPtr createSlice(ImagePtr image, PLANE_TYPE planeType, Vector3D outputSpacing, Eigen::Array3i outputDimensions, ToolPtr sliceTool, PatientModelServicePtr patientModel, bool applyLUT)
createSlice Creates a 2D slice through a 3D volume. Result slice will be oriented for radiological vi...
bool isDark(unsigned char *colorsPtr)
ptSAGITTAL
a slice seen from the side of the patient
Definition: cxDefinitions.h:39
ImagePtr duplicateImage(PatientModelServicePtr dataManager, ImagePtr image)
ImagePtr createDerivedImage(PatientModelServicePtr dataManager, QString uid, QString name, vtkImageDataPtr raw, ImagePtr parent)
vtkSmartPointer< class vtkImageReslice > vtkImageReslicePtr
boost::shared_ptr< class PatientModelService > PatientModelServicePtr
Vector3D get3DpositionFromSliceVoxel(ImagePtr image, PLANE_TYPE planeType, std::vector< int > voxel, int sliceNumber)
Transform3D createTransformTranslate(const Vector3D &translation)
Representation of an integer bounding box in 3D. The data are stored as {xmin,xmax,ymin,ymax,zmin,zmax}, in order to simplify communication with vtk.
Representation of a floating-point bounding box in 3D. The data are stored as {xmin,xmax,ymin,ymax,zmin,zmax}, in order to simplify communication with vtk.
vtkSmartPointer< class vtkImageResample > vtkImageResamplePtr
QImage vtkImageDataToQImage(vtkImageDataPtr imageData, bool overlay, QColor overlayColor)
vtkSmartPointer< class vtkImageClip > vtkImageClipPtr
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:42
ptRADIALPLANE
y-rotated 90* relative to anyplane (bird&#39;s view)
Definition: cxDefinitions.h:39
QDateTime extractTimestamp(QString text)
#define CX_LOG_WARNING
Definition: cxLogger.h:98
std::vector< int > getSliceVoxelFrom3Dposition(ImagePtr image, PLANE_TYPE planeType, Vector3D position_r)
vtkSmartPointer< class vtkImageData > vtkImageDataPtr
QString enum2string(const ENUM &val)
Vector3D round(const Vector3D &a)
Definition: cxVector3D.cpp:75
Helper class for applying sscLUT2D to an image.
Namespace for all CustusX production code.
boost::shared_ptr< class Tool > ToolPtr