private void ReportBranchAndBoundCompletion(EnergyBound result) { // In order to report various masks we need to segment image again this.SegmentImageWithConstraints(result.Constraints.Collapse()); BranchAndBoundCompletedEventArgs args = new BranchAndBoundCompletedEventArgs( this.ImageSegmentator.GetLastSegmentationMask(), this.ImageSegmentator.GetLastUnaryTerms(), this.ImageSegmentator.GetLastShapeTerms(), result.Constraints, result.Bound); if (this.BranchAndBoundCompleted != null) { this.BranchAndBoundCompleted.Invoke(this, args); } }
private void ReportBranchAndBoundProgress(SortedSet <EnergyBound> front) { EnergyBound currentMin = front.Min; // In order to report various masks we need to segment image again this.SegmentImageWithConstraints(currentMin.Constraints); // Raise status report event BranchAndBoundProgressEventArgs args = new BranchAndBoundProgressEventArgs( front.Min.Bound, this.ImageSegmentator.GetLastSegmentationMask(), this.ImageSegmentator.GetLastUnaryTerms(), this.ImageSegmentator.GetLastShapeTerms(), currentMin.Constraints); if (this.BreadthFirstBranchAndBoundProgress != null) { this.BreadthFirstBranchAndBoundProgress.Invoke(this, args); } }
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); }
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)); }