public SegmentationSolution SegmentImage(Image2D <Color> image, ObjectBackgroundColorModels colorModels) { if (image == null) { throw new ArgumentNullException("image"); } if (colorModels == null) { throw new ArgumentNullException("colorModels"); } this.ImageSegmentator = new ImageSegmentator( image, colorModels, this.ColorDifferencePairwiseTermCutoff, this.ColorDifferencePairwiseTermWeight, this.ConstantPairwiseTermWeight, this.ObjectColorUnaryTermWeight, this.BackgroundColorUnaryTermWeight, this.ObjectShapeUnaryTermWeight, this.BackgroundShapeUnaryTermWeight); DebugConfiguration.WriteImportantDebugText( "Segmented image size is {0}x{1}.", this.ImageSegmentator.ImageSize.Width, this.ImageSegmentator.ImageSize.Height); SegmentationSolution solution = null; try { if (this.ShapeModel == null) { throw new InvalidOperationException("Shape model must be specified before segmenting image."); } DebugConfiguration.WriteImportantDebugText("Running segmentation algorithm..."); this.IsRunning = true; solution = this.SegmentCurrentImage(); if (solution == null) { throw new InvalidOperationException("Segmentation solution can not be null."); } } finally { if (this.IsStopping) { this.WasStopped = true; } this.IsRunning = false; this.IsStopping = false; } DebugConfiguration.WriteImportantDebugText("Finished"); return(solution); }
protected override SegmentationSolution SegmentCurrentImage() { DebugConfiguration.WriteImportantDebugText("Performing initial segmentation..."); this.ImageSegmentator.SegmentImageWithShapeTerms((x, y) => ObjectBackgroundTerm.Zero); Image2D <bool> prevMask = this.ImageSegmentator.GetLastSegmentationMask(); Shape prevShape = this.ShapeModel.FitMeanShape( this.ImageSegmentator.ImageSize.Width, this.ImageSegmentator.ImageSize.Height); double prevEnergy = 0; for (int iteration = 1; iteration <= this.MaxIterationCount && !this.IsStopping; ++iteration) { this.WaitIfPaused(); DebugConfiguration.WriteImportantDebugText("Iteration {0}", iteration); Image2D <bool> prevMaskCopy = prevMask; Shape currentShape = this.ShapeFitter.Run( prevShape, (s, t) => this.ShapeMutator.MutateShape(s, this.ShapeModel, this.ImageSegmentator.ImageSize, t / this.ShapeFitter.StartTemperature), s => this.CalcObjective(s, prevMaskCopy)); double currentEnergy = this.ImageSegmentator.SegmentImageWithShapeTerms((x, y) => this.ShapeModel.CalculatePenalties(currentShape, new Vector(x, y))); Image2D <bool> currentMask = this.ImageSegmentator.GetLastSegmentationMask(); int differentValues = Image2D <bool> .DifferentValueCount(prevMask, currentMask); double changedPixelRate = (double)differentValues / (this.ImageSegmentator.ImageSize.Width * this.ImageSegmentator.ImageSize.Height); DebugConfiguration.WriteImportantDebugText("On iteration {0}:", iteration); DebugConfiguration.WriteImportantDebugText("Energy is {0:0.000}", currentEnergy); DebugConfiguration.WriteImportantDebugText("Changed pixel rate is {0:0.000000}", changedPixelRate); DebugConfiguration.WriteImportantDebugText(); if (iteration > this.MinIterationCount && changedPixelRate < this.MinChangeRate) { DebugConfiguration.WriteImportantDebugText("Changed pixel rate is too low, breaking..."); break; } prevMask = currentMask; prevShape = currentShape; prevEnergy = currentEnergy; if (IterationFinished != null) { IterationFinished(this, new SegmentationIterationFinishedEventArgs( iteration, currentShape, this.ImageSegmentator.GetLastSegmentationMask(), this.ImageSegmentator.GetLastUnaryTerms(), this.ImageSegmentator.GetLastShapeTerms())); } } return(new SegmentationSolution(prevShape, prevMask, prevEnergy)); }
protected override SegmentationSolution SegmentCurrentImage() { if (this.Shape != null && this.Shape.Structure != this.ShapeModel.Structure) { throw new InvalidOperationException("Specified shape differs in structure from shape model."); } double segmentationEnergy = this.ImageSegmentator.SegmentImageWithShapeTerms( (x, y) => this.Shape == null ? ObjectBackgroundTerm.Zero : CalculateShapeTerms(new Vector(x, y))); double shapeEnergy = this.Shape == null ? 0 : this.ShapeModel.CalculateEnergy(this.Shape); double totalEnergy = segmentationEnergy + shapeEnergy * this.ShapeEnergyWeight; DebugConfiguration.WriteImportantDebugText( "Solution energy: {0:0.0000} ({1:0.0000} + {2:0.0000} * {3:0.0000})", totalEnergy, segmentationEnergy, this.ShapeEnergyWeight, shapeEnergy); return(new SegmentationSolution(this.Shape, this.ImageSegmentator.GetLastSegmentationMask(), totalEnergy)); }
private double CalcObjective(Shape shape, bool report) { this.UpdateShapeTerms(shape); double shapeEnergy = this.ShapeModel.CalculateEnergy(shape); double labelingEnergy = this.ImageSegmentator.SegmentImageWithShapeTerms((x, y) => this.shapeTerms[x, y]); double energy = shapeEnergy * this.ShapeEnergyWeight + labelingEnergy; double additionalPenalty = this.AdditionalShapePenalty == null ? 0 : this.AdditionalShapePenalty(shape); double totalEnergy = energy + additionalPenalty; if (report) { DebugConfiguration.WriteImportantDebugText( "Solution energy: {0:0.0000} ({1:0.0000} + {2:0.0000} * {3:0.0000} + {4:0.0000})", totalEnergy, labelingEnergy, this.ShapeEnergyWeight, shapeEnergy, additionalPenalty); } return(totalEnergy); }
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)); }