Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkKinectDevice.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,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 #include "mitkKinectDevice.h"
17 #include <mitkRealTimeClock.h>
18 
19 #include <itkMultiThreader.h>
20 #include <itksys/SystemTools.hxx>
21 
22 
23 namespace mitk
24 {
25 
27 {
29 }
30 
32 {
33 }
34 
36 {
37  bool ok = false;
38  if (m_Controller)
39  {
40  ok = m_Controller->OpenCameraConnection();
41  if (ok)
42  {
43  this->m_CaptureWidth = m_Controller->GetCaptureWidth();
44  this->m_CaptureHeight = m_Controller->GetCaptureHeight();
45  this->m_PixelNumber = this->m_CaptureWidth * this->m_CaptureHeight;
46 
50 
51  this->SetBoolProperty("HasAmplitudeImage", m_Controller->GetUseIR());
52  this->SetBoolProperty("HasRGBImage", !m_Controller->GetUseIR());
53 
54  // allocate buffer
55  this->m_DistanceArray = new float[this->m_PixelNumber];
56  for(int i=0; i<this->m_PixelNumber; i++) {this->m_DistanceArray[i]=0.0;}
57  this->m_AmplitudeArray = new float[this->m_PixelNumber];
58  for(int i=0; i<this->m_PixelNumber; i++) {this->m_AmplitudeArray[i]=0.0;}
59 
60  this->m_DistanceDataBuffer = new float*[this->m_MaxBufferSize];
61  for(int i=0; i<this->m_MaxBufferSize; i++)
62  {
63  this->m_DistanceDataBuffer[i] = new float[this->m_PixelNumber];
64  }
65  this->m_AmplitudeDataBuffer = new float*[this->m_MaxBufferSize];
66  for(int i=0; i<this->m_MaxBufferSize; i++)
67  {
68  this->m_AmplitudeDataBuffer[i] = new float[this->m_PixelNumber];
69  }
70  this->m_RGBDataBuffer = new unsigned char*[this->m_MaxBufferSize];
71  for (int i=0; i<this->m_MaxBufferSize; i++)
72  {
73  this->m_RGBDataBuffer[i] = new unsigned char[this->m_PixelNumber*3];
74  }
75 
76  m_CameraConnected = true;
77  }
78  }
79  return ok;
80 }
81 
83 {
84  bool ok = false;
85  if (m_Controller)
86  {
87  ok = m_Controller->CloseCameraConnection();
88 
89  // clean-up only if camera was connected
91  {
92  delete [] m_DistanceArray;
93  delete [] m_AmplitudeArray;
94 
95  for(int i=0; i<this->m_MaxBufferSize; i++)
96  {
97  delete[] this->m_DistanceDataBuffer[i];
98  delete[] this->m_AmplitudeDataBuffer[i];
99  delete[] this->m_RGBDataBuffer[i];
100  }
101  delete[] this->m_DistanceDataBuffer;
102  delete[] this->m_AmplitudeDataBuffer;
103  delete[] this->m_RGBDataBuffer;
104 
105  m_CameraConnected = false;
106  }
107 
108  }
109  return ok;
110 }
111 
113 {
114  if (m_CameraConnected)
115  {
116  // get the first image
117  this->m_Controller->UpdateCamera();
118  this->m_ImageMutex->Lock();
119  this->m_Controller->GetAllData(this->m_DistanceDataBuffer[this->m_FreePos],this->m_AmplitudeDataBuffer[this->m_FreePos],this->m_RGBDataBuffer[this->m_FreePos]);
120  this->m_FreePos = (this->m_FreePos+1) % this->m_BufferSize;
121  this->m_CurrentPos = (this->m_CurrentPos+1) % this->m_BufferSize;
122  this->m_ImageSequence++;
123  this->m_ImageMutex->Unlock();
124 
125  this->m_CameraActiveMutex->Lock();
126  this->m_CameraActive = true;
127  this->m_CameraActiveMutex->Unlock();
128  this->m_ThreadID = this->m_MultiThreader->SpawnThread(this->Acquire, this);
129  // wait a little to make sure that the thread is started
130  itksys::SystemTools::Delay(10);
131  }
132  else
133  {
134  MITK_INFO<<"Camera not connected";
135  }
136 }
137 
139 {
140  m_CameraActiveMutex->Lock();
141  m_CameraActive = false;
142  m_CameraActiveMutex->Unlock();
143  itksys::SystemTools::Delay(100);
144  if (m_MultiThreader.IsNotNull())
145  {
146  m_MultiThreader->TerminateThread(m_ThreadID);
147  }
148  // wait a little to make sure that the thread is terminated
149  itksys::SystemTools::Delay(10);
150 }
151 
153 {
154  m_CameraActiveMutex->Lock();
155  bool ok = m_CameraActive;
156  m_CameraActiveMutex->Unlock();
157  return ok;
158 }
159 
161 {
162  if (m_Controller)
163  {
164  m_Controller->UpdateCamera();
165  }
166 }
167 
168 ITK_THREAD_RETURN_TYPE KinectDevice::Acquire(void* pInfoStruct)
169 {
170  /* extract this pointer from Thread Info structure */
171  struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct;
172  if (pInfo == NULL)
173  {
174  return ITK_THREAD_RETURN_VALUE;
175  }
176  if (pInfo->UserData == NULL)
177  {
178  return ITK_THREAD_RETURN_VALUE;
179  }
180  KinectDevice* toFCameraDevice = (KinectDevice*)pInfo->UserData;
181  if (toFCameraDevice!=NULL)
182  {
183  mitk::RealTimeClock::Pointer realTimeClock;
184  realTimeClock = mitk::RealTimeClock::New();
185  double t1, t2;
186  t1 = realTimeClock->GetCurrentStamp();
187  int n = 100;
188  bool overflow = false;
189  bool printStatus = false;
190  while (toFCameraDevice->IsCameraActive())
191  {
192  // update the ToF camera
193  toFCameraDevice->UpdateCamera();
194  // get the image data from the camera and write it at the next free position in the buffer
195  toFCameraDevice->m_ImageMutex->Lock();
196  toFCameraDevice->m_Controller->GetAllData(toFCameraDevice->m_DistanceDataBuffer[toFCameraDevice->m_FreePos],toFCameraDevice->m_AmplitudeDataBuffer[toFCameraDevice->m_FreePos],toFCameraDevice->m_RGBDataBuffer[toFCameraDevice->m_FreePos]);
197  toFCameraDevice->m_ImageMutex->Unlock();
198 
199  // call modified to indicate that cameraDevice was modified
200  toFCameraDevice->Modified();
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 KinectDevice::GetAmplitudes(float* amplitudeArray, int& imageSequence)
231 {
232  m_ImageMutex->Lock();
233  if (m_CameraActive)
234  {
235  // copy the image buffer
236  imageSequence = this->m_ImageSequence;
237  }
238  else
239  {
240  MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active.";
241  }
242  m_ImageMutex->Unlock();
243 }
244 
245 void KinectDevice::GetIntensities(float *, int &)
246 {
247 }
248 
249 void KinectDevice::GetDistances(float* distanceArray, int& imageSequence)
250 {
251  m_ImageMutex->Lock();
252  if (m_CameraActive)
253  {
254  imageSequence = this->m_ImageSequence;
255  }
256  else
257  {
258  MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active.";
259  }
260  m_ImageMutex->Unlock();
261 }
262 
263 void KinectDevice::GetAllImages(float* distanceArray, float* amplitudeArray, float*, char*,
264  int requiredImageSequence, int& capturedImageSequence, unsigned char* rgbDataArray)
265 {
266  if (m_CameraActive)
267  {
268  // check for empty buffer
269  if (this->m_ImageSequence < 0)
270  {
271  // buffer empty
272  MITK_INFO << "Buffer empty!! ";
273  capturedImageSequence = this->m_ImageSequence;
274  return;
275  }
276 
277  // determine position of image in buffer
278  int pos = 0;
279  if ((requiredImageSequence < 0) || (requiredImageSequence > this->m_ImageSequence))
280  {
281  capturedImageSequence = this->m_ImageSequence;
282  pos = this->m_CurrentPos;
283  }
284  else if (requiredImageSequence <= this->m_ImageSequence - this->m_BufferSize)
285  {
286  capturedImageSequence = (this->m_ImageSequence - this->m_BufferSize) + 1;
287  pos = (this->m_CurrentPos + 1) % this->m_BufferSize;
288  }
289  else // (requiredImageSequence > this->m_ImageSequence - this->m_BufferSize) && (requiredImageSequence <= this->m_ImageSequence)
290  {
291  capturedImageSequence = requiredImageSequence;
292  pos = (this->m_CurrentPos + (10-(this->m_ImageSequence - requiredImageSequence))) % this->m_BufferSize;
293  }
294 
295  memcpy( distanceArray, this->m_DistanceDataBuffer[pos], m_PixelNumber*sizeof(float));
296  if(m_Controller->GetUseIR())
297  {
298  memcpy( amplitudeArray, this->m_AmplitudeDataBuffer[pos], m_PixelNumber*sizeof(float));
299  }
300  else
301  {
302  memcpy( rgbDataArray, this->m_RGBDataBuffer[pos], m_RGBPixelNumber*3*sizeof(unsigned char));
303  }
304  }
305  else
306  {
307  MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active.";
308  }
309 }
310 
312 {
313  return this->m_Controller;
314 }
315 
316 void KinectDevice::SetProperty( const char *propertyKey, BaseProperty* propertyValue )
317 {
318  ToFCameraDevice::SetProperty(propertyKey,propertyValue);
319  this->m_PropertyList->SetProperty(propertyKey, propertyValue);
320  if (strcmp(propertyKey, "RGB") == 0)
321  {
322  bool rgb = false;
323  GetBoolProperty(propertyKey, rgb);
324  m_Controller->SetUseIR(!rgb);
325  }
326  else if (strcmp(propertyKey, "IR") == 0)
327  {
328  bool ir = false;
329  GetBoolProperty(propertyKey, ir);
330  m_Controller->SetUseIR(ir);
331  }
332 }
333 
335 {
336  return this->GetCaptureWidth();
337 }
338 
340 {
341  return this->GetCaptureHeight();
342 }
343 }
virtual int GetCaptureHeight()
get the currently set capture height
itk::SmartPointer< Self > Pointer
#define MITK_INFO
Definition: mitkLogMacros.h:22
static ITK_THREAD_RETURN_TYPE Acquire(void *pInfoStruct)
Thread method continuously acquiring images from the ToF hardware.
float ** m_DistanceDataBuffer
buffer holding the last distance images
virtual void UpdateCamera()
updates the camera for image acquisition
float ** m_AmplitudeDataBuffer
buffer holding the last infra-red (IR) images
bool GetBoolProperty(const char *propertyKey, bool &boolValue)
get a bool from the property list
int m_RGBPixelNumber
number of pixels in the range image (m_RGBImageWidth*m_RGBImageHeight)
int m_PixelNumber
number of pixels in the range image (m_CaptureWidth*m_CaptureHeight)
virtual void GetDistances(float *distanceArray, int &imageSequence)
gets the distance data from the ToF camera measuring the distance between the camera and the differen...
DataCollection - Class to facilitate loading/accessing structured data.
PropertyList::Pointer m_PropertyList
a list of the corresponding properties
int GetRGBCaptureHeight()
returns the height of the RGB image
float * m_DistanceArray
float array holding the distance image
int m_ThreadID
ID of the started thread.
virtual bool OnConnectCamera()
opens a connection to the ToF camera
Interface for all representations of Kinect devices. KinectDevice internally holds an instance of Kin...
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.
virtual bool IsCameraActive()
returns whether the camera is currently active or not
virtual void SetProperty(const char *propertyKey, BaseProperty *propertyValue)
set a BaseProperty property in the property list
int m_RGBImageHeight
height of the RGB image (y dimension)
#define MITK_WARN
Definition: mitkLogMacros.h:23
bool m_CameraActive
flag indicating if the camera is currently active or not. Caution: thread safe access only! ...
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...
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! ...
KinectController::Pointer m_Controller
corresponding CameraController
int m_CaptureWidth
width of the range image (x dimension)
virtual void GetAllImages(float *distanceArray, float *amplitudeArray, float *intensityArray, char *sourceDataArray, int requiredImageSequence, int &capturedImageSequence, unsigned char *rgbDataArray=NULL)
gets the 3 images (distance, amplitude, intensity) from the ToF camera. Caution! The user is responsi...
itk::FastMutexLock::Pointer m_ImageMutex
mutex for images provided by the range camera
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...
int m_BufferSize
buffer size of the image buffer needed for loss-less acquisition of range data
KinectController::Pointer GetController()
returns the corresponding camera controller
static Pointer New()
virtual bool DisconnectCamera()
closes the connection to the camera
unsigned char ** m_RGBDataBuffer
buffer holding the last RGB image
int m_MaxBufferSize
maximal buffer size needed for initialization of data arrays. Default value is 100.
int m_CaptureHeight
height of the range image (y dimension)
virtual void StopCamera()
stops the continuous updating of the camera
virtual void StartCamera()
starts the continuous updating of the camera. A separate thread updates the source data...
float * m_AmplitudeArray
float array holding the amplitude image
virtual void SetProperty(const char *propertyKey, BaseProperty *propertyValue)
set a BaseProperty
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)
int GetRGBCaptureWidth()
returns the width of the RGB image
virtual int GetCaptureWidth()
get the currently set capture width
int m_ImageSequence
counter for acquired images