153 lines
4.9 KiB
C
153 lines
4.9 KiB
C
|
|
/*=========================================================================
|
||
|
|
|
||
|
|
Program: Visualization Toolkit
|
||
|
|
Module: vtkImageDifference.h
|
||
|
|
|
||
|
|
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
|
||
|
|
All rights reserved.
|
||
|
|
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
|
||
|
|
|
||
|
|
This software is distributed WITHOUT ANY WARRANTY; without even
|
||
|
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||
|
|
PURPOSE. See the above copyright notice for more information.
|
||
|
|
|
||
|
|
=========================================================================*/
|
||
|
|
/**
|
||
|
|
* @class vtkImageDifference
|
||
|
|
* @brief Compares images for regression tests.
|
||
|
|
*
|
||
|
|
* vtkImageDifference takes two rgb unsigned char images and compares them.
|
||
|
|
* It allows the images to be slightly different. If AllowShift is on,
|
||
|
|
* then each pixel can be shifted by two pixels. Threshold is the allowable
|
||
|
|
* error for each pixel.
|
||
|
|
*
|
||
|
|
* This is a symmetric filter and the difference computed is symmetric.
|
||
|
|
* The resulting value is the maximum error of the two directions
|
||
|
|
* A->B and B->A
|
||
|
|
*/
|
||
|
|
|
||
|
|
#ifndef vtkImageDifference_h
|
||
|
|
#define vtkImageDifference_h
|
||
|
|
|
||
|
|
#include "vtkImagingCoreModule.h" // For export macro
|
||
|
|
#include "vtkSmartPointer.h" // For smart pointer
|
||
|
|
#include "vtkThreadedImageAlgorithm.h"
|
||
|
|
|
||
|
|
class vtkImageDifferenceThreadData;
|
||
|
|
class vtkImageDifferenceSMPThreadLocal;
|
||
|
|
|
||
|
|
class VTKIMAGINGCORE_EXPORT vtkImageDifference : public vtkThreadedImageAlgorithm
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
static vtkImageDifference* New();
|
||
|
|
vtkTypeMacro(vtkImageDifference, vtkThreadedImageAlgorithm);
|
||
|
|
void PrintSelf(ostream& os, vtkIndent indent) override;
|
||
|
|
|
||
|
|
///@{
|
||
|
|
/**
|
||
|
|
* Specify the Image to compare the input to.
|
||
|
|
*/
|
||
|
|
void SetImageConnection(vtkAlgorithmOutput* output) { this->SetInputConnection(1, output); }
|
||
|
|
void SetImageData(vtkDataObject* image) { this->SetInputData(1, image); }
|
||
|
|
vtkImageData* GetImage();
|
||
|
|
///@}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Return the total error in comparing the two images.
|
||
|
|
*/
|
||
|
|
double GetError() { return this->Error; }
|
||
|
|
void GetError(double* e) { *e = this->GetError(); }
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Return the total thresholded error in comparing the two images.
|
||
|
|
* The thresholded error is the error for a given pixel minus the
|
||
|
|
* threshold and clamped at a minimum of zero.
|
||
|
|
*/
|
||
|
|
double GetThresholdedError() { return this->ThresholdedError; }
|
||
|
|
void GetThresholdedError(double* e) { *e = this->GetThresholdedError(); }
|
||
|
|
|
||
|
|
///@{
|
||
|
|
/**
|
||
|
|
* Specify a threshold tolerance for pixel differences.
|
||
|
|
*/
|
||
|
|
vtkSetMacro(Threshold, int);
|
||
|
|
vtkGetMacro(Threshold, int);
|
||
|
|
///@}
|
||
|
|
|
||
|
|
///@{
|
||
|
|
/**
|
||
|
|
* Specify whether the comparison will allow a shift of two
|
||
|
|
* pixels between the images. If set, then the minimum difference
|
||
|
|
* between input images will be used to determine the difference.
|
||
|
|
* Otherwise, the difference is computed directly between pixels
|
||
|
|
* of identical row/column values.
|
||
|
|
*/
|
||
|
|
vtkSetMacro(AllowShift, bool);
|
||
|
|
vtkGetMacro(AllowShift, bool);
|
||
|
|
vtkBooleanMacro(AllowShift, bool);
|
||
|
|
///@}
|
||
|
|
|
||
|
|
///@{
|
||
|
|
/**
|
||
|
|
* Specify whether the comparison will include comparison of
|
||
|
|
* averaged 3x3 data between the images. For graphics renderings
|
||
|
|
* you normally would leave this on. For imaging operations it
|
||
|
|
* should be off.
|
||
|
|
*/
|
||
|
|
vtkSetMacro(Averaging, bool);
|
||
|
|
vtkGetMacro(Averaging, bool);
|
||
|
|
vtkBooleanMacro(Averaging, bool);
|
||
|
|
///@}
|
||
|
|
|
||
|
|
///@{
|
||
|
|
/**
|
||
|
|
* When doing Averaging, adjust the threshold for the average
|
||
|
|
* by this factor. Defaults to 0.5 requiring a better match
|
||
|
|
*/
|
||
|
|
vtkSetMacro(AverageThresholdFactor, double);
|
||
|
|
vtkGetMacro(AverageThresholdFactor, double);
|
||
|
|
///@}
|
||
|
|
|
||
|
|
protected:
|
||
|
|
vtkImageDifference();
|
||
|
|
~vtkImageDifference() override = default;
|
||
|
|
|
||
|
|
// Parameters
|
||
|
|
// ideally threshold * averageThresholdFactor should be < 255/9
|
||
|
|
// to capture one pixel errors or 510/9 to capture 2 pixel errors
|
||
|
|
bool AllowShift = true;
|
||
|
|
bool Averaging = true;
|
||
|
|
int Threshold = 105;
|
||
|
|
double AverageThresholdFactor = 0.65;
|
||
|
|
|
||
|
|
// Outputs
|
||
|
|
const char* ErrorMessage = nullptr;
|
||
|
|
double Error = 0.;
|
||
|
|
double ThresholdedError = 0.;
|
||
|
|
|
||
|
|
int RequestInformation(vtkInformation*, vtkInformationVector**, vtkInformationVector*) override;
|
||
|
|
int RequestUpdateExtent(vtkInformation*, vtkInformationVector**, vtkInformationVector*) override;
|
||
|
|
int RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*) override;
|
||
|
|
|
||
|
|
void ThreadedRequestData(vtkInformation* request, vtkInformationVector** inputVector,
|
||
|
|
vtkInformationVector* outputVector, vtkImageData*** inData, vtkImageData** outData,
|
||
|
|
int outExt[6], int threadId) override;
|
||
|
|
|
||
|
|
void GrowExtent(int* uExt, int* wholeExtent);
|
||
|
|
int ComputeSumedValue(unsigned char* values, vtkIdType* indices, int comp);
|
||
|
|
|
||
|
|
// Used for vtkMultiThreader operation.
|
||
|
|
vtkImageDifferenceThreadData* ThreadData;
|
||
|
|
|
||
|
|
// Used for vtkSMPTools operation.
|
||
|
|
vtkImageDifferenceSMPThreadLocal* SMPThreadData = nullptr;
|
||
|
|
|
||
|
|
private:
|
||
|
|
vtkImageDifference(const vtkImageDifference&) = delete;
|
||
|
|
void operator=(const vtkImageDifference&) = delete;
|
||
|
|
|
||
|
|
friend class vtkImageDifferenceSMPFunctor;
|
||
|
|
};
|
||
|
|
|
||
|
|
#endif
|