bool AcceptMatch(VertexDescriptorType target, VertexDescriptorType source, float& computedEnergy) const override { itk::Index<2> targetPixel = ITKHelpers::CreateIndex(target); itk::ImageRegion<2> targetRegion = ITKHelpers::GetRegionInRadiusAroundPixel(targetPixel, HalfWidth); itk::Index<2> sourcePixel = ITKHelpers::CreateIndex(source); itk::ImageRegion<2> sourceRegion = ITKHelpers::GetRegionInRadiusAroundPixel(sourcePixel, HalfWidth); typedef itk::Image<float, 2> FloatImageType; typedef itk::VectorMagnitudeImageFilter<TImage, FloatImageType> VectorMagnitudeFilterType; typename VectorMagnitudeFilterType::Pointer magnitudeFilter = VectorMagnitudeFilterType::New(); magnitudeFilter->SetInput(Image); magnitudeFilter->Update(); std::vector<itk::Offset<2> > validOffsets = MaskImage->GetValidOffsetsInRegion(targetRegion); FloatImageType::Pointer sourceImage = FloatImageType::New(); // sourceImage->SetRegions(ITKHelpers::CornerRegion(sourceRegion.GetSize())); // sourceImage->Allocate(); ITKHelpers::ExtractRegion(magnitudeFilter->GetOutput(), sourceRegion, sourceImage.GetPointer()); FloatImageType::Pointer targetImage = FloatImageType::New(); // sourceImage->SetRegions(ITKHelpers::CornerRegion(targetRegion.GetSize())); // sourceImage->Allocate(); ITKHelpers::ExtractRegion(magnitudeFilter->GetOutput(), targetRegion, targetImage.GetPointer()); std::vector<itk::Index<2> > validIndices = ITKHelpers::OffsetsToIndices(validOffsets); VarianceFunctor varianceFunctor; AverageFunctor averageFunctor; /////////// Target region ////////// std::vector<FloatImageType::PixelType> validPixelsTargetRegion = ITKHelpers::GetPixelValues(targetImage.GetPointer(), validIndices); typename TypeTraits<FloatImageType::PixelType>::LargerType targetMean = averageFunctor(validPixelsTargetRegion); typename TypeTraits<FloatImageType::PixelType>::LargerType targetStandardDeviation = sqrt(varianceFunctor(validPixelsTargetRegion)); typedef itk::AddImageFilter <FloatImageType, FloatImageType, FloatImageType> AddImageFilterType; AddImageFilterType::Pointer targetAddImageFilter = AddImageFilterType::New(); targetAddImageFilter->SetInput(targetImage); targetAddImageFilter->SetConstant2(-1.0f * targetMean); targetAddImageFilter->Update(); typedef itk::MultiplyImageFilter<FloatImageType, FloatImageType, FloatImageType> MultiplyImageFilterType; MultiplyImageFilterType::Pointer targetMultiplyImageFilter = MultiplyImageFilterType::New(); targetMultiplyImageFilter->SetInput(targetImage); targetMultiplyImageFilter->SetConstant(1.0f/targetStandardDeviation); targetMultiplyImageFilter->Update(); /////////// Source region ////////// std::vector<FloatImageType::PixelType> validPixelsSourceRegion = ITKHelpers::GetPixelValues(sourceImage.GetPointer(), validIndices); typename TypeTraits<FloatImageType::PixelType>::LargerType sourceMean = averageFunctor(validPixelsSourceRegion); typename TypeTraits<FloatImageType::PixelType>::LargerType sourceStandardDeviation = sqrt(varianceFunctor(validPixelsSourceRegion)); AddImageFilterType::Pointer sourceAddImageFilter = AddImageFilterType::New(); sourceAddImageFilter->SetInput(sourceImage); sourceAddImageFilter->SetConstant2(-1.0f * sourceMean); sourceAddImageFilter->Update(); MultiplyImageFilterType::Pointer sourceMultiplyImageFilter = MultiplyImageFilterType::New(); sourceMultiplyImageFilter->SetInput(sourceImage); sourceMultiplyImageFilter->SetConstant(1.0f/sourceStandardDeviation); sourceMultiplyImageFilter->Update(); // Initialize computedEnergy = 0.0f; for(std::vector<itk::Index<2> >::const_iterator iter = validIndices.begin(); iter != validIndices.end(); ++iter) { computedEnergy += (sourceMultiplyImageFilter->GetOutput()->GetPixel(*iter) * targetMultiplyImageFilter->GetOutput()->GetPixel(*iter)); } computedEnergy /= static_cast<float>(validIndices.size()); if(computedEnergy < Threshold) { std::cout << this->VisitorName << ": Match accepted (" << computedEnergy << " is less than " << Threshold << ")" << std::endl << std::endl; return true; } else { std::cout << this->VisitorName << ": Match rejected (" << computedEnergy << " is greater than " << Threshold << ")" << std::endl << std::endl; return false; } };
bool AcceptMatch(VertexDescriptorType target, VertexDescriptorType source, float& computedEnergy) const { itk::Index<2> targetPixel = ITKHelpers::CreateIndex(target); itk::ImageRegion<2> targetRegion = ITKHelpers::GetRegionInRadiusAroundPixel(targetPixel, HalfWidth); itk::Index<2> sourcePixel = ITKHelpers::CreateIndex(source); itk::ImageRegion<2> sourceRegion = ITKHelpers::GetRegionInRadiusAroundPixel(sourcePixel, HalfWidth); // Get the pixels to use in the target region std::vector<typename TImage::PixelType> validPixelsTargetRegion = MaskOperations::GetValidPixelsInRegion(Image, MaskImage, targetRegion); // Get the pixels to use in the source region std::vector<itk::Offset<2> > validOffsets = MaskImage->GetValidOffsetsInRegion(targetRegion); std::vector<itk::Index<2> > sourcePatchValidPixelIndices = ITKHelpers::OffsetsToIndices(validOffsets, sourceRegion.GetIndex()); std::vector<typename TImage::PixelType> validPixelsSourceRegion = ITKHelpers::GetPixelValues(Image, sourcePatchValidPixelIndices); assert(validPixelsSourceRegion.size() == validPixelsTargetRegion.size()); unsigned int numberOfPixels = validPixelsTargetRegion.size(); float totalHistogramDifference = 0.0f; for(unsigned int component = 0; component < Image->GetNumberOfComponentsPerPixel(); ++component) { std::vector<float> targetValues(numberOfPixels); std::vector<float> sourceValues(numberOfPixels); for(unsigned int pixelId = 0; pixelId < numberOfPixels; ++pixelId) { targetValues[pixelId] = validPixelsTargetRegion[pixelId][component]; sourceValues[pixelId] = validPixelsSourceRegion[pixelId][component]; } float minTargetValue = *(std::min_element(targetValues.begin(), targetValues.end())); float minSourceValue = *(std::min_element(sourceValues.begin(), sourceValues.end())); float maxTargetValue = *(std::max_element(targetValues.begin(), targetValues.end())); float maxSourceValue = *(std::max_element(sourceValues.begin(), sourceValues.end())); float minValue = std::min(minTargetValue, minSourceValue); float maxValue = std::max(maxTargetValue, maxSourceValue); std::vector<float> targetHistogram = Histogram::ScalarHistogram(targetValues, 20, minValue, maxValue); std::vector<float> sourceHistogram = Histogram::ScalarHistogram(sourceValues, 20, minValue, maxValue); // We normalize the histograms because the magnitude of the histogram difference should not // change based on the number of pixels that were in the valid region of the patches. Helpers::NormalizeVector(targetHistogram); Helpers::NormalizeVector(sourceHistogram); float channelHistogramDifference = Helpers::VectorSumOfAbsoluteDifferences(targetHistogram, sourceHistogram); totalHistogramDifference += channelHistogramDifference; } // Compute the difference computedEnergy = totalHistogramDifference; std::cout << "HistogramDifferenceAcceptanceVisitor Energy: " << computedEnergy << std::endl; if(computedEnergy < DifferenceThreshold) { std::cout << "HistogramDifferenceAcceptanceVisitor: Match accepted (less than " << DifferenceThreshold << ")" << std::endl; return true; } else { std::cout << "HistogramDifferenceAcceptanceVisitor: Match rejected (greater than " << DifferenceThreshold << ")" << std::endl; return false; } };