Beispiel #1
0
        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);
        }
Beispiel #2
0
        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));
        }
Beispiel #3
0
        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));
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        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));
        }