1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
|
/*=========================================================================
*
* Copyright UMC Utrecht and contributors
*
* 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
*
* http://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 itkKNNGraphAlphaMutualInformationImageToImageMetric_h
#define itkKNNGraphAlphaMutualInformationImageToImageMetric_h
/** Includes for the Superclass. */
#include "itkMultiInputImageToImageMetricBase.h"
/** Includes for the kNN trees. */
#include "itkArray.h"
#include "itkListSampleCArray.h"
#include "itkBinaryTreeBase.h"
#include "itkBinaryTreeSearchBase.h"
/** Supported trees. */
#include "itkANNkDTree.h"
#include "itkANNbdTree.h"
#include "itkANNBruteForceTree.h"
/** Supported tree searchers. */
#include "itkANNStandardTreeSearch.h"
#include "itkANNFixedRadiusTreeSearch.h"
#include "itkANNPriorityTreeSearch.h"
/** Include for the spatial derivatives. */
#include "itkArray2D.h"
namespace itk
{
/**
* \class KNNGraphAlphaMutualInformationImageToImageMetric
*
* \brief Computes similarity between two images to be registered.
*
* This metric computes the alpha-Mutual Information (aMI) between
* two multi-channeled data sets. Said otherwise, given two sets of
* features, the aMI between them is calculated.
* Since for higher dimensional aMI it is infeasible to compute high
* dimensional joint histograms, here we adopt a framework based on
* the length of certain graphs, see Neemuchwala. Specifically, we use
* the k-Nearest Neighbour (kNN) graph, using an implementation provided
* by the Approximate Nearest Neighbour (ANN) software package.
*
* Note that the feature image are given beforehand, and that values
* are calculated by interpolation on the transformed point. For some
* features, it would be better (but slower) to first apply the transform
* on the image and then recalculate the feature.
*
* All the technical details can be found in:\n
* M. Staring, U.A. van der Heide, S. Klein, M.A. Viergever and J.P.W. Pluim,
* "Registration of Cervical MRI Using Multifeature Mutual Information,"
* IEEE Transactions on Medical Imaging, vol. 28, no. 9, pp. 1412 - 1421,
* September 2009.
*
* \ingroup RegistrationMetrics
*/
template <class TFixedImage, class TMovingImage>
class ITK_TEMPLATE_EXPORT KNNGraphAlphaMutualInformationImageToImageMetric
: public MultiInputImageToImageMetricBase<TFixedImage, TMovingImage>
{
public:
ITK_DISALLOW_COPY_AND_MOVE(KNNGraphAlphaMutualInformationImageToImageMetric);
/** Standard itk. */
using Self = KNNGraphAlphaMutualInformationImageToImageMetric;
using Superclass = MultiInputImageToImageMetricBase<TFixedImage, TMovingImage>;
using Pointer = SmartPointer<Self>;
using ConstPointer = SmartPointer<const Self>;
/** Method for creation through the object factory. */
itkNewMacro(Self);
/** Run-time type information (and related methods). */
itkTypeMacro(KNNGraphAlphaMutualInformationImageToImageMetric, MultiInputImageToImageMetricBase);
/** Typedefs from the superclass. */
using typename Superclass::CoordinateRepresentationType;
using typename Superclass::MovingImageType;
using typename Superclass::MovingImagePixelType;
using typename Superclass::MovingImageConstPointer;
using typename Superclass::FixedImageType;
using typename Superclass::FixedImageConstPointer;
using typename Superclass::FixedImageRegionType;
using typename Superclass::TransformType;
using typename Superclass::TransformPointer;
using typename Superclass::InputPointType;
using typename Superclass::OutputPointType;
using typename Superclass::TransformParametersType;
using typename Superclass::TransformJacobianType;
using typename Superclass::InterpolatorType;
using typename Superclass::InterpolatorPointer;
using typename Superclass::RealType;
using typename Superclass::GradientPixelType;
using typename Superclass::GradientImageType;
using typename Superclass::GradientImagePointer;
using typename Superclass::FixedImageMaskType;
using typename Superclass::FixedImageMaskPointer;
using typename Superclass::MovingImageMaskType;
using typename Superclass::MovingImageMaskPointer;
using typename Superclass::MeasureType;
using typename Superclass::DerivativeType;
using typename Superclass::ParametersType;
using typename Superclass::FixedImagePixelType;
using typename Superclass::MovingImageRegionType;
using typename Superclass::ImageSamplerType;
using typename Superclass::ImageSamplerPointer;
using typename Superclass::ImageSampleContainerType;
using typename Superclass::ImageSampleContainerPointer;
using typename Superclass::FixedImageLimiterType;
using typename Superclass::MovingImageLimiterType;
using typename Superclass::FixedImageLimiterOutputType;
using typename Superclass::MovingImageLimiterOutputType;
using typename Superclass::NonZeroJacobianIndicesType;
/** Typedef's for storing multiple inputs. */
using typename Superclass::FixedImageVectorType;
using typename Superclass::FixedImageMaskVectorType;
using typename Superclass::FixedImageRegionVectorType;
using typename Superclass::MovingImageVectorType;
using typename Superclass::MovingImageMaskVectorType;
using typename Superclass::InterpolatorVectorType;
using typename Superclass::FixedImageInterpolatorVectorType;
/** The fixed image dimension. */
itkStaticConstMacro(FixedImageDimension, unsigned int, FixedImageType::ImageDimension);
itkStaticConstMacro(MovingImageDimension, unsigned int, MovingImageType::ImageDimension);
/** Typedefs for the samples. */
using MeasurementVectorType = Array<double>;
using MeasurementVectorValueType = typename MeasurementVectorType::ValueType;
using ListSampleType = typename Statistics::ListSampleCArray<MeasurementVectorType, double>;
using ListSamplePointer = typename ListSampleType::Pointer;
/** Typedefs for trees. */
using BinaryKNNTreeType = BinaryTreeBase<ListSampleType>;
using BinaryKNNTreePointer = typename BinaryKNNTreeType::Pointer;
using ANNkDTreeType = ANNkDTree<ListSampleType>;
using ANNbdTreeType = ANNbdTree<ListSampleType>;
using ANNBruteForceTreeType = ANNBruteForceTree<ListSampleType>;
/** Typedefs for tree searchers. */
using BinaryKNNTreeSearchType = BinaryTreeSearchBase<ListSampleType>;
using BinaryKNNTreeSearchPointer = typename BinaryKNNTreeSearchType::Pointer;
using ANNStandardTreeSearchType = ANNStandardTreeSearch<ListSampleType>;
using ANNFixedRadiusTreeSearchType = ANNFixedRadiusTreeSearch<ListSampleType>;
using ANNPriorityTreeSearchType = ANNPriorityTreeSearch<ListSampleType>;
using IndexArrayType = typename BinaryKNNTreeSearchType::IndexArrayType;
using DistanceArrayType = typename BinaryKNNTreeSearchType::DistanceArrayType;
using typename Superclass::DerivativeValueType;
using TransformJacobianValueType = typename TransformJacobianType::ValueType;
/**
* *** Set trees: ***
* Currently kd, bd, and brute force trees are supported.
*/
/** Set ANNkDTree. */
void
SetANNkDTree(unsigned int bucketSize, std::string splittingRule);
/** Set ANNkDTree. */
void
SetANNkDTree(unsigned int bucketSize,
std::string splittingRuleFixed,
std::string splittingRuleMoving,
std::string splittingRuleJoint);
/** Set ANNbdTree. */
void
SetANNbdTree(unsigned int bucketSize, std::string splittingRule, std::string shrinkingRule);
/** Set ANNbdTree. */
void
SetANNbdTree(unsigned int bucketSize,
std::string splittingRuleFixed,
std::string splittingRuleMoving,
std::string splittingRuleJoint,
std::string shrinkingRuleFixed,
std::string shrinkingRuleMoving,
std::string shrinkingRuleJoint);
/** Set ANNBruteForceTree. */
void
SetANNBruteForceTree();
/**
* *** Set tree searchers: ***
* Currently standard, fixed radius, and priority tree searchers are supported.
*/
/** Set ANNStandardTreeSearch. */
void
SetANNStandardTreeSearch(unsigned int kNearestNeighbors, double errorBound);
/** Set ANNFixedRadiusTreeSearch. */
void
SetANNFixedRadiusTreeSearch(unsigned int kNearestNeighbors, double errorBound, double squaredRadius);
/** Set ANNPriorityTreeSearch. */
void
SetANNPriorityTreeSearch(unsigned int kNearestNeighbors, double errorBound);
/**
* *** Standard metric stuff: ***
*/
/** Initialize the metric. */
void
Initialize() override;
/** Get the derivatives of the match measure. */
void
GetDerivative(const TransformParametersType & parameters, DerivativeType & Derivative) const override;
/** Get the value for single valued optimizers. */
MeasureType
GetValue(const TransformParametersType & parameters) const override;
/** Get value and derivatives for multiple valued optimizers. */
void
GetValueAndDerivative(const TransformParametersType & parameters,
MeasureType & Value,
DerivativeType & Derivative) const override;
/** Set alpha from alpha - mutual information. */
itkSetClampMacro(Alpha, double, 0.0, 1.0);
/** Get alpha from alpha - mutual information. */
itkGetConstReferenceMacro(Alpha, double);
/** Avoid division by a small number. */
itkSetClampMacro(AvoidDivisionBy, double, 0.0, 1.0);
/** Avoid division by a small number. */
itkGetConstReferenceMacro(AvoidDivisionBy, double);
protected:
/** Constructor. */
KNNGraphAlphaMutualInformationImageToImageMetric();
/** Destructor. */
~KNNGraphAlphaMutualInformationImageToImageMetric() override = default;
/** PrintSelf. */
void
PrintSelf(std::ostream & os, Indent indent) const override;
/** Member variables. */
BinaryKNNTreePointer m_BinaryKNNTreeFixed{ nullptr };
BinaryKNNTreePointer m_BinaryKNNTreeMoving{ nullptr };
BinaryKNNTreePointer m_BinaryKNNTreeJoint{ nullptr };
BinaryKNNTreeSearchPointer m_BinaryKNNTreeSearcherFixed{ nullptr };
BinaryKNNTreeSearchPointer m_BinaryKNNTreeSearcherMoving{ nullptr };
BinaryKNNTreeSearchPointer m_BinaryKNNTreeSearcherJoint{ nullptr };
double m_Alpha{ 0.99 };
double m_AvoidDivisionBy{ 1e-10 };
private:
/** Typedef's for the computation of the derivative. */
using typename Superclass::FixedImagePointType;
using typename Superclass::MovingImagePointType;
using typename Superclass::MovingImageDerivativeType;
using typename Superclass::MovingImageContinuousIndexType;
using TransformJacobianContainerType = std::vector<TransformJacobianType>;
// typedef std::vector<ParameterIndexArrayType> TransformJacobianIndicesContainerType;
using TransformJacobianIndicesContainerType = std::vector<NonZeroJacobianIndicesType>;
using SpatialDerivativeType = vnl_matrix<double>;
using SpatialDerivativeContainerType = std::vector<SpatialDerivativeType>;
/** This function takes the fixed image samples from the ImageSampler
* and puts them in the listSampleFixed, together with the fixed feature
* image samples. Also the corresponding moving image values and moving
* feature values are computed and put into listSampleMoving. The
* concatenation is put into listSampleJoint.
* If desired, i.e. if doDerivative is true, then also things needed to
* compute the derivative of the cost function to the transform parameters
* are computed:
* - The sparse Jacobian of the transformation (dT/dmu).
* - The spatial derivatives of the moving (feature) images (dm/dx).
*/
void
ComputeListSampleValuesAndDerivativePlusJacobian(const ListSamplePointer & listSampleFixed,
const ListSamplePointer & listSampleMoving,
const ListSamplePointer & listSampleJoint,
const bool doDerivative,
TransformJacobianContainerType & jacobians,
TransformJacobianIndicesContainerType & jacobiansIndices,
SpatialDerivativeContainerType & spatialDerivatives) const;
/** This function calculates the spatial derivative of the
* featureNr feature image at the point mappedPoint.
* \todo move this to base class.
*/
virtual void
EvaluateMovingFeatureImageDerivatives(const MovingImagePointType & mappedPoint,
SpatialDerivativeType & featureGradients) const;
/** This function essentially computes D1 - D2, but also takes
* care of going from a sparse matrix (hence the indices) to a
* full sized matrix.
*/
virtual void
UpdateDerivativeOfGammas(const SpatialDerivativeType & D1sparse,
const SpatialDerivativeType & D2sparse_M,
const SpatialDerivativeType & D2sparse_J,
// const ParameterIndexArrayType & D1indices,
// const ParameterIndexArrayType & D2indices_M,
// const ParameterIndexArrayType & D2indices_J,
const NonZeroJacobianIndicesType & D1indices,
const NonZeroJacobianIndicesType & D2indices_M,
const NonZeroJacobianIndicesType & D2indices_J,
const MeasurementVectorType & diff_M,
const MeasurementVectorType & diff_J,
const MeasureType & distance_M,
const MeasureType & distance_J,
DerivativeType & dGamma_M,
DerivativeType & dGamma_J) const;
};
} // end namespace itk
#ifndef ITK_MANUAL_INSTANTIATION
# include "itkKNNGraphAlphaMutualInformationImageToImageMetric.hxx"
#endif
#endif // end #ifndef itkKNNGraphAlphaMutualInformationImageToImageMetric_h
|