CustusX  20.03-rc1
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 
21 #include "cxImage.h"
22 #include "cxPatientModelService.h"
23 #include "cxUtilHelpers.h"
24 #include "cxImageTF3D.h"
25 #include "cxImageLUT2D.h"
27 
28 #include "cxTime.h"
29 #include "cxVolumeHelpers.h"
30 
31 #include "cxSlicedImageProxy.h"
32 #include "cxSliceProxy.h"
33 
34 
35 namespace cx
36 {
37 
42 {
43  //TODO: fix error:
44  // There is an error in the transfer functions of the returned image from this function
45 
46  // provide a resampled volume for algorithms requiring that (such as PickerRep)
47  vtkMatrix4x4Ptr orientatorMatrix = vtkMatrix4x4Ptr::New();
48  vtkImageReslicePtr orientator = vtkImageReslicePtr::New();
49  orientator->SetInputData(image->getBaseVtkImageData());
50  orientator->SetInterpolationModeToLinear();
51  orientator->SetOutputDimensionality(3);
52  orientator->SetResliceAxes(qMd.inv().getVtkMatrix());
53  orientator->AutoCropOutputOn();
54  orientator->Update();
55  vtkImageDataPtr rawResult = orientator->GetOutput();
56 
57 // rawResult->Update();
58 
59  QString uid = image->getUid() + "_or%1";
60  QString name = image->getName()+" or%1";
61 // ImagePtr oriented = dataManager->createDerivedImage(rawResult, uid, name, image);
62 
63  ImagePtr oriented = createDerivedImage(dataManager,
64  uid, name,
65  rawResult, image);
66 
67  oriented->get_rMd_History()->setRegistration(image->get_rMd() * qMd.inv());
68  oriented->mergevtkSettingsIntosscTransform();
69 
70  return oriented;
71 }
72 
76 ImagePtr resampleImage(PatientModelServicePtr dataManager, ImagePtr image, const Vector3D spacing, QString uid, QString name)
77 {
78  vtkImageResamplePtr resampler = vtkImageResamplePtr::New();
79  resampler->SetInputData(image->getBaseVtkImageData());
80  resampler->SetAxisOutputSpacing(0, spacing[0]);
81  resampler->SetAxisOutputSpacing(1, spacing[1]);
82  resampler->SetAxisOutputSpacing(2, spacing[2]);
83  resampler->Update();
84  vtkImageDataPtr rawResult = resampler->GetOutput();
85 
86  if (uid.isEmpty())
87  {
88  uid = image->getUid() + "_res%1";
89  name = image->getName()+" res%1";
90  }
91 
92  ImagePtr retval = createDerivedImage(dataManager,
93  uid, name,
94  rawResult, image);
95  return retval;
96 }
97 
102 {
103  Vector3D spacing(image->getBaseVtkImageData()->GetSpacing());
104  return resampleImage(dataManager, image, spacing, image->getUid()+"_copy%1", image->getName()+" copy%1");
105 }
106 
111 {
112  vtkImageClipPtr clip = vtkImageClipPtr::New();
113  clip->SetInputData(input);
114  clip->SetOutputWholeExtent(cropbox.begin());
115  clip->ClipDataOn();
116  clip->Update();
117  vtkImageDataPtr rawResult = clip->GetOutput();
118 
119 // rawResult->Update();
120 // rawResult->UpdateInformation();
121  rawResult->ComputeBounds();
122  return rawResult;
123 }
124 
129 {
130  DoubleBoundingBox3D bb = image->getCroppingBox();
131  double* sp = image->getBaseVtkImageData()->GetSpacing();
132  IntBoundingBox3D cropbox(
133  static_cast<int>(bb[0]/sp[0]+0.5), static_cast<int>(bb[1]/sp[0]+0.5),
134  static_cast<int>(bb[2]/sp[1]+0.5), static_cast<int>(bb[3]/sp[1]+0.5),
135  static_cast<int>(bb[4]/sp[2]+0.5), static_cast<int>(bb[5]/sp[2]+0.5));
136  vtkImageDataPtr rawResult = cropImage(image->getBaseVtkImageData(), cropbox);
137 
138  QString uid = image->getUid() + "_crop%1";
139  QString name = image->getName()+" crop%1";
140  ImagePtr result = createDerivedImage(dataManager,
141  uid, name,
142  rawResult, image);
143  result->mergevtkSettingsIntosscTransform();
144 
145  return result;
146 }
147 
150 QDateTime extractTimestamp(QString text)
151 {
152  // retrieve timestamp as
153  QRegExp tsReg("[0-9]{8}T[0-9]{6}");
154  if (tsReg.indexIn(text)>0)
155  {
156  QDateTime datetime = QDateTime::fromString(tsReg.cap(0), timestampSecondsFormat());
157  return datetime;
158  }
159  return QDateTime();
160 }
161 
162 //From https://www.vtk.org/Wiki/VTK/Examples/Cxx/Qt/ImageDataToQImage
163 QImage vtkImageDataToQImage(vtkImageDataPtr imageData, bool overlay, QColor overlayColor)
164 {
165  if ( !imageData ) { return QImage(); }
166 
167  int width = imageData->GetDimensions()[0];
168  int height = imageData->GetDimensions()[1];
169 
170  QImage image( width, height, QImage::Format_ARGB32 ); //32 bit
171  QRgb *rgbPtr = reinterpret_cast<QRgb *>( image.bits() ) + width * ( height - 1 );
172  unsigned char *colorsPtr = reinterpret_cast<unsigned char *>( imageData->GetScalarPointer() );
173 
174  // Loop over the vtkImageData contents.
175  for ( int row = 0; row < height; row++ )
176  {
177  for ( int col = 0; col < width; col++ )
178  {
179  // Swap the vtkImageData RGB values with an equivalent QColor
180  *( rgbPtr++ ) = convertToQColor(colorsPtr, overlay, overlayColor);
181 
182  colorsPtr += imageData->GetNumberOfScalarComponents();
183  }
184 
185  rgbPtr -= width * 2;
186  }
187 
188  return image;
189 }
190 
191 QRgb convertToQColor(unsigned char *colorsPtr, bool overlay, QColor overlayColor)
192 {
193  if(overlay)
194  return modifyOverlayColor(colorsPtr, overlayColor);
195 
196  //32 bit
197  QRgb rgb;
198  rgb = QColor(colorsPtr[0], colorsPtr[1], colorsPtr[2], colorsPtr[3] ).rgba();
199  // rgb = QColor(colorsPtr[0], colorsPtr[1], colorsPtr[2], opacity ).rgba(); //Don't use alpha for now
200 
201  return rgb;
202 }
203 
204 bool isDark(unsigned char *colorsPtr)
205 {
206  unsigned char threshold = 10;
207  if (colorsPtr[0] < threshold &&
208  colorsPtr[1] < threshold &&
209  colorsPtr[2] < threshold)
210  return true;
211  return false;
212 }
213 
214 QRgb modifyOverlayColor(unsigned char *colorsPtr, QColor overlayColor)
215 {
216  if(isDark(colorsPtr))
217  overlayColor.setAlpha(0);
218 
219  QRgb retval = overlayColor.rgba();
220  return retval;
221 }
222 
223 vtkImageDataPtr createSlice(ImagePtr image, PLANE_TYPE planeType, Vector3D outputSpacing, Eigen::Array3i outputDimensions, ToolPtr sliceTool, PatientModelServicePtr patientModel, bool applyLUT)
224 {
225  vtkImageDataPtr retval = vtkImageDataPtr::New();
226 
227  if(!image || !patientModel)
228  {
229  return retval;
230  }
231 
232  cx::SliceProxyPtr proxy = cx::SliceProxy::create(patientModel);
233  SlicedImageProxyPtr imageSlicer(new SlicedImageProxy);
234 
235  proxy->setTool(sliceTool);
236 
237  imageSlicer->setSliceProxy(proxy);
238  imageSlicer->setImage(image);
239 
240  proxy->initializeFromPlane(planeType, false, false, 1, 0);
241  proxy->setClinicalApplicationToFixedValue(mdRADIOLOGICAL);//Always create slices in radiological view
242 
243  // Using these values centers image in view, but seems to lock the manual image movement in some directions.
244  double screenX = outputDimensions[0]*outputSpacing[0] / 2;
245  double screenY = outputDimensions[1]*outputSpacing[1] / 2;
246 
247  imageSlicer->setOutputFormat(Vector3D(-screenX,-screenY,0), outputDimensions, outputSpacing);
248 
249  imageSlicer->update();
250  if (applyLUT)
251  {
252  imageSlicer->getOutputPort()->Update();
253  retval->DeepCopy(imageSlicer->getOutput());
254  }
255  else //Don't use LUT
256  {
257  imageSlicer->getOutputPortWithoutLUT()->Update();
258  retval->DeepCopy(imageSlicer->getOutputWithoutLUT());
259 
260  }
261 
262  return retval;
263 }
264 
265 } // namespace cx
vtkSmartPointer< class vtkMatrix4x4 > vtkMatrix4x4Ptr
Definition: cxMathBase.h:37
QRgb modifyOverlayColor(unsigned char *colorsPtr, QColor overlayColor)
ImagePtr resampleImage(PatientModelServicePtr dataManager, ImagePtr image, Transform3D qMd)
static SliceProxyPtr create(PatientModelServicePtr dataManager)
mdRADIOLOGICAL
Definition: cxDefinitions.h:58
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
boost::shared_ptr< class SlicedImageProxy > SlicedImageProxyPtr
QString timestampSecondsFormat()
Definition: cxTime.cpp:18
Helper class for slicing an image given a SliceProxy and an image.
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)
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
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
QDateTime extractTimestamp(QString text)
vtkSmartPointer< class vtkImageData > vtkImageDataPtr
Namespace for all CustusX production code.
boost::shared_ptr< class Tool > ToolPtr