Ejemplo n.º 1
0
        public double SegmentImageWithShapeTerms(
            Func <int, int, ObjectBackgroundTerm> shapeTermCalculator)
        {
            // Calculate shape terms, check for changes)
            for (int x = 0; x < this.lastUnaryTerms.Width; ++x)
            {
                for (int y = 0; y < this.lastUnaryTerms.Height; ++y)
                {
                    ObjectBackgroundTerm shapeTerms = shapeTermCalculator(x, y);

                    if (firstTime || shapeTerms != this.lastShapeTerms[x, y])
                    {
                        double objectTermNew     = this.UnaryTermScaleCoeff * (this.colorTerms[x, y].ObjectTerm * this.ObjectColorUnaryTermWeight + shapeTerms.ObjectTerm * this.ObjectShapeUnaryTermWeight);
                        double backgroundTermNew = this.UnaryTermScaleCoeff * (this.colorTerms[x, y].BackgroundTerm * this.BackgroundColorUnaryTermWeight + shapeTerms.BackgroundTerm * this.BackgroundShapeUnaryTermWeight);
                        Debug.Assert(!Double.IsInfinity(objectTermNew) && !Double.IsNaN(objectTermNew));
                        Debug.Assert(!Double.IsInfinity(backgroundTermNew) && !Double.IsNaN(backgroundTermNew));

                        if (firstTime)
                        {
                            this.graphCutCalculator.SetTerminalWeights(x, y, backgroundTermNew, objectTermNew);
                        }
                        else
                        {
                            this.graphCutCalculator.UpdateTerminalWeights(
                                x, y, this.lastUnaryTerms[x, y].BackgroundTerm, this.lastUnaryTerms[x, y].ObjectTerm, backgroundTermNew, objectTermNew);
                        }

                        this.lastShapeTerms[x, y] = shapeTerms;
                        this.lastUnaryTerms[x, y] = new ObjectBackgroundTerm(objectTermNew, backgroundTermNew);
                    }
                }
            }

            // Actually segment image
            double graphCutEnergy = this.graphCutCalculator.Calculate();
            bool   wasFirstTime   = this.firstTime;

            this.firstTime = false;

            // Fill segmentation mask
            for (int x = 0; x < this.lastSegmentationMask.Width; ++x)
            {
                for (int y = 0; y < this.lastSegmentationMask.Height; ++y)
                {
                    bool isObject = this.graphCutCalculator.BelongsToSource(x, y);
                    this.lastSegmentationMask[x, y] = isObject;
                }
            }

            // Compute energy
            ImageSegmentationFeatures features = this.ExtractSegmentationFeaturesForMask(this.lastSegmentationMask);
            double energy = features.FeatureSum;

            // Sanity check: energies should be the same if graph cut calculator is "fresh"
            Trace.Assert(!wasFirstTime || Math.Abs(graphCutEnergy - energy) < 1e-6);

            return(energy);
        }
        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));
                    }
                }
            }
        }