/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef itkKappaSigmaThresholdImageCalculator_hxx #define itkKappaSigmaThresholdImageCalculator_hxx #include "itkImageRegionConstIteratorWithIndex.h" #include "itkImageRegionConstIterator.h" namespace itk { template KappaSigmaThresholdImageCalculator::KappaSigmaThresholdImageCalculator() : m_MaskValue(NumericTraits::max()) , m_Output(InputPixelType{}) {} template void KappaSigmaThresholdImageCalculator::Compute() { if (!this->m_Image) { return; } // Initialize the values InputPixelType threshold = NumericTraits::max(); // use all // the // pixels // to begin for (unsigned int iteration = 0; iteration < this->m_NumberOfIterations; ++iteration) { ImageRegionConstIteratorWithIndex iIt(this->m_Image, this->m_Image->GetRequestedRegion()); // Compute the mean iIt.GoToBegin(); SizeValueType count = 0; double mean = 0; while (!iIt.IsAtEnd()) { if (!this->m_Mask || this->m_Mask->GetPixel(iIt.GetIndex()) == this->m_MaskValue) { const InputPixelType & v = iIt.Get(); if (v <= threshold) { mean += v; ++count; } } ++iIt; } mean = mean / count; // Compute sigma iIt.GoToBegin(); double sigma = 0; while (!iIt.IsAtEnd()) { if (!this->m_Mask || this->m_Mask->GetPixel(iIt.GetIndex()) == this->m_MaskValue) { const InputPixelType & v = iIt.Get(); if (v <= threshold) { sigma += itk::Math::sqr(v - mean); } } ++iIt; } sigma = std::sqrt(sigma / (count - 1)); // Compute the threshold for the next iteration auto newThreshold = static_cast(mean + this->m_SigmaFactor * sigma); if (newThreshold == threshold) { // No need to continue - the threshold is the same and will produce the // same result break; } threshold = newThreshold; } this->m_Output = threshold; this->m_Valid = true; } template auto KappaSigmaThresholdImageCalculator::GetOutput() const -> const InputPixelType & { if (!this->m_Valid) { itkExceptionMacro("GetOutput() invoked, but the output have not been computed. Call Compute() first."); } return this->m_Output; } template void KappaSigmaThresholdImageCalculator::PrintSelf(std::ostream & os, Indent indent) const { Superclass::PrintSelf(os, indent); os << indent << "Valid: " << this->m_Valid << std::endl; os << indent << "MaskValue: " << this->m_MaskValue << std::endl; os << indent << "SigmaFactor: " << this->m_SigmaFactor << std::endl; os << indent << "NumberOfIterations: " << this->m_NumberOfIterations << std::endl; os << indent << "Output: " << static_cast::PrintType>(m_Output) << std::endl; itkPrintSelfObjectMacro(Image); itkPrintSelfObjectMacro(Mask); } } // end namespace itk #endif