[Insight-developers] RescaleIntensityImageFilter is broken!

John M. Galeotti jgaleotti@cmu.edu
Thu, 27 Feb 2003 18:00:28 -0500


--Apple-Mail-4--639848275
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
	charset=US-ASCII;
	format=flowed

RescaleIntensityImageFilter does not work for some output data types.  
Specifically, it incorrectly chooses the scaling parameter when 
converting from unsigned char to either int or long, and as a result 
produces a completely black image.  Also, the VNL numeric traits 
implementation seems to be missing a definition for the type unsigned.

I've attached a relatively simple program (110 lines) to demonstrate 
the problems.  It is explained in the first 40 lines of code.

This should probably be fixed before the upcoming release.

Thank you,
John Galeotti


--Apple-Mail-4--639848275
Content-Disposition: attachment;
	filename=CMakeLists.txt
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
	x-unix-mode=0644;
	name="CMakeLists.txt"

PROJECT(DeadTest)

# Find ITK
INCLUDE (${CMAKE_ROOT}/Modules/FindITK.cmake)

# Use ITK.  This sets up include/link directories for us.
IF (USE_ITK_FILE)
  INCLUDE(${USE_ITK_FILE})
ENDIF(USE_ITK_FILE)

# Add the executable with our source file.
ADD_EXECUTABLE(DeadTestRescaleFilter DeadTestRescaleFilter.cxx)

# We need a few of the ITK libraries
TARGET_LINK_LIBRARIES(DeadTestRescaleFilter ITKCommon ITKIO)

--Apple-Mail-4--639848275
Content-Disposition: attachment;
	filename=DeadTestRescaleFilter.cxx
Content-Transfer-Encoding: 7bit
Content-Type: application/octet-stream;
	x-unix-mode=0644;
	name="DeadTestRescaleFilter.cxx"

// DeadTestRescaleFilter.cxx, tests itk::RescaleIntensityImageFilter
// John M. Galeotti, jgaleotti@cmu.edu, CMU Robotics Institute PhD student
// Created 2-27-03

#include <iostream.h>
#include "itkPNGImageIO.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkImage.h"
#include "itkRescaleIntensityImageFilter.h"

// This program rescales an input PNG image (unsigned char) to an arbitrary data
// type, making full use of the available dynamic range of the new data type. 
// It then rescales the new image back to the original data type to write back
// to another PNG image.  In general, the output image should have at least as
// much contrast as the input imag.  If the input image had good contrast, then
// the input and output should be virtually the same.

// To BREAK this program, try setting RescalerPixelType, below, to type long.
// The problem seems to be that RescaleIntensityImageFilter incorrectly
// calculates the scaling value.

int main(int argc, char *argv[])
{
/* ** The type of RescalerPixelType determines whether or not rescaling the
   ** image intensity works.
   ** 
   ** Types that work for me:
   **     char, unsigned char, short, unsigned short, unsigned long, double.
   ** 
   ** Types that DO NOT WORK for me:
   **     int, long.
   ** 
   ** Furthermore, the type unsigned int will not even compile; the linker
   ** complains that vnl_numeric_limits<unsigned>::min() is an undefined symbol.
*/
  typedef int RescalerPixelType;
  typedef itk::Image<RescalerPixelType, 2> RescalerImageType;

  typedef unsigned char PixelType;
  typedef itk::Image<PixelType, 2> ImageType;

  // Input Rescaler 1
  typedef itk::RescaleIntensityImageFilter< ImageType, RescalerImageType>
      InputRescaler1Type;
  // Input Rescaler 2
  typedef itk::RescaleIntensityImageFilter< RescalerImageType, ImageType>
      InputRescaler2Type;
  
  // Create the IO object to read and write PNG images
  itk::PNGImageIO::Pointer io;
  io = itk::PNGImageIO::New();
  
  // Check for File name on command line
  if( argc < 2 )
    {
    cerr << "Error:  No input-image file name given" << endl;
    return 1;
    }
  
  // Image Reader
  itk::ImageFileReader<ImageType>::Pointer reader;
  reader = itk::ImageFileReader<ImageType>::New();
  // Set the parameters of the reader
  reader->SetFileName(argv[1]);
  reader->SetImageIO(io);
  
  // Input rescaler 1
  InputRescaler1Type::Pointer rescalerIn1 = InputRescaler1Type::New();
//rescalerIn1->DebugOn();
  rescalerIn1->SetInput( reader->GetOutput() );
  rescalerIn1->SetOutputMinimum(
      itk::NumericTraits<RescalerPixelType>::min() );
  rescalerIn1->SetOutputMaximum(
      itk::NumericTraits<RescalerPixelType>::max() );
  // Input rescaler 2
  InputRescaler2Type::Pointer rescalerIn2 = InputRescaler2Type::New();
//rescalerIn2->DebugOn();
  rescalerIn2->SetInput( rescalerIn1->GetOutput() );
  rescalerIn2->SetOutputMinimum( itk::NumericTraits<PixelType>::min() );
  rescalerIn2->SetOutputMaximum( itk::NumericTraits<PixelType>::max() );
  
  // Image Writer
  itk::ImageFileWriter<ImageType>::Pointer writer;
  writer = itk::ImageFileWriter<ImageType>::New();
  // Set the parameters of the writer
  writer->SetInput(rescalerIn2->GetOutput());
  writer->SetFileName("RescaledImage.png");
  writer->SetImageIO(io);
  // Write the output
  writer->Write();
  
  // Print a helpful message
  cout << "Input image first rescaled from the range [" <<
      double(rescalerIn1->GetInputMinimum()) << "," << double(rescalerIn1->GetInputMaximum())
      << "] to the range [" <<
      double(rescalerIn1->GetOutputMinimum()) << "," << double(rescalerIn1->GetOutputMaximum())
      << "] by scaling " << rescalerIn1->GetScale() << " and by shifting "
      << rescalerIn1->GetShift() << "." << endl;
  cout << "Input image then rescaled from the range [" <<
      double(rescalerIn2->GetInputMinimum()) << "," << double(rescalerIn2->GetInputMaximum())
      << "] to the range [" <<
      double(rescalerIn2->GetOutputMinimum()) << "," << double(rescalerIn2->GetOutputMaximum())
      << "] by scaling " << rescalerIn2->GetScale() << " and by shifting "
      << rescalerIn2->GetShift() << "." << endl;
  cout << "Doubly rescaled image saved as RescaledImage.png" << endl;
  
  // Exit successfully
  return 0;
}

--Apple-Mail-4--639848275--