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;
        }
示例#11
0
        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));
        }
示例#12
0
        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;
        }
示例#14
0
 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());
 }
示例#15
0
        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);
        }
示例#16
0
        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));
            }
        }
示例#18
0
        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));
                    }
                }
            }
        }