diff --git a/Modules/ToFProcessing/mitkToFCompositeFilter.cpp b/Modules/ToFProcessing/mitkToFCompositeFilter.cpp index 16080085a9..2eceead661 100644 --- a/Modules/ToFProcessing/mitkToFCompositeFilter.cpp +++ b/Modules/ToFProcessing/mitkToFCompositeFilter.cpp @@ -1,401 +1,419 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Module: $RCSfile$ Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include #include //#include #include mitk::ToFCompositeFilter::ToFCompositeFilter() : m_ImageWidth(0), m_ImageHeight(0), m_ImageSize(0), -m_IplDistanceImage(NULL), m_IplOutputImage(NULL), m_ItkInputImage(NULL), m_ApplyTemporalMedianFilter(false), +m_IplDistanceImage(NULL), m_IplOutputImage(NULL), m_ItkInputImage(NULL), m_ApplyTemporalMedianFilter(false), m_ApplyAverageFilter(false), m_ApplyMedianFilter(false), m_ApplyThresholdFilter(false), m_ApplyBilateralFilter(false), m_DataBuffer(NULL), m_DataBufferCurrentIndex(0), m_DataBufferMaxSize(0), m_TemporalMedianFilterNumOfFrames(10), m_ThresholdFilterMin(1), m_ThresholdFilterMax(7000), m_BilateralFilterDomainSigma(2), m_BilateralFilterRangeSigma(60), m_BilateralFilterKernelRadius(0) { } mitk::ToFCompositeFilter::~ToFCompositeFilter() { cvReleaseImage(&(this->m_IplDistanceImage)); cvReleaseImage(&(this->m_IplOutputImage)); if (m_DataBuffer!=NULL) { delete [] m_DataBuffer; } } void mitk::ToFCompositeFilter::SetInput( mitk::Image* distanceImage ) { this->SetInput(0, distanceImage); } void mitk::ToFCompositeFilter::SetInput( unsigned int idx, mitk::Image* distanceImage ) { if ((distanceImage == NULL) && (idx == this->GetNumberOfInputs() - 1)) // if the last input is set to NULL, reduce the number of inputs by one { this->SetNumberOfInputs(this->GetNumberOfInputs() - 1); } else { if (idx==0) //create IPL image holding distance data { if (distanceImage->GetData()) { this->m_ImageWidth = distanceImage->GetDimension(0); this->m_ImageHeight = distanceImage->GetDimension(1); this->m_ImageSize = this->m_ImageWidth * this->m_ImageHeight * sizeof(float); if (this->m_IplDistanceImage != NULL) { cvReleaseImage(&(this->m_IplDistanceImage)); } float* distanceFloatData = (float*)distanceImage->GetSliceData(0, 0, 0)->GetData(); this->m_IplDistanceImage = cvCreateImage(cvSize(this->m_ImageWidth, this->m_ImageHeight), IPL_DEPTH_32F, 1); memcpy(this->m_IplDistanceImage->imageData, (void*)distanceFloatData, this->m_ImageSize); if (this->m_IplOutputImage != NULL) { cvReleaseImage(&(this->m_IplOutputImage)); } this->m_IplOutputImage = cvCreateImage(cvSize(this->m_ImageWidth, this->m_ImageHeight), IPL_DEPTH_32F, 1); CreateItkImage(this->m_ItkInputImage); } } this->ProcessObject::SetNthInput(idx, distanceImage); // Process object is not const-correct so the const_cast is required here } this->CreateOutputsForAllInputs(); } mitk::Image* mitk::ToFCompositeFilter::GetInput() { return this->GetInput(0); } mitk::Image* mitk::ToFCompositeFilter::GetInput( unsigned int idx ) { if (this->GetNumberOfInputs() < 1) return NULL; //TODO: geeignete exception werfen return static_cast< mitk::Image*>(this->ProcessObject::GetInput(idx)); } void mitk::ToFCompositeFilter::GenerateData() { // copy input 1...n to output 1...n for (unsigned int idx=0; idxGetNumberOfOutputs(); idx++) { mitk::Image::Pointer outputImage = this->GetOutput(idx); mitk::Image::Pointer inputImage = this->GetInput(idx); if (outputImage.IsNotNull()&&inputImage.IsNotNull()) { outputImage->CopyInformation(inputImage); outputImage->Initialize(inputImage); outputImage->SetSlice(inputImage->GetSliceData()->GetData()); } } mitk::Image::Pointer outputDistanceImage = this->GetOutput(0); float* outputDistanceFloatData = (float*)outputDistanceImage->GetSliceData(0, 0, 0)->GetData(); mitk::Image::Pointer inputDistanceImage = this->GetInput(); // copy initial distance image to ipl image float* distanceFloatData = (float*)inputDistanceImage->GetSliceData(0, 0, 0)->GetData(); memcpy(this->m_IplDistanceImage->imageData, (void*)distanceFloatData, this->m_ImageSize); if (m_ApplyThresholdFilter) { ProcessThresholdFilter(this->m_IplDistanceImage, this->m_ThresholdFilterMin, this->m_ThresholdFilterMax); } - if (this->m_ApplyTemporalMedianFilter) + if (this->m_ApplyTemporalMedianFilter||this->m_ApplyAverageFilter) { ProcessStreamedQuickSelectMedianImageFilter(this->m_IplDistanceImage, this->m_TemporalMedianFilterNumOfFrames); } if (this->m_ApplyMedianFilter) { ProcessCVMedianFilter(this->m_IplDistanceImage, this->m_IplOutputImage); memcpy( this->m_IplDistanceImage->imageData, this->m_IplOutputImage->imageData, this->m_ImageSize ); } if (this->m_ApplyBilateralFilter) { float* itkFloatData = this->m_ItkInputImage->GetBufferPointer(); memcpy(itkFloatData, this->m_IplDistanceImage->imageData, this->m_ImageSize ); ItkImageType2D::Pointer itkOutputImage = ProcessItkBilateralFilter(this->m_ItkInputImage, this->m_BilateralFilterDomainSigma, this->m_BilateralFilterRangeSigma, this->m_BilateralFilterKernelRadius); memcpy( this->m_IplDistanceImage->imageData, itkOutputImage->GetBufferPointer(), this->m_ImageSize ); //ProcessCVBilateralFilter(this->m_IplDistanceImage, this->m_OutputIplImage, domainSigma, rangeSigma, kernelRadius); //memcpy( distanceFloatData, this->m_OutputIplImage->imageData, distanceImageSize ); } memcpy( outputDistanceFloatData, this->m_IplDistanceImage->imageData, this->m_ImageSize ); } void mitk::ToFCompositeFilter::CreateOutputsForAllInputs() { this->SetNumberOfOutputs(this->GetNumberOfInputs()); // create outputs for all inputs for (unsigned int idx = 0; idx < this->GetNumberOfOutputs(); ++idx) if (this->GetOutput(idx) == NULL) { DataObjectPointer newOutput = this->MakeOutput(idx); this->SetNthOutput(idx, newOutput); } this->Modified(); } void mitk::ToFCompositeFilter::GenerateOutputInformation() { mitk::Image::ConstPointer input = this->GetInput(); mitk::Image::Pointer output = this->GetOutput(); if (output->IsInitialized()) return; itkDebugMacro(<<"GenerateOutputInformation()"); output->Initialize(input->GetPixelType(), *input->GetTimeSlicedGeometry()); output->SetPropertyList(input->GetPropertyList()->Clone()); } void mitk::ToFCompositeFilter::ProcessThresholdFilter(IplImage* inputIplImage, int min, int max) { for(int i=0; im_ImageWidth*this->m_ImageHeight; i++) { float *f = (float*)inputIplImage->imageData; if (f[i]<=min) { f[i] = 0.0; } else if (f[i]>=max) { f[i] = 0.0; } } } ItkImageType2D::Pointer mitk::ToFCompositeFilter::ProcessItkBilateralFilter(ItkImageType2D::Pointer inputItkImage, int domainSigma, int rangeSigma, int kernelRadius) { ItkImageType2D::Pointer outputItkImage; BilateralFilterType::Pointer bilateralFilter = BilateralFilterType::New(); bilateralFilter->SetInput(inputItkImage); bilateralFilter->SetDomainSigma(domainSigma); bilateralFilter->SetRangeSigma(rangeSigma); //bilateralFilter->SetRadius(kernelRadius); outputItkImage = bilateralFilter->GetOutput(); outputItkImage->Update(); return outputItkImage; } void mitk::ToFCompositeFilter::ProcessCVBilateralFilter(IplImage* inputIplImage, IplImage* outputIplImage, int domainSigma, int rangeSigma, int kernelRadius) { int diameter = kernelRadius; double sigmaColor = rangeSigma; double sigmaSpace = domainSigma; cvSmooth(inputIplImage, outputIplImage, CV_BILATERAL, diameter, 0, sigmaColor, sigmaSpace); } void mitk::ToFCompositeFilter::ProcessCVMedianFilter(IplImage* inputIplImage, IplImage* outputIplImage, int radius) { cvSmooth(inputIplImage, outputIplImage, CV_MEDIAN, radius, 0, 0, 0); } void mitk::ToFCompositeFilter::ProcessStreamedQuickSelectMedianImageFilter(IplImage* inputIplImage, int numOfImages) { float* data = (float*)inputIplImage->imageData; int imageSize = inputIplImage->width * inputIplImage->height; float* tmpArray; if (numOfImages == 0) { return; } if (numOfImages != this->m_DataBufferMaxSize) // reset { //delete current buffer for( int i=0; im_DataBufferMaxSize; i++ ) { delete[] this->m_DataBuffer[i]; } if (this->m_DataBuffer != NULL) { delete[] this->m_DataBuffer; } this->m_DataBufferMaxSize = numOfImages; // create new buffer with current size this->m_DataBuffer = new float*[this->m_DataBufferMaxSize]; for(int i=0; im_DataBufferMaxSize; i++) { this->m_DataBuffer[i] = NULL; } this->m_DataBufferCurrentIndex = 0; } int currentBufferSize = this->m_DataBufferMaxSize; tmpArray = new float[this->m_DataBufferMaxSize]; // copy data to buffer if (this->m_DataBuffer[this->m_DataBufferCurrentIndex] == NULL) { this->m_DataBuffer[this->m_DataBufferCurrentIndex] = new float[imageSize]; currentBufferSize = this->m_DataBufferCurrentIndex + 1; } for(int j=0; jm_DataBuffer[this->m_DataBufferCurrentIndex][j] = data[j]; } + float tmpValue = 0.0f; for(int i=0; im_DataBuffer[j][i]; + tmpValue = 0.0f; + for(int j=0; jm_DataBuffer[j][i]; + } + data[i] = tmpValue/numOfImages; + } + else if (m_ApplyTemporalMedianFilter) + { + for(int j=0; jm_DataBuffer[j][i]; + } + data[i] = quick_select(tmpArray, currentBufferSize); } - data[i] = quick_select(tmpArray, currentBufferSize); } this->m_DataBufferCurrentIndex = (this->m_DataBufferCurrentIndex + 1) % this->m_DataBufferMaxSize; delete[] tmpArray; } #define ELEM_SWAP(a,b) { register float t=(a);(a)=(b);(b)=t; } float mitk::ToFCompositeFilter::quick_select(float arr[], int n) { int low = 0; int high = n-1; int median = (low + high)/2; int middle = 0; int ll = 0; int hh = 0; for (;;) { if (high <= low) /* One element only */ return arr[median] ; if (high == low + 1) { /* Two elements only */ if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]) ; return arr[median] ; } /* Find median of low, middle and high items; swap into position low */ middle = (low + high) / 2; if (arr[middle] > arr[high]) ELEM_SWAP(arr[middle], arr[high]) ; if (arr[low] > arr[high]) ELEM_SWAP(arr[low], arr[high]) ; if (arr[middle] > arr[low]) ELEM_SWAP(arr[middle], arr[low]) ; /* Swap low item (now in position middle) into position (low+1) */ ELEM_SWAP(arr[middle], arr[low+1]) ; /* Nibble from each end towards middle, swapping items when stuck */ ll = low + 1; hh = high; for (;;) { do ll++; while (arr[low] > arr[ll]) ; do hh--; while (arr[hh] > arr[low]) ; if (hh < ll) break; ELEM_SWAP(arr[ll], arr[hh]) ; } /* Swap middle item (in position low) back into correct position */ ELEM_SWAP(arr[low], arr[hh]) ; /* Re-set active partition */ if (hh <= median) low = ll; if (hh >= median) high = hh - 1; } } #undef ELEM_SWAP bool mitk::ToFCompositeFilter::GetApplyTemporalMedianFilter() { return this->m_ApplyTemporalMedianFilter; } bool mitk::ToFCompositeFilter::GetApplyMedianFilter() { return this->m_ApplyMedianFilter; } bool mitk::ToFCompositeFilter::GetApplyThresholdFilter() { return this->m_ApplyThresholdFilter; } bool mitk::ToFCompositeFilter::GetApplyBilateralFilter() { return this->m_ApplyBilateralFilter; } void mitk::ToFCompositeFilter::SetApplyTemporalMedianFilter(bool flag) { this->m_ApplyTemporalMedianFilter = flag; } +void mitk::ToFCompositeFilter::SetApplyAverageFilter(bool flag) +{ + this->m_ApplyAverageFilter = flag; +} + void mitk::ToFCompositeFilter::SetApplyMedianFilter(bool flag) { this->m_ApplyMedianFilter = flag; } void mitk::ToFCompositeFilter::SetApplyThresholdFilter(bool flag) { this->m_ApplyThresholdFilter = flag; } void mitk::ToFCompositeFilter::SetApplyBilateralFilter(bool flag) { this->m_ApplyBilateralFilter = flag; } void mitk::ToFCompositeFilter::SetTemporalMedianFilterParameter(int tmporalMedianFilterNumOfFrames) { this->m_TemporalMedianFilterNumOfFrames = tmporalMedianFilterNumOfFrames; } void mitk::ToFCompositeFilter::SetThresholdFilterParameter(int min, int max) { if (min > max) { min = max; } this->m_ThresholdFilterMin = min; this->m_ThresholdFilterMax = max; } void mitk::ToFCompositeFilter::SetBilateralFilterParameter(int domainSigma, int rangeSigma, int kernelRadius = 0) { this->m_BilateralFilterDomainSigma = domainSigma; this->m_BilateralFilterRangeSigma = rangeSigma; this->m_BilateralFilterKernelRadius = kernelRadius; } void mitk::ToFCompositeFilter::CreateItkImage(ItkImageType2D::Pointer &itkInputImage) { itkInputImage = ItkImageType2D::New(); ItkImageType2D::IndexType startIndex; startIndex[0] = 0; // first index on X startIndex[1] = 0; // first index on Y ItkImageType2D::SizeType size; size[0] = this->m_ImageWidth; // size along X size[1] = this->m_ImageHeight; // size along Y ItkImageType2D::RegionType region; region.SetSize( size ); region.SetIndex( startIndex ); itkInputImage->SetRegions( region ); itkInputImage->Allocate(); } diff --git a/Modules/ToFProcessing/mitkToFCompositeFilter.h b/Modules/ToFProcessing/mitkToFCompositeFilter.h index 48a9baa862..db990b93c2 100644 --- a/Modules/ToFProcessing/mitkToFCompositeFilter.h +++ b/Modules/ToFProcessing/mitkToFCompositeFilter.h @@ -1,230 +1,241 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Module: $RCSfile$ Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef __mitkToFCompositeFilter_h #define __mitkToFCompositeFilter_h #include #include "mitkImageToImageFilter.h" #include #include #include typedef itk::Image ItkImageType2D; typedef itk::Image ItkImageType3D; typedef itk::BilateralImageFilter BilateralFilterType; namespace mitk { /** * @brief Applies a common filter-pipeline to the first input of this filter * * This class intends to allow quick preprocessing of (ToF) range data. Input 0 of this filter, holding the range image, * is processed using the following image processing filters: * - threshold filter * - temporal median filter * - spatial median filter * - bilateral filter * * @ingroup ToFProcessing */ class mitkToFProcessing_EXPORT ToFCompositeFilter : public ImageToImageFilter { public: mitkClassMacro( ToFCompositeFilter , ImageToImageFilter ); itkNewMacro( Self ); /*! \brief sets the input of this filter \param distanceImage input is the distance image of e.g. a ToF camera */ virtual void SetInput( Image* distanceImage); /*! \brief sets the input of this filter at idx \param idx number of the current input \param distanceImage input is the distance image of e.g. a ToF camera \param CameraModel This is the camera model which holds parameters like focal length, pixel size, etc. which are needed for the reconstruction of the surface. */ virtual void SetInput(unsigned int idx, Image* distanceImage); /*! \brief returns the input of this filter */ Image* GetInput(); /*! \brief returns the input with id idx of this filter */ Image* GetInput(unsigned int idx); /*! \brief Returns if the temporal median filter is currently selected for application to the distance image \return flag m_ApplyTemporalMedianFilter */ bool GetApplyTemporalMedianFilter(); /*! + \brief Returns if the average filter is currently selected for application to the distance image + \return flag m_ApplyAverageFilter + */ + bool GetApplyAverageFilter(); + /*! \brief Returns if the median filter is currently selected for application to the distance image \return flag m_ApplyMedianFilter */ bool GetApplyMedianFilter(); /*! \brief Returns if the threshold filter is currently selected for application to the distance image \return flag m_ApplyThresholdFilter */ bool GetApplyThresholdFilter(); /*! \brief Returns if the bilateral filter is currently selected for application to the distance image \return flag m_ApplyBilateralFilter */ bool GetApplyBilateralFilter(); /*! \brief Set if the temporal median filter should be applied to the distance image \param flag flag m_ApplyTemporalMedianFilter will be set to */ void SetApplyTemporalMedianFilter(bool flag); /*! + \brief Set if the average filter should be applied to the distance image + \param flag flag m_ApplyAverageFilter will be set to + */ + void SetApplyAverageFilter(bool flag); + /*! \brief Set if the median filter should be applied to the distance image \param flag flag m_ApplyMedianFilter will be set to */ void SetApplyMedianFilter(bool flag); /*! \brief Set if the threshold filter should be applied to the distance image \param flag flag m_ApplyThresholdFilter will be set to */ void SetApplyThresholdFilter(bool flag); /*! \brief Sets if the bilateral filter should be applied to the distance image \param flag flag m_ApplyBilateralFilter will be set to */ void SetApplyBilateralFilter(bool flag); /*! \brief Sets the parameter of the temporal median filter \param tmporalMedianFilterNumOfFrames number of frames to be considered for calulating the temporal median */ void SetTemporalMedianFilterParameter(int tmporalMedianFilterNumOfFrames); /*! \brief Sets the parameters (lower, upper threshold) of the threshold filter \param min lower threshold of the threshold filter \param max upper threshold of the threshold filter */ void SetThresholdFilterParameter(int min, int max); /*! \brief Sets the parameters (domain sigma, range sigma, kernel radius) of the bilateral filter \param domainSigma Parameter controlling the smoothing effect of the bilateral filter. Default value: 2 \param rangeSigma Parameter controlling the edge preserving effect of the bilateral filter. Default value: 60 \param kernelRadius radius of the filter mask of the bilateral filter */ void SetBilateralFilterParameter(int domainSigma, int rangeSigma, int kernelRadius); protected: /*! \brief standard constructor */ ToFCompositeFilter(); /*! \brief standard destructor */ ~ToFCompositeFilter(); virtual void GenerateOutputInformation(); /*! \brief method generating the output of this filter. Called in the updated process of the pipeline. This method generates the output of the ToFSurfaceSource: The generated surface of the 3d points */ virtual void GenerateData(); /** * \brief Create an output for each input * * This Method sets the number of outputs to the number of inputs * and creates missing outputs objects. * \warning any additional outputs that exist before the method is called are deleted */ void CreateOutputsForAllInputs(); /*! \brief Applies a thresholding to the input image. All pixels with values below the lower threshold (min) and above the upper threshold (max) are assigned the pixel value 0 \param min lower threshold \param max upper thresold */ void ProcessThresholdFilter(IplImage* inputIplImage, int min, int max); /*! \brief Applies the ITK bilateral filter to the input image See http://www.itk.org/Doxygen320/html/classitk_1_1BilateralImageFilter.html for more details. \param domainSigma parameter controlling the smoothing effect of the filter \param rangeSigma parameter controlling the edge preserving effect of the filter \param kernelRadius radius of the filter mask of the bilateral filter */ ItkImageType2D::Pointer ProcessItkBilateralFilter(ItkImageType2D::Pointer inputItkImage, int domainSigma, int rangeSigma, int kernelRadius); /*! \brief Applies the OpenCV bilateral filter to the input image. See http://opencv.willowgarage.com/documentation/c/image_filtering.html#smooth for more details \param domainSigma parameter controlling the smoothing effect of the filter \param rangeSigma parameter controlling the edge preserving effect of the filter \param kernelRadius radius of the filter mask of the bilateral filter */ void ProcessCVBilateralFilter(IplImage* inputIplImage, IplImage* outputIplImage, int domainSigma, int rangeSigma, int kernelRadius); /*! \brief Applies the OpenCV median filter to the input image. See http://opencv.willowgarage.com/documentation/c/image_filtering.html#smooth for more details */ void ProcessCVMedianFilter(IplImage* inputIplImage, IplImage* outputIplImage, int radius = 3); /*! \brief Performs temporal median filter on an image given the number of frames to be considered */ void ProcessStreamedQuickSelectMedianImageFilter(IplImage* inputIplImage, int numOfImages); /*! \brief Quickselect algorithm * This Quickselect routine is based on the algorithm described in * "Numerical recipes in C", Second Edition, * Cambridge University Press, 1992, Section 8.5, ISBN 0-521-43108-5 * This code by Nicolas Devillard - 1998. Public domain. */ float quick_select(float arr[], int n); /*! \brief Initialize and allocate a 2D ITK image of dimension m_ImageWidth*m_ImageHeight */ void CreateItkImage(ItkImageType2D::Pointer &itkInputImage); int m_ImageWidth; ///< x-dimension of the image int m_ImageHeight; ///< y-dimension of the image int m_ImageSize; ///< size of the image in bytes IplImage* m_IplDistanceImage; ///< OpenCV-representation of the distance image IplImage* m_IplOutputImage; ///< OpenCV-representation of the output image ItkImageType2D::Pointer m_ItkInputImage; ///< ITK representation of the distance image bool m_ApplyTemporalMedianFilter; ///< Flag indicating if the temporal median filter is currently active for processing the distance image + bool m_ApplyAverageFilter; ///< Flag indicating if the average filter is currently active for processing the distance image bool m_ApplyMedianFilter; ///< Flag indicating if the spatial median filter is currently active for processing the distance image bool m_ApplyThresholdFilter; ///< Flag indicating if the threshold filter is currently active for processing the distance image bool m_ApplyBilateralFilter; ///< Flag indicating if the bilateral filter is currently active for processing the distance image float** m_DataBuffer; ///< Buffer used for calculating the pixel-wise median over the last n (m_TemporalMedianFilterNumOfFrames) number of frames int m_DataBufferCurrentIndex; ///< Current index in the buffer of the temporal median filter int m_DataBufferMaxSize; ///< Maximal size for the buffer of the temporal median filter (m_DataBuffer) int m_TemporalMedianFilterNumOfFrames; ///< Number of frames to be used in the calculation of the temporal median int m_ThresholdFilterMin; ///< Lower threshold of the threshold filter. Pixels with values below will be assigned value 0 when applying the threshold filter int m_ThresholdFilterMax; ///< Lower threshold of the threshold filter. Pixels with values above will be assigned value 0 when applying the threshold filter int m_BilateralFilterDomainSigma; ///< Parameter of the bilateral filter controlling the smoothing effect of the filter. Default value: 2 int m_BilateralFilterRangeSigma; ///< Parameter of the bilateral filter controlling the edge preserving effect of the filter. Default value: 60 int m_BilateralFilterKernelRadius; ///< Kernel radius of the bilateral filter mask }; } //END mitk namespace #endif diff --git a/Modules/ToFProcessing/mitkToFProcessingCommon.cpp b/Modules/ToFProcessing/mitkToFProcessingCommon.cpp index aadda2efb2..0bd3bfc5cb 100644 --- a/Modules/ToFProcessing/mitkToFProcessingCommon.cpp +++ b/Modules/ToFProcessing/mitkToFProcessingCommon.cpp @@ -1,66 +1,66 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Module: $RCSfile$ Language: C++ Date: $Date$ Version: $Revision$ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include "mitkToFProcessingCommon.h" namespace mitk { ToFProcessingCommon::ToFPoint3D ToFProcessingCommon::IndexToCartesianCoordinates(unsigned int i, unsigned int j, ToFScalarType distance, ToFScalarType focalLength, ToFScalarType interPixelDistanceX, ToFScalarType interPixelDistanceY, ToFScalarType principalPointX, ToFScalarType principalPointY) { ToFPoint3D cartesianCoordinates; // calculate image coordinates in mm; ToFScalarType imageX = (( i - principalPointX ) * interPixelDistanceX); ToFScalarType imageY = (( j - principalPointY ) * interPixelDistanceY); //distance from pinhole to pixel ToFScalarType d = sqrt(imageX*imageX + imageY*imageY + focalLength*focalLength); cartesianCoordinates[0] = (distance-d)*imageX / d; //Strahlensatz: x / imageX = (distance-d) / d cartesianCoordinates[1] = (distance-d)*imageY / d; //Strahlensatz: y / imageY = (distance-d) / d cartesianCoordinates[2] = ((distance*focalLength) / d) - focalLength; //Strahlensatz: z+f / f = distance / d. return cartesianCoordinates; } ToFProcessingCommon::ToFPoint3D ToFProcessingCommon::CartesianToIndexCoordinates(ToFScalarType cartesianPointX, ToFScalarType cartesianPointY,ToFScalarType cartesianPointZ, ToFScalarType focalLength, ToFScalarType interPixelDistanceX, ToFScalarType interPixelDistanceY, ToFScalarType principalPointX, ToFScalarType principalPointY, bool calculateDistance) { ToFPoint3D indexCoordinatesAndDistanceValue; - ToFScalarType imageX = focalLength/cartesianPointZ * cartesianPointX; - ToFScalarType imageY = focalLength/cartesianPointZ * cartesianPointY; + ToFScalarType imageX = cartesianPointX*focalLength/cartesianPointZ; + ToFScalarType imageY = cartesianPointY*focalLength/cartesianPointZ; indexCoordinatesAndDistanceValue[0] = imageX/interPixelDistanceX + principalPointX; indexCoordinatesAndDistanceValue[1] = imageY/interPixelDistanceY + principalPointY; ToFScalarType d = sqrt(imageX*imageX + imageY*imageY + focalLength*focalLength); if (calculateDistance) { indexCoordinatesAndDistanceValue[2] = d*(cartesianPointZ+focalLength) / focalLength; } else { indexCoordinatesAndDistanceValue[2] = 0.0; } return indexCoordinatesAndDistanceValue; } } diff --git a/Modules/ToFUI/Qmitk/QmitkToFCompositeFilterWidget.cpp b/Modules/ToFUI/Qmitk/QmitkToFCompositeFilterWidget.cpp index 971734e0b2..423e954314 100644 --- a/Modules/ToFUI/Qmitk/QmitkToFCompositeFilterWidget.cpp +++ b/Modules/ToFUI/Qmitk/QmitkToFCompositeFilterWidget.cpp @@ -1,194 +1,213 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Module: $RCSfile$ Language: C++ Date: $Date: 2009-05-20 13:35:09 +0200 (Mi, 20 Mai 2009) $ Version: $Revision: 17332 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #include //QT headers #include const std::string QmitkToFCompositeFilterWidget::VIEW_ID = "org.mitk.views.qmitktofcompositefilterwidget"; QmitkToFCompositeFilterWidget::QmitkToFCompositeFilterWidget(QWidget* parent, Qt::WindowFlags f): QWidget(parent, f) { this->m_ToFCompositeFilter = NULL; m_Controls = NULL; CreateQtPartControl(this); } QmitkToFCompositeFilterWidget::~QmitkToFCompositeFilterWidget() { } void QmitkToFCompositeFilterWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkToFCompositeFilterWidgetControls; m_Controls->setupUi(parent); QPlastiqueStyle *sliderStyle = new QPlastiqueStyle(); int min = m_Controls->m_ThresholdFilterMinValueSpinBox->value(); int max = m_Controls->m_ThresholdFilterMaxValueSpinBox->value(); m_Controls->m_ThresholdFilterRangeSlider->setMinimum(min); m_Controls->m_ThresholdFilterRangeSlider->setMaximum(max); m_Controls->m_ThresholdFilterRangeSlider->setLowerValue(min); m_Controls->m_ThresholdFilterRangeSlider->setUpperValue(max); m_Controls->m_ThresholdFilterRangeSlider->setHandleMovementMode(QxtSpanSlider::NoOverlapping); m_Controls->m_ThresholdFilterRangeSlider->setStyle(sliderStyle); this->CreateConnections(); } } void QmitkToFCompositeFilterWidget::CreateConnections() { if ( m_Controls ) { connect(m_Controls->m_TemporalMedianFilterNumOfFramesSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnTemporalMedianFilterNumOfFramesSpinBoxValueChanged(int))); connect(m_Controls->m_BilateralFilterDomainSigmaSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnBilateralFilterDomainSigmaSpinBoxValueChanged(int))); connect(m_Controls->m_BilateralFilterRangeSigmaSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnBilateralFilterRangeSigmaSpinBoxValueChanged(int))); connect(m_Controls->m_BilateralFilterKernelRadiusSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnBilateralFilterKernelRadiusSpinBoxValueChanged(int))); connect(m_Controls->m_ThresholdFilterMinValueSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnThresholdFilterMinValueChanged(int))); connect(m_Controls->m_ThresholdFilterMaxValueSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnThresholdFilterMaxValueChanged(int))); connect( (QObject*)(m_Controls->m_TemporalMedianFilterCheckBox), SIGNAL(toggled(bool)), this, SLOT(OnTemporalMedianFilterCheckBoxChecked(bool)) ); + connect( (QObject*)(m_Controls->m_AverageFilterCheckBox), SIGNAL(toggled(bool)), this, SLOT(OnAverageFilterCheckBoxChecked(bool)) ); connect( (QObject*)(m_Controls->m_ThresholdFilterCheckBox), SIGNAL(toggled(bool)), this, SLOT(OnThresholdFilterCheckBoxChecked(bool)) ); connect( (QObject*)(m_Controls->m_BilateralFilterCheckBox), SIGNAL(toggled(bool)), this, SLOT(OnBilateralFilterCheckBoxChecked(bool)) ); connect( (QObject*)(m_Controls->m_MedianFilterCheckBox), SIGNAL(toggled(bool)), this, SLOT(OnMedianFilterCheckBoxChecked(bool)) ); connect(m_Controls->m_ThresholdFilterRangeSlider, SIGNAL(spanChanged(int, int) ),this, SLOT( OnSpanChanged(int , int ) )); //reset button connect(m_Controls->m_ThresholdFilterRangeSliderReset, SIGNAL(pressed()), this, SLOT(OnResetThresholdFilterRangeSlider())); } } void QmitkToFCompositeFilterWidget::SetToFCompositeFilter(mitk::ToFCompositeFilter* toFCompositeFilter) { this->m_ToFCompositeFilter = toFCompositeFilter; } mitk::ToFCompositeFilter* QmitkToFCompositeFilterWidget::GetToFCompositeFilter() { if (this->m_ToFCompositeFilter.IsNull()) { this->m_ToFCompositeFilter = mitk::ToFCompositeFilter::New(); } return this->m_ToFCompositeFilter; } void QmitkToFCompositeFilterWidget::UpdateFilterParameter() { OnTemporalMedianFilterCheckBoxChecked(m_Controls->m_TemporalMedianFilterCheckBox->isChecked()); + OnAverageFilterCheckBoxChecked(m_Controls->m_AverageFilterCheckBox->isChecked()); OnMedianFilterCheckBoxChecked(m_Controls->m_MedianFilterCheckBox->isChecked()); OnThresholdFilterCheckBoxChecked(m_Controls->m_ThresholdFilterCheckBox->isChecked()); OnBilateralFilterCheckBoxChecked(m_Controls->m_BilateralFilterCheckBox->isChecked()); } void QmitkToFCompositeFilterWidget::OnTemporalMedianFilterCheckBoxChecked(bool checked) { this->m_ToFCompositeFilter->SetApplyTemporalMedianFilter(checked); + // disable average filter if temporal median filter is enabled + if (checked) + { + m_Controls->m_AverageFilterCheckBox->setChecked(false); + this->m_ToFCompositeFilter->SetApplyAverageFilter(false); + } +} + +void QmitkToFCompositeFilterWidget::OnAverageFilterCheckBoxChecked(bool checked) +{ + this->m_ToFCompositeFilter->SetApplyAverageFilter(checked); + // disable temporal median filter if average filter is enabled + if (checked) + { + m_Controls->m_TemporalMedianFilterCheckBox->setChecked(false); + this->m_ToFCompositeFilter->SetApplyTemporalMedianFilter(false); + } } void QmitkToFCompositeFilterWidget::OnThresholdFilterCheckBoxChecked(bool checked) { this->m_ToFCompositeFilter->SetApplyThresholdFilter(checked); } void QmitkToFCompositeFilterWidget::OnMedianFilterCheckBoxChecked(bool checked) { this->m_ToFCompositeFilter->SetApplyMedianFilter(checked); } void QmitkToFCompositeFilterWidget::OnBilateralFilterCheckBoxChecked(bool checked) { this->m_ToFCompositeFilter->SetApplyBilateralFilter(checked); } void QmitkToFCompositeFilterWidget::OnTemporalMedianFilterNumOfFramesSpinBoxValueChanged(int value) { this->m_ToFCompositeFilter->SetTemporalMedianFilterParameter(value); } void QmitkToFCompositeFilterWidget::OnBilateralFilterDomainSigmaSpinBoxValueChanged(int value) { SetBilateralFilterParameter(); } void QmitkToFCompositeFilterWidget::OnBilateralFilterRangeSigmaSpinBoxValueChanged(int value) { SetBilateralFilterParameter(); } void QmitkToFCompositeFilterWidget::OnBilateralFilterKernelRadiusSpinBoxValueChanged(int value) { SetBilateralFilterParameter(); } void QmitkToFCompositeFilterWidget::OnThresholdFilterMinValueChanged(int value) { m_Controls->m_ThresholdFilterRangeSlider->setLowerValue(value); SetThresholdFilterParameter(); } void QmitkToFCompositeFilterWidget::OnThresholdFilterMaxValueChanged(int value) { m_Controls->m_ThresholdFilterRangeSlider->setUpperValue(value); SetThresholdFilterParameter(); } void QmitkToFCompositeFilterWidget::SetThresholdFilterParameter() { int min = m_Controls->m_ThresholdFilterMinValueSpinBox->value(); int max = m_Controls->m_ThresholdFilterMaxValueSpinBox->value(); this->m_ToFCompositeFilter->SetThresholdFilterParameter(min, max); } void QmitkToFCompositeFilterWidget::SetBilateralFilterParameter() { int domainSigma = m_Controls->m_BilateralFilterDomainSigmaSpinBox->value(); int rangeSigma = m_Controls->m_BilateralFilterRangeSigmaSpinBox->value(); int kernelRadius = m_Controls->m_BilateralFilterKernelRadiusSpinBox->value(); this->m_ToFCompositeFilter->SetBilateralFilterParameter(domainSigma, rangeSigma, kernelRadius); } void QmitkToFCompositeFilterWidget::OnSpanChanged(int lower, int upper) { int lowerVal = m_Controls->m_ThresholdFilterRangeSlider->lowerValue(); int upperVal = m_Controls->m_ThresholdFilterRangeSlider->upperValue(); m_Controls->m_ThresholdFilterMinValueSpinBox->setValue(lowerVal); m_Controls->m_ThresholdFilterMaxValueSpinBox->setValue(upperVal); } void QmitkToFCompositeFilterWidget::OnResetThresholdFilterRangeSlider() { int lower = 1; int upper = 7000; m_Controls->m_ThresholdFilterRangeSlider->setLowerValue(lower); m_Controls->m_ThresholdFilterRangeSlider->setUpperValue(upper); m_Controls->m_ThresholdFilterMinValueSpinBox->setValue(lower); m_Controls->m_ThresholdFilterMaxValueSpinBox->setValue(upper); } diff --git a/Modules/ToFUI/Qmitk/QmitkToFCompositeFilterWidget.h b/Modules/ToFUI/Qmitk/QmitkToFCompositeFilterWidget.h index 15b641eecc..9830327ec8 100644 --- a/Modules/ToFUI/Qmitk/QmitkToFCompositeFilterWidget.h +++ b/Modules/ToFUI/Qmitk/QmitkToFCompositeFilterWidget.h @@ -1,139 +1,143 @@ /*========================================================================= Program: Medical Imaging & Interaction Toolkit Module: $RCSfile$ Language: C++ Date: $Date: 2009-05-20 13:35:09 +0200 (Mi, 20 Mai 2009) $ Version: $Revision: 17332 $ Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ #ifndef _QMITKTOFCOMPOSITEFILTERWIDGET_H_INCLUDED #define _QMITKTOFCOMPOSITEFILTERWIDGET_H_INCLUDED #include "mitkTOFUIExports.h" #include "ui_QmitkToFCompositeFilterWidgetControls.h" //mitk headers #include /** * @brief Widget for controlling the ToFCompositeFilter (located in module ToFProcessing) * * The widget allows to enable/disable the filters internally used in the ToFCompositeFilter * and to set the individual filter parameters using GUI elements * * @ingroup ToFUI */ class mitkTOFUI_EXPORT QmitkToFCompositeFilterWidget :public QWidget { //this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) Q_OBJECT public: static const std::string VIEW_ID; QmitkToFCompositeFilterWidget(QWidget* p = 0, Qt::WindowFlags f1 = 0); virtual ~QmitkToFCompositeFilterWidget(); /* @brief This method is part of the widget an needs not to be called seperately. */ virtual void CreateQtPartControl(QWidget *parent); /* @brief This method is part of the widget an needs not to be called seperately. (Creation of the connections of main and control widget.)*/ virtual void CreateConnections(); /*! \brief Sets the ToFCompositeFilter used by this widget \param tofCompositeFilter pointer to the internally used ToFCompositeFilter */ void SetToFCompositeFilter(mitk::ToFCompositeFilter* toFCompositeFilter); /*! \brief Returns the ToFCompositeFilter used by this widget \return tofCompositeFilter pointer to the internally used ToFCompositeFilter */ mitk::ToFCompositeFilter* GetToFCompositeFilter(); /*! \brief update parameters of ToFCompositeFilter according to current GUI setting */ void UpdateFilterParameter(); signals: protected slots: /*! \brief slot en-/disabling temporal median filter in internal ToFCompositeFilter */ void OnTemporalMedianFilterCheckBoxChecked(bool checked); /*! + \brief slot en-/disabling average filter in internal ToFCompositeFilter + */ + void OnAverageFilterCheckBoxChecked(bool checked); + /*! \brief slot en-/disabling threshold filter in internal ToFCompositeFilter */ void OnThresholdFilterCheckBoxChecked(bool checked); /*! \brief slot en-/disabling median filter in internal ToFCompositeFilter */ void OnMedianFilterCheckBoxChecked(bool checked); /*! \brief slot en-/disabling bilateral filter in internal ToFCompositeFilter */ void OnBilateralFilterCheckBoxChecked(bool checked); /*! \brief slot updating threshold spin boxes according to slider position */ void OnSpanChanged(int lower, int upper); /*! \brief slot resetting threshold range slider to default values (min: 1, max: 7000) */ void OnResetThresholdFilterRangeSlider(); /*! \brief slot updating the parameter "number of frames" of the temporal median filter in the ToFCompositeFilter */ void OnTemporalMedianFilterNumOfFramesSpinBoxValueChanged(int value); /*! \brief slot updating the parameter "domain sigma" of the bilateral filter in the ToFCompositeFilter */ void OnBilateralFilterDomainSigmaSpinBoxValueChanged(int value); /*! \brief slot updating the paramter "range sigma" of the bilateral filter in the ToFCompositeFilter */ void OnBilateralFilterRangeSigmaSpinBoxValueChanged(int value); /*! \brief slot updating the paramter "kernel radius" of the bilateral filter in the ToFCompositeFilter */ void OnBilateralFilterKernelRadiusSpinBoxValueChanged(int value); /*! \brief slot updating the paramter "minimal threshold" of the threshold filter in the ToFCompositeFilter */ void OnThresholdFilterMinValueChanged(int value); /*! \brief slot updating the paramter "maximal threshold" of the threshold filter in the ToFCompositeFilter */ void OnThresholdFilterMaxValueChanged(int value); protected: Ui::QmitkToFCompositeFilterWidgetControls* m_Controls; ///< member holding the UI elements of this widget mitk::ToFCompositeFilter::Pointer m_ToFCompositeFilter; ///< member holding the internally used ToFCompositeFilter private: /*! \brief method updating the parameters of the bilateral filter in the ToFCompositeFilter */ void SetBilateralFilterParameter(); /*! \brief method updating the parameters of the threshold filter in the ToFCompositeFilter */ void SetThresholdFilterParameter(); }; #endif // _QMITKTOFCOMPOSITEFILTERWIDGET_H_INCLUDED diff --git a/Modules/ToFUI/Qmitk/QmitkToFCompositeFilterWidgetControls.ui b/Modules/ToFUI/Qmitk/QmitkToFCompositeFilterWidgetControls.ui index 8ca00700f5..6a3f232224 100644 --- a/Modules/ToFUI/Qmitk/QmitkToFCompositeFilterWidgetControls.ui +++ b/Modules/ToFUI/Qmitk/QmitkToFCompositeFilterWidgetControls.ui @@ -1,207 +1,214 @@ QmitkToFCompositeFilterWidgetControls 0 0 487 142 0 0 QmitkToFCompositeFilter - + 11 ToF Preprocessing Threshold Filter 7000 0 QFrame::StyledPanel QFrame::Raised 0 0 modify actual seen window by dragging left and right slider. Qt::Horizontal 0 0 48 16777215 Resets range to histogram minimum and maximum. Reset 7000 7000 true Median Filter (t) - - - - 100 - - - 10 + + + + Average Filter true Median Filter Bilateral Filter Domain σ: 99 2 Range σ: 99 60 Kernel Radius: + + + + 100 + + + 10 + + + QxtSpanSlider QSlider
qxtspanslider.h