#ifndef itkChamferDistanceTransformImageFilter_txx #define itkChamferDistanceTransformImageFilter_txx #include #include #include #include #include #include #include #include namespace itk { template ChamferDistanceTransformImageFilter ::ChamferDistanceTransformImageFilter() : distanceFromObject(true) { std::fill(m_Weights, m_Weights+OutputImage::ImageDimension, 1); } template template void ChamferDistanceTransformImageFilter ::SetWeights(Iterator begin, Iterator end) { std::copy(begin, end, m_Weights); } template std::vector ChamferDistanceTransformImageFilter ::GetWeights() const { std::vector result(OutputImage::ImageDimension); std::copy(m_Weights, m_Weights+OutputImage::ImageDimension, result.begin()); return result; } template void ChamferDistanceTransformImageFilter ::PrintSelf(std::ostream& os, Indent indent) const { Superclass::PrintSelf(os, indent); os << indent << "Weights : [ "; for(unsigned int i=0; i< OutputImage::ImageDimension; ++i) { os << m_Weights[i] << " "; } os << "]" << "\n"; } template void ChamferDistanceTransformImageFilter ::GenerateData() { // Allocate output image typename OutputImageType::RegionType region; typename OutputImageType::RegionType::IndexType start; start.Fill(0); region.SetIndex(start); typename OutputImageType::RegionType::SizeType size( this->GetInput()->GetRequestedRegion().GetSize() ); region.SetSize(size); typename OutputImageType::Pointer outputImage = this->GetOutput(); outputImage->SetRegions(region); outputImage->Allocate(); // Initialize output image : \infty where input is not 0, 0 where input is 0 if computing // the distance from the object, the opposite otherwise. typename OutputImageType::PixelType const fgValue = distanceFromObject?0:NumericTraits::max(); typename OutputImageType::PixelType const bgValue = NumericTraits::max() - fgValue; itk::ImageRegionConstIterator inputImageIt(this->GetInput(0), this->GetInput()->GetRequestedRegion()); itk::ImageRegionIterator outputImageIt(this->GetOutput(), this->GetOutput()->GetRequestedRegion()); while(!outputImageIt.IsAtEnd()) { typename OutputImageType::PixelType const value = (inputImageIt.Get() != NumericTraits::Zero) ? fgValue : bgValue; outputImageIt.Set(value); ++inputImageIt; ++outputImageIt; } // Create the mask of the weights Neighborhood mask; mask.SetRadius(1); for(unsigned int i=0; i::max(); continue; } Offset const offset = mask.GetOffset(i); int type=-1; for(unsigned int j=0; j::RadiusType r; r.Fill(1); NeighborhoodIterator it(r, this->GetOutput(), this->GetOutput()->GetRequestedRegion()); ConstantBoundaryCondition bc; bc.SetConstant(bgValue); it.OverrideBoundaryCondition(&bc); unsigned int const maskCenter = it.Size()/2; // First pass : forward scan, use backward mask it.GoToBegin(); while(!it.IsAtEnd()) { typename OutputImageType::PixelType minimum = NumericTraits::max(); for(unsigned int i=0; i::max() - mask[i]) { minimum = std::min(minimum, it.GetPixel(i) + mask[i]); } } if(minimum < it.GetCenterPixel()) { it.SetCenterPixel(minimum); } ++it; } // Second pass : bacward scan, use forward mask it.GoToEnd(); --it; while(!it.IsAtBegin()) { typename OutputImageType::PixelType minimum = NumericTraits::max(); for(unsigned int i=maskCenter+1; i::max() - mask[i]) { minimum = std::min(minimum, it.GetPixel(i) + mask[i]); } } if(minimum < it.GetCenterPixel()) { it.SetCenterPixel(minimum); } --it; } // Last pixel in the scan. typename OutputImageType::PixelType minimum = NumericTraits::max(); for(unsigned int i=maskCenter+1; i::max() - mask[i]) { minimum = std::min(minimum, it.GetPixel(i) + mask[i]); } } if(minimum < it.GetCenterPixel()) { it.SetCenterPixel(minimum); } } } #endif // itkChamferDistanceTransformImageFilter_txx