Vous avez reçu un message "Your GitLab account has been locked ..." ? Pas d'inquiétude : lisez cet article https://docs.gricad-pages.univ-grenoble-alpes.fr/help/unlock/

Commit 0e17d2ce authored by cfouard's avatar cfouard
Browse files

UPDATE replaced the itk filters module by 2 itk filters actions extensions.

FIXED no more image filter modules files in the core.

git-svn-id: svn+ssh://scm.forge.imag.fr/var/lib/gforge/chroot/scmrepos/svn/camitk/trunk/camitk@127 ec899d31-69d1-42ba-9299-647d76f65fb3
parent bad25228
......@@ -104,7 +104,12 @@ void ImageLutWidget::updateComponent(ImageComponent * comp) {
invert = false;
// initialize the sliders value
int nbOfColors = myComponent->getLut()->GetNumberOfTableValues();
// int nbOfColors = myComponent->getLut()->GetNumberOfTableValues();
double imgMinColor = myComponent->getImageData()->GetScalarTypeMin();
double imgMaxColor = myComponent->getImageData()->GetScalarTypeMax();
double nbColorsOrg = imgMaxColor - imgMinColor;
long int nbOfColors = (long int) (nbColorsOrg);
// as this widget is only grayscale, compute the average of the color values
lutMin = myComponent->getImageData()->GetScalarTypeMin();
lutMax = myComponent->getImageData()->GetScalarTypeMax();
......
#include "AnisotropicDiffusion.h"
#include <Application.h>
#include <ItkProgressObserver.h>
#include <QMessageBox>
#include <QString>
#include <QTextStream>
#include <itkImageToVTKImageFilter.h>
#include <itkVTKImageToImageFilter.h>
#include <itkCastImageFilter.h>
#include <itkRescaleIntensityImageFilter.h>
#include <itkGradientAnisotropicDiffusionImageFilter.h>
#include <itkCurvatureAnisotropicDiffusionImageFilter.h>
using namespace camitk;
// --------------- constructor -------------------
AnisotropicDiffusion::AnisotropicDiffusion(ActionExtension * extension) : Action(extension) {
// Setting name, description and input component
setName("Anisotropic Diffusion");
setDescription("<p>Anisotropic diffusion methods are formulated to reduce noise (or unwanted detail) in images while preserving specific image features. For many applications, there is an assumption that light-dark transitions (edges) are interesting. Standard isotropic diffusion methods move and blur light-dark boundaries. Anisotropic diffusion methods are formulated to specifically preserve edges.</p> \
<p>The numberOfIterations parameter specifies the number of iterations (time-step updates) that the solver will perform to produce a solution image. The appropriate number of iterations is dependent on the application and the image being processed. As a general rule, the more iterations performed, the more diffused the image will become.</p> \
<p>The conductance parameter controls the sensitivity of the conductance term in the basic anisotropic diffusion equation. It affect the conductance term in different ways depending on the particular variation on the basic equation. As a general rule, the lower the value, the more strongly the diffusion equation preserves image features (such as high gradients or curvature). A high value for conductance will cause the filter to diffuse image features more readily. Typical values range from 0.5 to 2.0 for data like the Visible Human color data, but the correct value for your application is wholly dependent on the results you want from a specific data set and the number or iterations you perform.</p> \
<p>The <i>Gradient</i> anisotropic diffusion implements an N-dimensional version of the classic Perona-Malik anisotropic diffusion equation for scal-valued images.</p> \
<p>The <i>Curvature</i> anisotrpic diffusion performs anisotropic diffusion on an image using a modified curvature diffusion equation (MCDE). MCDE does not exhibit the edge enhancing properties of classic anisotropic diffusion, which can under certain conditions undergo a <i>negative</i> diffusion, which enhances the contrast of edges. Equations of the form MCDE always undergo positive diffusion, with the conductance term only varying the stregth of that diffusion.</p> \
");
setComponent("ImageComponent");
setEmbedded(true);
// Setting classification family and tags
this->setFamily("ITK Filter");
this->addTag("Edge Preserving");
this->addTag("Smoothing");
this->addTag("Blur");
this->addTag("Perona and Malik");
// Setting parameters default values
setProperty("keepOriginalImageVoxelType", QVariant(true));
keepOrgVoxelType = true;
setProperty("numberOfIterations", QVariant(5));
setProperty("conductance", QVariant(1.0));
this->implementation = Curvature;
// Setting the widget containing the parameters
theWidget = NULL;
}
// --------------- destructor -------------------
AnisotropicDiffusion::~AnisotropicDiffusion() {
// do not delete the widget has it might have been used in the ActionViewer (i.e. the ownership might have been taken by the stacked widget)
}
// --------------- getWidget --------------
QWidget * AnisotropicDiffusion::getWidget() {
// build or update the widget
if (!theWidget) {
// Setting the widget containing the parameters, using the default widget
theWidget = new DefaultActionWidget(this);
}
else {
// theWidget is declared as a DefaultActionWidget*, therefore a call to update() is directly possible
theWidget->update();
}
return theWidget;
}
AnisotropicDiffusion::AnisoDiffType AnisotropicDiffusion::getMethod() {
return this->implementation;
}
void AnisotropicDiffusion::setMethod(AnisotropicDiffusion::AnisoDiffType implementation) {
this->implementation = implementation;
}
// --------------- apply -------------------
void AnisotropicDiffusion::apply() {
foreach (Component *comp, targetComponents) {
ImageComponent * input = dynamic_cast<ImageComponent *> ( comp );
process(input);
}
}
void AnisotropicDiffusion::process(ImageComponent * comp) {
// Get the parameters
keepOrgVoxelType = property("keepOriginalImageVoxelType").toBool();
numberOfIterations = property("numberOfIterations").toInt();
conductance = property("conductance").toDouble();
// ITK filter implementation using templates
vtkSmartPointer<vtkImageData> inputImage = comp->getImageData();
vtkSmartPointer<vtkImageData> outputImage = implementProcess (inputImage);
QString newName;
QTextStream(&newName) << comp->getName() << "_anisoDiff";
new ImageComponent(outputImage, newName);
Application::refresh();
}
#include "AnisotropicDiffusion_implementation"
// ITK filter implementation
template <class InputPixelType, class OutputPixelType, const int dim>
vtkSmartPointer<vtkImageData> AnisotropicDiffusion::itkProcess(vtkSmartPointer<vtkImageData> img)
{
vtkSmartPointer<vtkImageData> outputImage = vtkSmartPointer<vtkImageData>::New();
switch (getMethod())
{
default:
case AnisotropicDiffusion::Gradient:
outputImage = itkProcessGradientAnisotropicDiffusion<InputPixelType, OutputPixelType, dim>(img);
break;
case AnisotropicDiffusion::Curvature:
outputImage = itkProcessCurvatureAnisotropicDiffusion<InputPixelType, OutputPixelType, dim>(img);
break;
}
return outputImage;
}
template <class InputPixelType, class OutputPixelType, const int dim>
vtkSmartPointer<vtkImageData> AnisotropicDiffusion::itkProcessGradientAnisotropicDiffusion(vtkSmartPointer<vtkImageData> img)
{
vtkSmartPointer<vtkImageData> result = vtkSmartPointer<vtkImageData>::New();
vtkSmartPointer<vtkImageData> resultImage;
// --------------------- Filters declaration and creation ----------------------
// Define ITK input and output image types with respect to the instanciation
// types of the tamplate.
typedef itk::Image< InputPixelType, dim > InputImageType;
typedef itk::Image< OutputPixelType, dim > OutputImageType;
// Convert the image from CamiTK in VTK format to ITK format to use ITK filters.
typedef itk::VTKImageToImageFilter<InputImageType> vtkToItkFilterType;
typename vtkToItkFilterType::Pointer vtkToItkFilter = vtkToItkFilterType::New();
// To use anisotropic diffusion on real type data
typedef itk::CastImageFilter<InputImageType, OutputImageType> CastFilterType;
typename CastFilterType::Pointer toDoubleFilter = CastFilterType::New();
// Anisotropic filter
typedef itk::GradientAnisotropicDiffusionImageFilter<OutputImageType, OutputImageType> FilterType;
typename FilterType::Pointer filter = FilterType::New();
// To go back to the original image type.
typedef itk::RescaleIntensityImageFilter<OutputImageType, InputImageType> ToOrgFilterType;
typename ToOrgFilterType::Pointer toOrgFilter = ToOrgFilterType::New();
// In the same way, once the image is filtered, we need to convert it again to
// VTK format to give it to CamiTK.
typedef itk::ImageToVTKImageFilter<OutputImageType> ItkToVtkFloatFilterType;
typename ItkToVtkFloatFilterType::Pointer itkToVtkFloatFilter = ItkToVtkFloatFilterType::New();
typedef itk::ImageToVTKImageFilter<InputImageType> ItkToVtkOrgFilterType;
typename ItkToVtkOrgFilterType::Pointer itkToVtkOrgFilter = ItkToVtkOrgFilterType::New();
// ------------------------- WRITE YOUR CODE HERE ----------------------------------
// To update CamiTK progress bar while filtering, add an ITK observer to the filters.
ItkProgressObserver::Pointer observer = ItkProgressObserver::New();
// ITK observers generally give values between 0 and 1, and CamiTK progress bar
// wants values between 0 and 100...
observer->SetCoef(100.0);
// --------------------- Plug filters and parameters ---------------------------
// From VTK to ITK
vtkToItkFilter->SetInput(img);
vtkToItkFilter->SetInput(img);
vtkToItkFilter->AddObserver(itk::ProgressEvent(), observer);
vtkToItkFilter->Update();
observer->Reset();
toDoubleFilter->SetInput(vtkToItkFilter->GetOutput());
toDoubleFilter->AddObserver(itk::ProgressEvent(), observer);
toDoubleFilter->Update();
observer->Reset();
filter->SetInput(toDoubleFilter->GetOutput());
filter->SetNumberOfIterations(numberOfIterations);
filter->SetConductanceParameter(conductance);
filter->AddObserver(itk::ProgressEvent(), observer);
filter->Update();
observer->Reset();
if (keepOrgVoxelType) {
toOrgFilter->SetInput(filter->GetOutput());
toOrgFilter->AddObserver(itk::ProgressEvent(), observer);
toOrgFilter->Update();
observer->Reset();
itkToVtkOrgFilter->SetInput(toOrgFilter->GetOutput());
itkToVtkOrgFilter->AddObserver(itk::ProgressEvent(), observer);
itkToVtkOrgFilter->Update();
observer->Reset();
resultImage = itkToVtkOrgFilter->GetOutput();
}
else {
itkToVtkFloatFilter->SetInput(filter->GetOutput());
itkToVtkFloatFilter->AddObserver(itk::ProgressEvent(), observer);
itkToVtkFloatFilter->Update();
observer->Reset();
resultImage = itkToVtkFloatFilter->GetOutput();
}
// --------------------- Create and return a copy (the filters will be deleted)--
int extent[6];
resultImage->GetExtent(extent);
result->SetExtent(extent);
result->DeepCopy(resultImage);
result->Update();
// Set CamiTK progress bar back to zero (the processing filter is over)
observer->Reset();
return result;
}
template <class InputPixelType, class OutputPixelType, const int dim>
vtkSmartPointer<vtkImageData> AnisotropicDiffusion::itkProcessCurvatureAnisotropicDiffusion(vtkSmartPointer<vtkImageData> img)
{
vtkSmartPointer<vtkImageData> result = vtkSmartPointer<vtkImageData>::New();
vtkSmartPointer<vtkImageData> resultImage;
// --------------------- Filters declaration and creation ----------------------
// Define ITK input and output image types with respect to the instanciation
// types of the tamplate.
typedef itk::Image< InputPixelType, dim > InputImageType;
typedef itk::Image< OutputPixelType, dim > OutputImageType;
// Convert the image from CamiTK in VTK format to ITK format to use ITK filters.
typedef itk::VTKImageToImageFilter<InputImageType> vtkToItkFilterType;
typename vtkToItkFilterType::Pointer vtkToItkFilter = vtkToItkFilterType::New();
// To use anisotropic diffusion on real type data
typedef itk::CastImageFilter<InputImageType, OutputImageType> CastFilterType;
typename CastFilterType::Pointer toDoubleFilter = CastFilterType::New();
// Anisotropic filter
typedef itk::CurvatureAnisotropicDiffusionImageFilter<OutputImageType, OutputImageType> FilterType;
typename FilterType::Pointer filter = FilterType::New();
// To go back to the original image type.
typedef itk::RescaleIntensityImageFilter<OutputImageType, InputImageType> ToOrgFilterType;
typename ToOrgFilterType::Pointer toOrgFilter = ToOrgFilterType::New();
// In the same way, once the image is filtered, we need to convert it again to
// VTK format to give it to CamiTK.
typedef itk::ImageToVTKImageFilter<OutputImageType> ItkToVtkFloatFilterType;
typename ItkToVtkFloatFilterType::Pointer itkToVtkFloatFilter = ItkToVtkFloatFilterType::New();
typedef itk::ImageToVTKImageFilter<InputImageType> ItkToVtkOrgFilterType;
typename ItkToVtkOrgFilterType::Pointer itkToVtkOrgFilter = ItkToVtkOrgFilterType::New();
// ------------------------- WRITE YOUR CODE HERE ----------------------------------
// To update CamiTK progress bar while filtering, add an ITK observer to the filters.
ItkProgressObserver::Pointer observer = ItkProgressObserver::New();
// ITK observers generally give values between 0 and 1, and CamiTK progress bar
// wants values between 0 and 100...
observer->SetCoef(100.0);
// --------------------- Plug filters and parameters ---------------------------
// From VTK to ITK
vtkToItkFilter->SetInput(img);
vtkToItkFilter->SetInput(img);
vtkToItkFilter->AddObserver(itk::ProgressEvent(), observer);
vtkToItkFilter->Update();
observer->Reset();
toDoubleFilter->SetInput(vtkToItkFilter->GetOutput());
toDoubleFilter->AddObserver(itk::ProgressEvent(), observer);
toDoubleFilter->Update();
observer->Reset();
filter->SetInput(toDoubleFilter->GetOutput());
filter->SetNumberOfIterations(numberOfIterations);
filter->SetConductanceParameter(conductance);
filter->AddObserver(itk::ProgressEvent(), observer);
filter->Update();
observer->Reset();
if (keepOrgVoxelType) {
toOrgFilter->SetInput(filter->GetOutput());
toOrgFilter->AddObserver(itk::ProgressEvent(), observer);
toOrgFilter->Update();
observer->Reset();
itkToVtkOrgFilter->SetInput(toOrgFilter->GetOutput());
itkToVtkOrgFilter->AddObserver(itk::ProgressEvent(), observer);
itkToVtkOrgFilter->Update();
observer->Reset();
resultImage = itkToVtkOrgFilter->GetOutput();
}
else {
itkToVtkFloatFilter->SetInput(filter->GetOutput());
itkToVtkFloatFilter->AddObserver(itk::ProgressEvent(), observer);
itkToVtkFloatFilter->Update();
observer->Reset();
resultImage = itkToVtkFloatFilter->GetOutput();
}
// --------------------- Create and return a copy (the filters will be deleted)--
int extent[6];
resultImage->GetExtent(extent);
result->SetExtent(extent);
result->DeepCopy(resultImage);
result->Update();
// Set CamiTK progress bar back to zero (the processing filter is over)
observer->Reset();
return result;
}
#ifndef ANISOTROPICDIFFUSION_H
#define ANISOTROPICDIFFUSION_H
#include <QObject>
#include <Action.h>
#include <ImageComponent.h>
#include <DefaultActionWidget.h>
using namespace camitk;
class AnisotropicDiffusion : public Action {
Q_OBJECT
/// Enumerations
Q_ENUMS( AnisoDiffType )
Q_PROPERTY( AnisoDiffType implementation READ getMethod WRITE setMethod)
public:
/// Define the possible implementations of Gaussian filtering
typedef enum AnisoDiffType {Gradient, Curvature };
/// Default Constructor
AnisotropicDiffusion(ActionExtension * extension);
/// Default Destructor
virtual ~AnisotropicDiffusion();
/// Returns the widget that allows to modify the action parameters
virtual QWidget * getWidget();
/** this method is automatically called when the action is triggered.
* Use targetComponents QList to get the list of component to use.
* \note targetComponents is automatically filtered so that it only contains compatible components,
* i.e., instances of ImageComponent (or a subclass).
*/
virtual void apply();
AnisoDiffType getMethod();
void setMethod(AnisoDiffType implementation);
private:
/// helper method to simplify the target component processing
virtual void process(ImageComponent * comp);
vtkSmartPointer<vtkImageData> implementProcess(vtkSmartPointer<vtkImageData> img);
template <class InputPixelType, class OutputPixelType, const int dim>
vtkSmartPointer<vtkImageData> itkProcess(vtkSmartPointer<vtkImageData> img);
template <class InputPixelType, class OutputPixelType, const int dim>
vtkSmartPointer<vtkImageData> itkProcessGradientAnisotropicDiffusion(vtkSmartPointer<vtkImageData> img);
template <class InputPixelType, class OutputPixelType, const int dim>
vtkSmartPointer<vtkImageData> itkProcessCurvatureAnisotropicDiffusion(vtkSmartPointer<vtkImageData> img);
protected:
/// The widget will be filled with parameters
DefaultActionWidget * theWidget;
bool keepOrgVoxelType;
int numberOfIterations;
double conductance;
AnisoDiffType implementation;
};
#endif // ANISOTROPICDIFFUSION_H
vtkSmartPointer<vtkImageData> AnisotropicDiffusion::implementProcess(vtkSmartPointer<vtkImageData> img)
{
vtkSmartPointer<vtkImageData> result = NULL;
if (img == NULL)
return result;
int * dims = img->GetDimensions();
int dim = 0;
if (dims[2] == 0)
dim = 2;
else
dim = 3;
int scalarType = img->GetScalarType();
switch (scalarType)
{
case VTK_CHAR :
if (dim == 2)
result = itkProcess<char, double, 2>(img);
else // if dim == 3
result = itkProcess<char, double, 3>(img);
break;
case VTK_UNSIGNED_CHAR :
if (dim == 2)
result = itkProcess<unsigned char, double, 2>(img);
else // if dim == 3
result = itkProcess<unsigned char, double, 3>(img);
break;
case VTK_SIGNED_CHAR :
if (dim == 2)
result = itkProcess<signed char, double, 2>(img);
else // if dim == 3
result = itkProcess<signed char, double, 3>(img);
break;
case VTK_SHORT :
if (dim == 2)
result = itkProcess<short, double, 2>(img);
else // if dim == 3
result = itkProcess<short, double, 3>(img);
break;
case VTK_UNSIGNED_SHORT :
if (dim == 2)
result = itkProcess<unsigned short, double, 2>(img);
else // if dim == 3
result = itkProcess<unsigned short, double, 3>(img);
break;
case VTK_INT :
if (dim == 2)
result = itkProcess<int, double, 2>(img);
else // if dim == 3
result = itkProcess<int, double, 3>(img);
break;
case VTK_UNSIGNED_INT :
if (dim == 2)
result = itkProcess<unsigned int, double, 2>(img);
else // if dim == 3
result = itkProcess<unsigned int, double, 3>(img);
break;
case VTK_LONG :
if (dim == 2)
result = itkProcess<long, double, 2>(img);
else // if dim == 3
result = itkProcess<long, double, 3>(img);
break;
case VTK_UNSIGNED_LONG :
if (dim == 2)
result = itkProcess<unsigned long, double, 2>(img);
else // if dim == 3
result = itkProcess<unsigned long, double, 3>(img);
break;
case VTK_FLOAT :
if (dim == 2)
result = itkProcess<float, double, 2>(img);
else // if dim == 3
result = itkProcess<float, double, 3>(img);
break;
case VTK_DOUBLE :
if (dim == 2)
result = itkProcess<double, double, 2>(img);
else // if dim == 3
result = itkProcess<double, double, 3>(img);
break;
default :
break;
}
return result;
}
action_extension(
NEEDS_ITK
LIBRARIES ITKBasicFilters ITKCommon ITKIO
)
set(EXTENSION_NAME "itkfiltersextension")
cmake_minimum_required(VERSION 2.6)
project(${EXTENSION_NAME})
include(FindCamiTK.cmake)
include(CreateLaunchers)
action_extension(DEFAULT
NEEDS_ITK
LIBRARIES ITKBasicFilters ITKCommon ITKIO
)
# For Microsoft Visual C++, sets the default application to imp for the "ALL_BUILD" project
# (i.e. launches imp when we you click on "Debug" or "Start Without Debugging" button on Visual)
# In addition, but not the least, sets the environment to the debug dll directory for VTK (and ITK)
# to solve the dll incompatibility between debug and relase version of QVTK.dll and ITKCommon.dll
if ( MSVC )
create_default_target_launcher_special(
"imp"
EXTERNAL_COMMAND "${CAMITK_BIN_DIR}$(OutDir)/imp.exe"
RUNTIME_LIBRARY_DIRS "${CAMITK_BIN_DIR}$(OutDir)" "%VTK_DIR%/bin/$(OutDir)" "%ITK_DIR%/bin/$(OutDir)"
)
endif()
#include "CannyEdgeDetection.h"
#include <Application.h>
#include <ItkProgressObserver.h>
#include <QMessageBox>
#include <QString>
#include <QTextStream>
#include <itkImageToVTKImageFilter.h>
#include <itkVTKImageToImageFilter.h>
#include <itkCastImageFilter.h>
#include <itkRescaleIntensityImageFilter.h>
#include <itkCannyEdgeDetectionImageFilter.h>
using namespace camitk;
// --------------- constructor -------------------
CannyEdgeDetection::CannyEdgeDetection(ActionExtension * extension) : Action(extension) {
// Setting name, description and input component
setName("Canny Edge Detecton");
setDescription("<br>The <b> <i>Canny edge detector</i> </b> is an edge detection operator that uses a multi-stage algorithm to detect a wide range of edges in images. <br> \
It was developed by John F. Canny in 1986. <i>(source: Wikipedia)</i>.<br> \
This filter is widely used for edge detection since it is the optimal solution satisfying the constraints of good sensitivity, localization and noise robustness. <i>(source: ITK Developer's Guide)</i>.<br> ");
setComponent("ImageComponent");
setEmbedded(true);
// Setting classification family and tags
this->setFamily("ITK Filter");
this->addTag("canny");
this->addTag("Edge Detection");
this->addTag("Contours");
// Setting parameters default values
setProperty("keepOriginalImageVoxelType", QVariant(true));
setProperty("variance", QVariant(2.0));
setProperty("upperThreshold", QVariant(0.0));
setProperty("lowerThreshold", QVariant(0.0));
keepOrgVoxelType = true;
// Setting the widget containing the parameters
theWidget = NULL;
}
// --------------- destructor -------------------
CannyEdgeDetection::~CannyEdgeDetection() {
// do not delete the widget has it might have been used in the ActionViewer (i.e. the ownership might have been taken by the stacked widget)
}
// --------------- getWidget --------------
QWidget * CannyEdgeDetection::getWidget() {
// build or update the widget
if (!theWidget) {
// Setting the widget containing the parameters, using the default widget
theWidget = new DefaultActionWidget(this);
}
<