From 8e56950e24457d202a6a6c2c61c7ea90ca91f83c Mon Sep 17 00:00:00 2001 From: Proton local user Date: Fri, 1 Nov 2024 09:59:53 +0100 Subject: [PATCH] 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. --- ...nJacobsRayCastInterpolateImageFunction.hxx | 77 +++++++++++++++++-- 1 file changed, 72 insertions(+), 5 deletions(-) diff --git a/reg23Topograms/itkDTRrecon/itkgSiddonJacobsRayCastInterpolateImageFunction.hxx b/reg23Topograms/itkDTRrecon/itkgSiddonJacobsRayCastInterpolateImageFunction.hxx index 4bf5335..1c99d61 100644 --- a/reg23Topograms/itkDTRrecon/itkgSiddonJacobsRayCastInterpolateImageFunction.hxx +++ b/reg23Topograms/itkDTRrecon/itkgSiddonJacobsRayCastInterpolateImageFunction.hxx @@ -139,7 +139,6 @@ gSiddonJacobsRayCastInterpolateImageFunction::Evaluate(c const OutputType minOutputValue = itk::NumericTraits::NonpositiveMin(); const OutputType maxOutputValue = itk::NumericTraits::max(); - // If the volume was shifted, recalculate the overall inverse transform unsigned long int interpMTime = this->GetMTime(); unsigned long int vTransformMTime = m_Transform->GetMTime(); @@ -156,9 +155,12 @@ gSiddonJacobsRayCastInterpolateImageFunction::Evaluate(c } PointType PointReq = point; + //std::cout<<"PointReq: "<TransformPoint(PointReq); + //std::cout<<"drrPixelWorld: "<GetInputImage(); @@ -182,6 +184,7 @@ gSiddonJacobsRayCastInterpolateImageFunction::Evaluate(c SlidingSourcePoint[2] = 0.; PointType SourceWorld = m_InverseTransform->TransformPoint(SlidingSourcePoint); + //std::cout<<"SourceWorld: "<::Evaluate(c cIndex[1] = firstIntersectionIndexDown[1]; cIndex[2] = firstIntersectionIndexDown[2]; + while (alphaCmin < alphaMax) /* Check if the ray is still in the CT volume */ { /* Store the current ray position */ @@ -458,17 +462,80 @@ gSiddonJacobsRayCastInterpolateImageFunction::Evaluate(c alphaZ = alphaZ + alphaUz; } + if ((cIndex[0] >= 0) && (cIndex[0] < static_cast(sizeCT[0])) && (cIndex[1] >= 0) && - (cIndex[1] < static_cast(sizeCT[1])) && (cIndex[2] >= 0) && - (cIndex[2] < static_cast(sizeCT[2]))) + (cIndex[1] < static_cast(sizeCT[1])) && (cIndex[2] >= 0) && + (cIndex[2] < static_cast(sizeCT[2]))) { - /* If it is a valid index, get the voxel intensity. */ - value = static_cast(inputPtr->GetPixel(cIndex)); + // Calculate entry and exit points using alphaCmin and alphaCminPrev + + 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(inputPtr->GetPixel(baseIndex)); + baseIndex[0] += 1; float c100 = static_cast(inputPtr->GetPixel(baseIndex)); + baseIndex[1] += 1; float c110 = static_cast(inputPtr->GetPixel(baseIndex)); + baseIndex[0] -= 1; float c010 = static_cast(inputPtr->GetPixel(baseIndex)); + baseIndex[2] += 1; float c011 = static_cast(inputPtr->GetPixel(baseIndex)); + baseIndex[0] += 1; float c111 = static_cast(inputPtr->GetPixel(baseIndex)); + baseIndex[1] -= 1; float c101 = static_cast(inputPtr->GetPixel(baseIndex)); + baseIndex[0] -= 1; float c001 = static_cast(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(inputPtr->GetPixel(cIndex)); + } + + // Accumulate the interpolated intensity along the ray path if (value > m_Threshold) /* Ignore voxels whose intensities are below the threshold. */ { d12 += (alphaCmin - alphaCminPrev) * (value - m_Threshold); } } + } if (d12 < minOutputValue)