void CriminisiInpainting::ComputeIsophotes()
{
  
  try
  {
    Helpers::DebugWriteImageConditional<FloatVectorImageType>(this->CurrentImage, "Debug/ComputeIsophotes.input.mha", this->DebugImages);
    
    /*
    // This only works when the image is RGB
    typedef itk::VectorMagnitudeImageFilter<FloatVectorImageType, UnsignedCharScalarImageType>  VectorMagnitudeFilterType;
    VectorMagnitudeFilterType::Pointer magnitudeFilter = VectorMagnitudeFilterType::New();
    magnitudeFilter->SetInput(this->OriginalImage); // We use the original image here because the image that has been painted green inside the hole has a strong gradient around the hole.
    magnitudeFilter->Update();
    */
    RGBImageType::Pointer rgbImage = RGBImageType::New();
    Helpers::VectorImageToRGBImage(this->OriginalImage, rgbImage);
    
    Helpers::DebugWriteImageConditional<RGBImageType>(rgbImage, "Debug/ComputeIsophotes.rgb.mha", this->DebugImages);

    typedef itk::RGBToLuminanceImageFilter< RGBImageType, FloatScalarImageType > LuminanceFilterType;
    LuminanceFilterType::Pointer luminanceFilter = LuminanceFilterType::New();
    luminanceFilter->SetInput(rgbImage);
    luminanceFilter->Update();
  
    Helpers::DebugWriteImageConditional<FloatScalarImageType>(luminanceFilter->GetOutput(), "Debug/ComputeIsophotes.luminance.mha", this->DebugImages);
    
    // Blur the image to compute better gradient estimates
    typedef itk::DiscreteGaussianImageFilter<FloatScalarImageType, FloatScalarImageType >  BlurFilterType;
    BlurFilterType::Pointer blurFilter = BlurFilterType::New();
    blurFilter->SetInput(luminanceFilter->GetOutput());
    blurFilter->SetVariance(2);
    blurFilter->Update();

    Helpers::DebugWriteImageConditional<FloatScalarImageType>(blurFilter->GetOutput(), "Debug/ComputeIsophotes.blurred.mha", true);
    
    // Compute the gradient
    // Template parameters are <TInputImage, TOperatorValueType, TOutputValueType>
    typedef itk::GradientImageFilter<FloatScalarImageType, float, float>  GradientFilterType;
    GradientFilterType::Pointer gradientFilter = GradientFilterType::New();
    gradientFilter->SetInput(blurFilter->GetOutput());
    gradientFilter->Update();

    Helpers::DebugWriteImageConditional<FloatVector2ImageType>(gradientFilter->GetOutput(), "Debug/ComputeIsophotes.gradient.mha", this->DebugImages);
 
    // Rotate the gradient 90 degrees to obtain isophotes from gradient
    typedef itk::UnaryFunctorImageFilter<FloatVector2ImageType, FloatVector2ImageType,
    RotateVectors<
      FloatVector2ImageType::PixelType,
      FloatVector2ImageType::PixelType> > FilterType;

    FilterType::Pointer rotateFilter = FilterType::New();
    rotateFilter->SetInput(gradientFilter->GetOutput());
    rotateFilter->Update();

    Helpers::DebugWriteImageConditional<FloatVector2ImageType>(rotateFilter->GetOutput(), "Debug/ComputeIsophotes.rotatedGradient.mha", this->DebugImages);
      
    // Mask the isophote image with the expanded version of the inpainting mask.
    // That is, keep only the values outside of the expanded mask. To do this, we have to first invert the mask.

    // Invert the mask
    typedef itk::InvertIntensityImageFilter <Mask> InvertIntensityImageFilterType;
    InvertIntensityImageFilterType::Pointer invertMaskFilter = InvertIntensityImageFilterType::New();
    invertMaskFilter->SetInput(this->CurrentMask);
    invertMaskFilter->Update();

    if(this->DebugImages)
      {
      Helpers::WriteImage<Mask>(invertMaskFilter->GetOutput(), "Debug/ComputeIsophotes.invertedMask.mha");
      }

    //std::cout << "rotateFilter: " << rotateFilter->GetOutput()->GetLargestPossibleRegion() << std::endl;
    //std::cout << "invertMaskFilter: " << invertMaskFilter->GetOutput()->GetLargestPossibleRegion() << std::endl;
    
    // Keep only values outside the masked region
    typedef itk::MaskImageFilter< FloatVector2ImageType, Mask, FloatVector2ImageType > MaskFilterType;
    MaskFilterType::Pointer maskFilter = MaskFilterType::New();
    maskFilter->SetInput1(rotateFilter->GetOutput());
    maskFilter->SetInput2(invertMaskFilter->GetOutput());
    maskFilter->Update();

    if(this->DebugImages)
      {
      Helpers::WriteImage<FloatVector2ImageType>(maskFilter->GetOutput(), "Debug/ComputeIsophotes.maskedIsophotes.mha");
      }
      
    Helpers::DeepCopy<FloatVector2ImageType>(maskFilter->GetOutput(), this->IsophoteImage);
   
  }
  catch( itk::ExceptionObject & err )
  {
    std::cerr << "ExceptionObject caught in ComputeIsophotes!" << std::endl;
    std::cerr << err << std::endl;
    exit(-1);
  }
}
int exampleProcessImageFilter::update()
{
    typedef unsigned short PixelType;
    const unsigned int Dimension = 3;
    typedef itk::Image< PixelType, Dimension > ImageType;

    qDebug() << d->inputA->identifier();

    if (d->option == optionA)
    {

        if (d->inputA->identifier()=="itkDataImageUShort3" && d->inputB->identifier()=="itkDataImageUShort3")
        {
            typedef itk::MaskImageFilter< ImageType,ImageType,ImageType >    MaskFilterType;
            MaskFilterType::Pointer maskFilter = MaskFilterType::New();

            //convert from dtkImages to ItkImages and set as intputs for the itk::MaskImageFilter
            maskFilter->SetInput1(dynamic_cast<ImageType*>((itk::Object*)(d->inputA->output())));
            maskFilter->SetInput2(dynamic_cast<ImageType*>((itk::Object*)(d->inputB->output())));

            //Create an image where the output of the filter is going to be displayed
            d->output =dynamic_cast<medAbstractDataImage *>(dtkAbstractDataFactory::instance()->create ("itkDataImageUShort3"));

            maskFilter->Update();

            //Set the data for the output
            d->output->setData(maskFilter->GetOutput());

        }
        else if(d->inputA->identifier()=="itkDataImageDouble4" && d->inputB->identifier()=="itkDataImageDouble4")
        {
            typedef double PixelType4;
            const unsigned int Dimension4 = 4;
            typedef itk::Image< PixelType4, Dimension4 > ImageType4;

            typedef itk::MaskImageFilter< ImageType4,ImageType4,ImageType4 >    MaskFilterType4;
            MaskFilterType4::Pointer maskFilter4 = MaskFilterType4::New();

            //convert from dtkImages to ItkImages and set as intputs for the itk::MaskImageFilter
            maskFilter4->SetInput1(dynamic_cast<ImageType4*>((itk::Object*)(d->inputA->output())));
            maskFilter4->SetInput2(dynamic_cast<ImageType4*>((itk::Object*)(d->inputB->output())));

            maskFilter4->Update();

            //Create an image where the output of the filter is going to be displayed
            d->output =dynamic_cast<medAbstractDataImage *> (dtkAbstractDataFactory::instance()->create ("itkDataImageDouble4"));

            //Set the data for the output
            d->output->setData(maskFilter4->GetOutput());

            typedef itk::ImageFileWriter< ImageType4 > WriterType;
            WriterType::Pointer writer = WriterType::New();
            writer->SetFileName("/user/jgarciag/home/AnalyzeStuff/headerModify/ResulHalfMask4D.mha");
            writer->SetInput(/*dynamic_cast<ImageType4*>((itk::Object*)(d->output->output()))*/maskFilter4->GetOutput());
            writer->Update();
        }
        else
            qDebug("Not the right itkDataImageUShort3 type of images");
    }

    else if (d->option == optionB)
    {

        if (d->inputA->identifier()=="itkDataImageUShort3" && d->inputB->identifier()=="itkDataImageUShort3")
        {
            typedef itk::AddImageFilter< ImageType,ImageType,ImageType >    AddFilterType;
            AddFilterType::Pointer AddFilter = AddFilterType::New();

            AddFilter->SetInput1(dynamic_cast<ImageType*>((itk::Object*)(d->inputA->output())));
            AddFilter->SetInput2(dynamic_cast<ImageType*>((itk::Object*)(d->inputB->output())));

            d->output =dynamic_cast<medAbstractDataImage *> (dtkAbstractDataFactory::instance()->create ("itkDataImageUShort3"));
            AddFilter->Update();
            d->output->setData(AddFilter->GetOutput());


        }
        else
            qDebug("Not the right itkDataImageUShort3 type of images");
    }

    else if (d->option == optionC)
    {
        if (d->inputA->identifier()=="itkDataImageUShort3" && d->inputB->identifier()=="itkDataImageUShort3")
        {
            typedef itk::ConnectedThresholdImageFilter< ImageType, ImageType > ConnectedFilterType;
            ConnectedFilterType::Pointer connectedThreshold = ConnectedFilterType::New();
            connectedThreshold->SetInput( dynamic_cast<ImageType*>((itk::Object*)(d->inputA->output())) );
            connectedThreshold->SetLower((d->lowerThreshold));
            connectedThreshold->SetUpper((d->lowerThreshold)+150);

            ImageType::IndexType  index;

            index[0] = d->x;
            index[1] = d->y;
            index[2] = d->z;

            connectedThreshold->SetSeed( index );

            connectedThreshold->Update();

            d->output =dynamic_cast<medAbstractDataImage *> (dtkAbstractDataFactory::instance()->create ("itkDataImageUShort3"));

            d->output->setData(connectedThreshold->GetOutput());
        }
        else
            qDebug("Not the right itkDataImageUShort3 type of image");
    }
//    emit progressed (100);
    qDebug("Adios");
    return 0;
}