Trilinear interpolation along the ray

implementation of trilinear interpolation of CT voxel intensities to render properly sub-voxel transforms
related to issue #150
it seems to work, to understan how much the performance degrades and if this should be always performed or not.
This commit is contained in:
Proton local user
2024-11-01 09:59:53 +01:00
parent 7b9db5e25d
commit 8e56950e24

View File

@ -139,7 +139,6 @@ gSiddonJacobsRayCastInterpolateImageFunction<TInputImage, TCoordRep>::Evaluate(c
const OutputType minOutputValue = itk::NumericTraits<OutputType>::NonpositiveMin(); const OutputType minOutputValue = itk::NumericTraits<OutputType>::NonpositiveMin();
const OutputType maxOutputValue = itk::NumericTraits<OutputType>::max(); const OutputType maxOutputValue = itk::NumericTraits<OutputType>::max();
// If the volume was shifted, recalculate the overall inverse transform // If the volume was shifted, recalculate the overall inverse transform
unsigned long int interpMTime = this->GetMTime(); unsigned long int interpMTime = this->GetMTime();
unsigned long int vTransformMTime = m_Transform->GetMTime(); unsigned long int vTransformMTime = m_Transform->GetMTime();
@ -156,9 +155,12 @@ gSiddonJacobsRayCastInterpolateImageFunction<TInputImage, TCoordRep>::Evaluate(c
} }
PointType PointReq = point; PointType PointReq = point;
//std::cout<<"PointReq: "<<point[0] <<" "<<point[1] <<" "<<point[2] <<" "<<std::endl;
PointReq[0] += m_PanelOffset; PointReq[0] += m_PanelOffset;
drrPixelWorld = m_InverseTransform->TransformPoint(PointReq); drrPixelWorld = m_InverseTransform->TransformPoint(PointReq);
//std::cout<<"drrPixelWorld: "<<drrPixelWorld[0] <<" "<<drrPixelWorld[1] <<" "<<drrPixelWorld[2] <<" "<<std::endl;
// Get ths input pointers // Get ths input pointers
InputImageConstPointer inputPtr = this->GetInputImage(); InputImageConstPointer inputPtr = this->GetInputImage();
@ -182,6 +184,7 @@ gSiddonJacobsRayCastInterpolateImageFunction<TInputImage, TCoordRep>::Evaluate(c
SlidingSourcePoint[2] = 0.; SlidingSourcePoint[2] = 0.;
PointType SourceWorld = m_InverseTransform->TransformPoint(SlidingSourcePoint); PointType SourceWorld = m_InverseTransform->TransformPoint(SlidingSourcePoint);
//std::cout<<"SourceWorld: "<<SourceWorld[0] <<" "<<SourceWorld[1] <<" "<<SourceWorld[2] <<" "<<std::endl;
PointType O(3); PointType O(3);
O[0] = -ctPixelSpacing[0]/2.; O[0] = -ctPixelSpacing[0]/2.;
@ -431,6 +434,7 @@ gSiddonJacobsRayCastInterpolateImageFunction<TInputImage, TCoordRep>::Evaluate(c
cIndex[1] = firstIntersectionIndexDown[1]; cIndex[1] = firstIntersectionIndexDown[1];
cIndex[2] = firstIntersectionIndexDown[2]; cIndex[2] = firstIntersectionIndexDown[2];
while (alphaCmin < alphaMax) /* Check if the ray is still in the CT volume */ while (alphaCmin < alphaMax) /* Check if the ray is still in the CT volume */
{ {
/* Store the current ray position */ /* Store the current ray position */
@ -458,17 +462,80 @@ gSiddonJacobsRayCastInterpolateImageFunction<TInputImage, TCoordRep>::Evaluate(c
alphaZ = alphaZ + alphaUz; alphaZ = alphaZ + alphaUz;
} }
if ((cIndex[0] >= 0) && (cIndex[0] < static_cast<IndexValueType>(sizeCT[0])) && (cIndex[1] >= 0) && if ((cIndex[0] >= 0) && (cIndex[0] < static_cast<IndexValueType>(sizeCT[0])) && (cIndex[1] >= 0) &&
(cIndex[1] < static_cast<IndexValueType>(sizeCT[1])) && (cIndex[2] >= 0) && (cIndex[1] < static_cast<IndexValueType>(sizeCT[1])) && (cIndex[2] >= 0) &&
(cIndex[2] < static_cast<IndexValueType>(sizeCT[2]))) (cIndex[2] < static_cast<IndexValueType>(sizeCT[2])))
{ {
/* If it is a valid index, get the voxel intensity. */ // Calculate entry and exit points using alphaCmin and alphaCminPrev
value = static_cast<float>(inputPtr->GetPixel(cIndex));
PointType entryPoint;
entryPoint[0] = SourceWorld[0] + alphaCminPrev * rayVector[0] ;
entryPoint[1] = SourceWorld[1] + alphaCminPrev * rayVector[1] ;
entryPoint[2] = SourceWorld[2] + alphaCminPrev * rayVector[2] ;
PointType exitPoint;
exitPoint[0] = SourceWorld[0] + alphaCmin * rayVector[0] ;
exitPoint[1] = SourceWorld[1] + alphaCmin * rayVector[1] ;
exitPoint[2] = SourceWorld[2] + alphaCmin * rayVector[2] ;
// PointType entryPoint = SourceWorld + alphaCminPrev * rayVector;
// PointType exitPoint = SourceWorld + alphaCmin * rayVector;
PointType midpoint;
midpoint[0]= (entryPoint[0] + exitPoint[0]) * 0.5;
midpoint[1]= (entryPoint[1] + exitPoint[1]) * 0.5;
midpoint[2]= (entryPoint[2] + exitPoint[2]) * 0.5;
// = (entryPoint + exitPoint) * 0.5;
// Calculate fractional parts for interpolation at the midpoint
double x_frac = midpoint[0] - std::floor(midpoint[0]);
double y_frac = midpoint[1] - std::floor(midpoint[1]);
double z_frac = midpoint[2] - std::floor(midpoint[2]);
// Perform boundary checks for trilinear interpolation
IndexType baseIndex = cIndex;
bool within_bounds = (baseIndex[0] >= 0 && baseIndex[0] < sizeCT[0] - 1) &&
(baseIndex[1] >= 0 && baseIndex[1] < sizeCT[1] - 1) &&
(baseIndex[2] >= 0 && baseIndex[2] < sizeCT[2] - 1);
if (within_bounds)
{
// Fetch intensities from neighboring voxels for trilinear interpolation
float c000 = static_cast<float>(inputPtr->GetPixel(baseIndex));
baseIndex[0] += 1; float c100 = static_cast<float>(inputPtr->GetPixel(baseIndex));
baseIndex[1] += 1; float c110 = static_cast<float>(inputPtr->GetPixel(baseIndex));
baseIndex[0] -= 1; float c010 = static_cast<float>(inputPtr->GetPixel(baseIndex));
baseIndex[2] += 1; float c011 = static_cast<float>(inputPtr->GetPixel(baseIndex));
baseIndex[0] += 1; float c111 = static_cast<float>(inputPtr->GetPixel(baseIndex));
baseIndex[1] -= 1; float c101 = static_cast<float>(inputPtr->GetPixel(baseIndex));
baseIndex[0] -= 1; float c001 = static_cast<float>(inputPtr->GetPixel(baseIndex));
// Perform trilinear interpolation at the midpoint
float c00 = c000 * (1 - x_frac) + c100 * x_frac;
float c01 = c001 * (1 - x_frac) + c101 * x_frac;
float c10 = c010 * (1 - x_frac) + c110 * x_frac;
float c11 = c011 * (1 - x_frac) + c111 * x_frac;
float c0 = c00 * (1 - y_frac) + c10 * y_frac;
float c1 = c01 * (1 - y_frac) + c11 * y_frac;
value = c0 * (1 - z_frac) + c1 * z_frac;
}
else
{
// Fallback to nearest voxel intensity if out-of-bounds
value = static_cast<float>(inputPtr->GetPixel(cIndex));
}
// Accumulate the interpolated intensity along the ray path
if (value > m_Threshold) /* Ignore voxels whose intensities are below the threshold. */ if (value > m_Threshold) /* Ignore voxels whose intensities are below the threshold. */
{ {
d12 += (alphaCmin - alphaCminPrev) * (value - m_Threshold); d12 += (alphaCmin - alphaCminPrev) * (value - m_Threshold);
} }
} }
} }
if (d12 < minOutputValue) if (d12 < minOutputValue)