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)); } } } }