Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
mitkToFCameraMESADevice.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 ============================================================================*/
13 #include "mitkRealTimeClock.h"
14 
15 #include "itkMultiThreader.h"
16 #include <itksys/SystemTools.hxx>
17 
18 namespace mitk
19 {
21  {
22  }
23 
25  {
26  }
27 
29  {
30  bool ok = false;
31  if (m_Controller)
32  {
33  ok = m_Controller->OpenCameraConnection();
34  if (ok)
35  {
36  this->m_CaptureWidth = m_Controller->GetCaptureWidth();
37  this->m_CaptureHeight = m_Controller->GetCaptureHeight();
38  this->m_PixelNumber = this->m_CaptureWidth * this->m_CaptureHeight;
39 
40  // allocate buffer
41  this->m_IntensityArray = new float[this->m_PixelNumber];
42  for(int i=0; i<this->m_PixelNumber; i++) {this->m_IntensityArray[i]=0.0;}
43  this->m_DistanceArray = new float[this->m_PixelNumber];
44  for(int i=0; i<this->m_PixelNumber; i++) {this->m_DistanceArray[i]=0.0;}
45  this->m_AmplitudeArray = new float[this->m_PixelNumber];
46  for(int i=0; i<this->m_PixelNumber; i++) {this->m_AmplitudeArray[i]=0.0;}
47 
48  this->m_DistanceDataBuffer = new float*[this->m_MaxBufferSize];
49  for(int i=0; i<this->m_MaxBufferSize; i++)
50  {
51  this->m_DistanceDataBuffer[i] = new float[this->m_PixelNumber];
52  }
53  this->m_AmplitudeDataBuffer = new float*[this->m_MaxBufferSize];
54  for(int i=0; i<this->m_MaxBufferSize; i++)
55  {
56  this->m_AmplitudeDataBuffer[i] = new float[this->m_PixelNumber];
57  }
58  this->m_IntensityDataBuffer = new float*[this->m_MaxBufferSize];
59  for(int i=0; i<this->m_MaxBufferSize; i++)
60  {
61  this->m_IntensityDataBuffer[i] = new float[this->m_PixelNumber];
62  }
63 
64  m_CameraConnected = true;
65  }
66  }
67  return ok;
68  }
69 
71  {
72  bool ok = false;
73  if (m_Controller)
74  {
75  ok = m_Controller->CloseCameraConnection();
76 
77  // clean-up only if camera was connected
79  {
80  delete [] m_IntensityArray;
81  delete [] m_DistanceArray;
82  delete [] m_AmplitudeArray;
83 
84  for(int i=0; i<this->m_MaxBufferSize; i++)
85  {
86  delete[] this->m_DistanceDataBuffer[i];
87  }
88  delete[] this->m_DistanceDataBuffer;
89  for(int i=0; i<this->m_MaxBufferSize; i++)
90  {
91  delete[] this->m_AmplitudeDataBuffer[i];
92  }
93  delete[] this->m_AmplitudeDataBuffer;
94  for(int i=0; i<this->m_MaxBufferSize; i++)
95  {
96  delete[] this->m_IntensityDataBuffer[i];
97  }
98  delete[] this->m_IntensityDataBuffer;
99 
100  m_CameraConnected = false;
101  }
102 
103  }
104  return ok;
105  }
106 
108  {
109  if (m_CameraConnected)
110  {
111  // get the first image
112  this->m_Controller->UpdateCamera();
113  this->m_ImageMutex->Lock();
114  this->m_Controller->GetDistances(this->m_DistanceDataBuffer[this->m_FreePos]);
115  this->m_Controller->GetAmplitudes(this->m_AmplitudeDataBuffer[this->m_FreePos]);
116  this->m_Controller->GetIntensities(this->m_IntensityDataBuffer[this->m_FreePos]);
117  this->m_FreePos = (this->m_FreePos+1) % this->m_BufferSize;
118  this->m_CurrentPos = (this->m_CurrentPos+1) % this->m_BufferSize;
119  this->m_ImageSequence++;
120  this->m_ImageMutex->Unlock();
121 
122  this->m_CameraActiveMutex->Lock();
123  this->m_CameraActive = true;
124  this->m_CameraActiveMutex->Unlock();
125  this->m_ThreadID = this->m_MultiThreader->SpawnThread(this->Acquire, this);
126  // wait a little to make sure that the thread is started
127  itksys::SystemTools::Delay(10);
128  }
129  else
130  {
131  MITK_INFO<<"Camera not connected";
132  }
133  }
134 
136  {
137  m_CameraActiveMutex->Lock();
138  m_CameraActive = false;
139  m_CameraActiveMutex->Unlock();
140  itksys::SystemTools::Delay(100);
141  if (m_MultiThreader.IsNotNull())
142  {
143  m_MultiThreader->TerminateThread(m_ThreadID);
144  }
145  // wait a little to make sure that the thread is terminated
146  itksys::SystemTools::Delay(10);
147  }
148 
150  {
151  m_CameraActiveMutex->Lock();
152  bool ok = m_CameraActive;
153  m_CameraActiveMutex->Unlock();
154  return ok;
155  }
156 
158  {
159  if (m_Controller)
160  {
161  m_Controller->UpdateCamera();
162  }
163  }
164 
165  ITK_THREAD_RETURN_TYPE ToFCameraMESADevice::Acquire(void* pInfoStruct)
166  {
167  /* extract this pointer from Thread Info structure */
168  struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct;
169  if (pInfo == nullptr)
170  {
171  return ITK_THREAD_RETURN_VALUE;
172  }
173  if (pInfo->UserData == nullptr)
174  {
175  return ITK_THREAD_RETURN_VALUE;
176  }
177  ToFCameraMESADevice* toFCameraDevice = (ToFCameraMESADevice*)pInfo->UserData;
178  if (toFCameraDevice!=nullptr)
179  {
180  mitk::RealTimeClock::Pointer realTimeClock;
181  realTimeClock = mitk::RealTimeClock::New();
182  double t1, t2;
183  t1 = realTimeClock->GetCurrentStamp();
184  int n = 100;
185  bool overflow = false;
186  bool printStatus = false;
187  while (toFCameraDevice->IsCameraActive())
188  {
189  // update the ToF camera
190  toFCameraDevice->UpdateCamera();
191  // get the image data from the camera and write it at the next free position in the buffer
192  toFCameraDevice->m_ImageMutex->Lock();
193  toFCameraDevice->m_Controller->GetDistances(toFCameraDevice->m_DistanceDataBuffer[toFCameraDevice->m_FreePos]);
194  toFCameraDevice->m_Controller->GetAmplitudes(toFCameraDevice->m_AmplitudeDataBuffer[toFCameraDevice->m_FreePos]);
195  toFCameraDevice->m_Controller->GetIntensities(toFCameraDevice->m_IntensityDataBuffer[toFCameraDevice->m_FreePos]);
196  toFCameraDevice->m_ImageMutex->Unlock();
197 
198  // call modified to indicate that cameraDevice was modified
199  toFCameraDevice->Modified();
200 
201  toFCameraDevice->m_FreePos = (toFCameraDevice->m_FreePos+1) % toFCameraDevice->m_BufferSize;
202  toFCameraDevice->m_CurrentPos = (toFCameraDevice->m_CurrentPos+1) % toFCameraDevice->m_BufferSize;
203  toFCameraDevice->m_ImageSequence++;
204  if (toFCameraDevice->m_FreePos == toFCameraDevice->m_CurrentPos)
205  {
206  overflow = true;
207  }
208  if (toFCameraDevice->m_ImageSequence % n == 0)
209  {
210  printStatus = true;
211  }
212  if (overflow)
213  {
214  overflow = false;
215  }
216 
217  // print current framerate
218  if (printStatus)
219  {
220  t2 = realTimeClock->GetCurrentStamp() - t1;
221  MITK_INFO << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence;
222  t1 = realTimeClock->GetCurrentStamp();
223  printStatus = false;
224  }
225  } // end of while loop
226  }
227  return ITK_THREAD_RETURN_VALUE;
228  }
229 
230  void ToFCameraMESADevice::GetAmplitudes(float* amplitudeArray, int& imageSequence)
231  {
232  m_ImageMutex->Lock();
233  if (m_CameraActive)
234  {
235  // copy the image buffer
236  for (int i=0; i<this->m_PixelNumber; i++)
237  {
238  amplitudeArray[i] = this->m_AmplitudeDataBuffer[this->m_CurrentPos][i];
239  }
240  imageSequence = this->m_ImageSequence;
241  }
242  else
243  {
244  MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active.";
245  }
246  m_ImageMutex->Unlock();
247  }
248 
249  void ToFCameraMESADevice::GetIntensities(float* intensityArray, int& imageSequence)
250  {
251  m_ImageMutex->Lock();
252  if (m_CameraActive)
253  {
254  for (int i=0; i<this->m_PixelNumber; i++)
255  {
256  intensityArray[i] = this->m_IntensityDataBuffer[this->m_CurrentPos][i];
257  }
258  imageSequence = this->m_ImageSequence;
259  }
260  else
261  {
262  MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active.";
263  }
264  m_ImageMutex->Unlock();
265  }
266 
267  void ToFCameraMESADevice::GetDistances(float* distanceArray, int& imageSequence)
268  {
269  m_ImageMutex->Lock();
270  if (m_CameraActive)
271  {
272  for (int i=0; i<this->m_PixelNumber; i++)
273  {
274  distanceArray[i] = this->m_DistanceDataBuffer[this->m_CurrentPos][i];
275  }
276  imageSequence = this->m_ImageSequence;
277  }
278  else
279  {
280  MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active.";
281  }
282  m_ImageMutex->Unlock();
283  }
284 
285  void ToFCameraMESADevice::GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray,
286  int requiredImageSequence, int& capturedImageSequence, unsigned char* rgbDataArray)
287  {
288  if (m_CameraActive)
289  {
290  // check for empty buffer
291  if (this->m_ImageSequence < 0)
292  {
293  // buffer empty
294  MITK_INFO << "Buffer empty!! ";
295  capturedImageSequence = this->m_ImageSequence;
296  return;
297  }
298  // determine position of image in buffer
299  int pos = 0;
300  if ((requiredImageSequence < 0) || (requiredImageSequence > this->m_ImageSequence))
301  {
302  capturedImageSequence = this->m_ImageSequence;
303  pos = this->m_CurrentPos;
304  }
305  else if (requiredImageSequence <= this->m_ImageSequence - this->m_BufferSize)
306  {
307  capturedImageSequence = (this->m_ImageSequence - this->m_BufferSize) + 1;
308  pos = (this->m_CurrentPos + 1) % this->m_BufferSize;
309  }
310  else // (requiredImageSequence > this->m_ImageSequence - this->m_BufferSize) && (requiredImageSequence <= this->m_ImageSequence)
311 
312  {
313  capturedImageSequence = requiredImageSequence;
314  pos = (this->m_CurrentPos + (10-(this->m_ImageSequence - requiredImageSequence))) % this->m_BufferSize;
315  }
316 
317  // write image data to float arrays
318  for (int i=0; i<this->m_PixelNumber; i++)
319  {
320  distanceArray[i] = this->m_DistanceDataBuffer[pos][i] /* * 1000 */;
321  amplitudeArray[i] = this->m_AmplitudeDataBuffer[pos][i];
322  intensityArray[i] = this->m_IntensityDataBuffer[pos][i];
323  }
324  }
325  else
326  {
327  MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active.";
328  }
329  }
330 
331  ToFCameraMESAController::Pointer ToFCameraMESADevice::GetController()
332  {
333  return this->m_Controller;
334  }
335 
336  void ToFCameraMESADevice::SetProperty( const char *propertyKey, BaseProperty* propertyValue )
337  {
338  ToFCameraDevice::SetProperty(propertyKey,propertyValue);
339  this->m_PropertyList->SetProperty(propertyKey, propertyValue);
340  if (strcmp(propertyKey, "ModulationFrequency") == 0)
341  {
342  int modulationFrequency = 0;
343  GetIntProperty(propertyKey, modulationFrequency);
344  m_Controller->SetModulationFrequency(modulationFrequency);
345  }
346  else if (strcmp(propertyKey, "IntegrationTime") == 0)
347  {
348  int integrationTime = 0;
349  GetIntProperty(propertyKey, integrationTime);
350  m_Controller->SetIntegrationTime(integrationTime);
351  }
352  }
353 }
virtual void GetIntensities(float *intensityArray, int &imageSequence)
gets the intensity data from the ToF camera as a greyscale image. Caution! The user is responsible fo...
virtual bool IsCameraActive()
returns whether the camera is currently active or not
#define MITK_INFO
Definition: mitkLogMacros.h:18
virtual void SetProperty(const char *propertyKey, BaseProperty *propertyValue)
set a BaseProperty
virtual void GetDistances(float *distanceArray, int &imageSequence)
gets the distance data from the ToF camera measuring the distance between the camera and the differen...
float * m_IntensityArray
float array holding the intensity image
virtual void StopCamera()
stops the continuous updating of the camera
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
float * m_DistanceArray
float array holding the distance image
int m_ThreadID
ID of the started thread.
bool GetIntProperty(const char *propertyKey, int &integer)
get an int from the property list
itk::FastMutexLock::Pointer m_CameraActiveMutex
mutex for the cameraActive flag
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.
static ITK_THREAD_RETURN_TYPE Acquire(void *pInfoStruct)
Thread method continuously acquiring images from the ToF hardware.
virtual void SetProperty(const char *propertyKey, BaseProperty *propertyValue)
set a BaseProperty property in the property list
#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! ...
float ** m_AmplitudeDataBuffer
buffer holding the last amplitude images
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! ...
bool t2(false)
Interface for all representations of MESA ToF devices. ToFCameraMESADevice internally holds an instan...
int m_CaptureWidth
width of the range image (x dimension)
ToFCameraMESAController::Pointer GetController()
returns the corresponding camera controller
virtual bool OnConnectCamera()
opens a connection to the ToF camera
itk::FastMutexLock::Pointer m_ImageMutex
mutex for images provided by the range camera
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.
float ** m_DistanceDataBuffer
buffer holding the last distance images
int m_CaptureHeight
height of the range image (y dimension)
virtual void StartCamera()
starts the continuous updating of the camera. A separate thread updates the source data...
virtual bool DisconnectCamera()
closes the connection to the camera
virtual void GetAllImages(float *distanceArray, float *amplitudeArray, float *intensityArray, char *sourceDataArray, int requiredImageSequence, int &capturedImageSequence, unsigned char *rgbDataArray=nullptr)
gets the 3 images (distance, amplitude, intensity) from the ToF camera. Caution! The user is responsi...
float * m_AmplitudeArray
float array holding the amplitude image
static Pointer New(void)
instanciates a new, operating-system dependant, instance of mitk::RealTimeClock.
float ** m_IntensityDataBuffer
buffer holding the last intensity images
virtual void GetAmplitudes(float *amplitudeArray, int &imageSequence)
gets the amplitude data from the ToF camera as the strength of the active illumination of every pixel...
virtual void UpdateCamera()
updates the camera for image acquisition
int m_ImageSequence
counter for acquired images
ToFCameraMESAController::Pointer m_Controller
corresponding CameraController