Exemple #1
0
        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 AllowedLengthAngleChecker(
            VertexConstraints constraint1,
            VertexConstraints constraint2,
            GeneralizedDistanceTransform2D checkingTransform,
            double lengthRatio,
            double meanAngle)
        {
            this.lengthAngleStatus = new Image2D <byte>(checkingTransform.GridSize.Width, checkingTransform.GridSize.Height);
            LengthAngleSpaceSeparatorSet separator = new LengthAngleSpaceSeparatorSet(constraint1, constraint2);

            this.checkingTransform = checkingTransform;

            // Initial fill
            for (int i = 0; i < checkingTransform.GridSize.Width; ++i)
            {
                double scaledLength = checkingTransform.GridIndexToCoordX(i);
                double length       = scaledLength / lengthRatio;

                for (int j = 0; j < checkingTransform.GridSize.Height; ++j)
                {
                    double shiftedAngle = checkingTransform.GridIndexToCoordY(j);
                    double angle        = shiftedAngle + meanAngle;

                    if (separator.IsInside(length, angle))
                    {
                        this.lengthAngleStatus[i, j] = 2;
                    }
                    else if (i == 0 || j == 0 || this.lengthAngleStatus[i - 1, j] == 1 || this.lengthAngleStatus[i, j - 1] == 1)
                    {
                        this.lengthAngleStatus[i, j] = 1;
                    }
                }
            }

            // Fill holes
            for (int i = 0; i < checkingTransform.GridSize.Width; ++i)
            {
                for (int j = 0; j < checkingTransform.GridSize.Height; ++j)
                {
                    if (lengthAngleStatus[i, j] == 0)
                    {
                        lengthAngleStatus[i, j] = 2;
                    }
                }
            }
        }
Exemple #3
0
        private void SetupTransformFinitePenaltyRanges(
            GeneralizedDistanceTransform2D transform, ShapeEdgePairParams pairParams, ILengthAngleConstraints lengthAngleConstraints)
        {
            Range lengthRange = lengthAngleConstraints.LengthBoundary;
            Range angleRange  = lengthAngleConstraints.AngleBoundary;

            transform.AddFinitePenaltyRangeX(
                new Range(lengthRange.Left * pairParams.MeanLengthRatio, lengthRange.Right * pairParams.MeanLengthRatio));

            if (!angleRange.Outside)
            {
                transform.AddFinitePenaltyRangeY(new Range(angleRange.Left - pairParams.MeanAngle, angleRange.Right - pairParams.MeanAngle));
            }
            else
            {
                transform.AddFinitePenaltyRangeY(new Range(-Math.PI - pairParams.MeanAngle, angleRange.Left - pairParams.MeanAngle));
                transform.AddFinitePenaltyRangeY(new Range(angleRange.Right - pairParams.MeanAngle, Math.PI - pairParams.MeanAngle));
            }
        }
        public AllowedLengthAngleChecker(
            VertexConstraints constraint1,
            VertexConstraints constraint2,
            GeneralizedDistanceTransform2D checkingTransform,
            double lengthRatio,
            double meanAngle)
        {
            this.lengthAngleStatus = new Image2D<byte>(checkingTransform.GridSize.Width, checkingTransform.GridSize.Height);
            LengthAngleSpaceSeparatorSet separator = new LengthAngleSpaceSeparatorSet(constraint1, constraint2);

            this.checkingTransform = checkingTransform;
            
            // Initial fill
            for (int i = 0; i < checkingTransform.GridSize.Width; ++i)
            {
                double scaledLength = checkingTransform.GridIndexToCoordX(i);
                double length = scaledLength / lengthRatio;

                for (int j = 0; j < checkingTransform.GridSize.Height; ++j)
                {
                    double shiftedAngle = checkingTransform.GridIndexToCoordY(j);
                    double angle = shiftedAngle + meanAngle;

                    if (separator.IsInside(length, angle))
                        this.lengthAngleStatus[i, j] = 2;
                    else if (i == 0 || j == 0 || this.lengthAngleStatus[i - 1, j] == 1 || this.lengthAngleStatus[i, j - 1] == 1)
                        this.lengthAngleStatus[i, j] = 1;
                }
            }

            // Fill holes
            for (int i = 0; i < checkingTransform.GridSize.Width; ++i)
            {
                for (int j = 0; j < checkingTransform.GridSize.Height; ++j)
                {
                    if (lengthAngleStatus[i, j] == 0)
                        lengthAngleStatus[i, j] = 2;
                }
            }
        }
Exemple #5
0
        private GeneralizedDistanceTransform2D AllocateDistanceTransform()
        {
            GeneralizedDistanceTransform2D result;

            if (this.firstFreeTranform < this.transformPool.Count)
            {
                result = this.transformPool[this.firstFreeTranform++];
                result.ResetFinitePenaltyRange();
                result.ResetInterestRange();
            }
            else
            {
                result = new GeneralizedDistanceTransform2D(
                    new Range(0, this.currentMaxScaledLength),
                    new Range(-Math.PI * 2, Math.PI * 2),
                    new Size(this.LengthGridSize, this.AngleGridSize));
                this.firstFreeTranform++;
                this.transformPool.Add(result);
            }

            return(result);
        }
Exemple #6
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);
        }
Exemple #7
0
        private void SetupTransformInterestRanges(GeneralizedDistanceTransform2D transform, ILengthAngleConstraints lengthAngleConstraints)
        {
            Range lengthRange = lengthAngleConstraints.LengthBoundary;
            Range angleRange  = lengthAngleConstraints.AngleBoundary;

            transform.AddInterestRangeX(lengthRange);

            if (!angleRange.Outside)
            {
                transform.AddInterestRangeY(angleRange);

                if (angleRange.Right > 0)
                {
                    if (angleRange.Left > 0)
                    {
                        transform.AddInterestRangeY(new Range(angleRange.Left - Math.PI * 2, angleRange.Right - Math.PI * 2));
                    }
                    else
                    {
                        transform.AddInterestRangeY(new Range(-Math.PI * 2, angleRange.Right - Math.PI * 2));
                        transform.AddInterestRangeY(new Range(angleRange.Left + Math.PI * 2, Math.PI * 2));
                    }
                }
                else
                {
                    transform.AddInterestRangeY(new Range(angleRange.Left + Math.PI * 2, angleRange.Right + Math.PI * 2));
                }
            }
            else
            {
                transform.AddInterestRangeY(new Range(-Math.PI, angleRange.Left));
                transform.AddInterestRangeY(new Range(angleRange.Right, Math.PI));

                if (angleRange.Right > 0)
                {
                    transform.AddInterestRangeY(new Range(angleRange.Right - Math.PI * 2, -Math.PI));
                }
                else
                {
                    transform.AddInterestRangeY(new Range(-Math.PI * 2, -Math.PI));
                    transform.AddInterestRangeY(new Range(angleRange.Right + Math.PI * 2, Math.PI * 2));
                }

                if (angleRange.Left < 0)
                {
                    transform.AddInterestRangeY(new Range(Math.PI, angleRange.Left + Math.PI * 2));
                }
                else
                {
                    transform.AddInterestRangeY(new Range(Math.PI, Math.PI * 2));
                    transform.AddInterestRangeY(new Range(-Math.PI * 2, angleRange.Left - Math.PI * 2));
                }
            }

            // Add all the representations of zero angle
            if (angleRange.IntersectsWith(new Range(-transform.GridStepSizeY * 0.5, transform.GridStepSizeY * 0.5)))
            {
                if (!transform.IsCoordYOfInterest(-Math.PI * 2))
                {
                    transform.AddInterestRangeY(new Range(-Math.PI * 2, -Math.PI * 2));
                }
                if (!transform.IsCoordYOfInterest(0))
                {
                    transform.AddInterestRangeY(new Range(0, 0));
                }
                if (!transform.IsCoordYOfInterest(Math.PI * 2))
                {
                    transform.AddInterestRangeY(new Range(Math.PI * 2, Math.PI * 2));
                }
            }
        }
        private void SetupTransformFinitePenaltyRanges(
            GeneralizedDistanceTransform2D transform, ShapeEdgePairParams pairParams, ILengthAngleConstraints lengthAngleConstraints)
        {
            Range lengthRange = lengthAngleConstraints.LengthBoundary;
            Range angleRange = lengthAngleConstraints.AngleBoundary;
            
            transform.AddFinitePenaltyRangeX(
                new Range(lengthRange.Left * pairParams.MeanLengthRatio, lengthRange.Right * pairParams.MeanLengthRatio));

            if (!angleRange.Outside)
                transform.AddFinitePenaltyRangeY(new Range(angleRange.Left - pairParams.MeanAngle, angleRange.Right - pairParams.MeanAngle));
            else
            {
                transform.AddFinitePenaltyRangeY(new Range(-Math.PI - pairParams.MeanAngle, angleRange.Left - pairParams.MeanAngle));
                transform.AddFinitePenaltyRangeY(new Range(angleRange.Right - pairParams.MeanAngle, Math.PI - pairParams.MeanAngle));
            }
        }
        private void SetupTransformInterestRanges(GeneralizedDistanceTransform2D transform, ILengthAngleConstraints lengthAngleConstraints)
        {
            Range lengthRange = lengthAngleConstraints.LengthBoundary;
            Range angleRange = lengthAngleConstraints.AngleBoundary;
            
            transform.AddInterestRangeX(lengthRange);

            if (!angleRange.Outside)
            {
                transform.AddInterestRangeY(angleRange);

                if (angleRange.Right > 0)
                {
                    if (angleRange.Left > 0)
                        transform.AddInterestRangeY(new Range(angleRange.Left - Math.PI * 2, angleRange.Right - Math.PI * 2));
                    else
                    {
                        transform.AddInterestRangeY(new Range(-Math.PI * 2, angleRange.Right - Math.PI * 2));
                        transform.AddInterestRangeY(new Range(angleRange.Left + Math.PI * 2, Math.PI * 2));
                    }
                }
                else
                    transform.AddInterestRangeY(new Range(angleRange.Left + Math.PI * 2, angleRange.Right + Math.PI * 2));
            }
            else
            {
                transform.AddInterestRangeY(new Range(-Math.PI, angleRange.Left));
                transform.AddInterestRangeY(new Range(angleRange.Right, Math.PI));

                if (angleRange.Right > 0)
                    transform.AddInterestRangeY(new Range(angleRange.Right - Math.PI * 2, -Math.PI));
                else
                {
                    transform.AddInterestRangeY(new Range(-Math.PI * 2, -Math.PI));
                    transform.AddInterestRangeY(new Range(angleRange.Right + Math.PI * 2, Math.PI * 2));
                }

                if (angleRange.Left < 0)
                    transform.AddInterestRangeY(new Range(Math.PI, angleRange.Left + Math.PI * 2));
                else
                {
                    transform.AddInterestRangeY(new Range(Math.PI, Math.PI * 2));
                    transform.AddInterestRangeY(new Range(-Math.PI * 2, angleRange.Left - Math.PI * 2));
                }
            }

            // Add all the representations of zero angle
            if (angleRange.IntersectsWith(new Range(-transform.GridStepSizeY * 0.5, transform.GridStepSizeY * 0.5)))
            {
                if (!transform.IsCoordYOfInterest(-Math.PI * 2))
                    transform.AddInterestRangeY(new Range(-Math.PI * 2, -Math.PI * 2));
                if (!transform.IsCoordYOfInterest(0))
                    transform.AddInterestRangeY(new Range(0, 0));
                if (!transform.IsCoordYOfInterest(Math.PI * 2))
                    transform.AddInterestRangeY(new Range(Math.PI * 2, Math.PI * 2));    
            }
        }
        private GeneralizedDistanceTransform2D AllocateDistanceTransform()
        {
            GeneralizedDistanceTransform2D result;
            if (this.firstFreeTranform < this.transformPool.Count)
            {
                result = this.transformPool[this.firstFreeTranform++];
                result.ResetFinitePenaltyRange();
                result.ResetInterestRange();
            }
            else
            {
                result = new GeneralizedDistanceTransform2D(
                    new Range(0, this.currentMaxScaledLength),
                    new Range(-Math.PI * 2, Math.PI * 2),
                    new Size(this.LengthGridSize, this.AngleGridSize));
                this.firstFreeTranform++;
                this.transformPool.Add(result);
            }

            return result;
        }