private GeneralizedDistanceTransform2D CalculateMinEnergiesForAllParentEdges( ShapeModel model, ShapeConstraints shapeConstraints, int parentEdgeIndex, int currentEdgeIndex, IList <ILengthAngleConstraints> lengthAngleConstraints) { // Calculate child transforms List <GeneralizedDistanceTransform2D> childDistanceTransforms = new List <GeneralizedDistanceTransform2D>(); foreach (int neighborEdgeIndex in model.IterateNeighboringEdgeIndices(currentEdgeIndex)) { // Iterate only through children if (neighborEdgeIndex == parentEdgeIndex) { continue; } GeneralizedDistanceTransform2D childTransform = CalculateMinEnergiesForAllParentEdges( model, shapeConstraints, currentEdgeIndex, neighborEdgeIndex, lengthAngleConstraints); Debug.Assert(childTransform.IsComputed); childDistanceTransforms.Add(childTransform); } ShapeEdgePairParams pairParams = model.GetEdgePairParams(parentEdgeIndex, currentEdgeIndex); GeneralizedDistanceTransform2D transform = this.AllocateDistanceTransform(); SetupTransformFinitePenaltyRanges(transform, pairParams, lengthAngleConstraints[currentEdgeIndex]); SetupTransformInterestRanges(transform, lengthAngleConstraints[parentEdgeIndex]); Func <double, double, double> penaltyFunction = (scaledLength, shiftedAngle) => { double length = scaledLength / pairParams.MeanLengthRatio; double angle = shiftedAngle + pairParams.MeanAngle; double lengthTolerance = transform.GridStepSizeX / pairParams.MeanLengthRatio; double angleTolerance = transform.GridStepSizeY; if (!lengthAngleConstraints[currentEdgeIndex].InRange(length, lengthTolerance, angle, angleTolerance)) { return(1e+20); } double penalty = CalculateMinUnaryEdgeEnergy(currentEdgeIndex, model, shapeConstraints, length) + CalculateMinPairwiseEdgeEnergy(length, angle, childDistanceTransforms); return(penalty); }; transform.Compute( 0.5 / MathHelper.Sqr(pairParams.LengthDiffDeviation), 0.5 / MathHelper.Sqr(pairParams.AngleDeviation), penaltyFunction); return(transform); }
public double CalculateLowerBound(Size imageSize, ShapeModel model, ShapeConstraints shapeConstraints) { if (model == null) { throw new ArgumentNullException("model"); } if (shapeConstraints == null) { throw new ArgumentNullException("shapeConstraints"); } if (model.Structure != shapeConstraints.ShapeStructure) { throw new ArgumentException("Shape model and shape constraints correspond to different shape structures."); } List <ILengthAngleConstraints> lengthAngleConstraints = CalculateLengthAngleConstraints(shapeConstraints); if (model.ConstrainedEdgePairs.Count == 0) { double lowerBound = CalculateSingleEdgeLowerBound(model, shapeConstraints, lengthAngleConstraints); Debug.Assert(lowerBound >= 0); return(lowerBound); } // Determine max (scaled) length possible double maxRatio1 = (from edgePair in model.ConstrainedEdgePairs select model.GetEdgePairParams(edgePair.Item1, edgePair.Item2).MeanLengthRatio).Max(); double maxRatio2 = (from edgePair in model.ConstrainedEdgePairs select 1.0 / model.GetEdgePairParams(edgePair.Item1, edgePair.Item2).MeanLengthRatio).Max(); double maxRatio = Math.Max(maxRatio1, maxRatio2); double maxEdgeLength = (new Vector(imageSize.Width, imageSize.Height)).Length; double maxScaledLength = maxEdgeLength * maxRatio; if (maxScaledLength != this.currentMaxScaledLength) { this.currentMaxScaledLength = maxScaledLength; this.transformPool.Clear(); } this.FreeAllDistanceTransforms(); // Calculate distance transforms for all the child edges List <GeneralizedDistanceTransform2D> childTransforms = new List <GeneralizedDistanceTransform2D>(); foreach (int edgeIndex in model.IterateNeighboringEdgeIndices(model.RootEdgeIndex)) { childTransforms.Add(CalculateMinEnergiesForAllParentEdges(model, shapeConstraints, model.RootEdgeIndex, edgeIndex, lengthAngleConstraints)); } // Find best overall solution double minEnergySum = Double.PositiveInfinity; GeneralizedDistanceTransform2D transform = childTransforms[0]; foreach (int lengthGridIndex in transform.EnumerateInterestGridIndicesX()) { double length = transform.GridIndexToCoordX(lengthGridIndex); double minPairwiseEnergy = Double.PositiveInfinity; foreach (int angleGridIndex in transform.EnumerateInterestGridIndicesY()) { double angle = transform.GridIndexToCoordY(angleGridIndex); const double eps = 1e-8; if (angle > Math.PI + eps || angle < -Math.PI - eps) { continue; // Consider only natural angle representations here } minPairwiseEnergy = Math.Min(minPairwiseEnergy, CalculateMinPairwiseEdgeEnergy(length, angle, childTransforms)); } double unaryEdgeEnergy = CalculateMinUnaryEdgeEnergy(model.RootEdgeIndex, model, shapeConstraints, length); double rootEdgeEnergy = model.CalculateRootEdgeEnergyTerm(length); minEnergySum = Math.Min(minEnergySum, minPairwiseEnergy + unaryEdgeEnergy + rootEdgeEnergy); } Debug.Assert(minEnergySum >= 0); return(minEnergySum); }
public double CalculateLowerBound(Size imageSize, ShapeModel model, ShapeConstraints shapeConstraints) { if (model == null) throw new ArgumentNullException("model"); if (shapeConstraints == null) throw new ArgumentNullException("shapeConstraints"); if (model.Structure != shapeConstraints.ShapeStructure) throw new ArgumentException("Shape model and shape constraints correspond to different shape structures."); List<ILengthAngleConstraints> lengthAngleConstraints = CalculateLengthAngleConstraints(shapeConstraints); if (model.ConstrainedEdgePairs.Count == 0) { double lowerBound = CalculateSingleEdgeLowerBound(model, shapeConstraints, lengthAngleConstraints); Debug.Assert(lowerBound >= 0); return lowerBound; } // Determine max (scaled) length possible double maxRatio1 = (from edgePair in model.ConstrainedEdgePairs select model.GetEdgePairParams(edgePair.Item1, edgePair.Item2).MeanLengthRatio).Max(); double maxRatio2 = (from edgePair in model.ConstrainedEdgePairs select 1.0 / model.GetEdgePairParams(edgePair.Item1, edgePair.Item2).MeanLengthRatio).Max(); double maxRatio = Math.Max(maxRatio1, maxRatio2); double maxEdgeLength = (new Vector(imageSize.Width, imageSize.Height)).Length; double maxScaledLength = maxEdgeLength * maxRatio; if (maxScaledLength != this.currentMaxScaledLength) { this.currentMaxScaledLength = maxScaledLength; this.transformPool.Clear(); } this.FreeAllDistanceTransforms(); // Calculate distance transforms for all the child edges List<GeneralizedDistanceTransform2D> childTransforms = new List<GeneralizedDistanceTransform2D>(); foreach (int edgeIndex in model.IterateNeighboringEdgeIndices(model.RootEdgeIndex)) childTransforms.Add(CalculateMinEnergiesForAllParentEdges(model, shapeConstraints, model.RootEdgeIndex, edgeIndex, lengthAngleConstraints)); // Find best overall solution double minEnergySum = Double.PositiveInfinity; GeneralizedDistanceTransform2D transform = childTransforms[0]; foreach (int lengthGridIndex in transform.EnumerateInterestGridIndicesX()) { double length = transform.GridIndexToCoordX(lengthGridIndex); double minPairwiseEnergy = Double.PositiveInfinity; foreach (int angleGridIndex in transform.EnumerateInterestGridIndicesY()) { double angle = transform.GridIndexToCoordY(angleGridIndex); const double eps = 1e-8; if (angle > Math.PI + eps || angle < -Math.PI - eps) continue; // Consider only natural angle representations here minPairwiseEnergy = Math.Min(minPairwiseEnergy, CalculateMinPairwiseEdgeEnergy(length, angle, childTransforms)); } double unaryEdgeEnergy = CalculateMinUnaryEdgeEnergy(model.RootEdgeIndex, model, shapeConstraints, length); double rootEdgeEnergy = model.CalculateRootEdgeEnergyTerm(length); minEnergySum = Math.Min(minEnergySum, minPairwiseEnergy + unaryEdgeEnergy + rootEdgeEnergy); } Debug.Assert(minEnergySum >= 0); return minEnergySum; }
private GeneralizedDistanceTransform2D CalculateMinEnergiesForAllParentEdges( ShapeModel model, ShapeConstraints shapeConstraints, int parentEdgeIndex, int currentEdgeIndex, IList<ILengthAngleConstraints> lengthAngleConstraints) { // Calculate child transforms List<GeneralizedDistanceTransform2D> childDistanceTransforms = new List<GeneralizedDistanceTransform2D>(); foreach (int neighborEdgeIndex in model.IterateNeighboringEdgeIndices(currentEdgeIndex)) { // Iterate only through children if (neighborEdgeIndex == parentEdgeIndex) continue; GeneralizedDistanceTransform2D childTransform = CalculateMinEnergiesForAllParentEdges( model, shapeConstraints, currentEdgeIndex, neighborEdgeIndex, lengthAngleConstraints); Debug.Assert(childTransform.IsComputed); childDistanceTransforms.Add(childTransform); } ShapeEdgePairParams pairParams = model.GetEdgePairParams(parentEdgeIndex, currentEdgeIndex); GeneralizedDistanceTransform2D transform = this.AllocateDistanceTransform(); SetupTransformFinitePenaltyRanges(transform, pairParams, lengthAngleConstraints[currentEdgeIndex]); SetupTransformInterestRanges(transform, lengthAngleConstraints[parentEdgeIndex]); Func<double, double, double> penaltyFunction = (scaledLength, shiftedAngle) => { double length = scaledLength / pairParams.MeanLengthRatio; double angle = shiftedAngle + pairParams.MeanAngle; double lengthTolerance = transform.GridStepSizeX / pairParams.MeanLengthRatio; double angleTolerance = transform.GridStepSizeY; if (!lengthAngleConstraints[currentEdgeIndex].InRange(length, lengthTolerance, angle, angleTolerance)) return 1e+20; double penalty = CalculateMinUnaryEdgeEnergy(currentEdgeIndex, model, shapeConstraints, length) + CalculateMinPairwiseEdgeEnergy(length, angle, childDistanceTransforms); return penalty; }; transform.Compute( 0.5 / MathHelper.Sqr(pairParams.LengthDiffDeviation), 0.5 / MathHelper.Sqr(pairParams.AngleDeviation), penaltyFunction); return transform; }