#include "clitkProfileImageGenericFilter.h"
// itk include
-#include "itkBinaryThresholdImageFilter.h"
-#include "itkMaskImageFilter.h"
-#include "itkMaskNegatedImageFilter.h"
+#include <itkLineIterator.h>
+#include <itkPoint.h>
#include <clitkCommon.h>
+
+
namespace clitk
{
//--------------------------------------------------------------------
+//--------------------------------------------------------------------
+vtkFloatArray* ProfileImageGenericFilter::GetArrayX()
+{
+ return(mArrayX);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+vtkFloatArray* ProfileImageGenericFilter::GetArrayY()
+{
+ return(mArrayY);
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+vtkFloatArray* ProfileImageGenericFilter::GetCoord()
+{
+ return(mCoord);
+}
+//--------------------------------------------------------------------
+
+
//--------------------------------------------------------------------
void ProfileImageGenericFilter::SetArgsInfo(const args_info_type & a)
{
// Reading input
typename InputImageType::Pointer input = this->template GetInput<InputImageType>(0);
-
- // Main filter
typedef typename InputImageType::PixelType PixelType;
- typedef itk::Image<uchar, InputImageType::ImageDimension> OutputImageType;
-
- // Filter
- typedef itk::BinaryThresholdImageFilter<InputImageType, OutputImageType> BinaryThresholdImageFilterType;
- typename BinaryThresholdImageFilterType::Pointer thresholdFilter=BinaryThresholdImageFilterType::New();
- thresholdFilter->SetInput(input);
- thresholdFilter->SetInsideValue(mArgsInfo.fg_arg);
-
- if (mArgsInfo.lower_given) thresholdFilter->SetLowerThreshold(static_cast<PixelType>(mArgsInfo.lower_arg));
- if (mArgsInfo.upper_given) thresholdFilter->SetUpperThreshold(static_cast<PixelType>(mArgsInfo.upper_arg));
-
- /* Three modes :
- - FG -> only use FG value for pixel in the Foreground (or Inside), keep input values for outside
- - BG -> only use BG value for pixel in the Background (or Outside), keep input values for inside
- - both -> use FG and BG (real binary image)
- */
- if (mArgsInfo.mode_arg == std::string("both")) {
- thresholdFilter->SetOutsideValue(mArgsInfo.bg_arg);
- thresholdFilter->Update();
- typename OutputImageType::Pointer outputImage = thresholdFilter->GetOutput();
- this->template SetNextOutput<OutputImageType>(outputImage);
- } else {
- typename InputImageType::Pointer outputImage;
- thresholdFilter->SetOutsideValue(0);
- if (mArgsInfo.mode_arg == std::string("BG")) {
- typedef itk::MaskImageFilter<InputImageType,OutputImageType> maskFilterType;
- typename maskFilterType::Pointer maskFilter = maskFilterType::New();
- maskFilter->SetInput1(input);
- maskFilter->SetInput2(thresholdFilter->GetOutput());
- maskFilter->SetOutsideValue(mArgsInfo.bg_arg);
- maskFilter->Update();
- outputImage = maskFilter->GetOutput();
- } else {
- typedef itk::MaskNegatedImageFilter<InputImageType,OutputImageType> maskFilterType;
- typename maskFilterType::Pointer maskFilter = maskFilterType::New();
- maskFilter->SetInput1(input);
- maskFilter->SetInput2(thresholdFilter->GetOutput());
- maskFilter->SetOutsideValue(mArgsInfo.fg_arg);
- maskFilter->Update();
- outputImage = maskFilter->GetOutput();
+ typedef typename InputImageType::IndexType IndexType;
+
+ mArrayX = vtkSmartPointer<vtkFloatArray>::New();
+ mArrayY = vtkSmartPointer<vtkFloatArray>::New();
+ mCoord = vtkSmartPointer<vtkFloatArray>::New();
+ mCoord->SetNumberOfComponents(InputImageType::ImageDimension);
+ mCoordmm = vtkSmartPointer<vtkFloatArray>::New();
+ mCoordmm->SetNumberOfComponents(InputImageType::ImageDimension);
+ mDimension = InputImageType::ImageDimension;
+
+ /*typename InputImageType::Pointer outputImage;
+ outputImage = InputImageType::New();
+
+ outputImage->SetRegions(input->GetLargestPossibleRegion());
+ outputImage->Allocate();
+ outputImage->FillBuffer(0); */
+
+ //Iterator
+ IndexType pointBegin, pointEnd;
+
+ for (int i = 0; i < mArgsInfo.point1_given; ++i) {
+ pointBegin[i] = mArgsInfo.point1_arg[i];
+ pointEnd[i] = mArgsInfo.point2_arg[i];
+ }
+
+ itk::LineConstIterator<InputImageType> itProfile(input, pointBegin, pointEnd);
+ itProfile.GoToBegin();
+ int lineNumber(1);
+ double *tuple;
+ double distance;
+ tuple = new double[InputImageType::ImageDimension];
+ itk::Point<double, InputImageType::ImageDimension> transformedFirstPoint;
+ itk::Point<double, InputImageType::ImageDimension> transformedCurrentPoint;
+
+ input->TransformIndexToPhysicalPoint(itProfile.GetIndex(), transformedFirstPoint);
+
+ while (!itProfile.IsAtEnd())
+ {
+ // Fill in the table the intensity value
+ mArrayY->InsertNextTuple1(itProfile.Get());
+
+ for (int i=0; i<InputImageType::ImageDimension; ++i) {
+ tuple[i] = itProfile.GetIndex()[i];
}
- // Write/Save results
- this->template SetNextOutput<InputImageType>(outputImage);
+
+ input->TransformIndexToPhysicalPoint(itProfile.GetIndex(), transformedCurrentPoint);
+ distance = transformedFirstPoint.EuclideanDistanceTo(transformedCurrentPoint);
+
+ // Fill in the table the distance value
+ mArrayX->InsertNextTuple1(distance);
+
+ // Fill in the table the voxel coordinate value
+ mCoord->InsertNextTuple(tuple); //index
+ for (int i=0; i<InputImageType::ImageDimension; ++i) {
+ tuple[i] = transformedCurrentPoint[i];
+ }
+ mCoordmm->InsertNextTuple(tuple); //mm
+ ++lineNumber;
+ ++itProfile;
+ }
+
+ if (mArgsInfo.output_given) {
+ std::string str(mArgsInfo.output_arg);
+ this->WriteOutput(str);
+ }
+
+ /*
+ itk::LineIterator<InputImageType> otProfile(outputImage, pointBegin, pointEnd);
+ otProfile.GoToBegin();
+ while (!otProfile.IsAtEnd())
+ {
+ otProfile.Set(1.0);
+ ++otProfile;
+ }
+
+ this->template SetNextOutput<InputImageType>(outputImage): */
+
+ delete [] tuple;
+}
+//--------------------------------------------------------------------
+
+
+//--------------------------------------------------------------------
+void ProfileImageGenericFilter::WriteOutput(std::string outputFilename)
+{
+ ofstream fileOpen(outputFilename.c_str(), std::ofstream::trunc);
+
+ if(!fileOpen) {
+ cerr << "Error during saving" << endl;
+ return;
+ }
+
+ double *tuple;
+ tuple = new double[mDimension];
+ int i(0);
+ fileOpen << "The Bresenham algorithm is used to travel along the line. Values represent the center of each crossed voxel (in voxel and mm)" << endl;
+ fileOpen << "Id" << "\t" << "Value" << "\t" ;
+ fileOpen << "x(vox)" << "\t" << "y(vox)" << "\t";
+ if (mDimension >=3)
+ fileOpen << "z(vox)" << "\t";
+ if (mDimension >=4)
+ fileOpen << "t" << "\t";
+ fileOpen << "x(mm)" << "\t" << "y(mm)" << "\t";
+ if (mDimension >=3)
+ fileOpen << "z(mm)" << "\t";
+ if (mDimension >=4)
+ fileOpen << "t" << "\t";
+ fileOpen << endl;
+
+ while (i<mArrayX->GetNumberOfTuples()) {
+ fileOpen << i << "\t" << mArrayY->GetTuple(i)[0] << "\t" ;
+
+ mCoord->GetTuple(i, tuple);
+ for (int j=0; j<mDimension ; ++j) {
+ fileOpen << tuple[j] << "\t" ;
+ }
+ mCoordmm->GetTuple(i, tuple);
+ for (int j=0; j<mDimension ; ++j) {
+ fileOpen << tuple[j] << "\t" ;
+ }
+ if (mDimension == 4) {
+ fileOpen << tuple[3] << "\t" ;
+ }
+ fileOpen << endl;
+ ++i;
}
+
+ delete [] tuple;
+
+ fileOpen.close();
}
//--------------------------------------------------------------------