예제 #1
0
        /// <summary>
        /// Merges spectral values to clusters.
        /// </summary>
        private void MergeValuesToClusters()
        {
            Int32 minimalIndex = 0;
            for (Int32 rowIndex = 0; rowIndex < Source.Raster.NumberOfRows; rowIndex++)
            {
                for (Int32 columnIndex = 0; columnIndex < Source.Raster.NumberOfColumns; columnIndex++)
                {
                    switch (Source.Raster.Format)
                    {
                        case RasterFormat.Integer:
                            UInt32[] values = Source.Raster.GetValues(rowIndex, columnIndex);
                            minimalIndex = _clusterCenters.MinIndex(center => _distance.Distance(center, values));
                            break;
                        case RasterFormat.Floating:
                            Double[] floatValues = Source.Raster.GetFloatValues(rowIndex, columnIndex);
                            minimalIndex = _clusterCenters.MinIndex(center => _distance.Distance(center, floatValues));
                            break;
                    }

                    if (_clusters[minimalIndex] == null)
                        _clusters[minimalIndex] = ResultSegments.GetSegment(rowIndex, columnIndex);
                    else
                        ResultSegments.MergeSegments(_clusters[minimalIndex], rowIndex, columnIndex);
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Computes the result of the operation.
        /// </summary>
        protected override void ComputeResult()
        {
            InitializeClusterCenters();
            
            Int32 iterationIndex = 0;

            while (iterationIndex < _maximumIterations)
            {
                if (Source.Raster is ISegmentedRaster)
                    MergeSegmentsToClusters();
                else
                    MergeValuesToClusters();

                iterationIndex++;
                if (iterationIndex == _maximumIterations)
                    break;

                if (AreClustersCentersValid())
                    break;

                // create new clusters with new centers
                for (Int32 clusterIndex = 0; clusterIndex < _clusters.Length; clusterIndex++)
                {
                    _clusterCenters[clusterIndex] = _clusters[clusterIndex].Mean.ToArray();
                    _clusters[clusterIndex] = null;
                }

                ResultSegments.Clear();
            }
        }
예제 #3
0
        /// <summary>
        /// Merges segments to clusters.
        /// </summary>
        private void MergeSegmentsToClusters()
        {
            Segment[] clusters = new Segment[_numberOfClusters];

            Int32 minimalIndex = 0;

            List <Segment> segments = ResultSegments.GetSegments().ToList();

            foreach (Segment segment in segments)
            {
                if (!ResultSegments.Contains(segment))
                {
                    continue;
                }

                minimalIndex = _clusterCenters.MinIndex(center => _distance.Distance(segment, center));

                if (clusters[minimalIndex] == null)
                {
                    clusters[minimalIndex] = segment;
                }
                else
                {
                    clusters[minimalIndex] = ResultSegments.MergeSegments(clusters[minimalIndex], segment);
                }
            }
        }
        /// <summary>
        /// Computes the result of the operation.
        /// </summary>
        protected override void ComputeResult()
        {
            Boolean hasMerged = true;

            Double[] distances = new Double[4];

            for (Int32 iterationIndex = 0; iterationIndex < _numberOfIterations && hasMerged; iterationIndex++)
            {
                hasMerged = false;

                for (Int32 rowIndex = 0; rowIndex < Source.Raster.NumberOfRows; rowIndex++)
                {
                    for (Int32 columnIndex = 0; columnIndex < Source.Raster.NumberOfColumns; columnIndex++)
                    {
                        // select best merge direction

                        distances[0] = ComputeDistance(rowIndex, columnIndex, rowIndex, columnIndex - 1); // left
                        distances[1] = ComputeDistance(rowIndex, columnIndex, rowIndex - 1, columnIndex); // up
                        distances[2] = ComputeDistance(rowIndex, columnIndex, rowIndex, columnIndex + 1); // right
                        distances[3] = ComputeDistance(rowIndex, columnIndex, rowIndex + 1, columnIndex); // down

                        Double minDistance = distances.Min();

                        if (minDistance >= _mergeThreshold)
                        {
                            continue;
                        }

                        // apply merge

                        switch ((SegmentMergeDirection)Array.IndexOf(distances, minDistance))
                        {
                        case SegmentMergeDirection.Left:
                            ResultSegments.MergeSegments(rowIndex, columnIndex, rowIndex, columnIndex - 1);
                            break;

                        case SegmentMergeDirection.Up:
                            ResultSegments.MergeSegments(rowIndex, columnIndex, rowIndex - 1, columnIndex);
                            break;

                        case SegmentMergeDirection.Right:
                            ResultSegments.MergeSegments(rowIndex, columnIndex, rowIndex, columnIndex + 1);
                            break;

                        case SegmentMergeDirection.Down:
                            ResultSegments.MergeSegments(rowIndex, columnIndex, rowIndex + 1, columnIndex);
                            break;
                        }

                        hasMerged = true;
                    }
                }
            }
        }
        /// <summary>
        /// Computes the result of the operation.
        /// </summary>
        protected override void ComputeResult()
        {
            // source: Felzenszwalb, Huttenlocher: Efficient Graph-Based Image Segmentation

            List <SimpleGraphEdge> edges = GenerateEdgeList();

            _innerDiffences = new Dictionary <Segment, Single>();

            // remove the edges and merge segments
            while (edges.Count > 0)
            {
                SimpleGraphEdge edge = edges[edges.Count - 1];
                edges.RemoveAt(edges.Count - 1);

                Segment firstSegment  = ResultSegments[edge.Source / Source.Raster.NumberOfColumns, edge.Source % Source.Raster.NumberOfColumns];
                Segment secondSegment = ResultSegments[edge.Destination / Source.Raster.NumberOfColumns, edge.Destination % Source.Raster.NumberOfColumns];

                // if the two indices are already within the same segment
                if (firstSegment == secondSegment)
                {
                    continue;
                }

                Double internalDifference = ComputeMaximumInternalDifference(firstSegment, secondSegment);

                // if the weight of the edge does not influence the internal difference
                if (internalDifference > edge.Weight)
                {
                    // the segments should be merged
                    Segment mergedSegment = ResultSegments.MergeSegments(firstSegment, secondSegment);
                    Segment otherSegment  = mergedSegment == firstSegment ? firstSegment : secondSegment;

                    // modify internal difference
                    Single weight = edge.Weight;
                    if (_innerDiffences.ContainsKey(otherSegment))
                    {
                        weight = Math.Max(_innerDiffences[otherSegment], edge.Weight);
                        _innerDiffences.Remove(otherSegment);
                    }

                    if (!_innerDiffences.ContainsKey(mergedSegment))
                    {
                        _innerDiffences.Add(mergedSegment, (Single)edge.Weight);
                    }
                    else
                    {
                        _innerDiffences[mergedSegment] = Math.Max(_innerDiffences[mergedSegment], weight);
                    }
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Eliminates small clusters.
        /// </summary>
        private void EliminateSmallClusters()
        {
            _clusterCenters = null;

            Segment[] segments = ResultSegments.GetSegments().ToArray();

            foreach (Segment segment in segments)
            {
                if (segment.Count < _clusterSizeThreshold)
                {
                    ResultSegments.SplitSegment(segment);
                }
            }
        }
        /// <summary>
        /// Returns whether the ANOVA criteria hold for the specified band of the two segments.
        /// </summary>
        /// <param name="first">The first segment.</param>
        /// <param name="second">The second segment.</param>
        /// <param name="bandIndex">The band index.</param>
        /// <returns><c>true</c> if the ANOVA criteria are satisfied, otherwise <c>false</c>.</returns>
        private Boolean AnovaCriteria(Segment first, Segment second, Int32 bandIndex)
        {
            Double aX = first.Variance[bandIndex] * (first.Count - 1);
            Double aY = second.Variance[bandIndex] * (second.Count - 1);
            Int32  m  = first.Count;
            Int32  n  = second.Count;

            if (aX + aY == 0)
            {
                return(true);
            }

            Double denominator = Math.Pow((aX + aY) / (n + m), (n + m - 2));

            Double secondCriteriaValue = Math.Pow(aX / m, m - 1) * Math.Pow(aY / n, n - 1) / denominator;

            if (!Double.IsInfinity(denominator) && secondCriteriaValue < _varianceThresholdBeforeMerge)
            {
                return(false);
            }

            Double zMean = (first.Mean[bandIndex] * m + second.Mean[bandIndex] * n) / (m + n);

            Double bX = 0, bY = 0;

            foreach (UInt32 value in ResultSegments.GetFloatValues(first, bandIndex))
            {
                bX += (value - zMean) * (value - zMean);
            }

            foreach (UInt32 value in ResultSegments.GetFloatValues(second, bandIndex))
            {
                bY += (value - zMean) * (value - zMean);
            }

            if (bX + bY == 0)
            {
                return(false);
            }

            Double firstCriteriaValue = Math.Pow((aX + aY) / (bX + bY), (m + n) / 2.0);

            if (firstCriteriaValue < _varianceThresholdAfterMerge)
            {
                return(false);
            }

            return(true);
        }
예제 #8
0
        /// <summary>
        /// Merges segments to clusters.
        /// </summary>
        private void MergeSegmentsToClusters()
        {
            Int32 minimalIndex = 0;

            List<Segment> segments = ResultSegments.GetSegments().ToList();
            foreach (Segment segment in segments)
            {
                if (!ResultSegments.Contains(segment))
                    continue;

                minimalIndex = _clusterCenters.MinIndex(center => _distance.Distance(segment, center));

                if (_clusters[minimalIndex] == null)
                    _clusters[minimalIndex] = segment;
                else
                    _clusters[minimalIndex] = ResultSegments.MergeSegments(_clusters[minimalIndex], segment);
            }
        }
예제 #9
0
        /// <summary>
        /// Merges the clusters.
        /// </summary>
        private void MergeClusters()
        {
            HashSet <Segment> segmentsToCheck = new HashSet <Segment>(ResultSegments.GetSegments());

            do
            {
                List <Segment>    allSegments         = ResultSegments.GetSegments().ToList();
                HashSet <Segment> nextSegmentsToCheck = new HashSet <Segment>();

                foreach (Segment currentSegment in segmentsToCheck)
                {
                    for (Int32 index = 0; index < allSegments.Count; index++)
                    {
                        if (allSegments[index] == currentSegment ||
                            !ResultSegments.Contains(allSegments[index]) ||
                            !ResultSegments.Contains(currentSegment))
                        {
                            continue;
                        }

                        Double distance = _clusterCenterDistance.Distance(currentSegment, allSegments[index]);

                        if (distance < _clusterDistanceThreshold)
                        {
                            Segment mergedSegment = ResultSegments.MergeSegments(currentSegment, allSegments[index]);
                            if (mergedSegment == currentSegment)
                            {
                                allSegments.RemoveAt(index);
                            }
                            else
                            {
                                allSegments.Remove(currentSegment);
                            }

                            nextSegmentsToCheck.Add(mergedSegment);
                        }
                    }
                }

                segmentsToCheck = nextSegmentsToCheck;
            } while (segmentsToCheck.Count > 0);
        }
        /// <summary>
        /// Computes the result of the operation.
        /// </summary>
        protected override void ComputeResult()
        {
            for (Int32 rowIndex = 0; rowIndex < Source.Raster.NumberOfRows; rowIndex += 2)
            {
                // initialize the segments of the next rows with 2x2 sized segments
                for (Int32 columnIndex = 0; columnIndex < Source.Raster.NumberOfColumns; columnIndex += 2)
                {
                    if (columnIndex < Source.Raster.NumberOfColumns - 1)
                    {
                        ResultSegments.MergeSegments(rowIndex, columnIndex, rowIndex, columnIndex + 1);
                    }
                    if (rowIndex < Source.Raster.NumberOfRows - 1)
                    {
                        ResultSegments.MergeSegments(rowIndex, columnIndex, rowIndex + 1, columnIndex);
                        if (columnIndex < Source.Raster.NumberOfColumns - 1)
                        {
                            ResultSegments.MergeSegments(rowIndex, columnIndex, rowIndex + 1, columnIndex + 1);
                        }
                    }
                }

                // connect segments
                for (Int32 columnIndex = 0; columnIndex < Source.Raster.NumberOfColumns; columnIndex += 2)
                {
                    SegmentMergeDirection direction = SegmentMergeDirection.None;
                    Double currentDistance          = Double.MaxValue;

                    Segment currentSegment = ResultSegments[rowIndex, columnIndex];

                    // only connect if the cell is homogeneous
                    if (currentSegment.IsHomogeneous(_segmentHomogeneityThreshold))
                    {
                        // select the best merge direction based on the ANOVA criteria and the euclidean distance

                        // left
                        if (CanMergeSegments(currentSegment, rowIndex, columnIndex - 2))
                        {
                            currentDistance = _distance.Distance(currentSegment, ResultSegments[rowIndex, columnIndex - 2]);
                            direction       = SegmentMergeDirection.Left;
                        }

                        // up
                        if (CanMergeSegments(currentSegment, rowIndex - 2, columnIndex))
                        {
                            Double distance = _distance.Distance(currentSegment, ResultSegments[rowIndex - 2, columnIndex]);
                            if (distance < currentDistance)
                            {
                                direction = SegmentMergeDirection.Up;
                            }
                        }

                        // right 1
                        if (CanMergeSegments(rowIndex - 2, columnIndex + 2, rowIndex, columnIndex + 2))
                        {
                            Segment mergedSegment = ResultSegments.MergeSegments(ResultSegments[rowIndex - 2, columnIndex + 2], ResultSegments[rowIndex, columnIndex + 2]);

                            if (CanMergeSegments(mergedSegment, currentSegment))
                            {
                                Double distance = _distance.Distance(mergedSegment, currentSegment);
                                if (distance < currentDistance)
                                {
                                    direction = SegmentMergeDirection.Right1;
                                }
                            }
                        }

                        // right 2

                        /*if (direction == SegmentMergeDirection.Right1 && CanMergeSegments(rowIndex - 2, columnIndex + 4, rowIndex, columnIndex + 4))
                         * {
                         *  Segment upperSegment = Result[rowIndex - 2, columnIndex + 4];
                         *  Segment lowerSegment = Result[rowIndex, columnIndex + 4];
                         *  Segment mergedSegment = upperSegment + lowerSegment;
                         *
                         *  if (CanMergeSegments(mergedSegment, currentSegment))
                         *  {
                         *      Double distance = SpectralDistances.EuclideanDistance(mergedSegment, currentSegment);
                         *      if (distance < currentDistance)
                         *          direction = SegmentMergeDirection.Right2;
                         *  }
                         * }*/

                        // apply merge
                        switch (direction)
                        {
                        case SegmentMergeDirection.Left:
                            ResultSegments.MergeSegments(rowIndex, columnIndex, rowIndex, columnIndex - 2);
                            break;

                        case SegmentMergeDirection.Up:
                            ResultSegments.MergeSegments(rowIndex, columnIndex, rowIndex - 2, columnIndex);
                            break;

                        case SegmentMergeDirection.Right1:
                            ResultSegments.MergeSegments(rowIndex, columnIndex, rowIndex, columnIndex + 2);
                            ResultSegments.MergeSegments(rowIndex, columnIndex, rowIndex - 2, columnIndex + 2);
                            break;

                        case SegmentMergeDirection.Right2:
                            ResultSegments.MergeSegments(rowIndex, columnIndex, rowIndex, columnIndex + 2);
                            ResultSegments.MergeSegments(rowIndex, columnIndex, rowIndex - 2, columnIndex + 2);
                            ResultSegments.MergeSegments(rowIndex, columnIndex, rowIndex, columnIndex + 4);
                            ResultSegments.MergeSegments(rowIndex, columnIndex, rowIndex - 2, columnIndex + 4);
                            break;
                        }
                    }
                }
            }

            // remove original segments that are not homogeneous
            for (Int32 rowIndex = 0; rowIndex < Source.Raster.NumberOfRows; rowIndex += 2)
            {
                for (Int32 columnIndex = 0; columnIndex < Source.Raster.NumberOfColumns; columnIndex += 2)
                {
                    if (ResultSegments[rowIndex, columnIndex].Count <= 4 && !ResultSegments[rowIndex, columnIndex].IsHomogeneous(_segmentHomogeneityThreshold))
                    {
                        ResultSegments.SplitSegment(rowIndex, columnIndex);
                    }
                }
            }
        }