private ShapeConstraints(ShapeConstraints other) : this() { this.vertexConstraints = new List<VertexConstraints>(other.vertexConstraints); this.edgeConstraints = new List<EdgeConstraints>(other.edgeConstraints); this.ShapeStructure = other.ShapeStructure; }
public static ShapeConstraints CreateFromBounds( ShapeStructure structure, Vector coordMin, Vector coordMax, double minEdgeWidth, double maxEdgeWidth) { ShapeConstraints result = new ShapeConstraints(); result.ShapeStructure = structure; result.vertexConstraints = new List<VertexConstraints>(); result.edgeConstraints = new List<EdgeConstraints>(); for (int i = 0; i < structure.VertexCount; ++i) result.vertexConstraints.Add(new VertexConstraints(coordMin, coordMax)); for (int i = 0; i < structure.Edges.Count; ++i) result.edgeConstraints.Add(new EdgeConstraints(minEdgeWidth, maxEdgeWidth)); return result; }
public BranchAndBoundCompletedEventArgs( Image2D<bool> collapsedSolutionSegmentationMask, Image2D<ObjectBackgroundTerm> collapsedSolutionUnaryTermsImage, Image2D<ObjectBackgroundTerm> collapsedSolutionShapeTermsImage, ShapeConstraints resultConstraints, double lowerBound) { if (collapsedSolutionSegmentationMask == null) throw new ArgumentNullException("collapsedSolutionSegmentationMask"); if (collapsedSolutionUnaryTermsImage == null) throw new ArgumentNullException("collapsedSolutionUnaryTermsImage"); if (collapsedSolutionShapeTermsImage == null) throw new ArgumentNullException("collapsedSolutionShapeTermsImage"); if (resultConstraints == null) throw new ArgumentNullException("resultConstraints"); this.CollapsedSolutionSegmentationMask = collapsedSolutionSegmentationMask; this.CollapsedSolutionUnaryTermsImage = collapsedSolutionUnaryTermsImage; this.CollapsedSolutionShapeTermsImage = collapsedSolutionShapeTermsImage; this.ResultConstraints = resultConstraints; this.LowerBound = lowerBound; }
public BranchAndBoundProgressEventArgs( double lowerBound, Image2D<bool> segmentationMask, Image2D<ObjectBackgroundTerm> unaryTermsImage, Image2D<ObjectBackgroundTerm> shapeTermsImage, ShapeConstraints constraints) { if (segmentationMask == null) throw new ArgumentNullException("segmentationMask"); if (unaryTermsImage == null) throw new ArgumentNullException("unaryTermsImage"); if (shapeTermsImage == null) throw new ArgumentNullException("shapeTermsImage"); if (constraints == null) throw new ArgumentNullException("constraints"); this.LowerBound = lowerBound; this.SegmentationMask = segmentationMask; this.UnaryTermsImage = unaryTermsImage; this.ShapeTermsImage = shapeTermsImage; this.Constraints = constraints; }
public static ShapeConstraints CreateFromConstraints( ShapeStructure structure, IEnumerable<VertexConstraints> vertexConstraints, IEnumerable<EdgeConstraints> edgeConstraints) { if (structure == null) throw new ArgumentNullException("structure"); if (vertexConstraints == null) throw new ArgumentNullException("vertexConstraints"); if (edgeConstraints == null) throw new ArgumentNullException("edgeConstraints"); ShapeConstraints result = new ShapeConstraints(); result.ShapeStructure = structure; result.vertexConstraints = new List<VertexConstraints>(vertexConstraints); result.edgeConstraints = new List<EdgeConstraints>(edgeConstraints); if (result.vertexConstraints.Count != result.ShapeStructure.VertexCount) throw new ArgumentException("Vertex constraint should be given for every vertex (and for every vertex only).", "vertexConstraints"); if (result.edgeConstraints.Count != result.ShapeStructure.Edges.Count) throw new ArgumentException("Edge constraint should be given for every edge (and for every vertex only).", "edgeConstraints"); return result; }
private static double CalculateSingleEdgeLowerBound( ShapeModel model, ShapeConstraints shapeConstraints, IList<ILengthAngleConstraints> lengthAngleConstraints) { // TODO: support models with multiple edges but without pairwise constraints Debug.Assert(model.Structure.Edges.Count == 1); Debug.Assert(lengthAngleConstraints.Count == 1); double result; // Calculate best possible edge width penalty EdgeConstraints edgeConstraints = shapeConstraints.EdgeConstraints[0]; ShapeEdgeParams edgeParams = model.GetEdgeParams(0); Range lengthBoundary = lengthAngleConstraints[0].LengthBoundary; Range scaledLengthRange = new Range(lengthBoundary.Left * edgeParams.WidthToEdgeLengthRatio, lengthBoundary.Right * edgeParams.WidthToEdgeLengthRatio); Range widthRange = new Range(edgeConstraints.MinWidth, edgeConstraints.MaxWidth); if (scaledLengthRange.IntersectsWith(widthRange)) result = 0; else { result = model.CalculateEdgeWidthEnergyTerm(0, widthRange.Right, lengthBoundary.Left); result = Math.Min(result, model.CalculateEdgeWidthEnergyTerm(0, widthRange.Left, lengthBoundary.Right)); } return result; }
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; }
private static double CalculateMinUnaryEdgeEnergy(int edgeIndex, ShapeModel model, ShapeConstraints shapeConstraints, double edgeLength) { double bestWidth = edgeLength * model.GetEdgeParams(edgeIndex).WidthToEdgeLengthRatio; EdgeConstraints edgeConstraints = shapeConstraints.EdgeConstraints[edgeIndex]; bestWidth = MathHelper.Trunc(bestWidth, edgeConstraints.MinWidth, edgeConstraints.MaxWidth); return model.CalculateEdgeWidthEnergyTerm(edgeIndex, bestWidth, edgeLength); }
private static List<ILengthAngleConstraints> CalculateLengthAngleConstraints(ShapeConstraints shapeConstraints) { List<ILengthAngleConstraints> result = new List<ILengthAngleConstraints>(); for (int i = 0; i < shapeConstraints.ShapeStructure.Edges.Count; ++i) { ShapeEdge edge = shapeConstraints.ShapeStructure.Edges[i]; VertexConstraints vertex1Constraints = shapeConstraints.VertexConstraints[edge.Index1]; VertexConstraints vertex2Constraints = shapeConstraints.VertexConstraints[edge.Index2]; result.Add(BoxSetLengthAngleConstraints.FromVertexConstraints(vertex1Constraints, vertex2Constraints, 1, 16)); } return result; }
protected override SegmentationSolution SegmentCurrentImage() { if (this.minEdgeWidth >= this.maxEdgeWidth) { throw new InvalidOperationException("Min edge width should be less than max edge width."); } if (this.startConstraints != null) { if (this.startConstraints.ShapeStructure != this.ShapeModel.Structure) { throw new InvalidOperationException("Given start constraints have shape structure different from the one specified in shape model."); } // TODO: make this check work //foreach (VertexConstraints vertexConstraints in this.startConstraints.VertexConstraints) //{ // RectangleF imageRectangle = // new RectangleF(0, 0, this.ImageSegmentator.ImageSize.Width, this.ImageSegmentator.ImageSize.Height); // if (!imageRectangle.Contains(vertexConstraints.CoordRectangle)) // throw new InvalidOperationException("Given start constraints are not fully inside the segmented image."); //} } this.shapeUnaryTerms = new Image2D <ObjectBackgroundTerm>( this.ImageSegmentator.ImageSize.Width, this.ImageSegmentator.ImageSize.Height); ShapeConstraints constraints = this.startConstraints; if (constraints == null) { constraints = ShapeConstraints.CreateFromBounds( this.ShapeModel.Structure, Vector.Zero, new Vector(this.ImageSegmentator.ImageSize.Width, this.ImageSegmentator.ImageSize.Height), this.minEdgeWidth, this.maxEdgeWidth); } if (this.BranchAndBoundStarted != null) { this.BranchAndBoundStarted(this, EventArgs.Empty); } this.startTime = DateTime.Now; DebugConfiguration.WriteImportantDebugText("Breadth-first branch-and-bound started."); SortedSet <EnergyBound> front = this.BreadthFirstBranchAndBoundTraverse(constraints); ReportBranchAndBoundCompletion(front.Min); if (front.Min.Constraints.CheckIfSatisfied(this.maxCoordFreedom, this.maxWidthFreedom)) { DebugConfiguration.WriteImportantDebugText("Breadth-first branch-and-bound finished in {0}.", DateTime.Now - this.startTime); DebugConfiguration.WriteImportantDebugText("Best lower bound is {0:0.0000}", front.Min.Bound); } else { DebugConfiguration.WriteImportantDebugText("Breadth-first branch-and-bound forced to stop after {0}.", DateTime.Now - this.startTime); DebugConfiguration.WriteImportantDebugText("Min energy value achieved is {0:0.0000}", front.Min.Bound); } EnergyBound collapsedBfsSolution = this.CalculateEnergyBound(front.Min.Constraints.Collapse()); Shape resultShape = front.Min.Constraints.CollapseToShape(); DebugConfiguration.WriteImportantDebugText( "Collapsed solution energy value is {0:0.0000} ({1:0.0000} + {2:0.0000})", collapsedBfsSolution.Bound, collapsedBfsSolution.SegmentationEnergy, collapsedBfsSolution.ShapeEnergy * this.ShapeEnergyWeight); return(new SegmentationSolution(resultShape, this.ImageSegmentator.GetLastSegmentationMask(), collapsedBfsSolution.Bound)); }
private static double CalculateMinUnaryEdgeEnergy(int edgeIndex, ShapeModel model, ShapeConstraints shapeConstraints, double edgeLength) { double bestWidth = edgeLength * model.GetEdgeParams(edgeIndex).WidthToEdgeLengthRatio; EdgeConstraints edgeConstraints = shapeConstraints.EdgeConstraints[edgeIndex]; bestWidth = MathHelper.Trunc(bestWidth, edgeConstraints.MinWidth, edgeConstraints.MaxWidth); return(model.CalculateEdgeWidthEnergyTerm(edgeIndex, bestWidth, edgeLength)); }
public List<ShapeConstraints> SplitMostFree(double maxCoordFreedom, double maxWidthFreedom) { Debug.Assert(!this.CheckIfSatisfied(maxCoordFreedom, maxWidthFreedom)); // Most violated vertex constraint int mostFreeVertexConstraint = -1; double curMaxCoordFreedom = 0; for (int i = 0; i < vertexConstraints.Count; ++i) { if (vertexConstraints[i].Freedom > maxCoordFreedom && (mostFreeVertexConstraint == -1 || vertexConstraints[i].Freedom > curMaxCoordFreedom)) { mostFreeVertexConstraint = i; curMaxCoordFreedom = vertexConstraints[i].Freedom; } } // Most violated edge constraint int mostFreeEdgeConstraint = -1; double curMaxWidthFreedom = 0; for (int i = 0; i < edgeConstraints.Count; ++i) { if (edgeConstraints[i].Freedom > maxWidthFreedom && (mostFreeEdgeConstraint == -1 || edgeConstraints[i].Freedom > curMaxWidthFreedom)) { mostFreeEdgeConstraint = i; curMaxWidthFreedom = edgeConstraints[i].Freedom; } } bool splitEdgeConstraint = curMaxWidthFreedom > curMaxCoordFreedom; List<ShapeConstraints> result = new List<ShapeConstraints>(); if (splitEdgeConstraint) { List<EdgeConstraints> splittedEdgeConstraints = this.edgeConstraints[mostFreeEdgeConstraint].Split(); for (int i = 0; i < splittedEdgeConstraints.Count; ++i) { ShapeConstraints newSet = new ShapeConstraints(this); newSet.edgeConstraints[mostFreeEdgeConstraint] = splittedEdgeConstraints[i]; result.Add(newSet); } } else { List<VertexConstraints> splittedVertexConstraints = this.vertexConstraints[mostFreeVertexConstraint].Split(); for (int i = 0; i < splittedVertexConstraints.Count; ++i) { ShapeConstraints newSet = new ShapeConstraints(this); newSet.vertexConstraints[mostFreeVertexConstraint] = splittedVertexConstraints[i]; result.Add(newSet); } } return result; }
private Image2D <bool> SegmentImageWithConstraints(ShapeConstraints constraintsSet) { this.shapeTermsCalculator.CalculateShapeTerms(this.ShapeModel, constraintsSet, this.shapeUnaryTerms); this.ImageSegmentator.SegmentImageWithShapeTerms((x, y) => this.shapeUnaryTerms[x, y]); return(this.ImageSegmentator.GetLastSegmentationMask()); }
private SortedSet <EnergyBound> BreadthFirstBranchAndBoundTraverse(ShapeConstraints constraints) { SortedSet <EnergyBound> front = new SortedSet <EnergyBound> { this.CalculateEnergyBound(constraints) }; int currentIteration = 1; DateTime lastOutputTime = startTime; int processedConstraintSets = 0; while (!front.Min.Constraints.CheckIfSatisfied(this.maxCoordFreedom, this.maxWidthFreedom) && !this.IsStopping) { this.WaitIfPaused(); EnergyBound parentLowerBound = front.Min; front.Remove(parentLowerBound); List <ShapeConstraints> expandedConstraints = parentLowerBound.Constraints.SplitMostFree(this.maxCoordFreedom, this.maxWidthFreedom); foreach (ShapeConstraints constraintsSet in expandedConstraints) { EnergyBound lowerBound = this.CalculateEnergyBound(constraintsSet); front.Add(lowerBound); // Uncomment for strong invariants check //ObjectBackgroundTerm[,] lowerBoundShapeTerm = new ObjectBackgroundTerm[this.segmentedImage.Width, this.segmentedImage.Height]; //for (int i = 0; i < this.segmentedImage.Width; ++i) // for (int j = 0; j < this.segmentedImage.Height; ++j) // lowerBoundShapeTerm[i, j] = CpuBranchAndBoundShapeTermsCalculator.CalculateShapeTerm(lowerBound.Constraints, new Point(i, j)); //ObjectBackgroundTerm[,] parentLowerBoundShapeTerm = new ObjectBackgroundTerm[this.segmentedImage.Width, this.segmentedImage.Height]; //for (int i = 0; i < this.segmentedImage.Width; ++i) // for (int j = 0; j < this.segmentedImage.Height; ++j) // parentLowerBoundShapeTerm[i, j] = CpuBranchAndBoundShapeTermsCalculator.CalculateShapeTerm(parentLowerBound.Constraints, new Point(i, j)); //for (int i = 0; i < this.segmentedImage.Width; ++i) // for (int j = 0; j < this.segmentedImage.Height; ++j) // { // Debug.Assert(lowerBoundShapeTerm[i, j].ObjectTerm >= parentLowerBoundShapeTerm[i, j].ObjectTerm - 1e-7); // Debug.Assert(lowerBoundShapeTerm[i, j].BackgroundTerm >= parentLowerBoundShapeTerm[i, j].BackgroundTerm - 1e-7); // //CalculateShapeTerm(lowerBound.Constraints, new Point(0, 67)); // //CalculateShapeTerm(parentLowerBound.Constraints, new Point(0, 67)); // } // Lower bound should not decrease (check always, it's important!) Trace.Assert(lowerBound.SegmentationEnergy >= parentLowerBound.SegmentationEnergy - 1e-6); Trace.Assert(lowerBound.ShapeEnergy >= parentLowerBound.ShapeEnergy - 1e-6); //this.CalculateEnergyBound(lowerBound.Constraints); //this.CalculateEnergyBound(parentLowerBound.Constraints); ++processedConstraintSets; } // Some debug output if (currentIteration % this.ProgressReportRate == 0) { DateTime currentTime = DateTime.Now; EnergyBound currentMin = front.Min; DebugConfiguration.WriteDebugText( "On iteration {0} front contains {1} constraint sets.", currentIteration, front.Count); DebugConfiguration.WriteDebugText( "Current lower bound is {0:0.0000} ({1:0.0000} + {2:0.0000}).", currentMin.Bound, currentMin.SegmentationEnergy, currentMin.ShapeEnergy * this.ShapeEnergyWeight); double processingSpeed = processedConstraintSets / (currentTime - lastOutputTime).TotalSeconds; DebugConfiguration.WriteDebugText("Processing speed is {0:0.000} items per sec", processingSpeed); double maxVertexConstraintsFreedom = currentMin.Constraints.VertexConstraints.Max(c => c.Freedom); double maxEdgeConstraintsFreedom = currentMin.Constraints.EdgeConstraints.Max(c => c.Freedom); DebugConfiguration.WriteDebugText( "Max vertex freedom: {0:0.00}, max edge freedom: {1:0.00}", maxVertexConstraintsFreedom, maxEdgeConstraintsFreedom); DebugConfiguration.WriteDebugText("Elapsed time: {0}", DateTime.Now - this.startTime); DebugConfiguration.WriteDebugText(); this.ReportBranchAndBoundProgress(front); lastOutputTime = currentTime; processedConstraintSets = 0; } currentIteration += 1; } return(front); }
private static List <ILengthAngleConstraints> CalculateLengthAngleConstraints(ShapeConstraints shapeConstraints) { List <ILengthAngleConstraints> result = new List <ILengthAngleConstraints>(); for (int i = 0; i < shapeConstraints.ShapeStructure.Edges.Count; ++i) { ShapeEdge edge = shapeConstraints.ShapeStructure.Edges[i]; VertexConstraints vertex1Constraints = shapeConstraints.VertexConstraints[edge.Index1]; VertexConstraints vertex2Constraints = shapeConstraints.VertexConstraints[edge.Index2]; result.Add(BoxSetLengthAngleConstraints.FromVertexConstraints(vertex1Constraints, vertex2Constraints, 1, 16)); } return(result); }
public void CalculateShapeTerms(ShapeModel model, ShapeConstraints constraintsSet, Image2D<ObjectBackgroundTerm> result) { if (model == null) throw new ArgumentNullException("model"); if (constraintsSet == null) throw new ArgumentNullException("constraintsSet"); if (result == null) throw new ArgumentNullException("result"); if (model.Structure != constraintsSet.ShapeStructure) throw new ArgumentException("Shape model and shape constraints correspond to different shape structures."); if (model != this.shapeModel || result.Rectangle.Size != this.imageSize) this.SetTarget(model, result.Rectangle.Size); for (int x = 0; x < imageSize.Width; ++x) for (int y = 0; y < imageSize.Height; ++y) result[x, y] = new ObjectBackgroundTerm(Double.PositiveInfinity, 0); for (int edgeIndex = 0; edgeIndex < this.shapeModel.Structure.Edges.Count; ++edgeIndex) { ShapeEdge edge = this.shapeModel.Structure.Edges[edgeIndex]; VertexConstraints vertexConstraints1 = constraintsSet.VertexConstraints[edge.Index1]; VertexConstraints vertexConstraints2 = constraintsSet.VertexConstraints[edge.Index2]; EdgeConstraints edgeConstraints = constraintsSet.EdgeConstraints[edgeIndex]; Image2D<ObjectBackgroundTerm> edgeTerms; EdgeDescription edgeDescription = new EdgeDescription( vertexConstraints1, vertexConstraints2, edgeConstraints); if (!this.cachedEdgeTerms.TryGetValue(edgeDescription, out edgeTerms)) { edgeTerms = this.AllocateImage(); this.cachedEdgeTerms.Add(edgeDescription, edgeTerms); Polygon convexHull = constraintsSet.GetConvexHullForVertexPair(edge.Index1, edge.Index2); Parallel.For( 0, imageSize.Width, x => { for (int y = 0; y < imageSize.Height; ++y) { Vector pointAsVec = new Vector(x, y); double minDistanceSqr, maxDistanceSqr; MinMaxDistanceForEdge( pointAsVec, convexHull, vertexConstraints1, vertexConstraints2, out minDistanceSqr, out maxDistanceSqr); edgeTerms[x, y] = new ObjectBackgroundTerm( this.shapeModel.CalculateObjectPenaltyForEdge( minDistanceSqr, edgeConstraints.MaxWidth), this.shapeModel.CalculateBackgroundPenaltyForEdge( maxDistanceSqr, edgeConstraints.MinWidth)); } }); } for (int x = 0; x < imageSize.Width; ++x) for (int y = 0; y < imageSize.Height; ++y) result[x, y] = new ObjectBackgroundTerm( Math.Min(result[x, y].ObjectTerm, edgeTerms[x, y].ObjectTerm), Math.Max(result[x, y].BackgroundTerm, edgeTerms[x, y].BackgroundTerm)); } }
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 void CalculateShapeTerms(ShapeModel model, ShapeConstraints constraintsSet, Image2D <ObjectBackgroundTerm> result) { if (model == null) { throw new ArgumentNullException("model"); } if (constraintsSet == null) { throw new ArgumentNullException("constraintsSet"); } if (result == null) { throw new ArgumentNullException("result"); } if (model.Structure != constraintsSet.ShapeStructure) { throw new ArgumentException("Shape model and shape constraints correspond to different shape structures."); } if (model != this.shapeModel || result.Rectangle.Size != this.imageSize) { this.SetTarget(model, result.Rectangle.Size); } for (int x = 0; x < imageSize.Width; ++x) { for (int y = 0; y < imageSize.Height; ++y) { result[x, y] = new ObjectBackgroundTerm(Double.PositiveInfinity, 0); } } for (int edgeIndex = 0; edgeIndex < this.shapeModel.Structure.Edges.Count; ++edgeIndex) { ShapeEdge edge = this.shapeModel.Structure.Edges[edgeIndex]; VertexConstraints vertexConstraints1 = constraintsSet.VertexConstraints[edge.Index1]; VertexConstraints vertexConstraints2 = constraintsSet.VertexConstraints[edge.Index2]; EdgeConstraints edgeConstraints = constraintsSet.EdgeConstraints[edgeIndex]; Image2D <ObjectBackgroundTerm> edgeTerms; EdgeDescription edgeDescription = new EdgeDescription( vertexConstraints1, vertexConstraints2, edgeConstraints); if (!this.cachedEdgeTerms.TryGetValue(edgeDescription, out edgeTerms)) { edgeTerms = this.AllocateImage(); this.cachedEdgeTerms.Add(edgeDescription, edgeTerms); Polygon convexHull = constraintsSet.GetConvexHullForVertexPair(edge.Index1, edge.Index2); Parallel.For( 0, imageSize.Width, x => { for (int y = 0; y < imageSize.Height; ++y) { Vector pointAsVec = new Vector(x, y); double minDistanceSqr, maxDistanceSqr; MinMaxDistanceForEdge( pointAsVec, convexHull, vertexConstraints1, vertexConstraints2, out minDistanceSqr, out maxDistanceSqr); edgeTerms[x, y] = new ObjectBackgroundTerm( this.shapeModel.CalculateObjectPenaltyForEdge( minDistanceSqr, edgeConstraints.MaxWidth), this.shapeModel.CalculateBackgroundPenaltyForEdge( maxDistanceSqr, edgeConstraints.MinWidth)); } }); } for (int x = 0; x < imageSize.Width; ++x) { for (int y = 0; y < imageSize.Height; ++y) { result[x, y] = new ObjectBackgroundTerm( Math.Min(result[x, y].ObjectTerm, edgeTerms[x, y].ObjectTerm), Math.Max(result[x, y].BackgroundTerm, edgeTerms[x, y].BackgroundTerm)); } } } }