diff --git a/Modules/ToFHardware/Kinect/mitkKinectController.cpp b/Modules/ToFHardware/Kinect/mitkKinectController.cpp index 3a6123c8ee..05e8b97faf 100644 --- a/Modules/ToFHardware/Kinect/mitkKinectController.cpp +++ b/Modules/ToFHardware/Kinect/mitkKinectController.cpp @@ -1,290 +1,289 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkKinectController.h" #include namespace mitk { class KinectController::KinectControllerPrivate { public: KinectControllerPrivate(); ~KinectControllerPrivate(); bool ErrorText(unsigned int error); //OpenNI related stuff xn::Context m_Context; ///< OpenNI context xn::DepthGenerator m_DepthGenerator; ///< Depth generator to access depth image of kinect xn::ImageGenerator m_ImageGenerator; ///< Image generator to access RGB image of kinect xn::IRGenerator m_IRGenerator; ///< IR generator to access IR image of kinect bool m_ConnectionCheck; ///< check if camera is connected or not bool m_UseIR; ///< flag indicating whether IR image is used or not unsigned int m_CaptureWidth; ///< image width unsigned int m_CaptureHeight; ///< image height }; KinectController::KinectControllerPrivate::KinectControllerPrivate(): m_Context(NULL), m_DepthGenerator(NULL), m_ImageGenerator(NULL), m_IRGenerator(NULL), m_ConnectionCheck(false), m_UseIR(false), m_CaptureWidth(640), m_CaptureHeight(480) { } KinectController::KinectControllerPrivate::~KinectControllerPrivate() { } bool KinectController::KinectControllerPrivate::ErrorText(unsigned int error) { if(error != XN_STATUS_OK) { MITK_ERROR << "Kinect Camera Error " << xnGetStatusString(error); mitkThrow() << "Kinect Camera Error " << xnGetStatusString(error); return false; } else return true; } KinectController::KinectController(): d(new KinectControllerPrivate) { } KinectController::~KinectController() { delete d; } bool KinectController::OpenCameraConnection() { if (!d->m_ConnectionCheck) { // Initialize the OpenNI status d->m_ConnectionCheck = d->ErrorText(d->m_Context.Init()); if (!d->m_ConnectionCheck) return false; // Create a depth generator and set its resolution XnMapOutputMode DepthMode; d->m_ConnectionCheck = d->ErrorText(d->m_DepthGenerator.Create(d->m_Context)); if (!d->m_ConnectionCheck) return false; d->m_DepthGenerator.GetMapOutputMode(DepthMode); DepthMode.nXRes = xn::Resolution((XnResolution)XN_RES_VGA).GetXResolution(); DepthMode.nYRes = xn::Resolution((XnResolution)XN_RES_VGA).GetYResolution(); d->m_ConnectionCheck = d->ErrorText(d->m_DepthGenerator.SetMapOutputMode(DepthMode)); if (!d->m_ConnectionCheck) return false; if (d->m_UseIR) { // Create the IR generator and set its resolution d->m_ConnectionCheck = d->ErrorText(d->m_IRGenerator.Create(d->m_Context)); if (!d->m_ConnectionCheck) return false; XnMapOutputMode IRMode; d->m_IRGenerator.GetMapOutputMode(IRMode); IRMode.nXRes = XN_VGA_X_RES; IRMode.nYRes = XN_VGA_Y_RES; IRMode.nFPS = 30; d->m_ConnectionCheck = d->ErrorText(d->m_IRGenerator.SetMapOutputMode(IRMode)); if (!d->m_ConnectionCheck) return false; } else { // Create an image generator and set its resolution XnMapOutputMode ImageMode; d->m_ConnectionCheck = d->ErrorText(d->m_ImageGenerator.Create(d->m_Context)); if (!d->m_ConnectionCheck) return false; d->m_ImageGenerator.GetMapOutputMode(ImageMode); ImageMode.nXRes = xn::Resolution((XnResolution)XN_RES_VGA).GetXResolution(); ImageMode.nYRes = xn::Resolution((XnResolution)XN_RES_VGA).GetYResolution(); d->m_ConnectionCheck = d->ErrorText(d->m_ImageGenerator.SetMapOutputMode(ImageMode)); if (!d->m_ConnectionCheck) return false; } // Camera registration if ( d->m_DepthGenerator.IsCapabilitySupported(XN_CAPABILITY_ALTERNATIVE_VIEW_POINT) ) { if (d->m_UseIR) { d->m_ConnectionCheck = d->ErrorText(d->m_DepthGenerator.GetAlternativeViewPointCap().SetViewPoint(d->m_IRGenerator)); //if (!d->m_ConnectionCheck) return false; } else { d->m_ConnectionCheck = d->ErrorText(d->m_DepthGenerator.GetAlternativeViewPointCap().SetViewPoint(d->m_ImageGenerator)); //if (!d->m_ConnectionCheck) return false; } } else { std::cout << "Alternative view point not supported by the depth generator..." << std::endl; } if (d->m_UseIR) { if ( d->m_IRGenerator.IsCapabilitySupported(XN_CAPABILITY_ALTERNATIVE_VIEW_POINT) ) { d->m_ConnectionCheck = d->ErrorText(d->m_IRGenerator.GetAlternativeViewPointCap().SetViewPoint(d->m_DepthGenerator)); //if (!d->m_ConnectionCheck) return false; } else { std::cout << "Alternative view point not supported by the depth generator..." << std::endl; } } // Start data generation d->m_ConnectionCheck = d->ErrorText(d->m_Context.StartGeneratingAll()); if (!d->m_ConnectionCheck) return false; // // Update the connected flag // d->m_ConnectionCheck = true; } return d->m_ConnectionCheck; } bool KinectController::CloseCameraConnection() { d->m_ConnectionCheck = !d->ErrorText(d->m_Context.StopGeneratingAll()); return !d->m_ConnectionCheck; } bool KinectController::UpdateCamera() { bool updateSuccessful = d->ErrorText(d->m_Context.WaitAndUpdateAll()); xn::DepthMetaData DepthMD; d->m_DepthGenerator.GetMetaData(DepthMD); d->m_CaptureWidth = DepthMD.XRes(); d->m_CaptureHeight = DepthMD.YRes(); return updateSuccessful; } - // TODO flag image void KinectController::GetDistances(float* distances) { xn::DepthMetaData DepthMD; d->m_DepthGenerator.GetMetaData(DepthMD); const XnDepthPixel* DepthData = DepthMD.Data(); for (unsigned int i=0; im_CaptureWidth*d->m_CaptureHeight; i++) { distances[i] = DepthData[i]; } } void KinectController::GetRgb(unsigned char* rgb) { if (!d->m_UseIR) { xn::ImageMetaData ImageMD; d->m_ImageGenerator.GetMetaData(ImageMD); const XnRGB24Pixel* rgbPixelArray = ImageMD.RGB24Data(); for (int i=0; im_CaptureWidth*d->m_CaptureHeight; i++) { rgb[i*3] = rgbPixelArray[i].nRed; rgb[i*3+1] = rgbPixelArray[i].nGreen; rgb[i*3+2] = rgbPixelArray[i].nBlue; } } } void KinectController::GetAllData(float* distances, float* amplitudes, unsigned char* rgb) { // get current distance data xn::DepthMetaData DepthMD; d->m_DepthGenerator.GetMetaData(DepthMD); const XnDepthPixel* DepthData = DepthMD.Data(); // IR data xn::IRMetaData IRData; const XnIRPixel* IRPixelData; // Image data xn::ImageMetaData ImageMD; const XnRGB24Pixel* rgbPixelArray; if (d->m_UseIR) { d->m_IRGenerator.GetMetaData(IRData); IRPixelData = IRData.Data(); } else { // get current rgb data d->m_ImageGenerator.GetMetaData(ImageMD); rgbPixelArray = ImageMD.RGB24Data(); } for (unsigned int i=0; im_CaptureWidth*d->m_CaptureHeight; i++) { distances[i] = DepthData[i]; if (d->m_UseIR) { amplitudes[i] = IRPixelData[i]; } else { rgb[i*3] = rgbPixelArray[i].nRed; rgb[i*3+1] = rgbPixelArray[i].nGreen; rgb[i*3+2] = rgbPixelArray[i].nBlue; } } } void KinectController::GetAmplitudes( float* amplitudes ) { if (d->m_UseIR) { xn::IRMetaData IRData; d->m_IRGenerator.GetMetaData(IRData); const XnIRPixel* IRPixelData = IRData.Data(); for (unsigned int i=0; im_CaptureWidth*d->m_CaptureHeight; i++) { amplitudes[i] = IRPixelData[i]; } } } void KinectController::GetIntensities( float* intensities ) { } unsigned int KinectController::GetCaptureWidth() const { return d->m_CaptureWidth; } unsigned int KinectController::GetCaptureHeight() const { return d->m_CaptureHeight; } bool KinectController::GetUseIR() const { return d->m_UseIR; } void KinectController::SetUseIR(bool useIR) { if (d->m_UseIR!=useIR) { d->m_UseIR = useIR; this->Modified(); } } } diff --git a/Modules/ToFHardware/Kinect/mitkKinectDevice.cpp b/Modules/ToFHardware/Kinect/mitkKinectDevice.cpp index 27c2eadd9a..2be16951fe 100644 --- a/Modules/ToFHardware/Kinect/mitkKinectDevice.cpp +++ b/Modules/ToFHardware/Kinect/mitkKinectDevice.cpp @@ -1,456 +1,390 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkKinectDevice.h" #include "mitkRealTimeClock.h" #include "itkMultiThreader.h" #include namespace mitk { KinectDevice::KinectDevice() { m_Controller = mitk::KinectController::New(); } KinectDevice::~KinectDevice() { } //----------------------------J´s Implementation of Device Names?-------------------------------------------- /*! \brief Defining the Device´s Name+Suffix, here for the Kinect. */ std::string GetDeviceName() { //int kinectnumber = 1; std::stringstream out; out << "Microsoft Kinect Device "; //out << kinectnumber; //kinectnumber= kinectnumber++; return out.str(); } //---------------------------------------------------------------------------------------------------------------------- bool KinectDevice::OnConnectCamera() { bool ok = false; if (m_Controller) { ok = m_Controller->OpenCameraConnection(); if (ok) { this->m_CaptureWidth = m_Controller->GetCaptureWidth(); this->m_CaptureHeight = m_Controller->GetCaptureHeight(); this->m_PixelNumber = this->m_CaptureWidth * this->m_CaptureHeight; this->m_RGBImageWidth = m_CaptureWidth; this->m_RGBImageHeight = m_CaptureHeight; this->m_RGBPixelNumber = this->m_RGBImageWidth * this->m_RGBImageHeight; // allocate buffer this->m_IntensityArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_IntensityArray[i]=0.0;} this->m_DistanceArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_DistanceArray[i]=0.0;} this->m_AmplitudeArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_AmplitudeArray[i]=0.0;} this->m_DistanceDataBuffer = new float*[this->m_MaxBufferSize]; for(int i=0; im_MaxBufferSize; i++) { this->m_DistanceDataBuffer[i] = new float[this->m_PixelNumber]; } this->m_AmplitudeDataBuffer = new float*[this->m_MaxBufferSize]; for(int i=0; im_MaxBufferSize; i++) { this->m_AmplitudeDataBuffer[i] = new float[this->m_PixelNumber]; } this->m_IntensityDataBuffer = new float*[this->m_MaxBufferSize]; for(int i=0; im_MaxBufferSize; i++) { this->m_IntensityDataBuffer[i] = new float[this->m_PixelNumber]; } this->m_RGBDataBuffer = new unsigned char*[this->m_MaxBufferSize]; for (int i=0; im_MaxBufferSize; i++) { this->m_RGBDataBuffer[i] = new unsigned char[this->m_PixelNumber*3]; } m_CameraConnected = true; } } return ok; } bool KinectDevice::DisconnectCamera() { bool ok = false; if (m_Controller) { ok = m_Controller->CloseCameraConnection(); // clean-up only if camera was connected if (m_CameraConnected) { delete [] m_IntensityArray; delete [] m_DistanceArray; delete [] m_AmplitudeArray; for(int i=0; im_MaxBufferSize; i++) { delete[] this->m_DistanceDataBuffer[i]; delete[] this->m_AmplitudeDataBuffer[i]; delete[] this->m_IntensityDataBuffer[i]; delete[] this->m_RGBDataBuffer[i]; } delete[] this->m_DistanceDataBuffer; delete[] this->m_AmplitudeDataBuffer; delete[] this->m_IntensityDataBuffer; delete[] this->m_RGBDataBuffer; m_CameraConnected = false; } } return ok; } void KinectDevice::StartCamera() { if (m_CameraConnected) { // get the first image this->m_Controller->UpdateCamera(); this->m_ImageMutex->Lock(); this->m_Controller->GetAllData(this->m_DistanceDataBuffer[this->m_FreePos],this->m_AmplitudeDataBuffer[this->m_FreePos],this->m_RGBDataBuffer[this->m_FreePos]); this->m_FreePos = (this->m_FreePos+1) % this->m_BufferSize; this->m_CurrentPos = (this->m_CurrentPos+1) % this->m_BufferSize; this->m_ImageSequence++; this->m_ImageMutex->Unlock(); this->m_CameraActiveMutex->Lock(); this->m_CameraActive = true; this->m_CameraActiveMutex->Unlock(); this->m_ThreadID = this->m_MultiThreader->SpawnThread(this->Acquire, this); // wait a little to make sure that the thread is started itksys::SystemTools::Delay(10); } else { MITK_INFO<<"Camera not connected"; } } void KinectDevice::StopCamera() { m_CameraActiveMutex->Lock(); m_CameraActive = false; m_CameraActiveMutex->Unlock(); itksys::SystemTools::Delay(100); if (m_MultiThreader.IsNotNull()) { m_MultiThreader->TerminateThread(m_ThreadID); } // wait a little to make sure that the thread is terminated itksys::SystemTools::Delay(10); } bool KinectDevice::IsCameraActive() { m_CameraActiveMutex->Lock(); bool ok = m_CameraActive; m_CameraActiveMutex->Unlock(); return ok; } void KinectDevice::UpdateCamera() { if (m_Controller) { m_Controller->UpdateCamera(); } } ITK_THREAD_RETURN_TYPE KinectDevice::Acquire(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; if (pInfo == NULL) { return ITK_THREAD_RETURN_VALUE; } if (pInfo->UserData == NULL) { return ITK_THREAD_RETURN_VALUE; } KinectDevice* toFCameraDevice = (KinectDevice*)pInfo->UserData; if (toFCameraDevice!=NULL) { mitk::RealTimeClock::Pointer realTimeClock; realTimeClock = mitk::RealTimeClock::New(); double t1, t2; t1 = realTimeClock->GetCurrentStamp(); int n = 100; bool overflow = false; bool printStatus = false; while (toFCameraDevice->IsCameraActive()) { // update the ToF camera toFCameraDevice->UpdateCamera(); // get the image data from the camera and write it at the next free position in the buffer toFCameraDevice->m_ImageMutex->Lock(); toFCameraDevice->m_Controller->GetAllData(toFCameraDevice->m_DistanceDataBuffer[toFCameraDevice->m_FreePos],toFCameraDevice->m_AmplitudeDataBuffer[toFCameraDevice->m_FreePos],toFCameraDevice->m_RGBDataBuffer[toFCameraDevice->m_FreePos]); toFCameraDevice->m_ImageMutex->Unlock(); // call modified to indicate that cameraDevice was modified toFCameraDevice->Modified(); - /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - TODO Buffer Handling currently only works for buffer size 1 - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ - //toFCameraDevice->m_ImageSequence++; toFCameraDevice->m_FreePos = (toFCameraDevice->m_FreePos+1) % toFCameraDevice->m_BufferSize; toFCameraDevice->m_CurrentPos = (toFCameraDevice->m_CurrentPos+1) % toFCameraDevice->m_BufferSize; toFCameraDevice->m_ImageSequence++; if (toFCameraDevice->m_FreePos == toFCameraDevice->m_CurrentPos) { - // buffer overflow - //MITK_INFO << "Buffer overflow!! "; - //toFCameraDevice->m_CurrentPos = (toFCameraDevice->m_CurrentPos+1) % toFCameraDevice->m_BufferSize; - //toFCameraDevice->m_ImageSequence++; overflow = true; } if (toFCameraDevice->m_ImageSequence % n == 0) { printStatus = true; } if (overflow) { - //itksys::SystemTools::Delay(10); overflow = false; } - /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - END TODO Buffer Handling currently only works for buffer size 1 - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ // print current framerate if (printStatus) { t2 = realTimeClock->GetCurrentStamp() - t1; - //MITK_INFO << "t2: " << t2 <<" Time (s) for 1 image: " << (t2/1000) / n << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence; MITK_INFO << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence; t1 = realTimeClock->GetCurrentStamp(); printStatus = false; } } // end of while loop } return ITK_THREAD_RETURN_VALUE; } - // TODO: Buffer size currently set to 1. Once Buffer handling is working correctly, method may be reactivated - // void KinectDevice::ResetBuffer(int bufferSize) - // { - // this->m_BufferSize = bufferSize; - // this->m_CurrentPos = -1; - // this->m_FreePos = 0; - // } - void KinectDevice::GetAmplitudes(float* amplitudeArray, int& imageSequence) { m_ImageMutex->Lock(); if (m_CameraActive) { - // 1) copy the image buffer - // 2) Flip around y- axis (vertical axis) - - /* - this->m_Controller->GetAmplitudes(this->m_SourceDataBuffer[this->m_CurrentPos], this->m_AmplitudeArray); - for (int i=0; im_CaptureHeight; i++) - { - for (int j=0; jm_CaptureWidth; j++) - { - amplitudeArray[i*this->m_CaptureWidth+j] = this->m_AmplitudeArray[(i+1)*this->m_CaptureWidth-1-j]; - } - } - */ + // copy the image buffer for (int i=0; im_PixelNumber; i++) { amplitudeArray[i] = this->m_AmplitudeDataBuffer[this->m_CurrentPos][i]; } imageSequence = this->m_ImageSequence; } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } m_ImageMutex->Unlock(); } void KinectDevice::GetIntensities(float* intensityArray, int& imageSequence) { m_ImageMutex->Lock(); if (m_CameraActive) { - // 1) copy the image buffer - // 2) Flip around y- axis (vertical axis) - - /* - this->m_Controller->GetIntensities(this->m_SourceDataBuffer[this->m_CurrentPos], this->m_IntensityArray); - for (int i=0; im_CaptureHeight; i++) - { - for (int j=0; jm_CaptureWidth; j++) - { - intensityArray[i*this->m_CaptureWidth+j] = this->m_IntensityArray[(i+1)*this->m_CaptureWidth-1-j]; - } - } - */ for (int i=0; im_PixelNumber; i++) { intensityArray[i] = this->m_IntensityDataBuffer[this->m_CurrentPos][i]; } imageSequence = this->m_ImageSequence; } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } m_ImageMutex->Unlock(); } void KinectDevice::GetDistances(float* distanceArray, int& imageSequence) { m_ImageMutex->Lock(); if (m_CameraActive) { - // 1) copy the image buffer - // 2) convert the distance values from m to mm - // 3) Flip around y- axis (vertical axis) - - /* - this->m_Controller->GetDistances(this->m_SourceDataBuffer[this->m_CurrentPos], this->m_DistanceArray); - for (int i=0; im_CaptureHeight; i++) - { - for (int j=0; jm_CaptureWidth; j++) - { - distanceArray[i*this->m_CaptureWidth+j] = 1000 * this->m_DistanceArray[(i+1)*this->m_CaptureWidth-1-j]; - } - } - */ for (int i=0; im_PixelNumber; i++) { distanceArray[i] = this->m_DistanceDataBuffer[this->m_CurrentPos][i]; // * 1000 } imageSequence = this->m_ImageSequence; } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } m_ImageMutex->Unlock(); } void KinectDevice::GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray, int requiredImageSequence, int& capturedImageSequence, unsigned char* rgbDataArray) { if (m_CameraActive) { - // 1) copy the image buffer - // 2) convert the distance values from m to mm - // 3) Flip around y- axis (vertical axis) - // check for empty buffer if (this->m_ImageSequence < 0) { // buffer empty MITK_INFO << "Buffer empty!! "; capturedImageSequence = this->m_ImageSequence; return; } // determine position of image in buffer int pos = 0; if ((requiredImageSequence < 0) || (requiredImageSequence > this->m_ImageSequence)) { capturedImageSequence = this->m_ImageSequence; pos = this->m_CurrentPos; - //MITK_INFO << "Required image not found! Required: " << requiredImageSequence << " delivered/current: " << this->m_ImageSequence; } else if (requiredImageSequence <= this->m_ImageSequence - this->m_BufferSize) { capturedImageSequence = (this->m_ImageSequence - this->m_BufferSize) + 1; pos = (this->m_CurrentPos + 1) % this->m_BufferSize; - //MITK_INFO << "Out of buffer! Required: " << requiredImageSequence << " delivered: " << capturedImageSequence << " current: " << this->m_ImageSequence; } else // (requiredImageSequence > this->m_ImageSequence - this->m_BufferSize) && (requiredImageSequence <= this->m_ImageSequence) { capturedImageSequence = requiredImageSequence; pos = (this->m_CurrentPos + (10-(this->m_ImageSequence - requiredImageSequence))) % this->m_BufferSize; } // write image data to float arrays for (int i=0; im_PixelNumber; i++) { distanceArray[i] = this->m_DistanceDataBuffer[pos][i]; amplitudeArray[i] = this->m_AmplitudeDataBuffer[pos][i]; intensityArray[i] = this->m_IntensityDataBuffer[pos][i]; rgbDataArray[i*3] = this->m_RGBDataBuffer[pos][i*3]; rgbDataArray[i*3+1] = this->m_RGBDataBuffer[pos][i*3+1]; rgbDataArray[i*3+2] = this->m_RGBDataBuffer[pos][i*3+2]; } } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } } KinectController::Pointer KinectDevice::GetController() { return this->m_Controller; } void KinectDevice::SetProperty( const char *propertyKey, BaseProperty* propertyValue ) { ToFCameraDevice::SetProperty(propertyKey,propertyValue); this->m_PropertyList->SetProperty(propertyKey, propertyValue); if (strcmp(propertyKey, "RGB") == 0) { bool rgb = false; GetBoolProperty(propertyKey, rgb); m_Controller->SetUseIR(!rgb); } else if (strcmp(propertyKey, "IR") == 0) { bool ir = false; GetBoolProperty(propertyKey, ir); m_Controller->SetUseIR(ir); } } int KinectDevice::GetRGBCaptureWidth() { return this->GetCaptureWidth(); } int KinectDevice::GetRGBCaptureHeight() { return this->GetCaptureHeight(); } } diff --git a/Modules/ToFHardware/Kinect/mitkKinectDevice.h b/Modules/ToFHardware/Kinect/mitkKinectDevice.h index 4ddf45aeeb..9abe07fc90 100644 --- a/Modules/ToFHardware/Kinect/mitkKinectDevice.h +++ b/Modules/ToFHardware/Kinect/mitkKinectDevice.h @@ -1,160 +1,153 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkKinectDevice_h #define __mitkKinectDevice_h #include "mitkKinectModuleExports.h" #include "mitkCommon.h" #include "mitkToFCameraDevice.h" #include "mitkKinectController.h" #include "itkObject.h" #include "itkObjectFactory.h" #include "itkMultiThreader.h" #include "itkFastMutexLock.h" namespace mitk { /** * @brief Interface for all representations of MESA ToF devices. * KinectDevice internally holds an instance of KinectController and starts a thread * that continuously grabs images from the controller. A buffer structure buffers the last acquired images * to provide the image data loss-less. * * \throws mitkException In case of no connection, an exception is thrown! * * @ingroup ToFHardware */ class MITK_KINECTMODULE_EXPORT KinectDevice : public ToFCameraDevice { public: mitkClassMacro( KinectDevice , ToFCameraDevice ); itkNewMacro( Self ); /*! \brief opens a connection to the ToF camera \throws mitkException In case of no connection, an exception is thrown! */ virtual bool OnConnectCamera(); /*! \brief closes the connection to the camera */ virtual bool DisconnectCamera(); /*! \brief starts the continuous updating of the camera. A separate thread updates the source data, the main thread processes the source data and creates images and coordinates \throws mitkException In case of no connection, an exception is thrown! */ virtual void StartCamera(); /*! \brief stops the continuous updating of the camera */ virtual void StopCamera(); /*! \brief updates the camera for image acquisition \throws mitkException In case of no connection, an exception is thrown! */ virtual void UpdateCamera(); /*! \brief returns whether the camera is currently active or not */ virtual bool IsCameraActive(); /*! \brief gets the amplitude data from the ToF camera as the strength of the active illumination of every pixel. Caution! The user is responsible for allocating and deleting the images. These values can be used to determine the quality of the distance values. The higher the amplitude value, the higher the accuracy of the according distance value \param imageSequence the actually captured image sequence number \param amplitudeArray contains the returned amplitude data as an array. */ virtual void GetAmplitudes(float* amplitudeArray, int& imageSequence); /*! \brief gets the intensity data from the ToF camera as a greyscale image. Caution! The user is responsible for allocating and deleting the images. \param intensityArray contains the returned intensities data as an array. \param imageSequence the actually captured image sequence number */ virtual void GetIntensities(float* intensityArray, int& imageSequence); /*! \brief gets the distance data from the ToF camera measuring the distance between the camera and the different object points in millimeters. Caution! The user is responsible for allocating and deleting the images. \param distanceArray contains the returned distances data as an array. \param imageSequence the actually captured image sequence number */ virtual void GetDistances(float* distanceArray, int& imageSequence); /*! \brief gets the 3 images (distance, amplitude, intensity) from the ToF camera. Caution! The user is responsible for allocating and deleting the images. \param distanceArray contains the returned distance data as an array. \param amplitudeArray contains the returned amplitude data as an array. \param intensityArray contains the returned intensity data as an array. \param sourceDataArray contains the complete source data from the camera device. \param requiredImageSequence the required image sequence number \param capturedImageSequence the actually captured image sequence number */ virtual void GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray, int requiredImageSequence, int& capturedImageSequence, unsigned char* rgbDataArray=NULL); - // TODO: Buffer size currently set to 1. Once Buffer handling is working correctly, method may be reactivated - // /* // * TODO: Reenable doxygen comment when uncommenting, disabled to fix doxygen warning see bug 12882 - // \brief pure virtual method resetting the buffer using the specified bufferSize. Has to be implemented by sub-classes - // \param bufferSize buffer size the buffer should be reset to - // */ - // virtual void ResetBuffer(int bufferSize) = 0; - //TODO add/correct documentation for requiredImageSequence and capturedImageSequence in the GetAllImages, GetDistances, GetIntensities and GetAmplitudes methods. /*! \brief returns the corresponding camera controller */ KinectController::Pointer GetController(); /*! \brief set a BaseProperty */ virtual void SetProperty( const char *propertyKey, BaseProperty* propertyValue ); /*! \brief returns the width of the RGB image */ int GetRGBCaptureWidth(); /*! \brief returns the height of the RGB image */ int GetRGBCaptureHeight(); protected: KinectDevice(); ~KinectDevice(); /*! \brief Thread method continuously acquiring images from the ToF hardware */ static ITK_THREAD_RETURN_TYPE Acquire(void* pInfoStruct); /*! \brief moves the position pointer m_CurrentPos to the next position in the buffer if that's not the next free position to prevent reading from an empty buffer */ void GetNextPos(); KinectController::Pointer m_Controller; ///< corresponding CameraController float** m_DistanceDataBuffer; ///< buffer holding the last distance images float** m_AmplitudeDataBuffer; ///< buffer holding the last amplitude images float** m_IntensityDataBuffer; ///< buffer holding the last intensity images unsigned char** m_RGBDataBuffer; ///< buffer holding the last RGB image int m_KinectDeviceNumber; private: }; } //END mitk namespace #endif diff --git a/Modules/ToFHardware/MesaSR4000/mitkToFCameraMESAController.h b/Modules/ToFHardware/MesaSR4000/mitkToFCameraMESAController.h index 98d54eaf05..36d3df0dbf 100644 --- a/Modules/ToFHardware/MesaSR4000/mitkToFCameraMESAController.h +++ b/Modules/ToFHardware/MesaSR4000/mitkToFCameraMESAController.h @@ -1,143 +1,141 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkToFCameraMESAController_h #define __mitkToFCameraMESAController_h #include "mitkMESASR4000ModuleExports.h" #include "mitkCommon.h" #include "itkObject.h" #include "itkObjectFactory.h" namespace mitk { /** * @brief Virtual interface and base class for all MESA Time-of-Flight devices. Wraps MESA API provided in library * Provides methods for accessing current distance, amplitude, intensity and raw data. * Allows to set parameters like modulation frequency and integration time. * * @ingroup ToFHardware */ class MITK_MESASR4000MODULE_EXPORT ToFCameraMESAController : public itk::Object { public: mitkClassMacro( ToFCameraMESAController , itk::Object ); /*! \brief opens a connection to the ToF camera. Has to be implemented by the sub class */ - //TODO return value virtual bool OpenCameraConnection() = 0; /*! \brief closes the connection to the camera */ - //TODO return value virtual bool CloseCameraConnection(); /*! \brief Gets the current amplitude array from the device \param amplitudeArray float array where the amplitude data will be saved */ virtual bool GetAmplitudes(float* amplitudeArray); /*! \brief Gets the current intensity array from the device \param intensityArray float array where the intensity data will be saved */ virtual bool GetIntensities(float* intensityArray); /*! \brief Gets the current distance array from the device \param distanceArray float array where the distance data will be saved */ virtual bool GetDistances(float* distanceArray); /*! \brief calls update on the camera -> a new ToF-image is aquired */ virtual bool UpdateCamera(); /*! \brief Returns the currently set modulation frequency. \return modulation frequency */ virtual int GetModulationFrequency() = 0; /*! \brief Sets the modulation frequency of the ToF device. The method automatically calculates a valid value from the given frequency to make sure that only valid frequencies are used. \param modulationFrequency modulation frequency \return frequency set after validation step */ virtual int SetModulationFrequency(unsigned int modulationFrequency) = 0; /*! \brief Returns the currently set integration time. \return integration time */ virtual int GetIntegrationTime() = 0; /*! \brief Sets the integration time of the ToF device. The method automatically calculates a valid value from the given integration time to make sure that only valid times are used. \param integrationTime integration time \return integration time set after validation step */ virtual int SetIntegrationTime(unsigned int integrationTime) = 0; /*! \brief set input file name used by MESA player classes */ virtual void SetInputFileName(std::string inputFileName); /*! \brief Access the resolution of the image in x direction \return widht of image in pixel */ itkGetMacro(CaptureWidth, unsigned int); /*! \brief Access the resolution of the image in y direction \return height of image in pixel */ itkGetMacro(CaptureHeight, unsigned int); protected: ToFCameraMESAController(); ~ToFCameraMESAController(); /*! \brief Method printing the current error message to the console and returning whether the previous command was successful \param error error number returned by the MESA function \return flag indicating if an error occured (false) or not (true) */ bool ErrorText(int error); char m_MESAError[128]; ///< member holding the current error text int m_MESARes; ///< holds the current result message provided by MESA int m_PixelNumber; ///< holds the number of pixels contained in the image int m_NumberOfBytes; ///< holds the number of bytes contained in the image unsigned int m_CaptureWidth; ///< holds the width of the image in pixel unsigned int m_CaptureHeight; ///< holds the height of the image in pixel int m_NumImg; ///< holds the number of images the camera provided (distance, intensity, etc) float m_MaxRangeFactor; ///< holds the factor to calculate the real distance depends on the modulation frequency bool m_ConnectionCheck; ///< flag showing whether the camera is connected (true) or not (false) std::string m_InputFileName; ///< input file name used by MESA player classes private: }; } //END mitk namespace #endif diff --git a/Modules/ToFHardware/MesaSR4000/mitkToFCameraMESADevice.cpp b/Modules/ToFHardware/MesaSR4000/mitkToFCameraMESADevice.cpp index 945fa4009b..ff0cb385d0 100644 --- a/Modules/ToFHardware/MesaSR4000/mitkToFCameraMESADevice.cpp +++ b/Modules/ToFHardware/MesaSR4000/mitkToFCameraMESADevice.cpp @@ -1,446 +1,357 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkToFCameraMESADevice.h" #include "mitkRealTimeClock.h" #include "itkMultiThreader.h" #include namespace mitk { ToFCameraMESADevice::ToFCameraMESADevice() { } ToFCameraMESADevice::~ToFCameraMESADevice() { } bool ToFCameraMESADevice::OnConnectCamera() { bool ok = false; if (m_Controller) { ok = m_Controller->OpenCameraConnection(); if (ok) { this->m_CaptureWidth = m_Controller->GetCaptureWidth(); this->m_CaptureHeight = m_Controller->GetCaptureHeight(); this->m_PixelNumber = this->m_CaptureWidth * this->m_CaptureHeight; // allocate buffer this->m_IntensityArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_IntensityArray[i]=0.0;} this->m_DistanceArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_DistanceArray[i]=0.0;} this->m_AmplitudeArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_AmplitudeArray[i]=0.0;} this->m_DistanceDataBuffer = new float*[this->m_MaxBufferSize]; for(int i=0; im_MaxBufferSize; i++) { this->m_DistanceDataBuffer[i] = new float[this->m_PixelNumber]; } this->m_AmplitudeDataBuffer = new float*[this->m_MaxBufferSize]; for(int i=0; im_MaxBufferSize; i++) { this->m_AmplitudeDataBuffer[i] = new float[this->m_PixelNumber]; } this->m_IntensityDataBuffer = new float*[this->m_MaxBufferSize]; for(int i=0; im_MaxBufferSize; i++) { this->m_IntensityDataBuffer[i] = new float[this->m_PixelNumber]; } m_CameraConnected = true; } } return ok; } bool ToFCameraMESADevice::DisconnectCamera() { bool ok = false; if (m_Controller) { ok = m_Controller->CloseCameraConnection(); // clean-up only if camera was connected if (m_CameraConnected) { delete [] m_IntensityArray; delete [] m_DistanceArray; delete [] m_AmplitudeArray; for(int i=0; im_MaxBufferSize; i++) { delete[] this->m_DistanceDataBuffer[i]; } delete[] this->m_DistanceDataBuffer; for(int i=0; im_MaxBufferSize; i++) { delete[] this->m_AmplitudeDataBuffer[i]; } delete[] this->m_AmplitudeDataBuffer; for(int i=0; im_MaxBufferSize; i++) { delete[] this->m_IntensityDataBuffer[i]; } delete[] this->m_IntensityDataBuffer; m_CameraConnected = false; } } return ok; } void ToFCameraMESADevice::StartCamera() { if (m_CameraConnected) { // get the first image this->m_Controller->UpdateCamera(); this->m_ImageMutex->Lock(); this->m_Controller->GetDistances(this->m_DistanceDataBuffer[this->m_FreePos]); this->m_Controller->GetAmplitudes(this->m_AmplitudeDataBuffer[this->m_FreePos]); this->m_Controller->GetIntensities(this->m_IntensityDataBuffer[this->m_FreePos]); this->m_FreePos = (this->m_FreePos+1) % this->m_BufferSize; this->m_CurrentPos = (this->m_CurrentPos+1) % this->m_BufferSize; this->m_ImageSequence++; this->m_ImageMutex->Unlock(); this->m_CameraActiveMutex->Lock(); this->m_CameraActive = true; this->m_CameraActiveMutex->Unlock(); this->m_ThreadID = this->m_MultiThreader->SpawnThread(this->Acquire, this); // wait a little to make sure that the thread is started itksys::SystemTools::Delay(10); } else { MITK_INFO<<"Camera not connected"; } } void ToFCameraMESADevice::StopCamera() { m_CameraActiveMutex->Lock(); m_CameraActive = false; m_CameraActiveMutex->Unlock(); itksys::SystemTools::Delay(100); if (m_MultiThreader.IsNotNull()) { m_MultiThreader->TerminateThread(m_ThreadID); } // wait a little to make sure that the thread is terminated itksys::SystemTools::Delay(10); } bool ToFCameraMESADevice::IsCameraActive() { m_CameraActiveMutex->Lock(); bool ok = m_CameraActive; m_CameraActiveMutex->Unlock(); return ok; } void ToFCameraMESADevice::UpdateCamera() { if (m_Controller) { m_Controller->UpdateCamera(); } } ITK_THREAD_RETURN_TYPE ToFCameraMESADevice::Acquire(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; if (pInfo == NULL) { return ITK_THREAD_RETURN_VALUE; } if (pInfo->UserData == NULL) { return ITK_THREAD_RETURN_VALUE; } ToFCameraMESADevice* toFCameraDevice = (ToFCameraMESADevice*)pInfo->UserData; if (toFCameraDevice!=NULL) { mitk::RealTimeClock::Pointer realTimeClock; realTimeClock = mitk::RealTimeClock::New(); double t1, t2; t1 = realTimeClock->GetCurrentStamp(); int n = 100; bool overflow = false; bool printStatus = false; while (toFCameraDevice->IsCameraActive()) { // update the ToF camera toFCameraDevice->UpdateCamera(); // get the image data from the camera and write it at the next free position in the buffer toFCameraDevice->m_ImageMutex->Lock(); toFCameraDevice->m_Controller->GetDistances(toFCameraDevice->m_DistanceDataBuffer[toFCameraDevice->m_FreePos]); toFCameraDevice->m_Controller->GetAmplitudes(toFCameraDevice->m_AmplitudeDataBuffer[toFCameraDevice->m_FreePos]); toFCameraDevice->m_Controller->GetIntensities(toFCameraDevice->m_IntensityDataBuffer[toFCameraDevice->m_FreePos]); toFCameraDevice->m_ImageMutex->Unlock(); // call modified to indicate that cameraDevice was modified toFCameraDevice->Modified(); - /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - TODO Buffer Handling currently only works for buffer size 1 - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ - //toFCameraDevice->m_ImageSequence++; toFCameraDevice->m_FreePos = (toFCameraDevice->m_FreePos+1) % toFCameraDevice->m_BufferSize; toFCameraDevice->m_CurrentPos = (toFCameraDevice->m_CurrentPos+1) % toFCameraDevice->m_BufferSize; toFCameraDevice->m_ImageSequence++; if (toFCameraDevice->m_FreePos == toFCameraDevice->m_CurrentPos) { - // buffer overflow - //MITK_INFO << "Buffer overflow!! "; - //toFCameraDevice->m_CurrentPos = (toFCameraDevice->m_CurrentPos+1) % toFCameraDevice->m_BufferSize; - //toFCameraDevice->m_ImageSequence++; overflow = true; } if (toFCameraDevice->m_ImageSequence % n == 0) { printStatus = true; } if (overflow) { - //itksys::SystemTools::Delay(10); overflow = false; } - /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - END TODO Buffer Handling currently only works for buffer size 1 - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ // print current framerate if (printStatus) { t2 = realTimeClock->GetCurrentStamp() - t1; - //MITK_INFO << "t2: " << t2 <<" Time (s) for 1 image: " << (t2/1000) / n << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence; MITK_INFO << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence; t1 = realTimeClock->GetCurrentStamp(); printStatus = false; } } // end of while loop } return ITK_THREAD_RETURN_VALUE; } - // TODO: Buffer size currently set to 1. Once Buffer handling is working correctly, method may be reactivated - // void ToFCameraMESADevice::ResetBuffer(int bufferSize) - // { - // this->m_BufferSize = bufferSize; - // this->m_CurrentPos = -1; - // this->m_FreePos = 0; - // } - void ToFCameraMESADevice::GetAmplitudes(float* amplitudeArray, int& imageSequence) { m_ImageMutex->Lock(); if (m_CameraActive) { - // 1) copy the image buffer - // 2) Flip around y- axis (vertical axis) - - /* - this->m_Controller->GetAmplitudes(this->m_SourceDataBuffer[this->m_CurrentPos], this->m_AmplitudeArray); - for (int i=0; im_CaptureHeight; i++) - { - for (int j=0; jm_CaptureWidth; j++) - { - amplitudeArray[i*this->m_CaptureWidth+j] = this->m_AmplitudeArray[(i+1)*this->m_CaptureWidth-1-j]; - } - } - */ + // copy the image buffer for (int i=0; im_PixelNumber; i++) { amplitudeArray[i] = this->m_AmplitudeDataBuffer[this->m_CurrentPos][i]; } imageSequence = this->m_ImageSequence; } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } m_ImageMutex->Unlock(); } void ToFCameraMESADevice::GetIntensities(float* intensityArray, int& imageSequence) { m_ImageMutex->Lock(); if (m_CameraActive) { - // 1) copy the image buffer - // 2) Flip around y- axis (vertical axis) - - /* - this->m_Controller->GetIntensities(this->m_SourceDataBuffer[this->m_CurrentPos], this->m_IntensityArray); - for (int i=0; im_CaptureHeight; i++) - { - for (int j=0; jm_CaptureWidth; j++) - { - intensityArray[i*this->m_CaptureWidth+j] = this->m_IntensityArray[(i+1)*this->m_CaptureWidth-1-j]; - } - } - */ for (int i=0; im_PixelNumber; i++) { intensityArray[i] = this->m_IntensityDataBuffer[this->m_CurrentPos][i]; } imageSequence = this->m_ImageSequence; } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } m_ImageMutex->Unlock(); } void ToFCameraMESADevice::GetDistances(float* distanceArray, int& imageSequence) { m_ImageMutex->Lock(); if (m_CameraActive) { - // 1) copy the image buffer - // 2) convert the distance values from m to mm - // 3) Flip around y- axis (vertical axis) - - /* - this->m_Controller->GetDistances(this->m_SourceDataBuffer[this->m_CurrentPos], this->m_DistanceArray); - for (int i=0; im_CaptureHeight; i++) - { - for (int j=0; jm_CaptureWidth; j++) - { - distanceArray[i*this->m_CaptureWidth+j] = 1000 * this->m_DistanceArray[(i+1)*this->m_CaptureWidth-1-j]; - } - } - */ for (int i=0; im_PixelNumber; i++) { - distanceArray[i] = this->m_DistanceDataBuffer[this->m_CurrentPos][i]; // * 1000 + distanceArray[i] = this->m_DistanceDataBuffer[this->m_CurrentPos][i]; } imageSequence = this->m_ImageSequence; } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } m_ImageMutex->Unlock(); } void ToFCameraMESADevice::GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray, int requiredImageSequence, int& capturedImageSequence, unsigned char* rgbDataArray) { if (m_CameraActive) { - // 1) copy the image buffer - // 2) convert the distance values from m to mm - // 3) Flip around y- axis (vertical axis) - // check for empty buffer if (this->m_ImageSequence < 0) { // buffer empty MITK_INFO << "Buffer empty!! "; capturedImageSequence = this->m_ImageSequence; return; } // determine position of image in buffer int pos = 0; if ((requiredImageSequence < 0) || (requiredImageSequence > this->m_ImageSequence)) { capturedImageSequence = this->m_ImageSequence; pos = this->m_CurrentPos; - //MITK_INFO << "Required image not found! Required: " << requiredImageSequence << " delivered/current: " << this->m_ImageSequence; } else if (requiredImageSequence <= this->m_ImageSequence - this->m_BufferSize) { capturedImageSequence = (this->m_ImageSequence - this->m_BufferSize) + 1; pos = (this->m_CurrentPos + 1) % this->m_BufferSize; - //MITK_INFO << "Out of buffer! Required: " << requiredImageSequence << " delivered: " << capturedImageSequence << " current: " << this->m_ImageSequence; } else // (requiredImageSequence > this->m_ImageSequence - this->m_BufferSize) && (requiredImageSequence <= this->m_ImageSequence) { capturedImageSequence = requiredImageSequence; pos = (this->m_CurrentPos + (10-(this->m_ImageSequence - requiredImageSequence))) % this->m_BufferSize; } // write image data to float arrays for (int i=0; im_PixelNumber; i++) { distanceArray[i] = this->m_DistanceDataBuffer[pos][i] /* * 1000 */; amplitudeArray[i] = this->m_AmplitudeDataBuffer[pos][i]; intensityArray[i] = this->m_IntensityDataBuffer[pos][i]; } - - - /* - this->m_Controller->GetDistances(this->m_SourceDataBuffer[pos], this->m_DistanceArray); - this->m_Controller->GetAmplitudes(this->m_SourceDataBuffer[pos], this->m_AmplitudeArray); - this->m_Controller->GetIntensities(this->m_SourceDataBuffer[pos], this->m_IntensityArray); - - int u, v; - for (int i=0; im_CaptureHeight; i++) - { - for (int j=0; jm_CaptureWidth; j++) - { - u = i*this->m_CaptureWidth+j; - v = (i+1)*this->m_CaptureWidth-1-j; - distanceArray[u] = 1000 * this->m_DistanceArray[v]; // unit in mm - //distanceArray[u] = this->m_DistanceArray[v]; // unit in meter - amplitudeArray[u] = this->m_AmplitudeArray[v]; - intensityArray[u] = this->m_IntensityArray[v]; - } - } - - memcpy(sourceDataArray, this->m_SourceDataBuffer[this->m_CurrentPos], this->m_SourceDataSize); - */ } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } } ToFCameraMESAController::Pointer ToFCameraMESADevice::GetController() { return this->m_Controller; } void ToFCameraMESADevice::SetProperty( const char *propertyKey, BaseProperty* propertyValue ) { ToFCameraDevice::SetProperty(propertyKey,propertyValue); this->m_PropertyList->SetProperty(propertyKey, propertyValue); if (strcmp(propertyKey, "ModulationFrequency") == 0) { int modulationFrequency = 0; GetIntProperty(propertyKey, modulationFrequency); m_Controller->SetModulationFrequency(modulationFrequency); } else if (strcmp(propertyKey, "IntegrationTime") == 0) { int integrationTime = 0; GetIntProperty(propertyKey, integrationTime); m_Controller->SetIntegrationTime(integrationTime); } } } diff --git a/Modules/ToFHardware/MesaSR4000/mitkToFCameraMESADevice.h b/Modules/ToFHardware/MesaSR4000/mitkToFCameraMESADevice.h index 484cd470c8..f950fbb7bf 100644 --- a/Modules/ToFHardware/MesaSR4000/mitkToFCameraMESADevice.h +++ b/Modules/ToFHardware/MesaSR4000/mitkToFCameraMESADevice.h @@ -1,146 +1,139 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkToFCameraMESADevice_h #define __mitkToFCameraMESADevice_h #include "mitkMESASR4000ModuleExports.h" #include "mitkCommon.h" #include "mitkToFCameraDevice.h" #include "mitkToFCameraMESAController.h" #include "itkObject.h" #include "itkObjectFactory.h" #include "itkMultiThreader.h" #include "itkFastMutexLock.h" namespace mitk { /** * @brief Interface for all representations of MESA ToF devices. * ToFCameraMESADevice internally holds an instance of ToFCameraMESAController and starts a thread * that continuously grabs images from the controller. A buffer structure buffers the last acquired images * to provide the image data loss-less. * * @ingroup ToFHardware */ class MITK_MESASR4000MODULE_EXPORT ToFCameraMESADevice : public ToFCameraDevice { public: mitkClassMacro( ToFCameraMESADevice , ToFCameraDevice ); itkNewMacro( Self ); /*! \brief opens a connection to the ToF camera */ virtual bool OnConnectCamera(); /*! \brief closes the connection to the camera */ virtual bool DisconnectCamera(); /*! \brief starts the continuous updating of the camera. A separate thread updates the source data, the main thread processes the source data and creates images and coordinates */ virtual void StartCamera(); /*! \brief stops the continuous updating of the camera */ virtual void StopCamera(); /*! \brief updates the camera for image acquisition */ virtual void UpdateCamera(); /*! \brief returns whether the camera is currently active or not */ virtual bool IsCameraActive(); /*! \brief gets the amplitude data from the ToF camera as the strength of the active illumination of every pixel. Caution! The user is responsible for allocating and deleting the images. These values can be used to determine the quality of the distance values. The higher the amplitude value, the higher the accuracy of the according distance value \param imageSequence the actually captured image sequence number \param amplitudeArray contains the returned amplitude data as an array. */ virtual void GetAmplitudes(float* amplitudeArray, int& imageSequence); /*! \brief gets the intensity data from the ToF camera as a greyscale image. Caution! The user is responsible for allocating and deleting the images. \param intensityArray contains the returned intensities data as an array. \param imageSequence the actually captured image sequence number */ virtual void GetIntensities(float* intensityArray, int& imageSequence); /*! \brief gets the distance data from the ToF camera measuring the distance between the camera and the different object points in millimeters. Caution! The user is responsible for allocating and deleting the images. \param distanceArray contains the returned distances data as an array. \param imageSequence the actually captured image sequence number */ virtual void GetDistances(float* distanceArray, int& imageSequence); /*! \brief gets the 3 images (distance, amplitude, intensity) from the ToF camera. Caution! The user is responsible for allocating and deleting the images. \param distanceArray contains the returned distance data as an array. \param amplitudeArray contains the returned amplitude data as an array. \param intensityArray contains the returned intensity data as an array. \param sourceDataArray contains the complete source data from the camera device. \param requiredImageSequence the required image sequence number \param capturedImageSequence the actually captured image sequence number */ virtual void GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray, int requiredImageSequence, int& capturedImageSequence, unsigned char* rgbDataArray=NULL); -// TODO: Buffer size currently set to 1. Once Buffer handling is working correctly, method may be reactivated -// /* // * TODO: Reenable doxygen comment when uncommenting, disabled to fix doxygen warning see bug 12882 -// \brief pure virtual method resetting the buffer using the specified bufferSize. Has to be implemented by sub-classes -// \param bufferSize buffer size the buffer should be reset to -// */ -// virtual void ResetBuffer(int bufferSize) = 0; - //TODO add/correct documentation for requiredImageSequence and capturedImageSequence in the GetAllImages, GetDistances, GetIntensities and GetAmplitudes methods. /*! \brief returns the corresponding camera controller */ ToFCameraMESAController::Pointer GetController(); /*! \brief set a BaseProperty */ virtual void SetProperty( const char *propertyKey, BaseProperty* propertyValue ); protected: ToFCameraMESADevice(); ~ToFCameraMESADevice(); /*! \brief Thread method continuously acquiring images from the ToF hardware */ static ITK_THREAD_RETURN_TYPE Acquire(void* pInfoStruct); /*! \brief moves the position pointer m_CurrentPos to the next position in the buffer if that's not the next free position to prevent reading from an empty buffer */ void GetNextPos(); ToFCameraMESAController::Pointer m_Controller; ///< corresponding CameraController float** m_DistanceDataBuffer; ///< buffer holding the last distance images float** m_AmplitudeDataBuffer; ///< buffer holding the last amplitude images float** m_IntensityDataBuffer; ///< buffer holding the last intensity images private: }; } //END mitk namespace #endif diff --git a/Modules/ToFHardware/MesaSR4000/mitkToFCameraMESASR4000Controller.cpp b/Modules/ToFHardware/MesaSR4000/mitkToFCameraMESASR4000Controller.cpp index 622b63cca6..1dea2ffd1e 100644 --- a/Modules/ToFHardware/MesaSR4000/mitkToFCameraMESASR4000Controller.cpp +++ b/Modules/ToFHardware/MesaSR4000/mitkToFCameraMESASR4000Controller.cpp @@ -1,227 +1,227 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkToFCameraMESASR4000Controller.h" #include "mitkToFConfig.h" #include extern CMesaDevice* m_MESAHandle; namespace mitk { ToFCameraMESASR4000Controller::ToFCameraMESASR4000Controller() { this->m_Lambda = new float[MF_LAST]; this->m_Frequency = new float[MF_LAST]; this->m_Lambda[0] = 3.75f; this->m_Lambda[1] = 5.0f; this->m_Lambda[2] = 7.142857f; this->m_Lambda[3] = 7.5f; this->m_Lambda[4] = 7.894737f; this->m_Lambda[5] = 2.5f; this->m_Lambda[6] = 10.0f; this->m_Lambda[7] = 15.0f; this->m_Lambda[8] = 5.172414f; this->m_Lambda[9] = 4.838710f; this->m_Lambda[10] = 10.344828f; this->m_Lambda[11] = 9.677419f; this->m_Frequency[0] = 40.0f; this->m_Frequency[1] = 30.0f; this->m_Frequency[2] = 21.0f; this->m_Frequency[3] = 20.0f; this->m_Frequency[4] = 19.0f; this->m_Frequency[5] = 60.0f; this->m_Frequency[6] = 15.0f; this->m_Frequency[7] = 10.0f; this->m_Frequency[8] = 29.0f; this->m_Frequency[9] = 31.0f; this->m_Frequency[10] = 14.5f; this->m_Frequency[11] = 15.5f; } ToFCameraMESASR4000Controller::~ToFCameraMESASR4000Controller() { } bool ToFCameraMESASR4000Controller::OpenCameraConnection() { if(!m_ConnectionCheck) { /* m_PMDRes = pmdOpen (&m_PMDHandle , m_SourcePlugin , m_SourceParam , m_ProcPlugin , m_ProcParam ); m_ConnectionCheck = ErrorText(m_PMDRes); if (!m_ConnectionCheck) { return m_ConnectionCheck; } // get image properties from camera this->UpdateCamera(); m_PMDRes = pmdGetSourceDataDescription(m_PMDHandle, &m_DataDescription); ErrorText(m_PMDRes); m_CaptureWidth = m_DataDescription.img.numColumns; m_CaptureHeight = m_DataDescription.img.numRows; m_PixelNumber = m_CaptureWidth*m_CaptureHeight; m_NumberOfBytes = m_PixelNumber * sizeof(float); m_SourceDataSize = m_DataDescription.size; m_SourceDataStructSize = m_DataDescription.size + sizeof(PMDDataDescription); char serial[16]; m_PMDRes = pmdSourceCommand (m_PMDHandle, serial, 16, "GetSerialNumber"); ErrorText(m_PMDRes); MITK_INFO << "Serial-No: " << serial <m_SourceDataSize <GetIntegrationTime(); MITK_INFO << "Modulation Frequence: " << this->GetModulationFrequency(); return m_ConnectionCheck; */ //m_MESARes = SR_OpenDlg(&m_MESAHandle, 3, 0); this->m_MESARes = SR_OpenUSB(&m_MESAHandle, 0); this->m_ConnectionCheck = ErrorText(this->m_MESARes); if (m_MESARes <= 0) { this->m_ConnectionCheck = false; return this->m_ConnectionCheck; } this->m_MESARes = SR_GetRows(m_MESAHandle); this->m_CaptureHeight = this->m_MESARes; this->m_MESARes = SR_GetCols(m_MESAHandle); this->m_CaptureWidth = this->m_MESARes; this->m_PixelNumber = this->m_CaptureWidth*this->m_CaptureHeight; this->m_NumberOfBytes = this->m_PixelNumber * sizeof(float); ImgEntry* imgEntryArray; this->m_NumImg = SR_GetImageList(m_MESAHandle, &imgEntryArray); //float lambda[MF_LAST]={3.75f, 5.f, 7.142857f, 7.5f, 7.894737f, 2.5f, 10.f, 15.f, 5.172414f, 4.838710f, 10.344828f, 9.677419f};//MF_40MHz,MF_30MHz,MF_21MHz,MF_20MHz,MF_19MHz,... //float frequency[MF_LAST]={40.00f, 30.00f, 21.00f, 20.00f, 19.00f, 60.00f, 15.00f, 10.00f, 29.00f, 31.00f, 14.50f, 15.50f}; ModulationFrq frq = SR_GetModulationFrequency(m_MESAHandle); this->m_MaxRangeFactor = (this->m_Lambda[frq] * 1000.00) / (float)0xffff; unsigned char integrationTime8bit = SR_GetIntegrationTime(m_MESAHandle); float integrationTime = (0.3 + ((int)integrationTime8bit) * 0.1) * 1000; // for MESA4000 char deviceText[1024]; this->m_MESARes = SR_GetDeviceString(m_MESAHandle, deviceText, _countof(deviceText));//returns the device ID used in other calls MITK_INFO << "Device ID: " << deviceText <m_NumImg <m_CaptureWidth << " x " << this->m_CaptureHeight <m_Frequency[frq] << " MHz" <m_Lambda[frq] << " m" <m_MESARes = SR_SetIntegrationTime(m_MESAHandle, intTime); MITK_INFO << "New integration time: " << integrationTime << " microsec" <m_MESARes = SR_SetModulationFrequency (m_MESAHandle, frq); if (this->m_MESARes == 0) { this->m_MaxRangeFactor = (this->m_Lambda[frq] * 1000.00) / (float)0xffff; MITK_INFO << "New modulation frequency: " << this->m_Frequency[frq] << " MHz" <m_MESARes; } } int ToFCameraMESASR4000Controller::GetModulationFrequency() { ModulationFrq frq = SR_GetModulationFrequency(m_MESAHandle); this->m_MaxRangeFactor = (this->m_Lambda[frq] * 1000.00) / (float)0xffff; float frequency = this->m_Frequency[frq]; - return (int)frequency; // TODO float!! + return (int)frequency; // Attetntion frequency is converted to int to be consistent with MITK-ToF structure!! } void ToFCameraMESASR4000Controller::SetFPN( bool fpn ) { int acquireMode; acquireMode = SR_GetMode(m_MESAHandle); acquireMode &= ~AM_COR_FIX_PTRN; if (fpn) { acquireMode |= AM_COR_FIX_PTRN; } this->m_MESARes = SR_SetMode(m_MESAHandle, acquireMode); } void ToFCameraMESASR4000Controller::SetConvGray( bool ConvGray ) { int acquireMode; acquireMode = SR_GetMode(m_MESAHandle); acquireMode &= ~AM_CONV_GRAY; if (ConvGray) { acquireMode |= AM_CONV_GRAY; } this->m_MESARes = SR_SetMode(m_MESAHandle, acquireMode); } void ToFCameraMESASR4000Controller::SetMedian( bool median ) { int acquireMode; acquireMode = SR_GetMode(m_MESAHandle); acquireMode &= ~AM_MEDIAN; if (median) { acquireMode |= AM_MEDIAN; } this->m_MESARes = SR_SetMode(m_MESAHandle, acquireMode); } void ToFCameraMESASR4000Controller::SetANF( bool anf ) { int acquireMode; acquireMode = SR_GetMode(m_MESAHandle); acquireMode &= ~AM_DENOISE_ANF; if (anf) { acquireMode |= AM_DENOISE_ANF; } this->m_MESARes = SR_SetMode(m_MESAHandle, acquireMode); } } diff --git a/Modules/ToFHardware/PMD/Testing/mitkToFCameraPMDPlayerControllerTest.cpp b/Modules/ToFHardware/PMD/Testing/mitkToFCameraPMDPlayerControllerTest.cpp index 437c9b57d5..fdb5132e7e 100644 --- a/Modules/ToFHardware/PMD/Testing/mitkToFCameraPMDPlayerControllerTest.cpp +++ b/Modules/ToFHardware/PMD/Testing/mitkToFCameraPMDPlayerControllerTest.cpp @@ -1,71 +1,71 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkToFConfig.h" #include #include #include #include "mitkToFPMDConfig.h" #include /**Documentation * test for the class "ToFCameraPMDPlayerController". */ int mitkToFCameraPMDPlayerControllerTest(int /* argc */, char* /*argv*/[]) { MITK_TEST_BEGIN("ToFCameraPMDPlayerController"); //initialize test mitk::ToFCameraPMDPlayerDevice::Pointer pmdPlayerDevice = mitk::ToFCameraPMDPlayerDevice::New(); mitk::ToFCameraPMDPlayerController::Pointer pmdPlayerController = mitk::ToFCameraPMDPlayerController::New(); MITK_TEST_CONDITION_REQUIRED( pmdPlayerController.IsNotNull(),"Testing object initialization!"); MITK_TEST_CONDITION_REQUIRED( pmdPlayerController->GetCaptureHeight()== 200,"Testing GetCaptureHeight()"); MITK_TEST_CONDITION_REQUIRED( pmdPlayerController->GetCaptureWidth() == 200 ,"Testing GetCaptureWidth()"); //nice one! MITK_TEST_CONDITION_REQUIRED( !pmdPlayerController->OpenCameraConnection(),"Testing OpenConnection without valid data!"); - // set some valid data and test connecting again! TODO: Set the data to generic dir!! + // set some valid data and test connecting again! std::string filePath = MITK_TOF_DATA_DIR; std::string fileName = "/TestSequence.pmd"; filePath.append(fileName); pmdPlayerDevice->SetStringProperty("PMDFileName", filePath.c_str()); pmdPlayerController = dynamic_cast(pmdPlayerDevice->GetController().GetPointer()); // current implementation for mitkToFCameraPMDPlayerController only works for 32 bit machines, so we need to check // the platform we are working on! std::string platformVar = MITK_TOF_PLATFORM; if( platformVar == "W32") { if(std::string(MITK_TOF_PMDFILE_SOURCE_PLUGIN) != "") { MITK_TEST_CONDITION_REQUIRED( pmdPlayerController->OpenCameraConnection(),"Testing OpenConnection with valid data!"); MITK_TEST_CONDITION_REQUIRED( !pmdPlayerController->GetIntegrationTime() == 0, "Testing passing of integration time from PMD data!"); MITK_TEST_CONDITION_REQUIRED( !pmdPlayerController->GetModulationFrequency() == 0, "Testing passing of modulation frequency from PMD data!") } // testing disconnection MITK_TEST_CONDITION_REQUIRED ( pmdPlayerController->CloseCameraConnection(), "Testing CloseConnection with data!"); } else { MITK_TEST_CONDITION_REQUIRED( true, "Test case skipped! Wrong platfrom configuration, no driver available!"); } // test end MITK_TEST_END(); } diff --git a/Modules/ToFHardware/PMD/mitkToFCameraPMDCamBoardController.cpp b/Modules/ToFHardware/PMD/mitkToFCameraPMDCamBoardController.cpp index 25011746c2..babdaca5c9 100644 --- a/Modules/ToFHardware/PMD/mitkToFCameraPMDCamBoardController.cpp +++ b/Modules/ToFHardware/PMD/mitkToFCameraPMDCamBoardController.cpp @@ -1,172 +1,172 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkToFCameraPMDCamBoardController.h" #include "mitkToFConfig.h" #include #include "mitkToFPMDConfig.h" // vnl includes #include "vnl/vnl_matrix.h" //Plugin defines for CamBoard #define SOURCE_PARAM "" #define PROC_PARAM "" -extern PMDHandle m_PMDHandle; //TODO -extern PMDDataDescription m_DataDescription; //TODO +extern PMDHandle m_PMDHandle; +extern PMDDataDescription m_DataDescription; namespace mitk { ToFCameraPMDCamBoardController::ToFCameraPMDCamBoardController() { m_SourcePlugin = MITK_TOF_PMDCAMBOARD_SOURCE_PLUGIN; m_SourceParam = SOURCE_PARAM; m_ProcPlugin = MITK_TOF_PMDCAMBOARD_PROCESSING_PLUGIN; m_ProcParam = PROC_PARAM; } ToFCameraPMDCamBoardController::~ToFCameraPMDCamBoardController() { } bool ToFCameraPMDCamBoardController::OpenCameraConnection() { if(!m_ConnectionCheck) { m_PMDRes = pmdOpen (&m_PMDHandle , m_SourcePlugin , m_SourceParam , m_ProcPlugin , m_ProcParam ); m_ConnectionCheck = ErrorText(m_PMDRes); if (!m_ConnectionCheck) { return m_ConnectionCheck; } // get image properties from camera this->UpdateCamera(); this->m_PMDRes = pmdGetSourceDataDescription(m_PMDHandle, &m_DataDescription); ErrorText(m_PMDRes); this->m_CaptureWidth = m_DataDescription.img.numColumns; this->m_InternalCaptureWidth = 200; this->m_CaptureHeight = m_DataDescription.img.numRows; this->m_InternalCaptureHeight = 200; this->m_PixelNumber = m_CaptureWidth*m_CaptureHeight; this->m_NumberOfBytes = m_PixelNumber * sizeof(float); this->m_SourceDataSize = m_DataDescription.size; this->m_SourceDataStructSize = m_DataDescription.size + sizeof(PMDDataDescription); MITK_INFO << "Datasource size: " << this->m_SourceDataSize <GetIntegrationTime(); MITK_INFO << "Modulation Frequency: " << this->GetModulationFrequency(); return m_ConnectionCheck; } else return m_ConnectionCheck; } bool mitk::ToFCameraPMDCamBoardController::SetDistanceOffset( float offset ) { std::stringstream command; command<<"SetSoftOffset "<m_PMDRes = pmdSourceCommand(m_PMDHandle,0,0,command.str().c_str()); return ErrorText(this->m_PMDRes); } float mitk::ToFCameraPMDCamBoardController::GetDistanceOffset() { char offset[16]; this->m_PMDRes = pmdSourceCommand(m_PMDHandle, offset, 16, "GetSoftOffset"); ErrorText(this->m_PMDRes); return atof(offset); } bool mitk::ToFCameraPMDCamBoardController::SetRegionOfInterest( unsigned int leftUpperCornerX, unsigned int leftUpperCornerY, unsigned int width, unsigned int height ) { // CAVE: This function does not work properly, don't use unless you know what you're doing!! // check if leftUpperCornerX and width are divisible by 3 otherwise round to the next value divisible by 3 unsigned int factor = leftUpperCornerX/3; leftUpperCornerX = 3*factor; factor = width/3; width = 3*factor; std::stringstream command; command<<"SetROI "<m_PMDRes = pmdSourceCommand(m_PMDHandle,0,0,command.str().c_str()); return ErrorText(this->m_PMDRes); } bool mitk::ToFCameraPMDCamBoardController::SetRegionOfInterest( unsigned int roi[4] ) { return this->SetRegionOfInterest(roi[0],roi[1],roi[2],roi[3]); } unsigned int* mitk::ToFCameraPMDCamBoardController::GetRegionOfInterest() { /* char result[64]; this->m_PMDRes = pmdSourceCommand(m_PMDHandle, result, 64, "GetROI"); ErrorText(this->m_PMDRes); // convert char array to uint array unsigned int roi[4]; std::stringstream currentValue; int counter = 0; std::string resultString = result; char blank = ' '; for (int i=0; i<64; i++) { if (result[i]!=blank) { currentValue<m_PMDRes = pmdProcessingCommand(m_PMDHandle, 0, 0, commandStream.str().c_str()); return ErrorText(this->m_PMDRes); } void ToFCameraPMDCamBoardController::TransformCameraOutput( float* in, float* out, bool isDist) { vnl_matrix inMat = vnl_matrix(m_CaptureHeight,m_CaptureWidth); inMat.copy_in(in); vnl_matrix outMat = vnl_matrix(m_InternalCaptureHeight, m_InternalCaptureWidth); vnl_matrix temp = vnl_matrix(m_InternalCaptureHeight, m_InternalCaptureWidth); temp = inMat.extract(m_InternalCaptureHeight, m_InternalCaptureWidth, 0,1); outMat = temp.transpose(); if(isDist) { outMat*=1000; } outMat.copy_out(out); inMat.clear(); outMat.clear(); temp.clear(); } } diff --git a/Modules/ToFHardware/PMD/mitkToFCameraPMDCamCubeController.cpp b/Modules/ToFHardware/PMD/mitkToFCameraPMDCamCubeController.cpp index 22a7f76d03..a9edb964fd 100644 --- a/Modules/ToFHardware/PMD/mitkToFCameraPMDCamCubeController.cpp +++ b/Modules/ToFHardware/PMD/mitkToFCameraPMDCamCubeController.cpp @@ -1,251 +1,251 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkToFCameraPMDCamCubeController.h" #include "mitkToFConfig.h" #include "mitkToFPMDConfig.h" #include #include "vnl/vnl_matrix.h" //Plugin defines for CamCube #define SOURCE_PARAM "" #define PROC_PARAM "" -extern PMDHandle m_PMDHandle; //TODO +extern PMDHandle m_PMDHandle; -extern PMDDataDescription m_DataDescription; //TODO +extern PMDDataDescription m_DataDescription; namespace mitk { ToFCameraPMDCamCubeController::ToFCameraPMDCamCubeController() { m_SourcePlugin = MITK_TOF_PMDCAMCUBE_SOURCE_PLUGIN; m_SourceParam = SOURCE_PARAM; m_ProcPlugin = MITK_TOF_PMDCAMCUBE_PROCESSING_PLUGIN; m_ProcParam = PROC_PARAM; } ToFCameraPMDCamCubeController::~ToFCameraPMDCamCubeController() { } bool ToFCameraPMDCamCubeController::OpenCameraConnection() { if(!m_ConnectionCheck) { m_PMDRes = pmdOpen(&m_PMDHandle , m_SourcePlugin , m_SourceParam , m_ProcPlugin , m_ProcParam ); m_ConnectionCheck = ErrorText(m_PMDRes); if (!m_ConnectionCheck) { return m_ConnectionCheck; } // get image properties from camera this->UpdateCamera(); m_PMDRes = pmdGetSourceDataDescription(m_PMDHandle, &m_DataDescription); ErrorText(m_PMDRes); m_CaptureWidth = m_DataDescription.img.numColumns; m_CaptureHeight = m_DataDescription.img.numRows; m_InternalCaptureWidth = m_CaptureWidth; m_InternalCaptureHeight = m_CaptureHeight; m_PixelNumber = m_CaptureWidth*m_CaptureHeight; m_NumberOfBytes = m_PixelNumber * sizeof(float); m_SourceDataSize = m_DataDescription.size; m_SourceDataStructSize = m_DataDescription.size + sizeof(PMDDataDescription); char serial[16]; m_PMDRes = pmdSourceCommand (m_PMDHandle, serial, 16, "GetSerialNumber"); ErrorText(m_PMDRes); MITK_INFO << "Serial-No: " << serial <m_SourceDataSize <GetIntegrationTime(); MITK_INFO << "Modulation Frequence: " << this->GetModulationFrequency(); return m_ConnectionCheck; } else return m_ConnectionCheck; } bool mitk::ToFCameraPMDCamCubeController::SetDistanceOffset( float offset ) { std::stringstream command; command<<"SetSoftOffset "<m_PMDRes = pmdSourceCommand(m_PMDHandle,0,0,command.str().c_str()); return ErrorText(this->m_PMDRes); } float mitk::ToFCameraPMDCamCubeController::GetDistanceOffset() { char offset[16]; this->m_PMDRes = pmdSourceCommand(m_PMDHandle, offset, 16, "GetSoftOffset"); ErrorText(this->m_PMDRes); return atof(offset); } bool mitk::ToFCameraPMDCamCubeController::SetRegionOfInterest( unsigned int leftUpperCornerX, unsigned int leftUpperCornerY, unsigned int width, unsigned int height ) { // check if leftUpperCornerX and width are divisible by 3 otherwise round to the next value divisible by 3 unsigned int factor = leftUpperCornerX/3; leftUpperCornerX = 3*factor; factor = width/3; width = 3*factor; std::stringstream command; command<<"SetROI "<m_PMDRes = pmdSourceCommand(m_PMDHandle,0,0,command.str().c_str()); return ErrorText(this->m_PMDRes); } bool mitk::ToFCameraPMDCamCubeController::SetRegionOfInterest( unsigned int roi[4] ) { return this->SetRegionOfInterest(roi[0],roi[1],roi[2],roi[3]); } unsigned int* mitk::ToFCameraPMDCamCubeController::GetRegionOfInterest() { /* char result[64]; this->m_PMDRes = pmdSourceCommand(m_PMDHandle, result, 64, "GetROI"); ErrorText(this->m_PMDRes); // convert char array to uint array unsigned int roi[4]; std::stringstream currentValue; int counter = 0; std::string resultString = result; char blank = ' '; for (int i=0; i<64; i++) { if (result[i]!=blank) { currentValue<m_PMDRes = pmdSourceCommand(m_PMDHandle, 0, 0, "SetExposureMode Normal"); return ErrorText(this->m_PMDRes); } else if (mode==1) // SMB mode { this->m_PMDRes = pmdSourceCommand(m_PMDHandle, 0, 0, "SetExposureMode SMB"); return ErrorText(this->m_PMDRes); } else { MITK_ERROR<<"Specified exposure mode not supported. Exposure mode must be 0 (Normal) or 1 (SMB)"; return false; } } bool mitk::ToFCameraPMDCamCubeController::SetFieldOfView( float fov ) { std::stringstream commandStream; commandStream<<"SetFOV "<m_PMDRes = pmdProcessingCommand(m_PMDHandle, 0, 0, commandStream.str().c_str()); return ErrorText(this->m_PMDRes); } bool mitk::ToFCameraPMDCamCubeController::SetFPNCalibration( bool on ) { if(on) { this->m_PMDRes=pmdSourceCommand(m_PMDHandle,0,0,"SetFPNCalibration On"); return this->ErrorText(this->m_PMDRes); } else { this->m_PMDRes=pmdSourceCommand(m_PMDHandle,0,0,"SetFPNCalibration Off"); return this->ErrorText(this->m_PMDRes); } } bool mitk::ToFCameraPMDCamCubeController::SetFPPNCalibration( bool on ) { if(on) { this->m_PMDRes=pmdProcessingCommand(m_PMDHandle,0,0,"SetFPPNCalibration On"); return this->ErrorText(this->m_PMDRes); } else { this->m_PMDRes=pmdProcessingCommand(m_PMDHandle,0,0,"SetFPPNCalibration Off"); return this->ErrorText(this->m_PMDRes); } } bool mitk::ToFCameraPMDCamCubeController::SetLinearityCalibration( bool on ) { if(on) { this->m_PMDRes=pmdProcessingCommand(m_PMDHandle,0,0,"SetLinearityCalibration On"); return this->ErrorText(this->m_PMDRes); } else { this->m_PMDRes=pmdProcessingCommand(m_PMDHandle,0,0,"SetLinearityCalibration Off"); return this->ErrorText(this->m_PMDRes); } } bool mitk::ToFCameraPMDCamCubeController::SetLensCalibration( bool on ) { if (on) { this->m_PMDRes = pmdProcessingCommand(m_PMDHandle, 0, 0, "SetLensCalibration On"); return ErrorText(this->m_PMDRes); } else { this->m_PMDRes = pmdProcessingCommand(m_PMDHandle, 0, 0, "SetLensCalibration Off"); return ErrorText(this->m_PMDRes); } } void ToFCameraPMDCamCubeController::TransformCameraOutput( float* in, float* out, bool isDist ) { vnl_matrix inMat = vnl_matrix(m_CaptureHeight,m_CaptureWidth); inMat.copy_in(in); vnl_matrix outMat = vnl_matrix(m_InternalCaptureHeight, m_InternalCaptureWidth); outMat = inMat.extract(m_InternalCaptureHeight, m_InternalCaptureWidth, 0,0); outMat.fliplr(); if(isDist) { outMat*=1000; } outMat.copy_out(out); inMat.clear(); outMat.clear(); } } diff --git a/Modules/ToFHardware/PMD/mitkToFCameraPMDController.cpp b/Modules/ToFHardware/PMD/mitkToFCameraPMDController.cpp index dea574ea64..facc6438c6 100644 --- a/Modules/ToFHardware/PMD/mitkToFCameraPMDController.cpp +++ b/Modules/ToFHardware/PMD/mitkToFCameraPMDController.cpp @@ -1,201 +1,201 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkToFCameraPMDController.h" #include #include // vnl includes #include "vnl/vnl_matrix.h" -PMDHandle m_PMDHandle; //TODO -PMDDataDescription m_DataDescription; //TODO +PMDHandle m_PMDHandle; +PMDDataDescription m_DataDescription; struct SourceDataStruct { PMDDataDescription dataDescription; char sourceData; }; namespace mitk { ToFCameraPMDController::ToFCameraPMDController(): m_PMDRes(0), m_PixelNumber(40000), m_NumberOfBytes(0), m_CaptureWidth(200), m_CaptureHeight(200),m_InternalCaptureWidth(m_CaptureWidth),m_InternalCaptureHeight(m_CaptureHeight), m_SourceDataSize(0), m_SourceDataStructSize(0), m_ConnectionCheck(false), m_InputFileName("") { } ToFCameraPMDController::~ToFCameraPMDController() { } bool ToFCameraPMDController::CloseCameraConnection() { m_PMDRes = pmdClose(m_PMDHandle); m_ConnectionCheck = ErrorText(m_PMDRes); m_PMDHandle = 0; return m_ConnectionCheck; } bool ToFCameraPMDController::ErrorText(int error) { if(error != PMD_OK) { pmdGetLastError (m_PMDHandle, m_PMDError, 128); MITK_ERROR << "PMD Error " << m_PMDError; mitkThrow() << "PMD Error " << m_PMDError; return false; } else return true; } bool ToFCameraPMDController::UpdateCamera() { m_PMDRes = pmdUpdate(m_PMDHandle); return ErrorText(m_PMDRes); } bool ToFCameraPMDController::GetAmplitudes(float* amplitudeArray) { float* tempArray = new float[m_CaptureWidth*m_CaptureHeight]; this->m_PMDRes = pmdGetAmplitudes(m_PMDHandle, tempArray, this->m_NumberOfBytes); TransformCameraOutput(tempArray, amplitudeArray, false); delete[] tempArray; return ErrorText(this->m_PMDRes); } bool ToFCameraPMDController::GetAmplitudes(char* sourceData, float* amplitudeArray) { float* tempArray = new float[m_CaptureWidth*m_CaptureHeight]; this->m_PMDRes = pmdCalcAmplitudes(m_PMDHandle, tempArray, this->m_NumberOfBytes, m_DataDescription, &((SourceDataStruct*)sourceData)->sourceData); TransformCameraOutput(tempArray, amplitudeArray, false); delete[] tempArray; return ErrorText(this->m_PMDRes); } bool ToFCameraPMDController::GetIntensities(float* intensityArray) { float* tempArray = new float[m_CaptureWidth*m_CaptureHeight]; this->m_PMDRes = pmdGetIntensities(m_PMDHandle, tempArray, this->m_NumberOfBytes); TransformCameraOutput(tempArray, intensityArray, false); delete[] tempArray; return ErrorText(this->m_PMDRes); } bool ToFCameraPMDController::GetIntensities(char* sourceData, float* intensityArray) { float* tempArray = new float[m_CaptureWidth*m_CaptureHeight]; this->m_PMDRes = pmdCalcIntensities(m_PMDHandle, tempArray, this->m_NumberOfBytes, m_DataDescription, &((SourceDataStruct*)sourceData)->sourceData); TransformCameraOutput(tempArray, intensityArray, false); delete[] tempArray; return ErrorText(this->m_PMDRes); } bool ToFCameraPMDController::GetDistances(float* distanceArray) { float* tempArray = new float[m_CaptureWidth*m_CaptureHeight]; this->m_PMDRes = pmdGetDistances(m_PMDHandle, tempArray, this->m_NumberOfBytes); TransformCameraOutput(tempArray, distanceArray, true); delete[] tempArray; return ErrorText(this->m_PMDRes); } bool ToFCameraPMDController::GetDistances(char* sourceData, float* distanceArray) { float* tempArray = new float[m_CaptureWidth*m_CaptureHeight]; this->m_PMDRes = pmdCalcDistances(m_PMDHandle, tempArray, this->m_NumberOfBytes, m_DataDescription, &((SourceDataStruct*)sourceData)->sourceData); TransformCameraOutput(tempArray, distanceArray, true); delete[] tempArray; return ErrorText(this->m_PMDRes); } bool ToFCameraPMDController::GetSourceData(char* sourceDataArray) { this->m_PMDRes = pmdGetSourceDataDescription(m_PMDHandle, &m_DataDescription); if (!ErrorText(this->m_PMDRes)) { return false; } memcpy(&((SourceDataStruct*)sourceDataArray)->dataDescription, &m_DataDescription, sizeof(m_DataDescription)); this->m_PMDRes = pmdGetSourceData(m_PMDHandle, &((SourceDataStruct*)sourceDataArray)->sourceData, this->m_SourceDataSize); return ErrorText(this->m_PMDRes); } bool ToFCameraPMDController::GetShortSourceData( short* sourceData) { this->m_PMDRes = pmdGetSourceDataDescription(m_PMDHandle,&m_DataDescription); ErrorText( this->m_PMDRes); this->m_PMDRes = pmdGetSourceData(m_PMDHandle,sourceData,m_DataDescription.size); return ErrorText( this->m_PMDRes); } int ToFCameraPMDController::SetIntegrationTime(unsigned int integrationTime) { if(!m_ConnectionCheck) { return integrationTime; } unsigned int result; this->m_PMDRes = pmdGetValidIntegrationTime(m_PMDHandle, &result, 0, CloseTo, integrationTime); MITK_INFO << "Valid Integration Time = " << result; ErrorText(this->m_PMDRes); if (this->m_PMDRes != 0) { return 0; } this->m_PMDRes = pmdSetIntegrationTime(m_PMDHandle, 0, result); ErrorText(this->m_PMDRes); return result; } int ToFCameraPMDController::GetIntegrationTime() { unsigned int integrationTime = 0; this->m_PMDRes = pmdGetIntegrationTime(m_PMDHandle, &integrationTime, 0); ErrorText(this->m_PMDRes); return integrationTime; } int ToFCameraPMDController::SetModulationFrequency(unsigned int modulationFrequency) { if(!m_ConnectionCheck) { return modulationFrequency; } unsigned int result; this->m_PMDRes = pmdGetValidModulationFrequency(m_PMDHandle, &result, 0, AtLeast, (modulationFrequency*1000000)); MITK_INFO << "Valid Modulation Frequency = " << result; ErrorText(this->m_PMDRes); if (this->m_PMDRes != 0) { return 0; } this->m_PMDRes = pmdSetModulationFrequency(m_PMDHandle, 0, result); ErrorText(this->m_PMDRes); return (result/1000000);; } int ToFCameraPMDController::GetModulationFrequency() { unsigned int modulationFrequency = 0; this->m_PMDRes = pmdGetModulationFrequency (m_PMDHandle, &modulationFrequency, 0); ErrorText(this->m_PMDRes); return (modulationFrequency/1000000); } void ToFCameraPMDController::SetInputFileName(std::string inputFileName) { this->m_InputFileName = inputFileName; } } diff --git a/Modules/ToFHardware/PMD/mitkToFCameraPMDController.h b/Modules/ToFHardware/PMD/mitkToFCameraPMDController.h index 8fce336a0e..ede4ca3155 100644 --- a/Modules/ToFHardware/PMD/mitkToFCameraPMDController.h +++ b/Modules/ToFHardware/PMD/mitkToFCameraPMDController.h @@ -1,201 +1,199 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkToFCameraPMDController_h #define __mitkToFCameraPMDController_h #include "mitkPMDModuleExports.h" #include "mitkCommon.h" #include "itkObject.h" #include "itkObjectFactory.h" namespace mitk { /** * @brief Virtual interface and base class for all PMD Time-of-Flight devices. Wraps PMD API provided in PMDSDK2 * Provides methods for accessing current distance, amplitude, intensity and raw data. * Allows to set parameters like modulation frequency and integration time. * * @ingroup ToFHardware */ class MITK_PMDMODULE_EXPORT ToFCameraPMDController : public itk::Object { public: mitkClassMacro( ToFCameraPMDController , itk::Object ); /*! \brief opens a connection to the ToF camera. Has to be implemented by the sub class \throws mitkException In case of no connection, an exception is thrown! */ - //TODO return value virtual bool OpenCameraConnection() = 0; /*! \brief closes the connection to the camera */ - //TODO return value virtual bool CloseCameraConnection(); /*! \brief Gets the current amplitude array from the device \param amplitudeArray float array where the amplitude data will be saved */ virtual bool GetAmplitudes(float* amplitudeArray); /*! \brief Calculates the current amplitude data from the raw source data using the processing plugin of the PMDSDK \param sourceData raw data array \param amplitudeArray float array where the amplitude data will be saved */ virtual bool GetAmplitudes(char* sourceData, float* amplitudeArray); /*! \brief Gets the current intensity array from the device \param intensityArray float array where the intensity data will be saved */ virtual bool GetIntensities(float* intensityArray); /*! \brief Calculates the current intensity data from the raw source data using the processing plugin of the PMDSDK \param sourceData raw data array \param intensityArray float array where the intensity data will be saved */ virtual bool GetIntensities(char* sourceData, float* intensityArray); /*! \brief Gets the current distance array from the device \param distanceArray float array where the distance data will be saved */ virtual bool GetDistances(float* distanceArray); /*! \brief Calculates the current distance data from the raw source data using the processing plugin of the PMDSDK \param sourceData raw data array \param distanceArray float array where the distance data will be saved */ virtual bool GetDistances(char* sourceData, float* distanceArray); /*! \brief Gets the PMD raw data from the ToF device. \param sourceDataArray array where the raw data will be saved */ virtual bool GetSourceData(char* sourceDataArray); /*! \brief Convenience method to get the PMD raw data from the ToF device as short array. \param sourceData array where the short raw data will be saved */ bool GetShortSourceData(short* sourceData); /*! \brief calls update on the camera -> a new ToF-image is aquired \throws mitkException In case of no connection, an exception is thrown! */ virtual bool UpdateCamera(); /*! \brief Returns the currently set modulation frequency. \return modulation frequency */ virtual int GetModulationFrequency(); /*! \brief Sets the modulation frequency of the ToF device. The method automatically calculates a valid value from the given frequency to make sure that only valid frequencies are used. \param modulationFrequency modulation frequency \return frequency set after validation step */ virtual int SetModulationFrequency(unsigned int modulationFrequency); /*! \brief Returns the currently set integration time. \return integration time */ virtual int GetIntegrationTime(); /*! \brief Sets the integration time of the ToF device. The method automatically calculates a valid value from the given integration time to make sure that only valid times are used. \param integrationTime integration time \return integration time set after validation step */ virtual int SetIntegrationTime(unsigned int integrationTime); /*! \brief set input file name used by PMD player classes */ virtual void SetInputFileName(std::string inputFileName); /*! \brief Access the resolution of the image in x direction \return widht of image in pixel */ itkGetMacro(CaptureWidth, unsigned int); /*! \brief Access the resolution of the image in y direction \return height of image in pixel */ itkGetMacro(CaptureHeight, unsigned int); /*! \brief Access the chosen width of the resulting image in x direction \return widht of image in pixel */ itkGetMacro(InternalCaptureWidth, unsigned int); /*! \brief Access the chosen width of the resulting image in y direction \return height of image in pixel */ itkGetMacro(InternalCaptureHeight, unsigned int); itkGetMacro(SourceDataStructSize, int); protected: ToFCameraPMDController(); ~ToFCameraPMDController(); /*! \brief Method printing the current error message to the console and returning whether the previous command was successful \param error error number returned by the PMD function \return flag indicating if an error occured (false) or not (true) */ bool ErrorText(int error); /* \brief Abstract method that should be used to transform the camera output (e.g. flip / rotate / select region of interest). To be implemented by subclasses \param input data array of original size (m_CaptureWidth x m_CaptureHeight) \param rotated output data array of reduced size (m_InternalCaptureWidth x m_InternalCaputureHeight) \param isDist flag indicating whether the input contains PMD distance information */ virtual void TransformCameraOutput(float* in, float* out, bool isDist)=0; char m_PMDError[128]; ///< member holding the current error text int m_PMDRes; ///< holds the current result message provided by PMD int m_PixelNumber; ///< holds the number of pixels contained in the image int m_NumberOfBytes; ///< holds the number of bytes contained in the image unsigned int m_CaptureWidth; ///< holds the width of the image in pixel as it is originally acquired by the camera unsigned int m_CaptureHeight; ///< holds the height of the image in pixel as it is originally acquired by the camera unsigned int m_InternalCaptureWidth; ///< holds the width of the image in pixel as it is requested by the user (cf. TransformCameraOutput()) Default: m_CaptureWidth unsigned int m_InternalCaptureHeight; ///< holds the height of the image in pixel as is it requested by the user (cf. TransformCameraOutput()) Default: m_CaptureHeight int m_SourceDataSize; ///< size of the original PMD source data int m_SourceDataStructSize; ///< size of the PMD source data struct and the PMD source data bool m_ConnectionCheck; ///< flag showing whether the camera is connected (true) or not (false) std::string m_InputFileName; ///< input file name used by PMD player classes char *m_SourcePlugin; ///< holds name of source plugin to be loaded (e.g. camcube3.W64.pap for CamCube 3.0 on Win64 platform) char *m_SourceParam; ///< holds source parameter(s) char *m_ProcPlugin; ///< holds name of processing plugin to be loaded (e.g. camcubeproc.W64.pap for CamCube 3.0 on Win64 platform) char *m_ProcParam; ///< holds processing parameter(s) private: }; } //END mitk namespace #endif diff --git a/Modules/ToFHardware/PMD/mitkToFCameraPMDDevice.cpp b/Modules/ToFHardware/PMD/mitkToFCameraPMDDevice.cpp index 82d0afcdfc..573aae6cf1 100644 --- a/Modules/ToFHardware/PMD/mitkToFCameraPMDDevice.cpp +++ b/Modules/ToFHardware/PMD/mitkToFCameraPMDDevice.cpp @@ -1,397 +1,359 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkToFCameraPMDDevice.h" #include "mitkRealTimeClock.h" #include "itkMultiThreader.h" #include namespace mitk { ToFCameraPMDDevice::ToFCameraPMDDevice() : m_SourceDataBuffer(NULL), m_SourceDataArray(NULL) { } ToFCameraPMDDevice::~ToFCameraPMDDevice() { this->CleanUpSourceData(); CleanupPixelArrays(); } bool ToFCameraPMDDevice::OnConnectCamera() { bool ok = false; if (m_Controller) { ok = m_Controller->OpenCameraConnection(); if (ok) { this->m_CaptureWidth = m_Controller->GetInternalCaptureWidth(); this->m_CaptureHeight = m_Controller->GetInternalCaptureHeight(); this->m_SourceDataSize = m_Controller->GetSourceDataStructSize(); this->m_PixelNumber = this->m_CaptureWidth * this->m_CaptureHeight; // allocate buffers this->AllocatePixelArrays(); this->AllocateSourceData(); this->m_CameraConnected = true; } } return ok; } bool ToFCameraPMDDevice::DisconnectCamera() { bool ok = false; if (m_Controller) { ok = m_Controller->CloseCameraConnection(); if (ok) { m_CameraConnected = false; } } return ok; } void ToFCameraPMDDevice::StartCamera() { if (m_CameraConnected) { // get the first image this->m_Controller->UpdateCamera(); this->m_ImageMutex->Lock(); //this->m_Controller->GetSourceData(this->m_SourceDataArray); this->m_Controller->GetSourceData(this->m_SourceDataBuffer[this->m_FreePos]); this->m_FreePos = (this->m_FreePos+1) % this->m_BufferSize; this->m_CurrentPos = (this->m_CurrentPos+1) % this->m_BufferSize; this->m_ImageSequence++; this->m_ImageMutex->Unlock(); this->m_CameraActiveMutex->Lock(); this->m_CameraActive = true; this->m_CameraActiveMutex->Unlock(); this->m_ThreadID = this->m_MultiThreader->SpawnThread(this->Acquire, this); // wait a little to make sure that the thread is started itksys::SystemTools::Delay(10); } else { MITK_INFO<<"Camera not connected"; } } void ToFCameraPMDDevice::UpdateCamera() { if (m_Controller) { m_Controller->UpdateCamera(); } } ITK_THREAD_RETURN_TYPE ToFCameraPMDDevice::Acquire(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; if (pInfo == NULL) { return ITK_THREAD_RETURN_VALUE; } if (pInfo->UserData == NULL) { return ITK_THREAD_RETURN_VALUE; } ToFCameraPMDDevice* toFCameraDevice = (ToFCameraPMDDevice*)pInfo->UserData; if (toFCameraDevice!=NULL) { mitk::RealTimeClock::Pointer realTimeClock; realTimeClock = mitk::RealTimeClock::New(); double t1, t2; t1 = realTimeClock->GetCurrentStamp(); int n = 100; bool overflow = false; bool printStatus = false; while (toFCameraDevice->IsCameraActive()) { // update the ToF camera toFCameraDevice->UpdateCamera(); // get the source data from the camera and write it at the next free position in the buffer toFCameraDevice->m_ImageMutex->Lock(); toFCameraDevice->m_Controller->GetSourceData(toFCameraDevice->m_SourceDataBuffer[toFCameraDevice->m_FreePos]); toFCameraDevice->m_ImageMutex->Unlock(); // call modified to indicate that cameraDevice was modified toFCameraDevice->Modified(); - /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - TODO Buffer Handling currently only works for buffer size 1 - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ - //toFCameraDevice->m_ImageSequence++; toFCameraDevice->m_FreePos = (toFCameraDevice->m_FreePos+1) % toFCameraDevice->m_BufferSize; toFCameraDevice->m_CurrentPos = (toFCameraDevice->m_CurrentPos+1) % toFCameraDevice->m_BufferSize; toFCameraDevice->m_ImageSequence++; if (toFCameraDevice->m_FreePos == toFCameraDevice->m_CurrentPos) { - // buffer overflow - //MITK_INFO << "Buffer overflow!! "; - //toFCameraDevice->m_CurrentPos = (toFCameraDevice->m_CurrentPos+1) % toFCameraDevice->m_BufferSize; - //toFCameraDevice->m_ImageSequence++; overflow = true; } if (toFCameraDevice->m_ImageSequence % n == 0) { printStatus = true; } if (overflow) { overflow = false; } - /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - END TODO Buffer Handling currently only works for buffer size 1 - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ - - // print current framerate if (printStatus) { t2 = realTimeClock->GetCurrentStamp() - t1; - //MITK_INFO << "t2: " << t2 <<" Time (s) for 1 image: " << (t2/1000) / n << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence; MITK_INFO << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence; t1 = realTimeClock->GetCurrentStamp(); printStatus = false; } } // end of while loop } return ITK_THREAD_RETURN_VALUE; } - // TODO: Buffer size currently set to 1. Once Buffer handling is working correctly, method may be reactivated - // void ToFCameraPMDDevice::ResetBuffer(int bufferSize) - // { - // this->m_BufferSize = bufferSize; - // this->m_CurrentPos = -1; - // this->m_FreePos = 0; - // } - void ToFCameraPMDDevice::GetAmplitudes(float* amplitudeArray, int& imageSequence) { if (m_CameraActive) { // 1) copy the image buffer // 2) Flip around y- axis (vertical axis) m_ImageMutex->Lock(); this->m_Controller->GetAmplitudes(this->m_SourceDataBuffer[this->m_CurrentPos], this->m_AmplitudeArray); m_ImageMutex->Unlock(); for (int i=0; im_CaptureHeight; i++) { for (int j=0; jm_CaptureWidth; j++) { amplitudeArray[i*this->m_CaptureWidth+j] = this->m_AmplitudeArray[(i+1)*this->m_CaptureWidth-1-j]; } } imageSequence = this->m_ImageSequence; } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } } void ToFCameraPMDDevice::GetIntensities(float* intensityArray, int& imageSequence) { if (m_CameraActive) { // 1) copy the image buffer // 2) Flip around y- axis (vertical axis) m_ImageMutex->Lock(); this->m_Controller->GetIntensities(this->m_SourceDataBuffer[this->m_CurrentPos], this->m_IntensityArray); m_ImageMutex->Unlock(); for (int i=0; im_CaptureHeight; i++) { for (int j=0; jm_CaptureWidth; j++) { intensityArray[i*this->m_CaptureWidth+j] = this->m_IntensityArray[(i+1)*this->m_CaptureWidth-1-j]; } } imageSequence = this->m_ImageSequence; } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } m_ImageMutex->Unlock(); } void ToFCameraPMDDevice::GetDistances(float* distanceArray, int& imageSequence) { if (m_CameraActive) { // 1) copy the image buffer // 2) convert the distance values from m to mm // 3) Flip around y- axis (vertical axis) m_ImageMutex->Lock(); this->m_Controller->GetDistances(this->m_SourceDataBuffer[this->m_CurrentPos], this->m_DistanceArray); m_ImageMutex->Unlock(); for (int i=0; im_CaptureHeight; i++) { for (int j=0; jm_CaptureWidth; j++) { distanceArray[i*this->m_CaptureWidth+j] = this->m_DistanceArray[(i+1)*this->m_CaptureWidth-1-j]; } } imageSequence = this->m_ImageSequence; } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } } void ToFCameraPMDDevice::GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray, int requiredImageSequence, int& capturedImageSequence, unsigned char* rgbDataArray) { if (m_CameraActive) { // 1) copy the image buffer // 2) convert the distance values from m to mm // 3) Flip around y- axis (vertical axis) // check for empty buffer if (this->m_ImageSequence < 0) { // buffer empty MITK_INFO << "Buffer empty!! "; capturedImageSequence = this->m_ImageSequence; return; } // determine position of image in buffer int pos = 0; if ((requiredImageSequence < 0) || (requiredImageSequence > this->m_ImageSequence)) { capturedImageSequence = this->m_ImageSequence; pos = this->m_CurrentPos; - //MITK_INFO << "Required image not found! Required: " << requiredImageSequence << " delivered/current: " << this->m_ImageSequence; } else if (requiredImageSequence <= this->m_ImageSequence - this->m_BufferSize) { capturedImageSequence = (this->m_ImageSequence - this->m_BufferSize) + 1; pos = (this->m_CurrentPos + 1) % this->m_BufferSize; - //MITK_INFO << "Out of buffer! Required: " << requiredImageSequence << " delivered: " << capturedImageSequence << " current: " << this->m_ImageSequence; } else // (requiredImageSequence > this->m_ImageSequence - this->m_BufferSize) && (requiredImageSequence <= this->m_ImageSequence) { capturedImageSequence = requiredImageSequence; pos = (this->m_CurrentPos + (10-(this->m_ImageSequence - requiredImageSequence))) % this->m_BufferSize; } m_ImageMutex->Lock(); this->m_Controller->GetDistances(this->m_SourceDataBuffer[pos], this->m_DistanceArray); this->m_Controller->GetAmplitudes(this->m_SourceDataBuffer[pos], this->m_AmplitudeArray); this->m_Controller->GetIntensities(this->m_SourceDataBuffer[pos], this->m_IntensityArray); memcpy(sourceDataArray, this->m_SourceDataBuffer[this->m_CurrentPos], this->m_SourceDataSize); m_ImageMutex->Unlock(); memcpy(distanceArray, this->m_DistanceArray, this->m_CaptureWidth*this->m_CaptureHeight*sizeof(float)); memcpy(intensityArray, this->m_IntensityArray, this->m_CaptureWidth*this->m_CaptureHeight*sizeof(float)); memcpy(amplitudeArray, this->m_AmplitudeArray, this->m_CaptureWidth*this->m_CaptureHeight*sizeof(float)); - - //int u, v; - //for (int i=0; im_CaptureHeight; i++) - //{ - // for (int j=0; jm_CaptureWidth; j++) - // { - // u = i*this->m_CaptureWidth+j; - // v = (i+1)*this->m_CaptureWidth-1-j; - // distanceArray[u] = 1000 * this->m_DistanceArray[v]; // unit in minimeter - // //distanceArray[u] = this->m_DistanceArray[v]; // unit in meter - // amplitudeArray[u] = this->m_AmplitudeArray[v]; - // intensityArray[u] = this->m_IntensityArray[v]; - // } - //} } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } } ToFCameraPMDController::Pointer ToFCameraPMDDevice::GetController() { return this->m_Controller; } void ToFCameraPMDDevice::SetProperty( const char *propertyKey, BaseProperty* propertyValue ) { ToFCameraDevice::SetProperty(propertyKey,propertyValue); if (strcmp(propertyKey, "ModulationFrequency") == 0) { int modulationFrequency = 0; GetIntProperty(propertyKey, modulationFrequency); modulationFrequency = m_Controller->SetModulationFrequency(modulationFrequency); static_cast(propertyValue)->SetValue(modulationFrequency); this->m_PropertyList->SetProperty(propertyKey, propertyValue ); } else if (strcmp(propertyKey, "IntegrationTime") == 0) { int integrationTime = 0; GetIntProperty(propertyKey, integrationTime); integrationTime = m_Controller->SetIntegrationTime(integrationTime); static_cast(propertyValue)->SetValue(integrationTime); this->m_PropertyList->SetProperty(propertyKey, propertyValue ); } } void ToFCameraPMDDevice::AllocateSourceData() { // clean up if array and data have already been allocated CleanUpSourceData(); // (re-) allocate memory this->m_SourceDataArray = new char[this->m_SourceDataSize]; for(int i=0; im_SourceDataSize; i++) {this->m_SourceDataArray[i]=0;} this->m_SourceDataBuffer = new char*[this->m_MaxBufferSize]; for(int i=0; im_MaxBufferSize; i++) { this->m_SourceDataBuffer[i] = new char[this->m_SourceDataSize]; } } void ToFCameraPMDDevice::CleanUpSourceData() { if (m_SourceDataArray) { delete[] m_SourceDataArray; } if (m_SourceDataBuffer) { for(int i=0; im_MaxBufferSize; i++) { delete[] this->m_SourceDataBuffer[i]; } delete[] this->m_SourceDataBuffer; } } } diff --git a/Modules/ToFHardware/PMD/mitkToFCameraPMDDevice.h b/Modules/ToFHardware/PMD/mitkToFCameraPMDDevice.h index cbc44c6115..0ceae9e1ac 100644 --- a/Modules/ToFHardware/PMD/mitkToFCameraPMDDevice.h +++ b/Modules/ToFHardware/PMD/mitkToFCameraPMDDevice.h @@ -1,150 +1,142 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkToFCameraPMDDevice_h #define __mitkToFCameraPMDDevice_h #include "mitkPMDModuleExports.h" #include "mitkCommon.h" #include "mitkToFCameraDevice.h" #include "mitkToFCameraPMDController.h" #include "itkObject.h" #include "itkObjectFactory.h" #include "itkMultiThreader.h" #include "itkFastMutexLock.h" namespace mitk { /** * @brief Interface for all representations of PMD ToF devices. * ToFCameraPMDDevice internally holds an instance of ToFCameraPMDController and starts a thread * that continuously grabs images from the controller. A buffer structure buffers the last acquired images * to provide the image data loss-less. * *\throws mitkException In case of no connection, an exception is thrown! * * @ingroup ToFHardware */ class MITK_PMDMODULE_EXPORT ToFCameraPMDDevice : public ToFCameraDevice { public: mitkClassMacro( ToFCameraPMDDevice , ToFCameraDevice ); itkNewMacro( Self ); /*! \brief opens a connection to the ToF camera \throws mitkException In case of no connection, an exception is thrown! */ virtual bool OnConnectCamera(); /*! \brief closes the connection to the camera */ virtual bool DisconnectCamera(); /*! \brief starts the continuous updating of the camera. A separate thread updates the source data, the main thread processes the source data and creates images and coordinates \throws mitkException In case of no connection, an exception is thrown! */ virtual void StartCamera(); /*! \brief updated the controller hold by this device \throws mitkException In case of no connection, an exception is thrown! */ virtual void UpdateCamera(); /*! \brief gets the amplitude data from the ToF camera as the strength of the active illumination of every pixel. Caution! The user is responsible for allocating and deleting the images. These values can be used to determine the quality of the distance values. The higher the amplitude value, the higher the accuracy of the according distance value \param imageSequence the actually captured image sequence number \param amplitudeArray contains the returned amplitude data as an array. */ virtual void GetAmplitudes(float* amplitudeArray, int& imageSequence); /*! \brief gets the intensity data from the ToF camera as a greyscale image. Caution! The user is responsible for allocating and deleting the images. \param intensityArray contains the returned intensities data as an array. \param imageSequence the actually captured image sequence number */ virtual void GetIntensities(float* intensityArray, int& imageSequence); /*! \brief gets the distance data from the ToF camera measuring the distance between the camera and the different object points in millimeters. Caution! The user is responsible for allocating and deleting the images. \param distanceArray contains the returned distances data as an array. \param imageSequence the actually captured image sequence number */ virtual void GetDistances(float* distanceArray, int& imageSequence); /*! \brief gets the 3 images (distance, amplitude, intensity) from the ToF camera. Caution! The user is responsible for allocating and deleting the images. \param distanceArray contains the returned distance data as an array. \param amplitudeArray contains the returned amplitude data as an array. \param intensityArray contains the returned intensity data as an array. \param sourceDataArray contains the complete source data from the camera device. \param requiredImageSequence the required image sequence number \param capturedImageSequence the actually captured image sequence number */ virtual void GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray, int requiredImageSequence, int& capturedImageSequence, unsigned char* rgbDataArray=NULL); -// TODO: Buffer size currently set to 1. Once Buffer handling is working correctly, method may be reactivated -// /* // * TODO: Reenable doxygen comment when uncommenting, disabled to fix doxygen warning see bug 12882 -// \brief pure virtual method resetting the buffer using the specified bufferSize. Has to be implemented by sub-classes -// \param bufferSize buffer size the buffer should be reset to -// */ -// virtual void ResetBuffer(int bufferSize) = 0; - //TODO add/correct documentation for requiredImageSequence and capturedImageSequence in the GetAllImages, GetDistances, GetIntensities and GetAmplitudes methods. - /*! \brief returns the corresponding camera controller */ ToFCameraPMDController::Pointer GetController(); /*! \brief set a BaseProperty */ virtual void SetProperty( const char *propertyKey, BaseProperty* propertyValue ); protected: ToFCameraPMDDevice(); ~ToFCameraPMDDevice(); /*! \brief method for allocating m_SourceDataArray and m_SourceDataBuffer */ virtual void AllocateSourceData(); /*! \brief method for cleaning up memory allocated for m_SourceDataArray and m_SourceDataBuffer */ virtual void CleanUpSourceData(); /*! \brief Thread method continuously acquiring images from the ToF hardware */ static ITK_THREAD_RETURN_TYPE Acquire(void* pInfoStruct); /*! \brief moves the position pointer m_CurrentPos to the next position in the buffer if that's not the next free position to prevent reading from an empty buffer */ void GetNextPos(); ToFCameraPMDController::Pointer m_Controller; ///< corresponding CameraController char** m_SourceDataBuffer; ///< buffer holding the last acquired images char* m_SourceDataArray; ///< array holding the current PMD source data private: }; } //END mitk namespace #endif diff --git a/Modules/ToFHardware/PMD/mitkToFCameraPMDO3Controller.cpp b/Modules/ToFHardware/PMD/mitkToFCameraPMDO3Controller.cpp index 43cf9484cc..8d97edffb8 100644 --- a/Modules/ToFHardware/PMD/mitkToFCameraPMDO3Controller.cpp +++ b/Modules/ToFHardware/PMD/mitkToFCameraPMDO3Controller.cpp @@ -1,92 +1,92 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkToFCameraPMDO3Controller.h" #include #include "mitkToFConfig.h" #include "mitkToFPMDConfig.h" #include "vnl/vnl_matrix.h" // IP Adress of the Camera, change here if needed #define CAMERA_ADDR "192.168.0.69" #define SOURCE_PARAM "192.168.0.69" #define PROC_PARAM "" -extern PMDHandle m_PMDHandle; //TODO +extern PMDHandle m_PMDHandle; -extern PMDDataDescription m_DataDescription; //TODO +extern PMDDataDescription m_DataDescription; namespace mitk { ToFCameraPMDO3Controller::ToFCameraPMDO3Controller() { m_IPAddress = CAMERA_ADDR; m_SourcePlugin = MITK_TOF_PMDO3_SOURCE_PLUGIN; m_SourceParam = SOURCE_PARAM; m_ProcPlugin = MITK_TOF_PMDO3_PROCESSING_PLUGIN; m_ProcParam = PROC_PARAM; } ToFCameraPMDO3Controller::~ToFCameraPMDO3Controller() { } bool ToFCameraPMDO3Controller::OpenCameraConnection() { if(!m_ConnectionCheck) { m_PMDRes = pmdOpen (&m_PMDHandle , m_SourcePlugin , m_SourceParam , m_ProcPlugin , m_ProcParam ); m_ConnectionCheck = ErrorText(m_PMDRes); // get image properties from camera this->UpdateCamera(); m_PMDRes = pmdGetSourceDataDescription(m_PMDHandle, &m_DataDescription); ErrorText(m_PMDRes); m_CaptureWidth = m_DataDescription.img.numColumns; m_CaptureHeight = m_DataDescription.img.numRows; m_InternalCaptureWidth = m_CaptureWidth; m_InternalCaptureHeight = m_CaptureHeight; m_PixelNumber = m_CaptureWidth*m_CaptureHeight; m_NumberOfBytes = m_PixelNumber * sizeof(float); m_SourceDataSize = m_DataDescription.size; m_SourceDataStructSize = m_DataDescription.size + sizeof(PMDDataDescription); MITK_INFO << "Datasource size: " << m_SourceDataSize <GetIntegrationTime(); MITK_INFO << "Modulation Frequence: " << this->GetModulationFrequency(); return m_ConnectionCheck; } else return m_ConnectionCheck; } void ToFCameraPMDO3Controller::TransformCameraOutput(float* in, float* out, bool isDist) { vnl_matrix inMat = vnl_matrix(m_CaptureHeight,m_CaptureWidth); inMat.copy_in(in); vnl_matrix outMat = vnl_matrix(m_InternalCaptureHeight, m_InternalCaptureWidth); vnl_matrix temp = vnl_matrix(m_InternalCaptureHeight, m_InternalCaptureWidth); outMat = inMat.extract(m_InternalCaptureHeight, m_InternalCaptureWidth, 0,0); outMat.fliplr(); if(isDist) { outMat*=1000; } outMat.copy_out(out); inMat.clear(); outMat.clear(); temp.clear(); } } diff --git a/Modules/ToFHardware/PMD/mitkToFCameraPMDPlayerController.cpp b/Modules/ToFHardware/PMD/mitkToFCameraPMDPlayerController.cpp index 2bbf09c951..aea475cd95 100644 --- a/Modules/ToFHardware/PMD/mitkToFCameraPMDPlayerController.cpp +++ b/Modules/ToFHardware/PMD/mitkToFCameraPMDPlayerController.cpp @@ -1,93 +1,93 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkToFCameraPMDPlayerController.h" #include #include #include //Plugin defines for Camcube 2.0 #define PROC_PARAM "" -extern PMDHandle m_PMDHandle; //TODO +extern PMDHandle m_PMDHandle; -extern PMDDataDescription m_DataDescription; //TODO +extern PMDDataDescription m_DataDescription; namespace mitk { ToFCameraPMDPlayerController::ToFCameraPMDPlayerController() { m_SourcePlugin = MITK_TOF_PMDFILE_SOURCE_PLUGIN; m_ProcPlugin = MITK_TOF_PMDCAMCUBE_PROCESSING_PLUGIN; m_ProcParam = PROC_PARAM; this->m_NumOfFrames = 0; } ToFCameraPMDPlayerController::~ToFCameraPMDPlayerController() { } bool ToFCameraPMDPlayerController::OpenCameraConnection() { bool ok = false; if( m_PMDFileName == "" ) { return ok; } this->m_PMDRes = pmdOpen(&m_PMDHandle , this->m_SourcePlugin , this->m_PMDFileName.c_str(), this->m_ProcPlugin, this->m_ProcParam ); ok = ErrorText(this->m_PMDRes); if (ok) { this->m_PMDRes = pmdUpdate(m_PMDHandle); ok = ErrorText(this->m_PMDRes); this->m_PMDRes = pmdGetSourceDataDescription(m_PMDHandle, &m_DataDescription); ok = ErrorText(m_PMDRes); if (ok) { this->m_CaptureWidth = m_DataDescription.img.numColumns; this->m_CaptureHeight = m_DataDescription.img.numRows; this->m_PixelNumber = this->m_CaptureWidth * this->m_CaptureHeight; this->m_NumberOfBytes = this->m_PixelNumber * sizeof(float); this->m_SourceDataSize = m_DataDescription.size; this->m_SourceDataStructSize = m_DataDescription.size + sizeof(PMDDataDescription); MITK_INFO << "Open PMD file: " << m_InputFileName.c_str(); MITK_INFO << "Datasource size: " << this->m_SourceDataSize <GetIntegrationTime(); MITK_INFO << "Modulation Frequence: " << this->GetModulationFrequency(); MITK_INFO << "NumOfFrames: " << this->m_NumOfFrames; } } return ok; } int ToFCameraPMDPlayerController::SetIntegrationTime(unsigned int integrationTime) { return m_DataDescription.img.integrationTime[0];; } int ToFCameraPMDPlayerController::SetModulationFrequency(unsigned int modulationFrequency) { return m_DataDescription.img.modulationFrequency[0];; } } diff --git a/Modules/ToFHardware/PMD/mitkToFCameraPMDRawDataDevice.cpp b/Modules/ToFHardware/PMD/mitkToFCameraPMDRawDataDevice.cpp index d2b4cdc362..527637012a 100644 --- a/Modules/ToFHardware/PMD/mitkToFCameraPMDRawDataDevice.cpp +++ b/Modules/ToFHardware/PMD/mitkToFCameraPMDRawDataDevice.cpp @@ -1,482 +1,462 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkToFCameraPMDRawDataDevice.h" #include "mitkRealTimeClock.h" #ifdef MITK_USE_TOF_PMDCAMBOARD #include "mitkToFCameraPMDCamBoardController.h" #endif #ifdef MITK_USE_TOF_PMDCAMCUBE #include "mitkToFCameraPMDCamCubeController.h" #endif #ifdef MITK_USE_TOF_PMDO3 #include "mitkToFCameraPMDO3Controller.h" #endif #include "itkMultiThreader.h" #include namespace mitk { ToFCameraPMDRawDataDevice::ToFCameraPMDRawDataDevice() : m_SourceDataBuffer(NULL), m_SourceDataArray(NULL), m_ShortSourceData(NULL), m_OriginControllerWidth(0), m_OriginControllerHeight(0) { m_RawDataSource = ThreadedToFRawDataReconstruction::New(); } ToFCameraPMDRawDataDevice::~ToFCameraPMDRawDataDevice() { this->CleanUpSourceData(); } bool ToFCameraPMDRawDataDevice::OnConnectCamera() { bool ok = false; if (m_Controller.IsNotNull()) { ok = m_Controller->OpenCameraConnection(); if (ok) { this->m_CaptureWidth = m_Controller->GetInternalCaptureWidth(); this->m_CaptureHeight = m_Controller->GetInternalCaptureHeight(); this->m_OriginControllerHeight = m_CaptureHeight; this->m_OriginControllerWidth = m_CaptureWidth; this->m_SourceDataSize = m_Controller->GetSourceDataStructSize(); this->m_PixelNumber = this->m_CaptureWidth * this->m_CaptureHeight; // allocate buffers this->AllocatePixelArrays(); this->AllocateSourceData(); this->m_CameraConnected = true; } } return ok; } bool ToFCameraPMDRawDataDevice::DisconnectCamera() { bool ok = false; if (m_Controller) { ok = m_Controller->CloseCameraConnection(); if (ok) { m_CameraConnected = false; } } return ok; } void ToFCameraPMDRawDataDevice::StartCamera() { if (m_CameraConnected) { // get the first image this->m_Controller->UpdateCamera(); this->m_ImageMutex->Lock(); this->m_Controller->GetSourceData(this->m_SourceDataBuffer[this->m_FreePos]); this->m_FreePos = (this->m_FreePos+1) % this->m_BufferSize; this->m_CurrentPos = (this->m_CurrentPos+1) % this->m_BufferSize; this->m_ImageSequence++; this->m_ImageMutex->Unlock(); this->m_CameraActiveMutex->Lock(); this->m_CameraActive = true; this->m_CameraActiveMutex->Unlock(); this->m_ThreadID = this->m_MultiThreader->SpawnThread(this->Acquire, this); // wait a little to make sure that the thread is started itksys::SystemTools::Delay(100); } else { MITK_INFO<<"Camera not connected"; } } void ToFCameraPMDRawDataDevice::StopCamera() { m_CameraActiveMutex->Lock(); m_CameraActive = false; m_CameraActiveMutex->Unlock(); itksys::SystemTools::Delay(100); if (m_MultiThreader.IsNotNull()) { m_MultiThreader->TerminateThread(m_ThreadID); } // wait a little to make sure that the thread is terminated itksys::SystemTools::Delay(10); } bool ToFCameraPMDRawDataDevice::IsCameraActive() { m_CameraActiveMutex->Lock(); bool ok = m_CameraActive; m_CameraActiveMutex->Unlock(); return ok; } void ToFCameraPMDRawDataDevice::UpdateCamera() { if (m_Controller) { m_Controller->UpdateCamera(); } } ITK_THREAD_RETURN_TYPE ToFCameraPMDRawDataDevice::Acquire(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; if (pInfo == NULL) { return ITK_THREAD_RETURN_VALUE; } if (pInfo->UserData == NULL) { return ITK_THREAD_RETURN_VALUE; } ToFCameraPMDRawDataDevice* toFCameraDevice = (ToFCameraPMDRawDataDevice*)pInfo->UserData; if (toFCameraDevice!=NULL) { mitk::RealTimeClock::Pointer realTimeClock = mitk::RealTimeClock::New(); double t1, t2; t1 = realTimeClock->GetCurrentStamp(); int n = 100; bool overflow = false; bool printStatus = false; while (toFCameraDevice->IsCameraActive()) { // update the ToF camera toFCameraDevice->UpdateCamera(); // get the source data from the camera and write it at the next free position in the buffer // call modified to indicate that cameraDevice was modified toFCameraDevice->Modified(); vtkShortArray* channelData = vtkShortArray::New(); //toFCameraDevice->m_ImageMutex->Lock(); toFCameraDevice->m_Controller->GetShortSourceData(toFCameraDevice->m_ShortSourceData); toFCameraDevice->GetChannelSourceData( toFCameraDevice->m_ShortSourceData, channelData ); //toFCameraDevice->m_ImageMutex->Unlock(); if(!toFCameraDevice->m_RawDataSource->GetInit()) { toFCameraDevice->m_RawDataSource->Initialize(toFCameraDevice->m_OriginControllerWidth, toFCameraDevice->m_OriginControllerHeight, toFCameraDevice->m_Controller->GetModulationFrequency(), toFCameraDevice->GetChannelSize()); } toFCameraDevice->m_RawDataSource->SetChannelData(channelData); toFCameraDevice->m_RawDataSource->Update(); toFCameraDevice->m_ImageMutex->Lock(); toFCameraDevice->m_Controller->GetSourceData(toFCameraDevice->m_SourceDataArray); toFCameraDevice->m_RawDataSource->GetAllData(toFCameraDevice->m_DistanceArray, toFCameraDevice->m_AmplitudeArray, toFCameraDevice->m_IntensityArray); toFCameraDevice->m_ImageMutex->Unlock(); - /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - TODO Buffer Handling currently only works for buffer size 1 - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ - toFCameraDevice->m_FreePos = (toFCameraDevice->m_FreePos+1) % toFCameraDevice->m_BufferSize; toFCameraDevice->m_CurrentPos = (toFCameraDevice->m_CurrentPos+1) % toFCameraDevice->m_BufferSize; toFCameraDevice->m_ImageSequence++; if (toFCameraDevice->m_FreePos == toFCameraDevice->m_CurrentPos) { overflow = true; } if (toFCameraDevice->m_ImageSequence % n == 0) { printStatus = true; } channelData->Delete(); if (overflow) { overflow = false; } - /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - END TODO Buffer Handling currently only works for buffer size 1 - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ // print current frame rate if (printStatus) { t2 = realTimeClock->GetCurrentStamp() - t1; - //MITK_INFO << "t2: " << t2 <<" Time (s) for 1 image: " << (t2/1000) / n << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence; MITK_INFO << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence; t1 = realTimeClock->GetCurrentStamp(); printStatus = false; } } // end of while loop } return ITK_THREAD_RETURN_VALUE; } - // TODO: Buffer size currently set to 1. Once Buffer handling is working correctly, method may be reactivated - // void ToFCameraPMDDevice::ResetBuffer(int bufferSize) - // { - // this->m_BufferSize = bufferSize; - // this->m_CurrentPos = -1; - // this->m_FreePos = 0; - // } - void ToFCameraPMDRawDataDevice::GetAmplitudes(float* amplitudeArray, int& imageSequence) { if (m_CameraActive) { memcpy(amplitudeArray, this->m_AmplitudeArray, this->m_PixelNumber*sizeof(float)); imageSequence = this->m_ImageSequence; } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } } void ToFCameraPMDRawDataDevice::GetIntensities(float* intensityArray, int& imageSequence) { if (m_CameraActive) { memcpy(intensityArray, this->m_IntensityArray, this->m_PixelNumber*sizeof(float)); imageSequence = this->m_ImageSequence; } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } } void ToFCameraPMDRawDataDevice::GetDistances(float* distanceArray, int& imageSequence) { if (m_CameraActive) { memcpy(distanceArray, this->m_DistanceArray, this->m_PixelNumber*sizeof(float)); imageSequence = this->m_ImageSequence; } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } } void ToFCameraPMDRawDataDevice::GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray, int requiredImageSequence, int& capturedImageSequence, unsigned char* rgbDataArray) { if (m_CameraActive) { - // 1) copy the image buffer - // 2) convert the distance values from m to mm - // 3) Flip around y- axis (vertical axis) - // check for empty buffer if (this->m_ImageSequence < 0) { // buffer empty MITK_INFO << "Buffer empty!! "; capturedImageSequence = this->m_ImageSequence; return; } // determine position of image in buffer int pos = 0; if ((requiredImageSequence < 0) || (requiredImageSequence > this->m_ImageSequence)) { capturedImageSequence = this->m_ImageSequence; pos = this->m_CurrentPos; //MITK_INFO << "Required image not found! Required: " << requiredImageSequence << " delivered/current: " << this->m_ImageSequence; } else if (requiredImageSequence <= this->m_ImageSequence - this->m_BufferSize) { capturedImageSequence = (this->m_ImageSequence - this->m_BufferSize) + 1; pos = (this->m_CurrentPos + 1) % this->m_BufferSize; //MITK_INFO << "Out of buffer! Required: " << requiredImageSequence << " delivered: " << capturedImageSequence << " current: " << this->m_ImageSequence; } else // (requiredImageSequence > this->m_ImageSequence - this->m_BufferSize) && (requiredImageSequence <= this->m_ImageSequence) { capturedImageSequence = requiredImageSequence; pos = (this->m_CurrentPos + (10-(this->m_ImageSequence - requiredImageSequence))) % this->m_BufferSize; } memcpy(distanceArray, this->m_DistanceArray, this->m_PixelNumber*sizeof(float)); memcpy(amplitudeArray, this->m_AmplitudeArray, this->m_PixelNumber*sizeof(float)); memcpy(intensityArray, this->m_IntensityArray, this->m_PixelNumber*sizeof(float)); memcpy(sourceDataArray, this->m_SourceDataBuffer[this->m_CurrentPos], this->m_SourceDataSize); } else { MITK_WARN("ToF") << "Warning: Data can only be acquired if camera is active."; } } void ToFCameraPMDRawDataDevice::XYAxisFlipImage( float* imageData, float* &flippedData, int xAxis, int yAxis, int dimension ) { int captureWidth = this->GetCaptureWidth(); int captureHeight = this->GetCaptureHeight(); // //flips image around x- axis (horizontal axis) // if(xAxis == 1 && yAxis != 1) { for (int i=0; im_Controller; } void ToFCameraPMDRawDataDevice::SetProperty( const char *propertyKey, BaseProperty* propertyValue ) { ToFCameraDevice::SetProperty(propertyKey,propertyValue); this->m_PropertyList->SetProperty(propertyKey, propertyValue); if (strcmp(propertyKey, "ModulationFrequency") == 0) { int modulationFrequency = 0; GetIntProperty(propertyKey, modulationFrequency); m_Controller->SetModulationFrequency(modulationFrequency); } else if (strcmp(propertyKey, "IntegrationTime") == 0) { int integrationTime = 0; GetIntProperty(propertyKey, integrationTime); m_Controller->SetIntegrationTime(integrationTime); } } void ToFCameraPMDRawDataDevice::CleanupPixelArrays() { if (m_IntensityArray) { delete [] m_IntensityArray; } if (m_DistanceArray) { delete [] m_DistanceArray; } if (m_AmplitudeArray) { delete [] m_AmplitudeArray; } if (m_ShortSourceData) { delete [] m_ShortSourceData; } } void ToFCameraPMDRawDataDevice::AllocatePixelArrays() { // free memory if it was already allocated CleanupPixelArrays(); // allocate buffer this->m_IntensityArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_IntensityArray[i]=0.0;} this->m_DistanceArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_DistanceArray[i]=0.0;} this->m_AmplitudeArray = new float[this->m_PixelNumber]; for(int i=0; im_PixelNumber; i++) {this->m_AmplitudeArray[i]=0.0;} this->m_ShortSourceData = new short[this->m_SourceDataSize]; for(int i=0; im_SourceDataSize; i++) {this->m_ShortSourceData[i]=0.0;} } void ToFCameraPMDRawDataDevice::AllocateSourceData() { // clean up if array and data have already been allocated CleanUpSourceData(); // (re-) allocate memory this->m_SourceDataArray = new char[this->m_SourceDataSize]; for(int i=0; im_SourceDataSize; i++) {this->m_SourceDataArray[i]=0;} this->m_SourceDataBuffer = new char*[this->m_MaxBufferSize]; for(int i=0; im_MaxBufferSize; i++) { this->m_SourceDataBuffer[i] = new char[this->m_SourceDataSize]; } } void ToFCameraPMDRawDataDevice::CleanUpSourceData() { if (m_SourceDataArray) { delete[] m_SourceDataArray; } if (m_SourceDataBuffer) { for(int i=0; im_MaxBufferSize; i++) { delete[] this->m_SourceDataBuffer[i]; } delete[] this->m_SourceDataBuffer; } } } diff --git a/Modules/ToFHardware/PMD/mitkToFCameraPMDRawDataDevice.h b/Modules/ToFHardware/PMD/mitkToFCameraPMDRawDataDevice.h index 928bd561e2..c67dd35a35 100644 --- a/Modules/ToFHardware/PMD/mitkToFCameraPMDRawDataDevice.h +++ b/Modules/ToFHardware/PMD/mitkToFCameraPMDRawDataDevice.h @@ -1,177 +1,169 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkToFCameraPMDRawDataDevice_h #define __mitkToFCameraPMDRawDataDevice_h #include "mitkPMDModuleExports.h" #include "mitkToFCameraDevice.h" #include "mitkToFCameraPMDController.h" #include "mitkThreadedToFRawDataReconstruction.h" namespace mitk { /** * @brief Interface for all representations of PMD ToF devices. * ToFCameraPMDDevice internally holds an instance of ToFCameraPMDController and starts a thread * that continuously grabs images from the controller. A buffer structure buffers the last acquired images * to provide the image data loss-less. * * @ingroup ToFHardware */ class MITK_PMDMODULE_EXPORT ToFCameraPMDRawDataDevice : public ToFCameraDevice { public: mitkClassMacro( ToFCameraPMDRawDataDevice , ToFCameraDevice ); itkNewMacro( Self ); itkSetMacro(ChannelSize, int); itkGetMacro(ChannelSize, int); /*! \brief opens a connection to the ToF camera */ virtual bool OnConnectCamera(); /*! \brief closes the connection to the camera */ virtual bool DisconnectCamera(); /*! \brief starts the continuous updating of the camera. A separate thread updates the source data, the main thread processes the source data and creates images and coordinates */ virtual void StartCamera(); /*! \brief stops the continuous updating of the camera */ virtual void StopCamera(); /*! \brief updates the camera for image acquisition */ virtual void UpdateCamera(); /*! \brief returns whether the camera is currently active or not */ virtual bool IsCameraActive(); /*! \brief gets the amplitude data from the ToF camera as the strength of the active illumination of every pixel. Caution! The user is responsible for allocating and deleting the images. These values can be used to determine the quality of the distance values. The higher the amplitude value, the higher the accuracy of the according distance value \param imageSequence the actually captured image sequence number \param amplitudeArray contains the returned amplitude data as an array. */ virtual void GetAmplitudes(float* amplitudeArray, int& imageSequence); /*! \brief gets the intensity data from the ToF camera as a greyscale image. Caution! The user is responsible for allocating and deleting the images. \param intensityArray contains the returned intensities data as an array. \param imageSequence the actually captured image sequence number */ virtual void GetIntensities(float* intensityArray, int& imageSequence); /*! \brief gets the distance data from the ToF camera measuring the distance between the camera and the different object points in millimeters. Caution! The user is responsible for allocating and deleting the images. \param distanceArray contains the returned distances data as an array. \param imageSequence the actually captured image sequence number */ virtual void GetDistances(float* distanceArray, int& imageSequence); /*! \brief gets the 3 images (distance, amplitude, intensity) from the ToF camera. Caution! The user is responsible for allocating and deleting the images. \param distanceArray contains the returned distance data as an array. \param amplitudeArray contains the returned amplitude data as an array. \param intensityArray contains the returned intensity data as an array. \param sourceDataArray contains the complete source data from the camera device. \param requiredImageSequence the required image sequence number \param capturedImageSequence the actually captured image sequence number */ virtual void GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray, int requiredImageSequence, int& capturedImageSequence, unsigned char* rgbDataArray=NULL); -// TODO: Buffer size currently set to 1. Once Buffer handling is working correctly, method may be reactivated -// /* // * TODO: Reenable doxygen comment when uncommenting, disabled to fix doxygen warning see bug 12882 -// \brief pure virtual method resetting the buffer using the specified bufferSize. Has to be implemented by sub-classes -// \param bufferSize buffer size the buffer should be reset to -// */ -// virtual void ResetBuffer(int bufferSize) = 0; - //TODO add/correct documentation for requiredImageSequence and capturedImageSequence in the GetAllImages, GetDistances, GetIntensities and GetAmplitudes methods. - /*! \brief returns the corresponding camera controller */ ToFCameraPMDController::Pointer GetController(); virtual void GetChannelSourceData(short* /*sourceData*/, vtkShortArray* /*vtkChannelArray*/ ){}; /*! \brief set a BaseProperty */ virtual void SetProperty( const char *propertyKey, BaseProperty* propertyValue ); protected: ToFCameraPMDRawDataDevice(); ~ToFCameraPMDRawDataDevice(); /*! \brief method for allocating m_SourceDataArray and m_SourceDataBuffer */ virtual void AllocateSourceData(); /*! \brief method for cleaning up memory allocated for m_SourceDataArray and m_SourceDataBuffer */ virtual void CleanUpSourceData(); /*! \brief method for allocating memory for pixel arrays m_IntensityArray, m_DistanceArray and m_AmplitudeArray */ virtual void AllocatePixelArrays(); /*! \brief method for cleanup memory allocated for pixel arrays m_IntensityArray, m_DistanceArray and m_AmplitudeArray */ virtual void CleanupPixelArrays(); /*! \brief Thread method continuously acquiring images from the ToF hardware */ static ITK_THREAD_RETURN_TYPE Acquire(void* pInfoStruct); /*! \brief moves the position pointer m_CurrentPos to the next position in the buffer if that's not the next free position to prevent reading from an empty buffer */ void GetNextPos(); /*! \brief gets the image data and flips it according to user needs Caution! The user is responsible for allocating and deleting the data. \param imageData contains array to the input data. \param flippedData contains flipped output array - Caution! The user is responsible for allocating and deleting the data. Size should be equal to imageData! \param xAxis flag is set to flip around x axis (1 - set, 0 - not set). \param yAxis flag is set to flip around y axis (1 - set, 0 - not set). \param dimension contains the extend of the z dimension (preset is 1) */ void XYAxisFlipImage( float* imageData, float* &flippedData, int xAxis, int yAxis, int dimension = 1 ); //member variables ToFCameraPMDController::Pointer m_Controller; ///< corresponding CameraController ThreadedToFRawDataReconstruction::Pointer m_RawDataSource; char** m_SourceDataBuffer; ///< buffer holding the last acquired images char* m_SourceDataArray; ///< array holding the current PMD source data short* m_ShortSourceData; ///< array holding the current PMD raw data unsigned int m_OriginControllerWidth; ///< holds the original controller width unsigned int m_OriginControllerHeight; ///< holds the original controller height private: int m_ChannelSize; ///< member holds the size of a single raw data channel }; } //END mitk namespace #endif diff --git a/Modules/ToFHardware/mitkToFCameraDevice.h b/Modules/ToFHardware/mitkToFCameraDevice.h index 6c9e0781c9..0212428c09 100644 --- a/Modules/ToFHardware/mitkToFCameraDevice.h +++ b/Modules/ToFHardware/mitkToFCameraDevice.h @@ -1,231 +1,224 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkToFCameraDevice_h #define __mitkToFCameraDevice_h #include "mitkToFHardwareExports.h" #include "mitkCommon.h" #include "mitkStringProperty.h" #include "mitkProperties.h" #include "mitkPropertyList.h" #include "itkObject.h" #include "itkObjectFactory.h" #include "itkMultiThreader.h" #include "itkFastMutexLock.h" // Microservices #include namespace mitk { /** * @brief Virtual interface and base class for all Time-of-Flight devices. * * @ingroup ToFHardware */ class MITK_TOFHARDWARE_EXPORT ToFCameraDevice : public itk::Object { public: mitkClassMacro(ToFCameraDevice, itk::Object); /*! \brief opens a connection to the ToF camera */ virtual bool OnConnectCamera() = 0; virtual bool ConnectCamera(); /*! \brief closes the connection to the camera */ virtual bool DisconnectCamera() = 0; /*! \brief starts the continuous updating of the camera. A separate thread updates the source data, the main thread processes the source data and creates images and coordinates */ virtual void StartCamera() = 0; /*! \brief stops the continuous updating of the camera */ virtual void StopCamera(); /*! \brief returns true if the camera is connected and started */ virtual bool IsCameraActive(); /*! \brief returns true if the camera is connected */ virtual bool IsCameraConnected(); /*! \brief updates the camera for image acquisition */ virtual void UpdateCamera() = 0; /*! \brief gets the amplitude data from the ToF camera as the strength of the active illumination of every pixel These values can be used to determine the quality of the distance values. The higher the amplitude value, the higher the accuracy of the according distance value \param imageSequence the actually captured image sequence number \param amplitudeArray contains the returned amplitude data as an array. */ virtual void GetAmplitudes(float* amplitudeArray, int& imageSequence) = 0; /*! \brief gets the intensity data from the ToF camera as a greyscale image \param intensityArray contains the returned intensities data as an array. \param imageSequence the actually captured image sequence number */ virtual void GetIntensities(float* intensityArray, int& imageSequence) = 0; /*! \brief gets the distance data from the ToF camera measuring the distance between the camera and the different object points in millimeters \param distanceArray contains the returned distances data as an array. \param imageSequence the actually captured image sequence number */ virtual void GetDistances(float* distanceArray, int& imageSequence) = 0; /*! \brief gets the 3 images (distance, amplitude, intensity) from the ToF camera. Caution! The user is responsible for allocating and deleting the images. \param distanceArray contains the returned distance data as an array. \param amplitudeArray contains the returned amplitude data as an array. \param intensityArray contains the returned intensity data as an array. \param sourceDataArray contains the complete source data from the camera device. \param requiredImageSequence the required image sequence number \param capturedImageSequence the actually captured image sequence number */ virtual void GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray, int requiredImageSequence, int& capturedImageSequence, unsigned char* rgbDataArray=NULL) = 0; -// TODO: Buffer size currently set to 1. Once Buffer handling is working correctly, method may be reactivated -// /* // * TODO: Reenable doxygen comment when uncommenting, disabled to fix doxygen warning see bug 12882 -// \brief pure virtual method resetting the buffer using the specified bufferSize. Has to be implemented by sub-classes -// \param bufferSize buffer size the buffer should be reset to -// */ -// virtual void ResetBuffer(int bufferSize) = 0; - //TODO add/correct documentation for requiredImageSequence and capturedImageSequence in the GetAllImages, GetDistances, GetIntensities and GetAmplitudes methods. /*! \brief get the currently set capture width \return capture width */ itkGetMacro(CaptureWidth, int); /*! \brief get the currently set capture height \return capture height */ itkGetMacro(CaptureHeight, int); /*! \brief get the currently set source data size \return source data size */ itkGetMacro(SourceDataSize, int); /*! \brief get the currently set buffer size \return buffer size */ itkGetMacro(BufferSize, int); /*! \brief get the currently set max buffer size \return max buffer size */ itkGetMacro(MaxBufferSize, int); /*! \brief set a bool property in the property list */ void SetBoolProperty( const char* propertyKey, bool boolValue ); /*! \brief set an int property in the property list */ void SetIntProperty( const char* propertyKey, int intValue ); /*! \brief set a float property in the property list */ void SetFloatProperty( const char* propertyKey, float floatValue ); /*! \brief set a string property in the property list */ void SetStringProperty( const char* propertyKey, const char* stringValue ); /*! \brief set a BaseProperty property in the property list */ virtual void SetProperty( const char *propertyKey, BaseProperty* propertyValue ); /*! \brief get a BaseProperty from the property list */ virtual BaseProperty* GetProperty( const char *propertyKey ); /*! \brief get a bool from the property list */ bool GetBoolProperty(const char *propertyKey, bool& boolValue); /*! \brief get a string from the property list */ bool GetStringProperty(const char *propertyKey, std::string& string); /*! \brief get an int from the property list */ bool GetIntProperty(const char *propertyKey, int& integer); virtual int GetRGBCaptureWidth(); virtual int GetRGBCaptureHeight(); protected: ToFCameraDevice(); ~ToFCameraDevice(); /*! \brief method for allocating memory for pixel arrays m_IntensityArray, m_DistanceArray and m_AmplitudeArray */ virtual void AllocatePixelArrays(); /*! \brief method for cleanup memory allocated for pixel arrays m_IntensityArray, m_DistanceArray and m_AmplitudeArray */ virtual void CleanupPixelArrays(); float* m_IntensityArray; ///< float array holding the intensity image float* m_DistanceArray; ///< float array holding the distance image 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_MaxBufferSize; ///< maximal buffer size needed for initialization of data arrays. Default value is 100. int m_CurrentPos; ///< current position in the buffer which will be retrieved by the Get methods int m_FreePos; ///< current position in the buffer which will be filled with data acquired from the hardware int m_CaptureWidth; ///< width of the range image (x dimension) int m_CaptureHeight; ///< height of the range image (y dimension) int m_PixelNumber; ///< number of pixels in the range image (m_CaptureWidth*m_CaptureHeight) int m_RGBImageWidth; int m_RGBImageHeight; int m_RGBPixelNumber; int m_SourceDataSize; ///< size of the PMD source data itk::MultiThreader::Pointer m_MultiThreader; ///< itk::MultiThreader used for thread handling itk::FastMutexLock::Pointer m_ImageMutex; ///< mutex for images provided by the range camera itk::FastMutexLock::Pointer m_CameraActiveMutex; ///< mutex for the cameraActive flag int m_ThreadID; ///< ID of the started thread bool m_CameraActive; ///< flag indicating if the camera is currently active or not. Caution: thread safe access only! bool m_CameraConnected; ///< flag indicating if the camera is successfully connected or not. Caution: thread safe access only! int m_ImageSequence; ///< counter for acquired images PropertyList::Pointer m_PropertyList; ///< a list of the corresponding properties }; } //END mitk namespace // This is the microservice declaration. Do not meddle! US_DECLARE_SERVICE_INTERFACE(mitk::ToFCameraDevice, "org.mitk.services.ToFCameraDevice") #endif diff --git a/Modules/ToFHardware/mitkToFCameraMITKPlayerDevice.cpp b/Modules/ToFHardware/mitkToFCameraMITKPlayerDevice.cpp index 02c02a5002..755d61f424 100644 --- a/Modules/ToFHardware/mitkToFCameraMITKPlayerDevice.cpp +++ b/Modules/ToFHardware/mitkToFCameraMITKPlayerDevice.cpp @@ -1,402 +1,370 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkToFCameraMITKPlayerDevice.h" #include "mitkToFCameraMITKPlayerController.h" #include "mitkRealTimeClock.h" #include "itkMultiThreader.h" #include namespace mitk { ToFCameraMITKPlayerDevice::ToFCameraMITKPlayerDevice() : m_DistanceDataBuffer(NULL), m_AmplitudeDataBuffer(NULL), m_IntensityDataBuffer(NULL), m_RGBDataBuffer(NULL) { m_Controller = ToFCameraMITKPlayerController::New(); } ToFCameraMITKPlayerDevice::~ToFCameraMITKPlayerDevice() { DisconnectCamera(); CleanUpDataBuffers(); } bool ToFCameraMITKPlayerDevice::OnConnectCamera() { bool ok = m_Controller->OpenCameraConnection(); if (ok) { this->m_CaptureWidth = m_Controller->GetCaptureWidth(); this->m_CaptureHeight = m_Controller->GetCaptureHeight(); this->m_RGBImageWidth = m_Controller->GetCaptureWidth(); this->m_RGBImageHeight = m_Controller->GetCaptureHeight(); this->m_PixelNumber = this->m_CaptureWidth * this->m_CaptureHeight; AllocatePixelArrays(); AllocateDataBuffers(); m_CameraConnected = true; } return ok; } bool ToFCameraMITKPlayerDevice::DisconnectCamera() { bool ok = m_Controller->CloseCameraConnection(); if (ok) { m_CameraConnected = false; } return ok; } void ToFCameraMITKPlayerDevice::StartCamera() { if (m_CameraConnected) { // get the first image this->m_Controller->UpdateCamera(); this->m_ImageMutex->Lock(); this->m_Controller->GetDistances(this->m_DistanceDataBuffer[this->m_FreePos]); this->m_Controller->GetAmplitudes(this->m_AmplitudeDataBuffer[this->m_FreePos]); this->m_Controller->GetIntensities(this->m_IntensityDataBuffer[this->m_FreePos]); this->m_Controller->GetRgb(this->m_RGBDataBuffer[this->m_FreePos]); this->m_FreePos = (this->m_FreePos+1) % this->m_BufferSize; this->m_CurrentPos = (this->m_CurrentPos+1) % this->m_BufferSize; this->m_ImageSequence++; this->m_ImageMutex->Unlock(); this->m_CameraActiveMutex->Lock(); this->m_CameraActive = true; this->m_CameraActiveMutex->Unlock(); this->m_ThreadID = this->m_MultiThreader->SpawnThread(this->Acquire, this); // wait a little to make sure that the thread is started itksys::SystemTools::Delay(10); } else { MITK_INFO<<"Camera not connected"; } } void ToFCameraMITKPlayerDevice::UpdateCamera() { m_Controller->UpdateCamera(); } ITK_THREAD_RETURN_TYPE ToFCameraMITKPlayerDevice::Acquire(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; if (pInfo == NULL) { return ITK_THREAD_RETURN_VALUE; } if (pInfo->UserData == NULL) { return ITK_THREAD_RETURN_VALUE; } ToFCameraMITKPlayerDevice* toFCameraDevice = (ToFCameraMITKPlayerDevice*)pInfo->UserData; if (toFCameraDevice!=NULL) { mitk::RealTimeClock::Pointer realTimeClock; realTimeClock = mitk::RealTimeClock::New(); int n = 100; double t1, t2; t1 = realTimeClock->GetCurrentStamp(); bool overflow = false; bool printStatus = false; while (toFCameraDevice->IsCameraActive()) { // update the ToF camera toFCameraDevice->UpdateCamera(); // get image data from controller and write it to the according buffer toFCameraDevice->m_Controller->GetDistances(toFCameraDevice->m_DistanceDataBuffer[toFCameraDevice->m_FreePos]); toFCameraDevice->m_Controller->GetAmplitudes(toFCameraDevice->m_AmplitudeDataBuffer[toFCameraDevice->m_FreePos]); toFCameraDevice->m_Controller->GetIntensities(toFCameraDevice->m_IntensityDataBuffer[toFCameraDevice->m_FreePos]); toFCameraDevice->m_Controller->GetRgb(toFCameraDevice->m_RGBDataBuffer[toFCameraDevice->m_FreePos]); toFCameraDevice->Modified(); - /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - TODO Buffer Handling currently only works for buffer size 1 - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ toFCameraDevice->m_ImageMutex->Lock(); toFCameraDevice->m_FreePos = (toFCameraDevice->m_FreePos+1) % toFCameraDevice->m_BufferSize; toFCameraDevice->m_CurrentPos = (toFCameraDevice->m_CurrentPos+1) % toFCameraDevice->m_BufferSize; toFCameraDevice->m_ImageSequence++; if (toFCameraDevice->m_FreePos == toFCameraDevice->m_CurrentPos) { - // buffer overflow - //MITK_INFO << "Buffer overflow!! "; - //toFCameraDevice->m_CurrentPos = (toFCameraDevice->m_CurrentPos+1) % toFCameraDevice->m_BufferSize; - //toFCameraDevice->m_ImageSequence++; overflow = true; } if (toFCameraDevice->m_ImageSequence % n == 0) { printStatus = true; } toFCameraDevice->m_ImageMutex->Unlock(); if (overflow) { - //itksys::SystemTools::Delay(10); overflow = false; } - /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - END TODO Buffer Handling currently only works for buffer size 1 - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ - // print current framerate if (printStatus) { t2 = realTimeClock->GetCurrentStamp() - t1; MITK_INFO << " Framerate (fps): " << n / (t2/1000) << " Sequence: " << toFCameraDevice->m_ImageSequence; t1 = realTimeClock->GetCurrentStamp(); printStatus = false; } } // end of while loop } return ITK_THREAD_RETURN_VALUE; } -// TODO: Buffer size currently set to 1. Once Buffer handling is working correctly, method may be reactivated -// void ToFCameraMITKPlayerDevice::ResetBuffer(int bufferSize) -// { -// this->m_BufferSize = bufferSize; -// this->m_CurrentPos = -1; -// this->m_FreePos = 0; -// } - void ToFCameraMITKPlayerDevice::GetAmplitudes(float* amplitudeArray, int& imageSequence) { m_ImageMutex->Lock(); - /*!!!!!!!!!!!!!!!!!!!!!! - TODO Buffer handling??? - !!!!!!!!!!!!!!!!!!!!!!!!*/ // write amplitude image data to float array for (int i=0; im_PixelNumber; i++) { amplitudeArray[i] = this->m_AmplitudeDataBuffer[this->m_CurrentPos][i]; } imageSequence = this->m_ImageSequence; m_ImageMutex->Unlock(); } void ToFCameraMITKPlayerDevice::GetIntensities(float* intensityArray, int& imageSequence) { m_ImageMutex->Lock(); - /*!!!!!!!!!!!!!!!!!!!!!! - TODO Buffer handling??? - !!!!!!!!!!!!!!!!!!!!!!!!*/ // write intensity image data to float array for (int i=0; im_PixelNumber; i++) { intensityArray[i] = this->m_IntensityDataBuffer[this->m_CurrentPos][i]; } imageSequence = this->m_ImageSequence; m_ImageMutex->Unlock(); } void ToFCameraMITKPlayerDevice::GetDistances(float* distanceArray, int& imageSequence) { m_ImageMutex->Lock(); - /*!!!!!!!!!!!!!!!!!!!!!! - TODO Buffer handling??? - !!!!!!!!!!!!!!!!!!!!!!!!*/ // write distance image data to float array for (int i=0; im_PixelNumber; i++) { distanceArray[i] = this->m_DistanceDataBuffer[this->m_CurrentPos][i]; } imageSequence = this->m_ImageSequence; m_ImageMutex->Unlock(); } void ToFCameraMITKPlayerDevice::GetRgb(unsigned char* rgbArray, int& imageSequence) { m_ImageMutex->Lock(); - /*!!!!!!!!!!!!!!!!!!!!!! - TODO Buffer handling??? - !!!!!!!!!!!!!!!!!!!!!!!!*/ // write intensity image data to unsigned char array for (int i=0; im_PixelNumber*3; i++) { rgbArray[i] = this->m_RGBDataBuffer[this->m_CurrentPos][i]; } imageSequence = this->m_ImageSequence; m_ImageMutex->Unlock(); } void ToFCameraMITKPlayerDevice::GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* /*sourceDataArray*/, int requiredImageSequence, int& capturedImageSequence, unsigned char* rgbDataArray) { /*!!!!!!!!!!!!!!!!!!!!!! TODO Document this method! !!!!!!!!!!!!!!!!!!!!!!!!*/ m_ImageMutex->Lock(); //check for empty buffer if (this->m_ImageSequence < 0) { // buffer empty MITK_INFO << "Buffer empty!! "; capturedImageSequence = this->m_ImageSequence; m_ImageMutex->Unlock(); return; } // determine position of image in buffer int pos = 0; if ((requiredImageSequence < 0) || (requiredImageSequence > this->m_ImageSequence)) { capturedImageSequence = this->m_ImageSequence; pos = this->m_CurrentPos; } else if (requiredImageSequence <= this->m_ImageSequence - this->m_BufferSize) { capturedImageSequence = (this->m_ImageSequence - this->m_BufferSize) + 1; pos = (this->m_CurrentPos + 1) % this->m_BufferSize; } else // (requiredImageSequence > this->m_ImageSequence - this->m_BufferSize) && (requiredImageSequence <= this->m_ImageSequence) { capturedImageSequence = requiredImageSequence; pos = (this->m_CurrentPos + (10-(this->m_ImageSequence - requiredImageSequence))) % this->m_BufferSize; } if(this->m_DistanceDataBuffer&&this->m_AmplitudeDataBuffer&&this->m_IntensityDataBuffer&&this->m_RGBDataBuffer) { // write image data to float arrays for (int i=0; im_PixelNumber; i++) { distanceArray[i] = this->m_DistanceDataBuffer[pos][i]; amplitudeArray[i] = this->m_AmplitudeDataBuffer[pos][i]; intensityArray[i] = this->m_IntensityDataBuffer[pos][i]; if (rgbDataArray) { rgbDataArray[i] = this->m_RGBDataBuffer[pos][i]; } } if (rgbDataArray) { for (int j=this->m_PixelNumber; jm_PixelNumber*3; j++) { rgbDataArray[j] = this->m_RGBDataBuffer[pos][j]; } } } m_ImageMutex->Unlock(); } void ToFCameraMITKPlayerDevice::SetInputFileName(std::string inputFileName) { this->m_InputFileName = inputFileName; this->m_Controller->SetInputFileName(inputFileName); } void ToFCameraMITKPlayerDevice::SetProperty( const char *propertyKey, BaseProperty* propertyValue ) { this->m_PropertyList->SetProperty(propertyKey, propertyValue); ToFCameraMITKPlayerController::Pointer myController = dynamic_cast(this->m_Controller.GetPointer()); std::string strValue; GetStringProperty(propertyKey, strValue); if (strcmp(propertyKey, "DistanceImageFileName") == 0) { myController->SetDistanceImageFileName(strValue); } else if (strcmp(propertyKey, "AmplitudeImageFileName") == 0) { this->m_PropertyList->SetBoolProperty("HasAmplitudeImage", true); myController->SetAmplitudeImageFileName(strValue); } else if (strcmp(propertyKey, "IntensityImageFileName") == 0) { this->m_PropertyList->SetBoolProperty("HasIntensityImage", true); myController->SetIntensityImageFileName(strValue); } else if (strcmp(propertyKey, "RGBImageFileName") == 0) { this->m_PropertyList->SetBoolProperty("HasRGBImage", true); myController->SetRGBImageFileName(strValue); } } void ToFCameraMITKPlayerDevice::CleanUpDataBuffers() { if (m_DistanceDataBuffer) { for(int i=0; im_MaxBufferSize; i++) { delete[] this->m_DistanceDataBuffer[i]; } delete[] this->m_DistanceDataBuffer; } if (m_AmplitudeDataBuffer) { for(int i=0; im_MaxBufferSize; i++) { delete[] this->m_AmplitudeDataBuffer[i]; } delete[] this->m_AmplitudeDataBuffer; } if (m_IntensityDataBuffer) { for(int i=0; im_MaxBufferSize; i++) { delete[] this->m_IntensityDataBuffer[i]; } delete[] this->m_IntensityDataBuffer; } if (m_RGBDataBuffer) { for(int i=0; im_MaxBufferSize; i++) { delete[] this->m_RGBDataBuffer[i]; } delete[] this->m_RGBDataBuffer; } } void ToFCameraMITKPlayerDevice::AllocateDataBuffers() { // free memory if it was already allocated this->CleanUpDataBuffers(); // allocate buffers this->m_DistanceDataBuffer = new float*[this->m_MaxBufferSize]; for(int i=0; im_MaxBufferSize; i++) { this->m_DistanceDataBuffer[i] = new float[this->m_PixelNumber]; } this->m_AmplitudeDataBuffer = new float*[this->m_MaxBufferSize]; for(int i=0; im_MaxBufferSize; i++) { this->m_AmplitudeDataBuffer[i] = new float[this->m_PixelNumber]; } this->m_IntensityDataBuffer = new float*[this->m_MaxBufferSize]; for(int i=0; im_MaxBufferSize; i++) { this->m_IntensityDataBuffer[i] = new float[this->m_PixelNumber]; } this->m_RGBDataBuffer = new unsigned char*[this->m_MaxBufferSize]; for(int i=0; im_MaxBufferSize; i++) { this->m_RGBDataBuffer[i] = new unsigned char[this->m_PixelNumber*3]; } } } diff --git a/Modules/ToFHardware/mitkToFCameraMITKPlayerDevice.h b/Modules/ToFHardware/mitkToFCameraMITKPlayerDevice.h index 2f6b0c2a5d..fcadd75390 100644 --- a/Modules/ToFHardware/mitkToFCameraMITKPlayerDevice.h +++ b/Modules/ToFHardware/mitkToFCameraMITKPlayerDevice.h @@ -1,146 +1,139 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkToFCameraMITKPlayerDevice_h #define __mitkToFCameraMITKPlayerDevice_h #include "mitkToFHardwareExports.h" #include "mitkCommon.h" #include "mitkToFCameraDevice.h" #include "mitkToFCameraMITKPlayerController.h" #include "itkObject.h" #include "itkObjectFactory.h" #include "itkMultiThreader.h" #include "itkFastMutexLock.h" namespace mitk { /** * @brief Device class representing a player for MITK-ToF images. * * @ingroup ToFHardware */ class MITK_TOFHARDWARE_EXPORT ToFCameraMITKPlayerDevice : public ToFCameraDevice { public: mitkClassMacro( ToFCameraMITKPlayerDevice , ToFCameraDevice ); itkNewMacro( Self ); /*! \brief opens a connection to the ToF camera */ virtual bool OnConnectCamera(); /*! \brief closes the connection to the camera */ virtual bool DisconnectCamera(); /*! \brief starts the continuous updating of the camera. A separate thread updates the source data, the main thread processes the source data and creates images and coordinates */ virtual void StartCamera(); /*! \brief gets the amplitude data from the ToF camera as the strength of the active illumination of every pixel. Caution! The user is responsible for allocating and deleting the images. These values can be used to determine the quality of the distance values. The higher the amplitude value, the higher the accuracy of the according distance value \param imageSequence the actually captured image sequence number \param amplitudeArray contains the returned amplitude data as an array. */ virtual void GetAmplitudes(float* amplitudeArray, int& imageSequence); /*! \brief gets the intensity data from the ToF camera as a greyscale image. Caution! The user is responsible for allocating and deleting the images. \param intensityArray contains the returned intensities data as an array. \param imageSequence the actually captured image sequence number */ virtual void GetIntensities(float* intensityArray, int& imageSequence); /*! \brief gets the rgb data from the ToF camera. Caution! The user is responsible for allocating and deleting the images. \param rgbArray contains the returned rgb data as an array. \param imageSequence the actually captured image sequence number */ virtual void GetRgb(unsigned char* rgbArray, int& imageSequence); /*! \brief gets the distance data from the ToF camera measuring the distance between the camera and the different object points in millimeters. Caution! The user is responsible for allocating and deleting the images. \param distanceArray contains the returned distances data as an array. \param imageSequence the actually captured image sequence number */ virtual void GetDistances(float* distanceArray, int& imageSequence); /*! \brief gets the 3 images (distance, amplitude, intensity) from the ToF camera. Caution! The user is responsible for allocating and deleting the images. \param distanceArray contains the returned distance data as an array. \param amplitudeArray contains the returned amplitude data as an array. \param intensityArray contains the returned intensity data as an array. \param sourceDataArray contains the complete source data from the camera device. \param requiredImageSequence the required image sequence number \param capturedImageSequence the actually captured image sequence number */ virtual void GetAllImages(float* distanceArray, float* amplitudeArray, float* intensityArray, char* sourceDataArray, int requiredImageSequence, int& capturedImageSequence, unsigned char* rgbDataArray=NULL); -// TODO: Buffer size currently set to 1. Once Buffer handling is working correctly, method may be reactivated -// /* // * TODO: Reenable doxygen comment when uncommenting, disabled to fix doxygen warning see bug 12882 -// \brief pure virtual method resetting the buffer using the specified bufferSize. Has to be implemented by sub-classes -// \param bufferSize buffer size the buffer should be reset to -// */ -// virtual void ResetBuffer(int bufferSize) = 0; - //TODO add/correct documentation for requiredImageSequence and capturedImageSequence in the GetAllImages, GetDistances, GetIntensities and GetAmplitudes methods. /*! \brief Set file name where the data is recorded \param inputFileName name of input file which should be played */ virtual void SetInputFileName(std::string inputFileName); /*! \brief set a BaseProperty */ virtual void SetProperty( const char *propertyKey, BaseProperty* propertyValue ); protected: ToFCameraMITKPlayerDevice(); ~ToFCameraMITKPlayerDevice(); /*! \brief updates the camera for image acquisition */ virtual void UpdateCamera(); /*! \brief Thread method continuously acquiring images from the specified input file */ static ITK_THREAD_RETURN_TYPE Acquire(void* pInfoStruct); /*! \brief Clean up memory (pixel buffers) */ void CleanUpDataBuffers(); /*! \brief Allocate pixel buffers */ void AllocateDataBuffers(); ToFCameraMITKPlayerController::Pointer m_Controller; ///< member holding the corresponding controller std::string m_InputFileName; ///< member holding the file name of the current input file private: float** m_DistanceDataBuffer; ///< buffer holding the last distance images float** m_AmplitudeDataBuffer; ///< buffer holding the last amplitude images float** m_IntensityDataBuffer; ///< buffer holding the last intensity images unsigned char** m_RGBDataBuffer; ///< buffer holding the last rgb images }; } //END mitk namespace #endif diff --git a/Modules/ToFHardware/mitkToFHardwareActivator.cpp b/Modules/ToFHardware/mitkToFHardwareActivator.cpp index 2bccd0ed35..2685dca6b0 100644 --- a/Modules/ToFHardware/mitkToFHardwareActivator.cpp +++ b/Modules/ToFHardware/mitkToFHardwareActivator.cpp @@ -1,75 +1,74 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkToFHardwareModuleActivator_h #define __mitkToFHardwareModuleActivator_h // Microservices #include #include #include #include "mitkIToFDeviceFactory.h" #include "mitkToFConfig.h" #include "mitkToFCameraMITKPlayerDeviceFactory.h" /* * This is the module activator for the "ToFHardware" module. It registers services * like the IToFDeviceFactory. */ namespace mitk { class ToFHardwareActivator : public us::ModuleActivator { public: void Load(us::ModuleContext* context) { //Registering MITKPlayerDevice as MicroService ToFCameraMITKPlayerDeviceFactory* toFCameraMITKPlayerDeviceFactory = new ToFCameraMITKPlayerDeviceFactory(); us::ServiceProperties mitkPlayerFactoryProps; mitkPlayerFactoryProps["ToFFactoryName"] = toFCameraMITKPlayerDeviceFactory->GetFactoryName(); context->RegisterService(toFCameraMITKPlayerDeviceFactory, mitkPlayerFactoryProps); //Create an instance of the player toFCameraMITKPlayerDeviceFactory->ConnectToFDevice(); m_Factories.push_back( toFCameraMITKPlayerDeviceFactory ); } void Unload(us::ModuleContext* ) { } ~ToFHardwareActivator() { - //todo iterieren über liste m_Factories und löschen if(m_Factories.size() > 0) { for(std::list< IToFDeviceFactory* >::iterator it = m_Factories.begin(); it != m_Factories.end(); ++it) { - delete (*it); //todo wie genau löschen? + delete (*it); } } } private: std::list< IToFDeviceFactory* > m_Factories; }; } US_EXPORT_MODULE_ACTIVATOR(mitkToFHardware, mitk::ToFHardwareActivator) #endif diff --git a/Modules/ToFHardware/mitkToFOpenCVImageGrabber.cpp b/Modules/ToFHardware/mitkToFOpenCVImageGrabber.cpp index 4cb78d27cf..708576b19f 100644 --- a/Modules/ToFHardware/mitkToFOpenCVImageGrabber.cpp +++ b/Modules/ToFHardware/mitkToFOpenCVImageGrabber.cpp @@ -1,188 +1,187 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkToFOpenCVImageGrabber.h" // mitk includes #include "mitkImageDataItem.h" #include #include "mitkImageReadAccessor.h" #include "vtkSmartPointer.h" #include "vtkColorTransferFunction.h" #include "vtkFloatArray.h" namespace mitk { ToFOpenCVImageGrabber::ToFOpenCVImageGrabber() { m_CurrentOpenCVIntensityImage = NULL; m_CurrentOpenCVAmplitudeImage = NULL; m_CurrentOpenCVDistanceImage = NULL; m_ImageType = 0; m_ImageDepth = IPL_DEPTH_32F; m_ImageGrabber = NULL; } ToFOpenCVImageGrabber::~ToFOpenCVImageGrabber() { } cv::Mat ToFOpenCVImageGrabber::GetImage() { m_ImageGrabber->Update(); unsigned int numOfPixel = m_ImageGrabber->GetCaptureWidth()*m_ImageGrabber->GetCaptureHeight(); // copy current mitk images unsigned int dimensions[4]; dimensions[0] = this->m_ImageGrabber->GetCaptureWidth(); dimensions[1] = this->m_ImageGrabber->GetCaptureHeight(); dimensions[2] = 1; dimensions[3] = 1; // create single component float pixel type mitk::PixelType FloatType = MakeScalarPixelType(); ImageReadAccessor imgGrabAcc0(m_ImageGrabber->GetOutput(0), m_ImageGrabber->GetOutput(0)->GetSliceData()); ImageReadAccessor imgGrabAcc1(m_ImageGrabber->GetOutput(1), m_ImageGrabber->GetOutput(1)->GetSliceData()); ImageReadAccessor imgGrabAcc2(m_ImageGrabber->GetOutput(2), m_ImageGrabber->GetOutput(2)->GetSliceData()); mitk::Image::Pointer currentMITKIntensityImage = mitk::Image::New(); currentMITKIntensityImage->Initialize(FloatType, 2, dimensions); currentMITKIntensityImage->SetSlice((float*) imgGrabAcc2.GetData(),0,0,0); mitk::Image::Pointer currentMITKAmplitudeImage = mitk::Image::New(); currentMITKAmplitudeImage->Initialize(FloatType, 2, dimensions); currentMITKAmplitudeImage->SetSlice((float*)imgGrabAcc1.GetData(),0,0,0); mitk::Image::Pointer currentMITKDistanceImage = mitk::Image::New(); currentMITKDistanceImage->Initialize(FloatType, 2, dimensions); currentMITKDistanceImage->SetSlice((float*)imgGrabAcc0.GetData(),0,0,0); // copy mitk images to OpenCV images if (m_ImageDepth==IPL_DEPTH_32F) { if (m_ImageType==1) { ImageReadAccessor currentAmplAcc(currentMITKAmplitudeImage, currentMITKAmplitudeImage->GetSliceData(0, 0, 0)); float* amplitudeFloatData = (float*) currentAmplAcc.GetData(); memcpy(m_CurrentOpenCVAmplitudeImage->imageData,(unsigned char*)amplitudeFloatData,numOfPixel*sizeof(float)); cv::Mat image(m_CurrentOpenCVAmplitudeImage); return image; } else if (m_ImageType==2) { ImageReadAccessor currentIntenAcc(currentMITKIntensityImage, currentMITKIntensityImage->GetSliceData(0, 0, 0)); float* intensityFloatData = (float*) currentIntenAcc.GetData(); memcpy(m_CurrentOpenCVIntensityImage->imageData,(unsigned char*)intensityFloatData,numOfPixel*sizeof(float)); cv::Mat image(m_CurrentOpenCVIntensityImage); return image; } else { ImageReadAccessor currentDistAcc(currentMITKDistanceImage, currentMITKDistanceImage->GetSliceData(0, 0, 0)); float* distanceFloatData = (float*) currentDistAcc.GetData(); memcpy(m_CurrentOpenCVDistanceImage->imageData,(unsigned char*)distanceFloatData,numOfPixel*sizeof(float)); cv::Mat image(m_CurrentOpenCVDistanceImage); return image; } } else { if (m_ImageType==1) { this->MapScalars(currentMITKAmplitudeImage, m_CurrentOpenCVAmplitudeImage); cv::Mat image(m_CurrentOpenCVAmplitudeImage); return image; } else if (m_ImageType==2) { this->MapScalars(currentMITKIntensityImage, m_CurrentOpenCVIntensityImage); cv::Mat image(m_CurrentOpenCVIntensityImage); return image; } else { this->MapScalars(currentMITKDistanceImage, m_CurrentOpenCVDistanceImage); cv::Mat image(m_CurrentOpenCVDistanceImage); return image; } } } void ToFOpenCVImageGrabber::SetImageType(unsigned int imageType) { m_ImageType = imageType; } void ToFOpenCVImageGrabber::SetImageDepth(unsigned int imageDepth) { m_ImageDepth = imageDepth; } void ToFOpenCVImageGrabber::SetToFImageGrabber(ToFImageGrabber::Pointer imageGrabber) { m_ImageGrabber = imageGrabber; //initialize OpenCV images m_CurrentOpenCVIntensityImage = cvCreateImage(cvSize(m_ImageGrabber->GetCaptureWidth(), m_ImageGrabber->GetCaptureHeight()), m_ImageDepth, 1); m_CurrentOpenCVAmplitudeImage = cvCreateImage(cvSize(m_ImageGrabber->GetCaptureWidth(), m_ImageGrabber->GetCaptureHeight()), m_ImageDepth, 1); m_CurrentOpenCVDistanceImage = cvCreateImage(cvSize(m_ImageGrabber->GetCaptureWidth(), m_ImageGrabber->GetCaptureHeight()), m_ImageDepth, 1); } ToFImageGrabber::Pointer ToFOpenCVImageGrabber::GetToFImageGrabber() { return m_ImageGrabber; } void ToFOpenCVImageGrabber::StartCapturing() { if (m_ImageGrabber.IsNotNull()) { m_ImageGrabber->ConnectCamera(); m_ImageGrabber->StartCamera(); } } void ToFOpenCVImageGrabber::StopCapturing() { if (m_ImageGrabber.IsNotNull()) { m_ImageGrabber->StopCamera(); m_ImageGrabber->DisconnectCamera(); } } void ToFOpenCVImageGrabber::MapScalars( mitk::Image::Pointer mitkImage, IplImage* openCVImage) { unsigned int numOfPixel = m_ImageGrabber->GetCaptureWidth()*m_ImageGrabber->GetCaptureHeight(); ImageReadAccessor imgAcc(mitkImage, mitkImage->GetSliceData(0, 0, 0)); float* floatData = (float*)imgAcc.GetData(); vtkSmartPointer colorTransferFunction = vtkSmartPointer::New(); vtkSmartPointer floatArrayInt = vtkSmartPointer::New(); floatArrayInt->Initialize(); floatArrayInt->SetArray(floatData, numOfPixel, 0); mitk::ScalarType min = mitkImage->GetStatistics()->GetScalarValueMin(); mitk::ScalarType max = mitkImage->GetStatistics()->GetScalarValueMaxNoRecompute(); MITK_INFO<<"Minimum: "<RemoveAllPoints(); colorTransferFunction->AddRGBPoint(min, 0, 0, 0); colorTransferFunction->AddRGBPoint(max, 1, 1, 1); colorTransferFunction->SetColorSpaceToHSV(); - //TODO other depth values colorTransferFunction->MapScalarsThroughTable(floatArrayInt, (unsigned char*)openCVImage->imageData, VTK_LUMINANCE); } -} // end namespace mitk \ No newline at end of file +} // end namespace mitk