Medical Imaging Interaction Toolkit  2018.4.99-07c45cb1
Medical Imaging Interaction Toolkit
mitkToFImageRecorder.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 #include "mitkToFImageRecorder.h"
13 #include <mitkRealTimeClock.h>
14 #include <itkMultiThreader.h>
15 #include <itksys/SystemTools.hxx>
16 #pragma GCC visibility push(default)
17 #include <itkEventObject.h>
18 #pragma GCC visibility pop
19 
20 namespace mitk
21 {
23 {
24  this->m_ToFCameraDevice = nullptr;
25  this->m_MultiThreader = itk::MultiThreader::New();
26  this->m_AbortMutex = itk::FastMutexLock::New();
27  this->m_ThreadID = 0;
28  this->m_NumOfFrames = 1; //lets record one frame per default
29  this->m_ToFImageWriter = nullptr;
30  this->m_DistanceImageSelected = true; //lets assume a device only has depth data by default
31  this->m_AmplitudeImageSelected = false;
32  this->m_IntensityImageSelected = false;
33  this->m_RGBImageSelected = false;
34  this->m_Abort = false;
35  this->m_ToFCaptureWidth = 0;
36  this->m_ToFCaptureHeight = 0;
37  this->m_RGBCaptureWidth = 0;
38  this->m_RGBCaptureHeight = 0;
39  this->m_FileFormat = ".nrrd"; //lets make nrrd the default
40  this->m_ToFPixelNumber = 0;
41  this->m_RGBPixelNumber = 0;
42  this->m_SourceDataSize = 0;
45  this->m_DistanceImageFileName = "";
46  this->m_AmplitudeImageFileName = "";
47  this->m_IntensityImageFileName = "";
48  this->m_RGBImageFileName = "";
49  this->m_ImageSequence = 0;
50  this->m_DistanceArray = nullptr;
51  this->m_AmplitudeArray = nullptr;
52  this->m_IntensityArray = nullptr;
53  this->m_RGBArray = nullptr;
54  this->m_SourceDataArray = nullptr;
55 }
56 
58 {
59  delete[] m_DistanceArray;
60  delete[] m_AmplitudeArray;
61  delete[] m_IntensityArray;
62  delete[] m_RGBArray;
63  delete[] m_SourceDataArray;
64 }
65 
67 {
68 
69  this->m_AbortMutex->Lock();
70  this->m_Abort = true;
71  this->m_AbortMutex->Unlock();
72 
73 }
74 
76 {
77  if (this->m_ToFCameraDevice.IsNull())
78  {
79  throw std::invalid_argument("ToFCameraDevice is nullptr.");
80  return;
81  }
82  if (this->m_FileFormat.compare(".csv") == 0)
83  {
85  }
86  else if(this->m_FileFormat.compare(".nrrd") == 0)
87  {
89  this->m_ToFImageWriter->SetExtension(m_FileFormat);
90  }
91  else
92  {
93  throw std::logic_error("No file format specified!");
94  }
95 
96  this->m_RGBCaptureWidth = this->m_ToFCameraDevice->GetRGBCaptureWidth();
97  this->m_RGBCaptureHeight = this->m_ToFCameraDevice->GetRGBCaptureHeight();
99 
100  this->m_ToFCaptureWidth = this->m_ToFCameraDevice->GetCaptureWidth();
101  this->m_ToFCaptureHeight = this->m_ToFCameraDevice->GetCaptureHeight();
103 
104  this->m_SourceDataSize = this->m_ToFCameraDevice->GetSourceDataSize();
105 
106  // allocate buffer
107  if(m_IntensityArray == nullptr)
108  {
109  this->m_IntensityArray = new float[m_ToFPixelNumber];
110  }
111  if(this->m_DistanceArray == nullptr)
112  {
113  this->m_DistanceArray = new float[m_ToFPixelNumber];
114  }
115  if(this->m_AmplitudeArray == nullptr)
116  {
117  this->m_AmplitudeArray = new float[m_ToFPixelNumber];
118  }
119  if(this->m_RGBArray == nullptr)
120  {
121  this->m_RGBArray = new unsigned char[m_RGBPixelNumber*3];
122  }
123  if(this->m_SourceDataArray == nullptr)
124  {
125  this->m_SourceDataArray = new char[m_SourceDataSize];
126  }
127 
128  this->m_ToFImageWriter->SetDistanceImageFileName(this->m_DistanceImageFileName);
129  this->m_ToFImageWriter->SetAmplitudeImageFileName(this->m_AmplitudeImageFileName);
130  this->m_ToFImageWriter->SetIntensityImageFileName(this->m_IntensityImageFileName);
131  this->m_ToFImageWriter->SetRGBImageFileName(this->m_RGBImageFileName);
132  this->m_ToFImageWriter->SetRGBCaptureWidth(this->m_RGBCaptureWidth);
133  this->m_ToFImageWriter->SetRGBCaptureHeight(this->m_RGBCaptureHeight);
134  this->m_ToFImageWriter->SetToFCaptureWidth(this->m_ToFCaptureWidth);
135  this->m_ToFImageWriter->SetToFCaptureHeight(this->m_ToFCaptureHeight);
136  this->m_ToFImageWriter->SetToFImageType(this->m_ToFImageType);
137  this->m_ToFImageWriter->SetDistanceImageSelected(this->m_DistanceImageSelected);
138  this->m_ToFImageWriter->SetAmplitudeImageSelected(this->m_AmplitudeImageSelected);
139  this->m_ToFImageWriter->SetIntensityImageSelected(this->m_IntensityImageSelected);
140  this->m_ToFImageWriter->SetRGBImageSelected(this->m_RGBImageSelected);
141  this->m_ToFImageWriter->Open();
142 
143  this->m_AbortMutex->Lock();
144  this->m_Abort = false;
145  this->m_AbortMutex->Unlock();
146  this->m_ThreadID = this->m_MultiThreader->SpawnThread(this->RecordData, this);
147 }
148 
150 {
151  this->m_MultiThreader->TerminateThread(this->m_ThreadID);
152 }
153 
154 ITK_THREAD_RETURN_TYPE ToFImageRecorder::RecordData(void* pInfoStruct)
155 {
156  struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct;
157  if (pInfo == nullptr)
158  {
159  return ITK_THREAD_RETURN_VALUE;
160  }
161  if (pInfo->UserData == nullptr)
162  {
163  return ITK_THREAD_RETURN_VALUE;
164  }
165  ToFImageRecorder* toFImageRecorder = (ToFImageRecorder*)pInfo->UserData;
166  if (toFImageRecorder!=nullptr)
167  {
168 
169  ToFCameraDevice::Pointer toFCameraDevice = toFImageRecorder->GetCameraDevice();
170 
171  mitk::RealTimeClock::Pointer realTimeClock;
172  realTimeClock = mitk::RealTimeClock::New();
173  int n = 100;
174  double t1 = 0;
175  double t2 = 0;
176  t1 = realTimeClock->GetCurrentStamp();
177  bool printStatus = false;
178  int requiredImageSequence = 0;
179  int numOfFramesRecorded = 0;
180 
181  bool abort = false;
182  toFImageRecorder->m_AbortMutex->Lock();
183  abort = toFImageRecorder->m_Abort;
184  toFImageRecorder->m_AbortMutex->Unlock();
185  while ( !abort )
186  {
187  if ( ((toFImageRecorder->m_RecordMode == ToFImageRecorder::PerFrames) && (numOfFramesRecorded < toFImageRecorder->m_NumOfFrames)) ||
188  (toFImageRecorder->m_RecordMode == ToFImageRecorder::Infinite) )
189  {
190 
191  toFCameraDevice->GetAllImages(toFImageRecorder->m_DistanceArray, toFImageRecorder->m_AmplitudeArray,
192  toFImageRecorder->m_IntensityArray, toFImageRecorder->m_SourceDataArray, requiredImageSequence, toFImageRecorder->m_ImageSequence, toFImageRecorder->m_RGBArray );
193 
194  if (toFImageRecorder->m_ImageSequence >= requiredImageSequence)
195  {
196  if (toFImageRecorder->m_ImageSequence > requiredImageSequence)
197  {
198  MITK_INFO << "Problem! required: " << requiredImageSequence << " captured: " << toFImageRecorder->m_ImageSequence;
199  }
200  requiredImageSequence = toFImageRecorder->m_ImageSequence + 1;
201  toFImageRecorder->m_ToFImageWriter->Add( toFImageRecorder->m_DistanceArray,
202  toFImageRecorder->m_AmplitudeArray, toFImageRecorder->m_IntensityArray, toFImageRecorder->m_RGBArray );
203  numOfFramesRecorded++;
204  if (numOfFramesRecorded % n == 0)
205  {
206  printStatus = true;
207  }
208  if (printStatus)
209  {
210  t2 = realTimeClock->GetCurrentStamp() - t1;
211  MITK_INFO << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFImageRecorder->m_ImageSequence;
212  t1 = realTimeClock->GetCurrentStamp();
213  printStatus = false;
214  }
215  }
216  toFImageRecorder->m_AbortMutex->Lock();
217  abort = toFImageRecorder->m_Abort;
218  toFImageRecorder->m_AbortMutex->Unlock();
219  }
220  else
221  {
222  abort = true;
223  }
224  } // end of while loop
225 
226  toFImageRecorder->InvokeEvent(itk::AbortEvent());
227 
228  toFImageRecorder->m_ToFImageWriter->Close();
229  }
230  return ITK_THREAD_RETURN_VALUE;
231 }
232 
234 {
235  this->m_ToFCameraDevice = aToFCameraDevice;
236 }
237 
239 {
240  return this->m_ToFCameraDevice;
241 }
242 
244 {
245  return this->m_ToFImageType;
246 }
247 
249 {
250  this->m_ToFImageType = toFImageType;
251 }
252 
254 {
255  return this->m_RecordMode;
256 }
257 
259 {
260  this->m_RecordMode = recordMode;
261 }
262 }
void StartRecording()
Starts the recording by spawning a Thread which streams the data to a file. Aborting of the record pr...
ToFImageRecorder::RecordMode m_RecordMode
mode of recording the images: specified number of frames (PerFrames) or infinite (Infinite) ...
int m_ImageSequence
number of images currently acquired
std::string m_AmplitudeImageFileName
file name for saving the amplitude image
itk::FastMutexLock::Pointer m_AbortMutex
mutex for thread-safe data access of abort flag
#define MITK_INFO
Definition: mitkLogMacros.h:18
ToFImageWriter::ToFImageType m_ToFImageType
type of image to be recorded: ToFImageType3D (0) or ToFImageType2DPlusT (1)
bool m_Abort
flag controlling the abort mechanism of the recording procedure. For thread-safety only use in combin...
int m_ToFCaptureHeight
height (y-dimension) of the images to record.
void SetToFImageType(ToFImageWriter::ToFImageType toFImageType)
Set the type of image to be recorded.
ToFCameraDevice::Pointer m_ToFCameraDevice
ToFCameraDevice used for acquiring the images.
Virtual interface and base class for all Time-of-Flight devices.
static Pointer New()
void StopRecording()
Stops the recording by setting the m_Abort flag to false.
DataCollection - Class to facilitate loading/accessing structured data.
std::string m_FileFormat
file format for saving images. If .csv is chosen, ToFImageCsvWriter is used
int m_ToFCaptureWidth
width (x-dimension) of the images to record.
int m_RGBCaptureHeight
height (y-dimension) of the images to record.
int m_NumOfFrames
number of frames to be recorded by this recorder
int m_RGBPixelNumber
number of pixels (widht*height) of the images to record
static Pointer New()
std::string m_DistanceImageFileName
file name for saving the distance image
int m_ToFPixelNumber
number of pixels (widht*height) of the images to record
ToFCameraDevice * GetCameraDevice()
Get the device used for acquiring ToF images.
ToFImageWriter::ToFImageType GetToFImageType()
Get the type of image to be recorded.
Recorder class for ToF images.
void WaitForThreadBeingTerminated()
Wait until thread is terinated.
int m_SourceDataSize
size of the source data provided by the device
void SetCameraDevice(ToFCameraDevice *aToFCameraDevice)
Set the device used for acquiring ToF images.
bool m_AmplitudeImageSelected
flag indicating if amplitude image should be recorded
bool t2(false)
float * m_DistanceArray
array holding the distance data
static ITK_THREAD_RETURN_TYPE RecordData(void *pInfoStruct)
Thread method acquiring data via the ToFCameraDevice and recording it to file via the ToFImageWriter...
std::string m_RGBImageFileName
file name for saving the rgb image
ToFImageRecorder::RecordMode GetRecordMode()
Returns the currently set RecordMode.
int m_RGBCaptureWidth
width (x-dimension) of the images to record.
float * m_IntensityArray
array holding the intensity data
itk::MultiThreader::Pointer m_MultiThreader
member for thread-handling (ITK-based)
ToFImageWriter::Pointer m_ToFImageWriter
image writer writing the acquired images to a file
bool m_DistanceImageSelected
flag indicating if distance image should be recorded
bool m_RGBImageSelected
flag indicating if rgb image should be recorded
void SetRecordMode(ToFImageRecorder::RecordMode recordMode)
Set the RecordMode.
unsigned char * m_RGBArray
array holding the RGB data if available (e.g. for Kinect)
static Pointer New(void)
instanciates a new, operating-system dependant, instance of mitk::RealTimeClock.
std::string m_IntensityImageFileName
file name for saving the intensity image
bool m_IntensityImageSelected
flag indicating if intensity image should be recorded
char * m_SourceDataArray
array holding the source data
int m_ThreadID
ID of the thread recording the data.
float * m_AmplitudeArray
array holding the amplitude data