Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
mitkToFCameraMITKPlayerDevice.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 ============================================================================*/
14 #include "mitkRealTimeClock.h"
15 
16 #include <iostream>
17 #include <fstream>
18 #include <itkMultiThreader.h>
19 #include <itksys/SystemTools.hxx>
20 
21 namespace mitk
22 {
24  m_DistanceDataBuffer(nullptr), m_AmplitudeDataBuffer(nullptr), m_IntensityDataBuffer(nullptr), m_RGBDataBuffer(nullptr)
25 {
27 }
28 
30 {
33 }
34 
36 {
37  bool ok = m_Controller->OpenCameraConnection();
38  if (ok)
39  {
40  this->m_CaptureWidth = m_Controller->GetCaptureWidth();
41  this->m_CaptureHeight = m_Controller->GetCaptureHeight();
42  this->m_RGBImageWidth = m_Controller->GetRGBCaptureWidth();
43  this->m_RGBImageHeight = m_Controller->GetRGBCaptureHeight();
44  this->m_PixelNumber = m_Controller->GetPixelNumber();
45  this->m_RGBPixelNumber = m_Controller->GetRGBPixelNumber();
46 
48  this->SetBoolProperty("RGBImageHasDifferentResolution", true);
49 
50 
53 
54  m_CameraConnected = true;
55  }
56  return ok;
57 }
58 
60 {
61  bool ok = m_Controller->CloseCameraConnection();
62  if (ok)
63  {
64  m_CameraConnected = false;
65  m_PropertyList->Clear();
66  }
67  return ok;
68 }
69 
71 {
73  {
74  // get the first image
75  this->m_Controller->UpdateCamera();
76  this->m_ImageMutex->Lock();
77  this->m_Controller->GetDistances(this->m_DistanceDataBuffer[this->m_FreePos]);
78  this->m_Controller->GetAmplitudes(this->m_AmplitudeDataBuffer[this->m_FreePos]);
79  this->m_Controller->GetIntensities(this->m_IntensityDataBuffer[this->m_FreePos]);
80  this->m_Controller->GetRgb(this->m_RGBDataBuffer[this->m_FreePos]);
81  this->m_FreePos = (this->m_FreePos+1) % this->m_BufferSize;
82  this->m_CurrentPos = (this->m_CurrentPos+1) % this->m_BufferSize;
83  this->m_ImageSequence++;
84  this->m_ImageMutex->Unlock();
85 
86  this->m_CameraActiveMutex->Lock();
87  this->m_CameraActive = true;
88  this->m_CameraActiveMutex->Unlock();
89  this->m_ThreadID = this->m_MultiThreader->SpawnThread(this->Acquire, this);
90  // wait a little to make sure that the thread is started
91  itksys::SystemTools::Delay(10);
92  }
93  else
94  {
95  MITK_INFO<<"Camera not connected";
96  }
97 }
98 
100 {
101  m_Controller->UpdateCamera();
102 }
103 
104 ITK_THREAD_RETURN_TYPE ToFCameraMITKPlayerDevice::Acquire(void* pInfoStruct)
105 {
106  /* extract this pointer from Thread Info structure */
107  struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct;
108  if (pInfo == nullptr)
109  {
110  return ITK_THREAD_RETURN_VALUE;
111  }
112  if (pInfo->UserData == nullptr)
113  {
114  return ITK_THREAD_RETURN_VALUE;
115  }
116  ToFCameraMITKPlayerDevice* toFCameraDevice = (ToFCameraMITKPlayerDevice*)pInfo->UserData;
117  if (toFCameraDevice!=nullptr)
118  {
119  mitk::RealTimeClock::Pointer realTimeClock;
120  realTimeClock = mitk::RealTimeClock::New();
121  int n = 100;
122  double t1, t2;
123  t1 = realTimeClock->GetCurrentStamp();
124  bool overflow = false;
125  bool printStatus = false;
126  while (toFCameraDevice->IsCameraActive())
127  {
128  // update the ToF camera
129  toFCameraDevice->UpdateCamera();
130  // get image data from controller and write it to the according buffer
131  toFCameraDevice->m_Controller->GetDistances(toFCameraDevice->m_DistanceDataBuffer[toFCameraDevice->m_FreePos]);
132  toFCameraDevice->m_Controller->GetAmplitudes(toFCameraDevice->m_AmplitudeDataBuffer[toFCameraDevice->m_FreePos]);
133  toFCameraDevice->m_Controller->GetIntensities(toFCameraDevice->m_IntensityDataBuffer[toFCameraDevice->m_FreePos]);
134  toFCameraDevice->m_Controller->GetRgb(toFCameraDevice->m_RGBDataBuffer[toFCameraDevice->m_FreePos]);
135  toFCameraDevice->Modified();
136  toFCameraDevice->m_ImageMutex->Lock();
137  toFCameraDevice->m_FreePos = (toFCameraDevice->m_FreePos+1) % toFCameraDevice->m_BufferSize;
138  toFCameraDevice->m_CurrentPos = (toFCameraDevice->m_CurrentPos+1) % toFCameraDevice->m_BufferSize;
139  toFCameraDevice->m_ImageSequence++;
140  if (toFCameraDevice->m_FreePos == toFCameraDevice->m_CurrentPos)
141  {
142  overflow = true;
143  }
144  if (toFCameraDevice->m_ImageSequence % n == 0)
145  {
146  printStatus = true;
147  }
148  toFCameraDevice->m_ImageMutex->Unlock();
149  if (overflow)
150  {
151  overflow = false;
152  }
153  // print current framerate
154  if (printStatus)
155  {
156  t2 = realTimeClock->GetCurrentStamp() - t1;
157  MITK_INFO << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence;
158  t1 = realTimeClock->GetCurrentStamp();
159  printStatus = false;
160  }
161  } // end of while loop
162  }
163  return ITK_THREAD_RETURN_VALUE;
164 }
165 
166 void ToFCameraMITKPlayerDevice::GetAmplitudes(float* amplitudeArray, int& imageSequence)
167 {
168  m_ImageMutex->Lock();
169  // write amplitude image data to float array
170  for (int i=0; i<this->m_PixelNumber; i++)
171  {
172  amplitudeArray[i] = this->m_AmplitudeDataBuffer[this->m_CurrentPos][i];
173  }
174  imageSequence = this->m_ImageSequence;
175  m_ImageMutex->Unlock();
176 }
177 
178 void ToFCameraMITKPlayerDevice::GetIntensities(float* intensityArray, int& imageSequence)
179 {
180  m_ImageMutex->Lock();
181  // write intensity image data to float array
182  for (int i=0; i<this->m_PixelNumber; i++)
183  {
184  intensityArray[i] = this->m_IntensityDataBuffer[this->m_CurrentPos][i];
185  }
186  imageSequence = this->m_ImageSequence;
187  m_ImageMutex->Unlock();
188 }
189 
190 void ToFCameraMITKPlayerDevice::GetDistances(float* distanceArray, int& imageSequence)
191 {
192  m_ImageMutex->Lock();
193  // write distance image data to float array
194  for (int i=0; i<this->m_PixelNumber; i++)
195  {
196  distanceArray[i] = this->m_DistanceDataBuffer[this->m_CurrentPos][i];
197  }
198  imageSequence = this->m_ImageSequence;
199  m_ImageMutex->Unlock();
200 }
201 
202 void ToFCameraMITKPlayerDevice::GetRgb(unsigned char* rgbArray, int& imageSequence)
203 {
204  m_ImageMutex->Lock();
205  // write intensity image data to unsigned char array
206  for (int i=0; i<this->m_RGBPixelNumber*3; i++)
207  {
208  rgbArray[i] = this->m_RGBDataBuffer[this->m_CurrentPos][i];
209  }
210  imageSequence = this->m_ImageSequence;
211  m_ImageMutex->Unlock();
212 }
213 
214 void ToFCameraMITKPlayerDevice::GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* /*sourceDataArray*/,
215  int requiredImageSequence, int& capturedImageSequence, unsigned char* rgbDataArray)
216 {
217  m_ImageMutex->Lock();
218 
219  //check for empty buffer
220  if (this->m_ImageSequence < 0)
221  {
222  // buffer empty
223  MITK_INFO << "Buffer empty!! ";
224  capturedImageSequence = this->m_ImageSequence;
225  m_ImageMutex->Unlock();
226  return;
227  }
228  // determine position of image in buffer
229  int pos = 0;
230  if ((requiredImageSequence < 0) || (requiredImageSequence > this->m_ImageSequence))
231  {
232  capturedImageSequence = this->m_ImageSequence;
233  pos = this->m_CurrentPos;
234  }
235  else if (requiredImageSequence <= this->m_ImageSequence - this->m_BufferSize)
236  {
237  capturedImageSequence = (this->m_ImageSequence - this->m_BufferSize) + 1;
238  pos = (this->m_CurrentPos + 1) % this->m_BufferSize;
239  }
240  else // (requiredImageSequence > this->m_ImageSequence - this->m_BufferSize) && (requiredImageSequence <= this->m_ImageSequence)
241  {
242  capturedImageSequence = requiredImageSequence;
243  pos = (this->m_CurrentPos + (10-(this->m_ImageSequence - requiredImageSequence))) % this->m_BufferSize;
244  }
245 
246  if(this->m_DistanceDataBuffer&&this->m_AmplitudeDataBuffer&&this->m_IntensityDataBuffer&&this->m_RGBDataBuffer)
247  {
248  // write image data to float arrays
249  memcpy(distanceArray, this->m_DistanceDataBuffer[pos], this->m_PixelNumber * sizeof(float));
250  memcpy(amplitudeArray, this->m_AmplitudeDataBuffer[pos], this->m_PixelNumber * sizeof(float));
251  memcpy(intensityArray, this->m_IntensityDataBuffer[pos], this->m_PixelNumber * sizeof(float));
252  memcpy(rgbDataArray, this->m_RGBDataBuffer[pos], this->m_RGBPixelNumber * 3 * sizeof(unsigned char));
253  }
254  m_ImageMutex->Unlock();
255 }
256 
257 void ToFCameraMITKPlayerDevice::SetInputFileName(std::string inputFileName)
258 {
259  this->m_InputFileName = inputFileName;
260  this->m_Controller->SetInputFileName(inputFileName);
261 }
262 
263 void ToFCameraMITKPlayerDevice::SetProperty( const char *propertyKey, BaseProperty* propertyValue )
264 {
265  this->m_PropertyList->SetProperty(propertyKey, propertyValue);
266 
267  ToFCameraMITKPlayerController::Pointer myController = dynamic_cast<mitk::ToFCameraMITKPlayerController*>(this->m_Controller.GetPointer());
268 
269  std::string strValue;
270  GetStringProperty(propertyKey, strValue);
271  if (strcmp(propertyKey, "DistanceImageFileName") == 0)
272  {
273  myController->SetDistanceImageFileName(strValue);
274  }
275  else if (strcmp(propertyKey, "AmplitudeImageFileName") == 0)
276  {
277  std::ifstream amplitudeImage(strValue.c_str());
278  if(amplitudeImage)
279  {
280  this->m_PropertyList->SetBoolProperty("HasAmplitudeImage", true);
281  myController->SetAmplitudeImageFileName(strValue);
282  }
283  else
284  {
285  MITK_WARN << "File " << strValue << " does not exist!";
286  }
287  }
288  else if (strcmp(propertyKey, "IntensityImageFileName") == 0)
289  {
290  std::ifstream intensityImage(strValue.c_str());
291  if(intensityImage)
292  {
293  this->m_PropertyList->SetBoolProperty("HasIntensityImage", true);
294  myController->SetIntensityImageFileName(strValue);
295  }
296  else
297  {
298  MITK_WARN << "File " << strValue << " does not exist!";
299  }
300  }
301  else if (strcmp(propertyKey, "RGBImageFileName") == 0)
302  {
303  std::ifstream intensityImage(strValue.c_str());
304  if(intensityImage)
305  {
306  this->m_PropertyList->SetBoolProperty("HasRGBImage", true);
307  myController->SetRGBImageFileName(strValue);
308  }
309  else
310  {
311  MITK_WARN << "File " << strValue << " does not exist!";
312  }
313  }
314 }
315 
317 {
318  if (m_DistanceDataBuffer)
319  {
320  for(int i=0; i<this->m_MaxBufferSize; i++)
321  {
322  delete[] this->m_DistanceDataBuffer[i];
323  }
324  delete[] this->m_DistanceDataBuffer;
325  }
326  if (m_AmplitudeDataBuffer)
327  {
328  for(int i=0; i<this->m_MaxBufferSize; i++)
329  {
330  delete[] this->m_AmplitudeDataBuffer[i];
331  }
332  delete[] this->m_AmplitudeDataBuffer;
333  }
334  if (m_IntensityDataBuffer)
335  {
336  for(int i=0; i<this->m_MaxBufferSize; i++)
337  {
338  delete[] this->m_IntensityDataBuffer[i];
339  }
340  delete[] this->m_IntensityDataBuffer;
341  }
342  if (m_RGBDataBuffer)
343  {
344  for(int i=0; i<this->m_MaxBufferSize; i++)
345  {
346  delete[] this->m_RGBDataBuffer[i];
347  }
348  delete[] this->m_RGBDataBuffer;
349  }
350 }
351 
353 {
354  // free memory if it was already allocated
355  this->CleanUpDataBuffers();
356  // allocate buffers
357  this->m_DistanceDataBuffer = new float*[this->m_MaxBufferSize];
358  for(int i=0; i<this->m_MaxBufferSize; i++)
359  {
360  this->m_DistanceDataBuffer[i] = new float[this->m_PixelNumber];
361  }
362  this->m_AmplitudeDataBuffer = new float*[this->m_MaxBufferSize];
363  for(int i=0; i<this->m_MaxBufferSize; i++)
364  {
365  this->m_AmplitudeDataBuffer[i] = new float[this->m_PixelNumber];
366  }
367  this->m_IntensityDataBuffer = new float*[this->m_MaxBufferSize];
368  for(int i=0; i<this->m_MaxBufferSize; i++)
369  {
370  this->m_IntensityDataBuffer[i] = new float[this->m_PixelNumber];
371  }
372  this->m_RGBDataBuffer = new unsigned char*[this->m_MaxBufferSize];
373  for(int i=0; i<this->m_MaxBufferSize; i++)
374  {
375  this->m_RGBDataBuffer[i] = new unsigned char[this->m_RGBPixelNumber*3];
376  }
377 }
378 }
void GetAllImages(float *distanceArray, float *amplitudeArray, float *intensityArray, char *sourceDataArray, int requiredImageSequence, int &capturedImageSequence, unsigned char *rgbDataArray=nullptr) override
gets the 3 images (distance, amplitude, intensity) from the ToF camera. Caution! The user is responsi...
#define MITK_INFO
Definition: mitkLogMacros.h:18
std::string m_InputFileName
member holding the file name of the current input file
int m_RGBPixelNumber
number of pixels in the range image (m_RGBImageWidth*m_RGBImageHeight)
bool GetStringProperty(const char *propertyKey, std::string &string)
get a string from the property list
virtual void SetInputFileName(std::string inputFileName)
Set file name where the data is recorded.
int m_PixelNumber
number of pixels in the range image (m_CaptureWidth*m_CaptureHeight)
DataCollection - Class to facilitate loading/accessing structured data.
PropertyList::Pointer m_PropertyList
a list of the corresponding properties
int m_ThreadID
ID of the started thread.
void CleanUpDataBuffers()
Clean up memory (pixel buffers)
bool DisconnectCamera() override
closes the connection to the camera
itk::FastMutexLock::Pointer m_CameraActiveMutex
mutex for the cameraActive flag
virtual void GetRgb(unsigned char *rgbArray, int &imageSequence)
gets the rgb data from the ToF camera. Caution! The user is responsible for allocating and deleting t...
itk::MultiThreader::Pointer m_MultiThreader
itk::MultiThreader used for thread handling
int m_FreePos
current position in the buffer which will be filled with data acquired from the hardware ...
Abstract base class for properties.
int m_RGBImageHeight
height of the RGB image (y dimension)
#define MITK_WARN
Definition: mitkLogMacros.h:19
bool m_CameraActive
flag indicating if the camera is currently active or not. Caution: thread safe access only! ...
int m_CurrentPos
current position in the buffer which will be retrieved by the Get methods
bool m_CameraConnected
flag indicating if the camera is successfully connected or not. Caution: thread safe access only! ...
Device class representing a player for MITK-ToF images.
bool t2(false)
int m_CaptureWidth
width of the range image (x dimension)
itk::FastMutexLock::Pointer m_ImageMutex
mutex for images provided by the range camera
ToFCameraMITKPlayerController::Pointer m_Controller
member holding the corresponding controller
virtual void AllocatePixelArrays()
method for allocating memory for pixel arrays m_IntensityArray, m_DistanceArray and m_AmplitudeArray ...
void UpdateCamera() override
updates the camera for image acquisition
int m_BufferSize
buffer size of the image buffer needed for loss-less acquisition of range data
int m_MaxBufferSize
maximal buffer size needed for initialization of data arrays. Default value is 100.
bool OnConnectCamera() override
opens a connection to the ToF camera
int m_CaptureHeight
height of the range image (y dimension)
void SetProperty(const char *propertyKey, BaseProperty *propertyValue) override
set a BaseProperty
void GetAmplitudes(float *amplitudeArray, int &imageSequence) override
gets the amplitude data from the ToF camera as the strength of the active illumination of every pixel...
void GetDistances(float *distanceArray, int &imageSequence) override
gets the distance data from the ToF camera measuring the distance between the camera and the differen...
void AllocateDataBuffers()
Allocate pixel buffers.
Controller for playing ToF images saved in MITK (.pic) format.
static Pointer New(void)
instanciates a new, operating-system dependant, instance of mitk::RealTimeClock.
void SetBoolProperty(const char *propertyKey, bool boolValue)
set a bool property in the property list
int m_RGBImageWidth
width of the RGB image (x dimension)
static ITK_THREAD_RETURN_TYPE Acquire(void *pInfoStruct)
Thread method continuously acquiring images from the specified input file.
int m_ImageSequence
counter for acquired images
virtual bool IsCameraActive()
returns true if the camera is connected and started
void GetIntensities(float *intensityArray, int &imageSequence) override
gets the intensity data from the ToF camera as a greyscale image. Caution! The user is responsible fo...
void StartCamera() override
starts the continuous updating of the camera. A separate thread updates the source data...