Skip to content

Commit

Permalink
Merge pull request #1251 from mathildemerle/registrationMedInria
Browse files Browse the repository at this point in the history
[Registration] cast data in LCC and Diffeo, enhance txt in Manual
  • Loading branch information
Florent2305 authored Oct 16, 2024
2 parents 14e61b1 + e011fa5 commit 7eb6a74
Show file tree
Hide file tree
Showing 9 changed files with 59 additions and 126 deletions.
6 changes: 5 additions & 1 deletion RELEASE_NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ medInria 4.0:
- Switch to Ubuntu 22.
- PolygonROI: update icons, fix a glitch when users change ROI label, hide label panel in pipelines.
- Fix some plugins wrongly loaded on Windows.
- BUGFIX 4.0.1: fix the path to the online documentation.
- BUGFIX 4.0.1:
* Fix the path to the online documentation.
* Allow to use data with different size or spacing in LCCLogDemons and DiffeomorphicDemons.
* Manual Registration: enhance landmark numbers for better user understanding.
* Fix Histogram Analysis width problem displaying multi-results.

medInria 3.3:
- Fix mirrored DICOM images problem
Expand Down
60 changes: 21 additions & 39 deletions src/plugins/legacy/LCCLogDemons/LCCLogDemons.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
// /////////////////////////////////////////////////////////////////

#include <itkImageRegistrationMethod.h>

#include <itkImage.h>
#include <itkResampleImageFilter.h>
#include <itkCastImageFilter.h>
Expand Down Expand Up @@ -167,17 +166,24 @@ QString LCCLogDemons::description() const
template <typename PixelType>
int LCCLogDemonsPrivate::update()
{
int testResult = proc->testInputs();
if (testResult != medAbstractProcessLegacy::SUCCESS)
{
return testResult;
}

RegImageType *inputFixed = static_cast<RegImageType*>(proc->fixedImage().GetPointer());
RegImageType *inputMoving = static_cast<RegImageType*>(proc->movingImages()[0].GetPointer());

// Cast spacing, origin, direction and size from the moving data to the fixed one
typedef itk::ResampleImageFilter<RegImageType, RegImageType> ResampleFilterType;
typename ResampleFilterType::Pointer resampleFilter = ResampleFilterType::New();
resampleFilter->SetOutputSpacing(inputFixed->GetSpacing());
resampleFilter->SetOutputOrigin(inputFixed->GetOrigin());
resampleFilter->SetOutputDirection(inputFixed->GetDirection());
resampleFilter->SetSize(inputFixed->GetLargestPossibleRegion().GetSize());
resampleFilter->SetInput(inputMoving);
resampleFilter->Update();
inputMoving = resampleFilter->GetOutput();

// Register the fixed and moving data
registrationMethod = new rpi::LCClogDemons<RegImageType,RegImageType,double> ();

registrationMethod->SetFixedImage((const RegImageType*) proc->fixedImage().GetPointer());
registrationMethod->SetMovingImage((const RegImageType*) proc->movingImages()[0].GetPointer());

registrationMethod->SetFixedImage(inputFixed);
registrationMethod->SetMovingImage(inputMoving);
registrationMethod->SetUpdateRule(updateRule);
registrationMethod->SetVerbosity(verbose);

Expand Down Expand Up @@ -219,12 +225,8 @@ int LCCLogDemonsPrivate::update()
typedef itk::ResampleImageFilter< RegImageType,RegImageType, double> ResampleFilterType;
typename ResampleFilterType::Pointer resampler = ResampleFilterType::New();
resampler->SetTransform(registrationMethod->GetDisplacementFieldTransformation());
resampler->SetInput((const RegImageType*)proc->movingImages()[0].GetPointer());
resampler->SetSize( proc->fixedImage()->GetLargestPossibleRegion().GetSize() );
resampler->SetOutputOrigin( proc->fixedImage()->GetOrigin() );
resampler->SetOutputSpacing( proc->fixedImage()->GetSpacing() );
resampler->SetOutputDirection( proc->fixedImage()->GetDirection() );
resampler->SetDefaultPixelValue( 0 );
resampler->SetInput(inputMoving);
resampler->SetDefaultPixelValue(0);

// Set the image interpolator
switch(interpolatorType)
Expand Down Expand Up @@ -266,31 +268,11 @@ int LCCLogDemonsPrivate::update()
qDebug() << "ExceptionObject caught (resampler): " << err.GetDescription();
return medAbstractProcessLegacy::FAILURE;
}

itk::ImageBase<3>::Pointer result = resampler->GetOutput();
result->DisconnectPipeline();

if (proc->output())
{
proc->output()->setData (result);
}
return medAbstractProcessLegacy::SUCCESS;
}

medAbstractProcessLegacy::DataError LCCLogDemons::testInputs()
{
if (d->proc->fixedImage()->GetLargestPossibleRegion().GetSize()
!= d->proc->movingImages()[0]->GetLargestPossibleRegion().GetSize())
{
return medAbstractProcessLegacy::MISMATCHED_DATA_SIZE;
}

if (d->proc->fixedImage()->GetSpacing()
!= d->proc->movingImages()[0]->GetSpacing())
if (proc->output())
{
return medAbstractProcessLegacy::MISMATCHED_DATA_SPACING;
proc->output()->setData(resampler->GetOutput());
}

return medAbstractProcessLegacy::SUCCESS;
}

Expand Down
5 changes: 0 additions & 5 deletions src/plugins/legacy/LCCLogDemons/LCCLogDemons.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,6 @@ class LCCLogDemonsPLUGIN_EXPORT LCCLogDemons : public itkProcessRegistration
*/
virtual QString getTitleAndParameters();

/**
* @brief testInputs() tests origin, dimension and spacing of the input
* @return medAbstractProcess::DataError according to the test result
*/
medAbstractProcessLegacy::DataError testInputs();
protected :
/**
* @brief
Expand Down
7 changes: 0 additions & 7 deletions src/plugins/legacy/LCCLogDemons/LCCLogDemonsToolBox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,8 @@ class LCCLogDemonsToolBoxPrivate
LCCLogDemonsToolBox::LCCLogDemonsToolBox(QWidget *parent) : medAbstractSelectableToolBox(parent), d(new LCCLogDemonsToolBoxPrivate)
{
QWidget *widget = new QWidget(this);

QVBoxLayout * layout = new QVBoxLayout();

QLabel *explanation = new QLabel("Drop 2 datasets with same size and spacing.\n");
explanation->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred);
explanation->setWordWrap(true);
explanation->setStyleSheet("font: italic");
layout->addWidget(explanation);

// Standard parameters
d->iterationsLine = new QLineEdit();
d->iterationsLine->setText("15x10x5");
Expand Down
79 changes: 25 additions & 54 deletions src/plugins/legacy/diffeomorphicDemons/diffeomorphicDemons.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

#include <dtkCoreSupport/dtkAbstractProcessFactory.h>
#include <DiffeomorphicDemons/rpiDiffeomorphicDemons.hxx>
#include <itkChangeInformationImageFilter.h>
#include <itkResampleImageFilter.h>
#include <rpiCommonTools.hxx>

// /////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -93,33 +93,29 @@ int diffeomorphicDemonsPrivate::update()
{
typedef itk::Image< PixelType, 3 > FixedImageType;
typedef itk::Image< PixelType, 3 > MovingImageType;

typedef itk::Image< float, 3 > RegImageType;
typedef double TransformScalarType;

int testResult = proc->testInputs();
if (testResult != medAbstractProcessLegacy::SUCCESS)
{
return testResult;
}

FixedImageType *inputFixed = (FixedImageType*) proc->fixedImage().GetPointer();
MovingImageType *inputMoving = (MovingImageType*) proc->movingImages()[0].GetPointer();

// The output volume is going to located at the origin/direction of the fixed input. Needed for rpi::DiffeomorphicDemons
typedef itk::ChangeInformationImageFilter< FixedImageType > FilterType;
typename FilterType::Pointer filter = FilterType::New();
filter->SetOutputOrigin(inputFixed->GetOrigin());
filter->ChangeOriginOn();
filter->SetOutputDirection(inputFixed->GetDirection());
filter->ChangeDirectionOn();
filter->SetInput(inputMoving);

FixedImageType *inputFixed = static_cast<FixedImageType*>(proc->fixedImage().GetPointer());
MovingImageType *inputMoving = static_cast<MovingImageType*>(proc->movingImages()[0].GetPointer());

// Cast spacing, origin, direction and size from the moving data to the fixed one
typedef itk::ResampleImageFilter<MovingImageType, MovingImageType> ResampleFilterType;
typename ResampleFilterType::Pointer resampleFilter = ResampleFilterType::New();
resampleFilter->SetOutputSpacing(inputFixed->GetSpacing());
resampleFilter->SetOutputOrigin(inputFixed->GetOrigin());
resampleFilter->SetOutputDirection(inputFixed->GetDirection());
resampleFilter->SetSize(inputFixed->GetLargestPossibleRegion().GetSize());
resampleFilter->SetInput(inputMoving);
resampleFilter->Update();
inputMoving = resampleFilter->GetOutput();

// Register the fixed and moving data
typedef rpi::DiffeomorphicDemons< RegImageType, RegImageType, TransformScalarType > RegistrationType;
RegistrationType *registration = new RegistrationType;
registrationMethod = registration;
registration->SetFixedImage(inputFixed);
registration->SetMovingImage(filter->GetOutput());
registration->SetMovingImage(inputMoving);
registration->SetNumberOfIterations(iterations);
registration->SetMaximumUpdateStepLength(maximumUpdateStepLength);
registration->SetUpdateFieldStandardDeviation(updateFieldStandardDeviation);
Expand Down Expand Up @@ -160,7 +156,6 @@ int diffeomorphicDemonsPrivate::update()

// Print method parameters
QString methodParameters = proc->getTitleAndParameters();

qDebug() << "METHOD PARAMETERS";
qDebug() << methodParameters;

Expand All @@ -181,53 +176,29 @@ int diffeomorphicDemonsPrivate::update()

emit proc->progressed(80);

typedef itk::ResampleImageFilter< MovingImageType,MovingImageType,TransformScalarType > ResampleFilterType;
typename ResampleFilterType::Pointer resampler = ResampleFilterType::New();
resampler->SetTransform(registration->GetTransformation());
resampler->SetInput((const MovingImageType*) inputMoving);
resampler->SetSize( proc->fixedImage()->GetLargestPossibleRegion().GetSize() );
resampler->SetOutputOrigin( proc->fixedImage()->GetOrigin() );
resampler->SetOutputSpacing( proc->fixedImage()->GetSpacing() );
resampler->SetOutputDirection( proc->fixedImage()->GetDirection() );
resampler->SetDefaultPixelValue( 0 );

// Cast new transformation
typedef itk::ResampleImageFilter< MovingImageType,MovingImageType,TransformScalarType > ResampleTransformation;
typename ResampleTransformation::Pointer resampleTransformation = ResampleTransformation::New();
resampleTransformation->SetTransform(registration->GetTransformation());
resampleTransformation->SetInput(inputMoving);
resampleTransformation->SetDefaultPixelValue(0);
try
{
resampler->Update();
resampleTransformation->Update();
}
catch (itk::ExceptionObject & err)
{
qDebug() << "ExceptionObject caught (resampler): " << err.GetDescription();
return medAbstractProcessLegacy::FAILURE;
}

itk::ImageBase<3>::Pointer result = resampler->GetOutput();
result->DisconnectPipeline();

if (proc->output())
{
proc->output()->setData (result);
proc->output()->setData(resampleTransformation->GetOutput());
}
return medAbstractProcessLegacy::SUCCESS;
}

medAbstractProcessLegacy::DataError diffeomorphicDemons::testInputs()
{
if (d->proc->fixedImage()->GetLargestPossibleRegion().GetSize()
!= d->proc->movingImages()[0]->GetLargestPossibleRegion().GetSize())
{
return medAbstractProcessLegacy::MISMATCHED_DATA_SIZE;
}

if (d->proc->fixedImage()->GetSpacing()
!= d->proc->movingImages()[0]->GetSpacing())
{
return medAbstractProcessLegacy::MISMATCHED_DATA_SPACING;
}

return medAbstractProcessLegacy::SUCCESS;
}

int diffeomorphicDemons::update(itkProcessRegistration::ImageType imgType)
{
// Cast has been done in itkProcessRegistration
Expand Down
6 changes: 0 additions & 6 deletions src/plugins/legacy/diffeomorphicDemons/diffeomorphicDemons.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,12 +138,6 @@ class DIFFEOMORPHICDEMONSPLUGIN_EXPORT diffeomorphicDemons : public itkProcessRe
*/
virtual QString getTitleAndParameters();

/**
* @brief testInputs() tests origin, dimension and spacing of the input
* @return medAbstractProcess::DataError according to the test result
*/
medAbstractProcessLegacy::DataError testInputs();

protected :
/**
* @brief Writes the transformation, in this case the displacement field,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,8 @@ diffeomorphicDemonsToolBox::diffeomorphicDemonsToolBox(QWidget *parent)
: medAbstractSelectableToolBox(parent), d(new diffeomorphicDemonsToolBoxPrivate)
{
QWidget *widget = new QWidget(this);

QVBoxLayout *layout = new QVBoxLayout();

QLabel *explanation = new QLabel("Drop 2 datasets with same size and spacing.\n");
explanation->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred);
explanation->setWordWrap(true);
explanation->setStyleSheet("font: italic");
layout->addWidget(explanation);

d->iterationsBox = new QLineEdit();
d->iterationsBox->setText("15x10x5");
d->iterationsBox->setToolTip(tr("Each number of iteration per level must be separated by \"x\". From coarser to finest levels"));
Expand Down
6 changes: 3 additions & 3 deletions src/plugins/legacy/manualRegistration/manualRegistration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,12 @@ template <typename PixelType, typename TransformType> int manualRegistrationPriv
typedef itk::ResampleImageFilter< MovingImageType,MovingImageType,TransformScalarType > ResampleFilterType;
typename ResampleFilterType::Pointer resampler = ResampleFilterType::New();
resampler->SetTransform(transform);
resampler->SetInput((const MovingImageType*)proc->movingImages()[0].GetPointer());
resampler->SetSize( proc->fixedImage()->GetLargestPossibleRegion().GetSize() );
resampler->SetInput(static_cast<const MovingImageType*>(proc->movingImages()[0].GetPointer()));
resampler->SetSize(proc->fixedImage()->GetLargestPossibleRegion().GetSize());
resampler->SetOutputOrigin( proc->fixedImage()->GetOrigin() );
resampler->SetOutputSpacing( proc->fixedImage()->GetSpacing() );
resampler->SetOutputDirection( proc->fixedImage()->GetDirection() );
resampler->SetDefaultPixelValue( 0 );
resampler->SetDefaultPixelValue(0);

try
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,10 @@ manualRegistrationToolBox::manualRegistrationToolBox(QWidget *parent)
d->b_startManualRegistration->setObjectName("startManualRegistrationButton");

d->explanation = new QLabel("To add a landmark: \n\tShift + left mouse button\nTo remove a pair of landmarks: \n\tBackspace + left mouse button", widget);
d->explanation->setStyleSheet("font: italic");

d->numberOfLdInLeftContainer = new QLabel("Number of landmarks in left container: 0", widget);
d->numberOfLdInRightContainer = new QLabel("Number of landmarks in right container: 0", widget);
d->numberOfLdInLeftContainer = new QLabel("Number of landmarks in left container: <b>0</b>", widget);
d->numberOfLdInRightContainer = new QLabel("Number of landmarks in right container: <b>0</b>", widget);

// Choice between transformations
QHBoxLayout* transformationLayout = new QHBoxLayout;
Expand Down Expand Up @@ -564,8 +565,8 @@ void manualRegistrationToolBox::displayButtons(bool show)

void manualRegistrationToolBox::updateGUI(int left, int right)
{
d->numberOfLdInLeftContainer->setText( "Number of landmarks in left container: " + QString::number(left));
d->numberOfLdInRightContainer->setText("Number of landmarks in right container: " + QString::number(right));
d->numberOfLdInLeftContainer->setText(QString("Number of landmarks in left container: <b>%1</b>").arg(left));
d->numberOfLdInRightContainer->setText(QString("Number of landmarks in right container: <b>%1</b>").arg(right));

if (left == right)
{
Expand Down

0 comments on commit 7eb6a74

Please sign in to comment.