Cloned library of VTK-5.0.0 with extra build files for internal package management.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

457 lines
14 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkImageAccumulate.cxx,v $
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.
=========================================================================*/
#include "vtkImageAccumulate.h"
#include "vtkImageData.h"
#include "vtkImageStencilData.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include <math.h>
vtkCxxRevisionMacro(vtkImageAccumulate, "$Revision: 1.64 $");
vtkStandardNewMacro(vtkImageAccumulate);
//----------------------------------------------------------------------------
// Constructor sets default values
vtkImageAccumulate::vtkImageAccumulate()
{
int idx;
for (idx = 0; idx < 3; ++idx)
{
this->ComponentSpacing[idx] = 1.0;
this->ComponentOrigin[idx] = 0.0;
this->ComponentExtent[idx*2] = 0;
this->ComponentExtent[idx*2+1] = 0;
}
this->ComponentExtent[1] = 255;
this->ReverseStencil = 0;
this->Min[0] = this->Min[1] = this->Min[2] = 0.0;
this->Max[0] = this->Max[1] = this->Max[2] = 0.0;
this->Mean[0] = this->Mean[1] = this->Mean[2] = 0.0;
this->StandardDeviation[0] = this->StandardDeviation[1] = this->StandardDeviation[2] = 0.0;
this->VoxelCount = 0;
// we have the image input and the optional stencil input
this->SetNumberOfInputPorts(2);
}
//----------------------------------------------------------------------------
vtkImageAccumulate::~vtkImageAccumulate()
{
}
//----------------------------------------------------------------------------
void vtkImageAccumulate::SetComponentExtent(int extent[6])
{
int idx, modified = 0;
for (idx = 0; idx < 6; ++idx)
{
if (this->ComponentExtent[idx] != extent[idx])
{
this->ComponentExtent[idx] = extent[idx];
this->Modified();
}
}
if (modified)
{
this->Modified();
}
}
//----------------------------------------------------------------------------
void vtkImageAccumulate::SetComponentExtent(int minX, int maxX,
int minY, int maxY,
int minZ, int maxZ)
{
int extent[6];
extent[0] = minX; extent[1] = maxX;
extent[2] = minY; extent[3] = maxY;
extent[4] = minZ; extent[5] = maxZ;
this->SetComponentExtent(extent);
}
//----------------------------------------------------------------------------
void vtkImageAccumulate::GetComponentExtent(int extent[6])
{
int idx;
for (idx = 0; idx < 6; ++idx)
{
extent[idx] = this->ComponentExtent[idx];
}
}
//----------------------------------------------------------------------------
void vtkImageAccumulate::SetStencil(vtkImageStencilData *stencil)
{
this->SetInput(1, stencil);
}
//----------------------------------------------------------------------------
vtkImageStencilData *vtkImageAccumulate::GetStencil()
{
if (this->GetNumberOfInputConnections(1) < 1)
{
return 0;
}
return vtkImageStencilData::SafeDownCast(
this->GetExecutive()->GetInputData(1, 0));
}
//----------------------------------------------------------------------------
// This templated function executes the filter for any type of data.
template <class T>
void vtkImageAccumulateExecute(vtkImageAccumulate *self,
vtkImageData *inData, T *inPtr,
vtkImageData *outData, int *outPtr,
double Min[3], double Max[3],
double Mean[3],
double StandardDeviation[3],
long int *VoxelCount,
int* updateExtent)
{
int idX, idY, idZ, idxC;
int iter, pmin0, pmax0, min0, max0, min1, max1, min2, max2;
vtkIdType inInc0, inInc1, inInc2;
T *tempPtr;
int *outPtrC;
int numC, outIdx, *outExtent;
vtkIdType *outIncs;
double *origin, *spacing;
unsigned long count = 0;
unsigned long target;
double sumSqr[3], variance;
// variables used to compute statistics (filter handles max 3 components)
double sum[3];
sum[0] = sum[1] = sum[2] = 0.0;
Min[0] = Min[1] = Min[2] = VTK_DOUBLE_MAX;
Max[0] = Max[1] = Max[2] = VTK_DOUBLE_MIN;
sumSqr[0] = sumSqr[1] = sumSqr[2] = 0.0;
StandardDeviation[0] = StandardDeviation[1] = StandardDeviation[2] = 0.0;
*VoxelCount = 0;
vtkImageStencilData *stencil = self->GetStencil();
// Zero count in every bin
outData->GetExtent(min0, max0, min1, max1, min2, max2);
memset((void *)outPtr, 0,
(max0-min0+1)*(max1-min1+1)*(max2-min2+1)*sizeof(int));
// Get information to march through data
numC = inData->GetNumberOfScalarComponents();
min0 = updateExtent[0];
max0 = updateExtent[1];
min1 = updateExtent[2];
max1 = updateExtent[3];
min2 = updateExtent[4];
max2 = updateExtent[5];
inData->GetIncrements(inInc0, inInc1, inInc2);
outExtent = outData->GetExtent();
outIncs = outData->GetIncrements();
origin = outData->GetOrigin();
spacing = outData->GetSpacing();
target = (unsigned long)((max2 - min2 + 1)*(max1 - min1 +1)/50.0);
target++;
int reverse = self->GetReverseStencil();
// Loop through input pixels
for (idZ = min2; idZ <= max2; idZ++)
{
for (idY = min1; idY <= max1; idY++)
{
if (!(count%target))
{
self->UpdateProgress(count/(50.0*target));
}
count++;
// loop over stencil sub-extents, -1 flags
// that we want the complementary extents
iter = reverse ? -1 : 0;
pmin0 = min0;
pmax0 = max0;
while ((stencil != 0 &&
stencil->GetNextExtent(pmin0,pmax0,min0,max0,idY,idZ,iter)) ||
(stencil == 0 && iter++ == 0))
{
// set up pointer for sub extent
tempPtr = inPtr + (inInc2*(idZ - min2) +
inInc1*(idY - min1) +
numC*(pmin0 - min0));
// accumulate over the sub extent
for (idX = pmin0; idX <= pmax0; idX++)
{
// find the bin for this pixel.
outPtrC = outPtr;
for (idxC = 0; idxC < numC; ++idxC)
{
// Gather statistics
sum[idxC]+= *tempPtr;
sumSqr[idxC]+= (*tempPtr * *tempPtr);
if (*tempPtr > Max[idxC])
{
Max[idxC] = *tempPtr;
}
else if (*tempPtr < Min[idxC])
{
Min[idxC] = *tempPtr;
}
(*VoxelCount)++;
// compute the index
outIdx = (int) floor((((double)*tempPtr++ - origin[idxC])
/ spacing[idxC]));
if (outIdx < outExtent[idxC*2] || outIdx > outExtent[idxC*2+1])
{
// Out of bin range
outPtrC = NULL;
break;
}
outPtrC += (outIdx - outExtent[idxC*2]) * outIncs[idxC];
}
if (outPtrC)
{
++(*outPtrC);
}
}
}
}
}
if (*VoxelCount) // avoid the div0
{
Mean[0] = sum[0] / (double)*VoxelCount;
Mean[1] = sum[1] / (double)*VoxelCount;
Mean[2] = sum[2] / (double)*VoxelCount;
variance = sumSqr[0] / (double)(*VoxelCount-1) - ((double) *VoxelCount * Mean[0] * Mean[0] / (double) (*VoxelCount - 1));
StandardDeviation[0] = sqrt(variance);
variance = sumSqr[1] / (double)(*VoxelCount-1) - ((double) *VoxelCount * Mean[1] * Mean[1] / (double) (*VoxelCount - 1));
StandardDeviation[1] = sqrt(variance);
variance = sumSqr[2] / (double)(*VoxelCount-1) - ((double) *VoxelCount * Mean[2] * Mean[2] / (double) (*VoxelCount - 1));
StandardDeviation[2] = sqrt(variance);
}
else
{
Mean[0] = Mean[1] = Mean[2] = 0.0;
StandardDeviation[0] = StandardDeviation[1] = StandardDeviation[2] = 0.0;
}
}
//----------------------------------------------------------------------------
// This method is passed a input and output Data, and executes the filter
// algorithm to fill the output from the input.
// It just executes a switch statement to call the correct function for
// the Datas data types.
int vtkImageAccumulate::RequestData(
vtkInformation* vtkNotUsed( request ),
vtkInformationVector** inputVector,
vtkInformationVector* outputVector)
{
void *inPtr;
void *outPtr;
// get the input
vtkInformation* in1Info = inputVector[0]->GetInformationObject(0);
vtkImageData *inData = vtkImageData::SafeDownCast(
in1Info->Get(vtkDataObject::DATA_OBJECT()));
int *uExt = in1Info->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT());
// get the output
vtkInformation *outInfo = outputVector->GetInformationObject(0);
vtkImageData *outData = vtkImageData::SafeDownCast(
outInfo->Get(vtkDataObject::DATA_OBJECT()));
vtkDebugMacro(<<"Executing image accumulate");
// We need to allocate our own scalars since we are overriding
// the superclasses "Execute()" method.
outData->SetExtent(outData->GetWholeExtent());
outData->AllocateScalars();
vtkDataArray *inArray = this->GetInputArrayToProcess(0,inputVector);
inPtr = inData->GetArrayPointerForExtent(inArray, uExt);
outPtr = outData->GetScalarPointer();
// Components turned into x, y and z
if (inData->GetNumberOfScalarComponents() > 3)
{
vtkErrorMacro("This filter can handle upto 3 components");
return 1;
}
// this filter expects that output is type int.
if (outData->GetScalarType() != VTK_INT)
{
vtkErrorMacro(<< "Execute: out ScalarType " << outData->GetScalarType()
<< " must be int\n");
return 1;
}
switch (inData->GetScalarType())
{
vtkTemplateMacro(vtkImageAccumulateExecute( this,
inData, (VTK_TT *)(inPtr),
outData, (int *)(outPtr),
this->Min, this->Max,
this->Mean,
this->StandardDeviation,
&this->VoxelCount,
uExt ));
default:
vtkErrorMacro(<< "Execute: Unknown ScalarType");
return 1;
}
return 1;
}
//----------------------------------------------------------------------------
int vtkImageAccumulate::RequestInformation (
vtkInformation* vtkNotUsed(request),
vtkInformationVector** inputVector,
vtkInformationVector* outputVector)
{
// get the info objects
vtkInformation* outInfo = outputVector->GetInformationObject(0);
vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
vtkInformation* inInfo2 = inputVector[1]->GetInformationObject(0);
outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),
this->ComponentExtent,6);
outInfo->Set(vtkDataObject::ORIGIN(),this->ComponentOrigin,3);
outInfo->Set(vtkDataObject::SPACING(),this->ComponentSpacing,3);
// need to set the spacing and origin of the stencil to match the output
if (inInfo2)
{
inInfo2->Set(vtkDataObject::SPACING(),
inInfo->Get(vtkDataObject::SPACING()),3);
inInfo2->Set(vtkDataObject::ORIGIN(),
inInfo->Get(vtkDataObject::ORIGIN()),3);
}
vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_INT, 1);
return 1;
}
//----------------------------------------------------------------------------
// Get ALL of the input.
int vtkImageAccumulate::RequestUpdateExtent (
vtkInformation* vtkNotUsed(request),
vtkInformationVector** inputVector,
vtkInformationVector* vtkNotUsed( outputVector ))
{
// get the info objects
vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
vtkInformation* stencilInfo = 0;
if(inputVector[1]->GetNumberOfInformationObjects() > 0)
{
stencilInfo = inputVector[1]->GetInformationObject(0);
}
// Use the whole extent of the first input as the update extent for
// both inputs. This way the stencil will be the same size as the
// input.
int extent[6] = {0,-1,0,-1,0,-1};
inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), extent);
inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), extent, 6);
if(stencilInfo)
{
stencilInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),
extent, 6);
}
return 1;
}
int vtkImageAccumulate::FillInputPortInformation(
int port, vtkInformation* info)
{
if (port == 1)
{
info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageStencilData");
// the stencil input is optional
info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(), 1);
}
else
{
info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData");
}
return 1;
}
void vtkImageAccumulate::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "Mean: ("
<< this->Mean[0] << ", "
<< this->Mean[1] << ", "
<< this->Mean[2] << ")\n";
os << indent << "Min: ("
<< this->Min[0] << ", "
<< this->Min[1] << ", "
<< this->Min[2] << ")\n";
os << indent << "Max: ("
<< this->Max[0] << ", "
<< this->Max[1] << ", "
<< this->Max[2] << ")\n";
os << indent << "StandardDeviation: ("
<< this->StandardDeviation[0] << ", "
<< this->StandardDeviation[1] << ", "
<< this->StandardDeviation[2] << ")\n";
os << indent << "VoxelCount: " << this->VoxelCount << "\n";
os << indent << "Stencil: " << this->GetStencil() << "\n";
os << indent << "ReverseStencil: " << (this->ReverseStencil ?
"On\n" : "Off\n");
os << indent << "ComponentOrigin: ( "
<< this->ComponentOrigin[0] << ", "
<< this->ComponentOrigin[1] << ", "
<< this->ComponentOrigin[2] << " )\n";
os << indent << "ComponentSpacing: ( "
<< this->ComponentSpacing[0] << ", "
<< this->ComponentSpacing[1] << ", "
<< this->ComponentSpacing[2] << " )\n";
os << indent << "ComponentExtent: ( "
<< this->ComponentExtent[0] << "," << this->ComponentExtent[1] << " "
<< this->ComponentExtent[2] << "," << this->ComponentExtent[3] << " "
<< this->ComponentExtent[4] << "," << this->ComponentExtent[5] << " }\n";
}