MITK-IGT
IGT Extension of MITK
Loading...
Searching...
No Matches
mitkKinectV2Device.cpp
Go to the documentation of this file.
1/*============================================================================
2
3The Medical Imaging Interaction Toolkit (MITK)
4
5Copyright (c) German Cancer Research Center (DKFZ)
6All rights reserved.
7
8Use of this source code is governed by a 3-clause BSD license that can be
9found in the LICENSE file.
10
11============================================================================*/
12#include "mitkKinectV2Device.h"
13
14
15#include <mitkRealTimeClock.h>
16#include <mitkSmartPointerProperty.h>
17#include <mitkSurface.h>
18
19#include <itkMultiThreader.h>
20#include <itksys/SystemTools.hxx>
21
22
23namespace mitk
24{
26
28 m_DistanceDataBuffer(nullptr),
29 m_AmplitudeDataBuffer(nullptr),
30 m_RGBDataBuffer(nullptr),
31 m_DepthBufferSize(sizeof(float)*512*424),
32 m_RGBBufferSize(3*1920*1080)
33 {
34 m_Controller = mitk::KinectV2Controller::New();
36 }
37
41
42 std::string GetDeviceName()
43 {
44 return "Microsoft Kinect 2 Device ";
45 }
46
48 {
49 bool ok = false;
50 if (m_Controller)
51 {
52 ok = m_Controller->OpenCameraConnection();
53 if (ok)
54 {
55 this->m_CaptureWidth = m_Controller->GetDepthCaptureWidth();
56 this->m_CaptureHeight = m_Controller->GetDepthCaptureHeight();
57 this->m_PixelNumber = this->m_CaptureWidth * this->m_CaptureHeight;
58
59 this->m_RGBImageWidth = m_Controller->GetRGBCaptureWidth();
60 this->m_RGBImageHeight = m_Controller->GetRGBCaptureHeight();
62
63 // allocate buffer
64 this->m_DistanceArray = new float[this->m_PixelNumber];
65 for(int i=0; i<this->m_PixelNumber; i++) {this->m_DistanceArray[i]=0.0;}
66 this->m_AmplitudeArray = new float[this->m_PixelNumber];
67 for(int i=0; i<this->m_PixelNumber; i++) {this->m_AmplitudeArray[i]=0.0;}
68
69 this->m_DistanceDataBuffer = new float*[this->m_MaxBufferSize];
70 for(int i=0; i<this->m_MaxBufferSize; i++)
71 {
72 this->m_DistanceDataBuffer[i] = new float[this->m_PixelNumber];
73 }
74 this->m_AmplitudeDataBuffer = new float*[this->m_MaxBufferSize];
75 for(int i=0; i<this->m_MaxBufferSize; i++)
76 {
77 this->m_AmplitudeDataBuffer[i] = new float[this->m_PixelNumber];
78 }
79 this->m_RGBDataBuffer = new unsigned char*[this->m_MaxBufferSize];
80 for (int i=0; i<this->m_MaxBufferSize; i++)
81 {
82 this->m_RGBDataBuffer[i] = new unsigned char[this->m_RGBPixelNumber*3];
83 }
84
85 m_CameraConnected = true;
86 }
87 }
88 return ok;
89 }
90
92 {
93 bool ok = false;
94 if (m_Controller)
95 {
96 ok = m_Controller->CloseCameraConnection();
97
98 // clean-up only if camera was connected
100 {
101 delete [] m_DistanceArray;
102 delete [] m_AmplitudeArray;
103
104 for(int i=0; i<this->m_MaxBufferSize; i++)
105 {
106 delete[] this->m_DistanceDataBuffer[i];
107 delete[] this->m_AmplitudeDataBuffer[i];
108 delete[] this->m_RGBDataBuffer[i];
109 }
110 delete[] this->m_DistanceDataBuffer;
111 delete[] this->m_AmplitudeDataBuffer;
112 delete[] this->m_RGBDataBuffer;
113
114 m_CameraConnected = false;
115 }
116 }
117 return ok;
118 }
119
121 {
123 {
124 // get the first image
125 this->m_Controller->UpdateCamera();
126 this->m_ImageMutex->Lock();
127 this->m_Controller->GetAllData(this->m_DistanceDataBuffer[this->m_FreePos],this->m_AmplitudeDataBuffer[this->m_FreePos],this->m_RGBDataBuffer[this->m_FreePos]);
128 this->m_FreePos = (this->m_FreePos+1) % this->m_BufferSize;
129 this->m_CurrentPos = (this->m_CurrentPos+1) % this->m_BufferSize;
130 this->m_ImageSequence++;
131 this->m_ImageMutex->Unlock();
132
133 this->m_CameraActiveMutex->Lock();
134 this->m_CameraActive = true;
135 this->m_CameraActiveMutex->Unlock();
136 this->m_ThreadID = this->m_MultiThreader->SpawnThread(this->Acquire, this);
137 // wait a little to make sure that the thread is started
138 itksys::SystemTools::Delay(10);
139 }
140 else
141 {
142 MITK_WARN << "Camera not connected";
143 }
144 }
145
147 {
148 m_CameraActiveMutex->Lock();
149 m_CameraActive = false;
150 m_CameraActiveMutex->Unlock();
151 itksys::SystemTools::Delay(100);
152 if (m_MultiThreader.IsNotNull())
153 {
154 m_MultiThreader->TerminateThread(m_ThreadID);
155 }
156 // wait a little to make sure that the thread is terminated
157 itksys::SystemTools::Delay(10);
158 }
159
161 {
162 m_CameraActiveMutex->Lock();
163 bool ok = m_CameraActive;
164 m_CameraActiveMutex->Unlock();
165 return ok;
166 }
167
169 {
170 if (m_Controller)
171 {
172 m_Controller->UpdateCamera();
173 }
174 }
175
176 ITK_THREAD_RETURN_TYPE KinectV2Device::Acquire(void* pInfoStruct)
177 {
178 /* extract this pointer from Thread Info structure */
179 struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct;
180 if (pInfo == nullptr)
181 {
182 return ITK_THREAD_RETURN_VALUE;
183 }
184 if (pInfo->UserData == nullptr)
185 {
186 return ITK_THREAD_RETURN_VALUE;
187 }
188 KinectV2Device* toFCameraDevice = (KinectV2Device*)pInfo->UserData;
189 if (toFCameraDevice!=nullptr)
190 {
191 mitk::RealTimeClock::Pointer realTimeClock;
192 realTimeClock = mitk::RealTimeClock::New();
193 double t1, t2;
194 t1 = realTimeClock->GetCurrentStamp();
195 int n = 100;
196 bool overflow = false;
197 bool printStatus = false;
198 while (toFCameraDevice->IsCameraActive())
199 {
200 // update the ToF camera
201 toFCameraDevice->UpdateCamera();
202 // get the image data from the camera and write it at the next free position in the buffer
203 toFCameraDevice->m_ImageMutex->Lock();
204 toFCameraDevice->m_Controller->GetAllData(toFCameraDevice->m_DistanceDataBuffer[toFCameraDevice->m_FreePos],toFCameraDevice->m_AmplitudeDataBuffer[toFCameraDevice->m_FreePos],toFCameraDevice->m_RGBDataBuffer[toFCameraDevice->m_FreePos]);
205 //Here we get also the PolyData, because the kinect V2 SDK offers an excellent
206 //default calibration and generates very nice, textured surfaces. The method
207 //GetAllData of MITK-ToF does not allow for passing the surface.
208 toFCameraDevice->m_PolyData = toFCameraDevice->m_Controller->GetVtkPolyData();
209 toFCameraDevice->m_ImageMutex->Unlock();
210
211 // call modified to indicate that cameraDevice was modified
212 toFCameraDevice->Modified();
213
214 bool generateTriangularMesh = false;
215 toFCameraDevice->GetBoolProperty("GenerateTriangularMesh", generateTriangularMesh);
216 toFCameraDevice->m_Controller->SetGenerateTriangularMesh(generateTriangularMesh);
217
218 float triangulationThreshold = static_cast<mitk::FloatProperty*>(toFCameraDevice->GetProperty("TriangulationThreshold"))->GetValue();
219 toFCameraDevice->m_Controller->SetTriangulationThreshold(triangulationThreshold);
220
221 toFCameraDevice->m_FreePos = (toFCameraDevice->m_FreePos+1) % toFCameraDevice->m_BufferSize;
222 toFCameraDevice->m_CurrentPos = (toFCameraDevice->m_CurrentPos+1) % toFCameraDevice->m_BufferSize;
223 toFCameraDevice->m_ImageSequence++;
224 if (toFCameraDevice->m_FreePos == toFCameraDevice->m_CurrentPos)
225 {
226 overflow = true;
227 }
228
229 if (overflow)
230 {
231 overflow = false;
232 }
233
235 {
236 if (toFCameraDevice->m_ImageSequence % n == 0)
237 {
238 printStatus = true;
239 }
240 // print current framerate
241 if (printStatus)
242 {
243 t2 = realTimeClock->GetCurrentStamp() - t1;
244 MITK_INFO << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence;
245 t1 = realTimeClock->GetCurrentStamp();
246 printStatus = false;
247 }
248 }
249 } // end of while loop
250 }
251 return ITK_THREAD_RETURN_VALUE;
252 }
253
254 void KinectV2Device::GetAmplitudes(float* amplitudeArray, int& imageSequence)
255 {
256 m_ImageMutex->Lock();
257 if (m_CameraActive)
258 {
259 memcpy(amplitudeArray, this->m_AmplitudeDataBuffer[this->m_CurrentPos], this->m_DepthBufferSize);
260 imageSequence = this->m_ImageSequence;
261 }
262 else
263 {
264 MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active.";
265 }
266 m_ImageMutex->Unlock();
267 }
268
270 {
271 }
272
273 void KinectV2Device::GetDistances(float* distanceArray, int& imageSequence)
274 {
275 m_ImageMutex->Lock();
276 if (m_CameraActive)
277 {
278 memcpy(distanceArray, this->m_DistanceDataBuffer[this->m_CurrentPos], this->m_DepthBufferSize);
279 imageSequence = this->m_ImageSequence;
280 }
281 else
282 {
283 MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active.";
284 }
285 m_ImageMutex->Unlock();
286 }
287
288 void KinectV2Device::GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray,
289 int requiredImageSequence, int& capturedImageSequence, unsigned char* rgbDataArray)
290 {
291 if (m_CameraActive)
292 {
293 // check for empty buffer
294 if (this->m_ImageSequence < 0)
295 {
296 // buffer empty
297 MITK_WARN << "Buffer empty!! ";
298 capturedImageSequence = this->m_ImageSequence;
299 return;
300 }
301 // determine position of image in buffer
302 int pos = 0;
303 if ((requiredImageSequence < 0) || (requiredImageSequence > this->m_ImageSequence))
304 {
305 capturedImageSequence = this->m_ImageSequence;
306 pos = this->m_CurrentPos;
307 }
308 else if (requiredImageSequence <= this->m_ImageSequence - this->m_BufferSize)
309 {
310 capturedImageSequence = (this->m_ImageSequence - this->m_BufferSize) + 1;
311 pos = (this->m_CurrentPos + 1) % this->m_BufferSize;
312 }
313 else // (requiredImageSequence > this->m_ImageSequence - this->m_BufferSize) && (requiredImageSequence <= this->m_ImageSequence)
314 {
315 capturedImageSequence = requiredImageSequence;
316 pos = (this->m_CurrentPos + (10-(this->m_ImageSequence - requiredImageSequence))) % this->m_BufferSize;
317 }
318 // write image data to arrays
319 m_ImageMutex->Lock();
320 memcpy(distanceArray, this->m_DistanceDataBuffer[pos], this->m_DepthBufferSize);
321 memcpy(amplitudeArray, this->m_AmplitudeDataBuffer[pos], this->m_DepthBufferSize);
322 memcpy(rgbDataArray, this->m_RGBDataBuffer[pos], this->m_RGBBufferSize);
323 m_ImageMutex->Unlock();
324
325 //Since the standard method GetAllImages does not allow transfering a surface,
326 //we use a property to pass the surface to the workbench.
327 mitk::Surface::Pointer surface = mitk::Surface::New();
328 surface->SetVtkPolyData(this->m_PolyData);
329 this->SetProperty("ToFSurface", mitk::SmartPointerProperty::New( surface ));
330
331 this->Modified();
332 }
333 else
334 {
335 MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active.";
336 }
337 }
338
339 KinectV2Controller::Pointer KinectV2Device::GetController()
340 {
341 return this->m_Controller;
342 }
343
345 {
346 return this->m_RGBImageWidth;
347 }
348
350 {
351 return this->m_RGBImageHeight;
352 }
353}
Interface for all representations of Microsoft Kinect V2 devices. Kinect2Device internally holds an i...
int GetRGBCaptureHeight()
returns the height of the RGB image
KinectV2Controller::Pointer m_Controller
corresponding CameraController
KinectV2Controller::Pointer GetController()
returns the corresponding camera controller
unsigned char ** m_RGBDataBuffer
buffer holding the last RGB image
vtkSmartPointer< vtkPolyData > m_PolyData
Surface generated via the Kinect V2 SDK with default/unknown calibration.
static ITK_THREAD_RETURN_TYPE Acquire(void *pInfoStruct)
Thread method continuously acquiring images from the ToF hardware.
virtual bool DisconnectCamera()
closes the connection to the camera
size_t m_DepthBufferSize
Size of depth buffer (i.e. memory size of depth and infrared image)
virtual void StopCamera()
stops the continuous updating of the camera
int GetRGBCaptureWidth()
returns the width of the RGB image
virtual void UpdateCamera()
updates the camera for image acquisition
float ** m_DistanceDataBuffer
buffer holding the last distance images
virtual void StartCamera()
starts the continuous updating of the camera. A separate thread updates the source data,...
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...
static bool m_PrintFrameRate
prints the framerate to the console every 100 frames, deactivated by default
float ** m_AmplitudeDataBuffer
buffer holding the last amplitude images
virtual void GetDistances(float *distanceArray, int &imageSequence)
gets the distance data from the ToF camera measuring the distance between the camera and the differen...
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...
size_t m_RGBBufferSize
Size of RGB buffer (i.e. memory size of RGB image)
virtual void GetIntensities(float *intensityArray, int &imageSequence)
Does nothing for Kinect V2 as there is no intensity data provided by the device.
virtual bool OnConnectCamera()
opens a connection to the ToF camera
virtual bool IsCameraActive()
returns whether the camera is currently active or not
static Pointer New(void)
instanciates a new, operating-system dependant, instance of mitk::RealTimeClock.
int m_ImageSequence
counter for acquired images
virtual void SetProperty(const char *propertyKey, BaseProperty *propertyValue)
set a BaseProperty property in the property list
int m_CaptureWidth
width of the range image (x dimension)
int m_FreePos
current position in the buffer which will be filled with data acquired from the hardware
virtual BaseProperty * GetProperty(const char *propertyKey)
get a BaseProperty from the property list
int m_RGBImageWidth
width of the RGB image (x dimension)
int m_CurrentPos
current position in the buffer which will be retrieved by the Get methods
bool GetBoolProperty(const char *propertyKey, bool &boolValue)
get a bool from the property list
int m_PixelNumber
number of pixels in the range image (m_CaptureWidth*m_CaptureHeight)
bool m_CameraConnected
flag indicating if the camera is successfully connected or not. Caution: thread safe access only!
int m_CaptureHeight
height of the range image (y dimension)
bool m_CameraActive
flag indicating if the camera is currently active or not. Caution: thread safe access only!
float * m_AmplitudeArray
float array holding the amplitude image
int m_BufferSize
buffer size of the image buffer needed for loss-less acquisition of range data
int m_RGBPixelNumber
number of pixels in the range image (m_RGBImageWidth*m_RGBImageHeight)
std::mutex m_CameraActiveMutex
mutex for the cameraActive flag
std::mutex m_ImageMutex
mutex for images provided by the range camera
float * m_DistanceArray
float array holding the distance image
int m_RGBImageHeight
height of the RGB image (y dimension)
int m_MaxBufferSize
maximal buffer size needed for initialization of data arrays. Default value is 100.
IGT Exceptions.
std::string GetDeviceName()