Exemple #1
0
        internal static unsafe DistanceTransformImage ComputeNaive(BinaryImage edges, bool computeSquareRoot)
        {
            int rows    = edges.Rows;
            int columns = edges.Columns;
            List <ImageCell>       cells = edges.GetCells();
            DistanceTransformImage dt    = new DistanceTransformImage();

            dt.SetDimensions(edges.Rows, edges.Columns, 3);
            for (int r = 0; r < rows; r++)
            {
                for (int c = 0; c < columns; c++)
                {
                    var distances = from index in cells
                                    select new
                    {
                        Distance = distance(index.Row, index.Column, r, c),
                        Index    = index
                    };
                    var nearest = distances.OrderBy(o => o.Distance).First();
                    if (computeSquareRoot)
                    {
                        dt[r, c, 0] = (int)Math.Sqrt(nearest.Distance);
                    }
                    else
                    {
                        dt[r, c, 0] = nearest.Distance;
                    }
                    dt[r, c, 1] = nearest.Index.Row;
                    dt[r, c, 2] = nearest.Index.Column;
                }
            }
            return(dt);
        }
Exemple #2
0
        /// <summary>
        /// Computes the distance transform using an efficient Euclidean distance transform.  If <paramref name="computeSquareRoot"/>
        /// is not set, the squared distance will be stored.
        /// </summary>
        /// <param name="edges">Edge image</param>
        /// <param name="computeSquareRoot">Whether to compute the actual distance from the squared distance</param>
        /// <returns>Distance transform</returns>
        public static unsafe DistanceTransformImage Compute(BinaryImage edges, bool computeSquareRoot)
        {
            int i, j, k;
            int r, c;
            int I_1, I_2, r_1, r_2, dr, intersection;
            int I2new, I2val, I2column, dtVal;
            int rows     = edges.Rows;
            int columns  = edges.Columns;
            int channels = 3;
            int stride   = columns * channels;

            Curve[] curves = new Curve[256];
            Curve * bottomPtr, curve0Ptr, curve1Ptr;
            int     curvesCount = 0;

            int[, ,] I2 = new int[rows, columns, channels];
            DistanceTransformImage dt = new DistanceTransformImage();

            dt.SetDimensions(rows, columns, channels);

            initLookup(Math.Max(rows, columns));

            fixed(bool *edgesBuf = edges.RawArray)
            {
                fixed(int *I2Buf = I2, squareBuf = _squareLookup, dtBuf = dt.RawArray)
                {
                    fixed(Curve *curvesBuf = curves)
                    {
                        bool *edgesPtr = edgesBuf;
                        int * I2Ptr = I2Buf;
                        int * squarePtr = squareBuf;
                        int   lastEdge, width;
                        bool *edgesScan;
                        int * I2RevPtr, I2LagPtr, dtPtr, dtScan, I2Scan;

                        for (r = 0, i = rows; i != 0; i--, r++)
                        {
                            lastEdge = INFINITY;

                            if (*edgesPtr)
                            {
                                I2Ptr[0]  = 0;
                                I2Ptr[1]  = r;
                                I2Ptr[2]  = 0;
                                lastEdge  = 0;
                                squarePtr = squareBuf;
                            }
                            else
                            {
                                *I2Ptr = INFINITY;
                            }

                            I2LagPtr = I2Ptr;
                            edgesPtr++;
                            I2Ptr += channels;

                            for (j = columns - 1, c = 1; j != 0; j--, c++, edgesPtr++, I2LagPtr += channels, I2Ptr += channels)
                            {
                                if (*edgesPtr)
                                {
                                    if (lastEdge == INFINITY)
                                    {
                                        for (k = c + 1, I2RevPtr = I2Ptr, squarePtr = squareBuf; k != 0; k--, I2RevPtr -= channels, squarePtr++)
                                        {
                                            I2RevPtr[0] = *squarePtr;
                                            I2RevPtr[1] = r;
                                            I2RevPtr[2] = c;
                                        }
                                    }
                                    else
                                    {
                                        width = c - lastEdge;
                                        width = width >> 1;
                                        for (k = width + 1, I2RevPtr = I2Ptr, squarePtr = squareBuf; k != 0; k--, I2RevPtr -= channels, squarePtr++)
                                        {
                                            I2RevPtr[0] = *squarePtr;
                                            I2RevPtr[1] = r;
                                            I2RevPtr[2] = c;
                                        }
                                    }
                                    lastEdge  = c;
                                    squarePtr = squareBuf;
                                }
                                else
                                {
                                    if (*I2LagPtr == INFINITY)
                                    {
                                        *I2Ptr = INFINITY;
                                    }
                                    else
                                    {
                                        I2Ptr[0] = *(++squarePtr);
                                        I2Ptr[1] = r;
                                        I2Ptr[2] = lastEdge;
                                    }
                                }
                            }
                        }


                        for (
                            edgesPtr = edgesBuf,
                            dtPtr = dtBuf,
                            I2Ptr = I2Buf,
                            c = 0,
                            i = columns;

                            i != 0;

                            I2Ptr += channels,
                            edgesPtr++,
                            dtPtr += channels,
                            c++,
                            i--)
                        {
                            curvesCount = 0;
                            bottomPtr   = null;
                            curve0Ptr   = null;
                            curve1Ptr   = null;

                            for (
                                I2Scan = I2Ptr,
                                edgesScan = edgesPtr,
                                dtScan = dtPtr,
                                j = rows,
                                r = 0;

                                j != 0;

                                I2Scan += stride,
                                edgesScan += columns,
                                dtScan += stride,
                                r++,
                                j--)
                            {
                                if (*edgesScan)
                                {
                                    curvesCount       = 1;
                                    bottomPtr         = curvesBuf;
                                    curve1Ptr         = curvesBuf;
                                    curve0Ptr         = null;
                                    bottomPtr->Row    = r;
                                    bottomPtr->End    = rows;
                                    bottomPtr->B      = 0;
                                    bottomPtr->Column = c;

                                    dtScan[1] = r;
                                    dtScan[2] = c;

                                    continue;
                                }

                                I2new    = INFINITY;
                                I2val    = I2Scan[0];
                                I2column = I2Scan[2];
                                if (I2val != INFINITY)
                                {
                                    if (curvesCount > 0)
                                    {
                                        dr    = r - bottomPtr->Row;
                                        I2new = _squareLookup[dr] + bottomPtr->B;
                                        if (I2val < I2new)
                                        {
                                            curvesCount       = 1;
                                            bottomPtr         = curvesBuf;
                                            curve1Ptr         = curvesBuf;
                                            curve0Ptr         = null;
                                            bottomPtr->Row    = r;
                                            bottomPtr->End    = rows;
                                            bottomPtr->B      = I2val;
                                            bottomPtr->Column = I2column;

                                            dtScan[0] = I2val;
                                            dtScan[1] = r;
                                            dtScan[2] = I2column;
                                            Debug.Assert(dtScan[0] == distance(r, c, dtScan[1], dtScan[2]));

                                            continue;
                                        }
                                    }

                                    for (; ;)
                                    {
                                        if (curvesCount == 0)
                                        {
                                            curvesCount       = 1;
                                            bottomPtr         = curvesBuf;
                                            curve1Ptr         = curvesBuf;
                                            curve0Ptr         = null;
                                            bottomPtr->Row    = r;
                                            bottomPtr->End    = rows;
                                            bottomPtr->B      = I2val;
                                            bottomPtr->Column = I2column;

                                            break;
                                        }


                                        if (I2val < curve1Ptr->B)
                                        {
                                            curvesCount--;
                                            if (curvesCount > 0)
                                            {
                                                curve1Ptr--;
                                                if (curvesCount > 1)
                                                {
                                                    curve0Ptr--;
                                                }
                                                else
                                                {
                                                    curve0Ptr = null;
                                                }
                                            }
                                            else
                                            {
                                                curve1Ptr = null;
                                                bottomPtr = null;
                                                curve0Ptr = null;
                                            }

                                            continue;
                                        }

                                        I_1          = curve1Ptr->B;
                                        I_2          = I2val;
                                        r_1          = curve1Ptr->Row;
                                        r_2          = r;
                                        dr           = r_2 - r_1;
                                        intersection = r_2 + ((I_2 - I_1 - _squareLookup[dr]) / (dr << 1));

                                        if (intersection >= rows)
                                        {
                                            *I2Scan = INFINITY;
                                            break;
                                        }

                                        if (curve0Ptr == null || intersection > curve0Ptr->End)
                                        {
                                            curvesCount++;
                                            curve1Ptr->End = intersection;
                                            curve0Ptr      = curve1Ptr;
                                            curve1Ptr++;
                                            curve1Ptr->Row    = r;
                                            curve1Ptr->End    = rows;
                                            curve1Ptr->B      = I_2;
                                            curve1Ptr->Column = I2column;

                                            break;
                                        }

                                        curvesCount--;
                                        if (curvesCount > 0)
                                        {
                                            curve1Ptr--;
                                            if (curvesCount > 1)
                                            {
                                                curve0Ptr--;
                                            }
                                            else
                                            {
                                                curve0Ptr = null;
                                            }
                                        }
                                        else
                                        {
                                            curve1Ptr = null;
                                            bottomPtr = null;
                                            curve0Ptr = null;
                                        }
                                    }
                                }

                                if (curvesCount == 0)
                                {
                                    continue;
                                }
                                if (I2new == INFINITY)
                                {
                                    dr    = r - bottomPtr->Row;
                                    I2new = _squareLookup[dr] + bottomPtr->B;
                                }
                                dtScan[0] = I2new;
                                dtScan[1] = bottomPtr->Row;
                                dtScan[2] = bottomPtr->Column;
                                Debug.Assert(dtScan[0] == distance(r, c, dtScan[1], dtScan[2]));
                                if (I2new < I2val)
                                {
                                    *I2Scan = INFINITY;
                                }

                                if (bottomPtr->End == r)
                                {
                                    curvesCount--;
                                    bottomPtr++;
                                }
                            }

                            //continue;

                            curvesCount = 0;
                            bottomPtr   = null;
                            curve0Ptr   = null;
                            curve1Ptr   = null;
                            I2Scan     -= stride;
                            dtScan     -= stride;
                            edgesScan  -= columns;

                            for (
                                j = rows,
                                r = rows - 1;

                                j != 0;

                                I2Scan -= stride,
                                dtScan -= stride,
                                edgesScan -= columns,
                                r--,
                                j--)
                            {
                                if (*edgesScan)
                                {
                                    curvesCount       = 1;
                                    bottomPtr         = curvesBuf;
                                    curve1Ptr         = curvesBuf;
                                    curve0Ptr         = null;
                                    bottomPtr->Row    = r;
                                    bottomPtr->End    = -1;
                                    bottomPtr->B      = 0;
                                    bottomPtr->Column = c;

                                    continue;
                                }

                                I2new    = INFINITY;
                                I2val    = I2Scan[0];
                                I2column = I2Scan[2];
                                dtVal    = *dtScan;
                                if (I2val != INFINITY)
                                {
                                    if (curvesCount > 0)
                                    {
                                        dr    = bottomPtr->Row - r;
                                        I2new = _squareLookup[dr] + bottomPtr->B;
                                        if (dtVal < I2new && dtVal < I2val)
                                        {
                                            curvesCount = 0;
                                            curve1Ptr   = null;
                                            bottomPtr   = null;
                                            curve0Ptr   = null;

                                            continue;
                                        }
                                        if (I2val < I2new)
                                        {
                                            curvesCount       = 1;
                                            bottomPtr         = curvesBuf;
                                            curve1Ptr         = curvesBuf;
                                            curve0Ptr         = null;
                                            bottomPtr->Row    = r;
                                            bottomPtr->End    = -1;
                                            bottomPtr->B      = I2val;
                                            bottomPtr->Column = I2column;

                                            dtScan[0] = I2val;
                                            dtScan[1] = r;
                                            dtScan[2] = I2column;
                                            Debug.Assert(dtScan[0] == distance(r, c, dtScan[1], dtScan[2]));
                                            continue;
                                        }
                                    }

                                    for (; ;)
                                    {
                                        if (curvesCount == 0)
                                        {
                                            curvesCount       = 1;
                                            bottomPtr         = curvesBuf;
                                            curve1Ptr         = curvesBuf;
                                            curve0Ptr         = null;
                                            bottomPtr->Row    = r;
                                            bottomPtr->End    = -1;
                                            bottomPtr->B      = I2val;
                                            bottomPtr->Column = I2column;

                                            break;
                                        }

                                        if (I2val < curve1Ptr->B)
                                        {
                                            curvesCount--;
                                            if (curvesCount > 0)
                                            {
                                                curve1Ptr--;
                                                if (curvesCount > 1)
                                                {
                                                    curve0Ptr--;
                                                }
                                                else
                                                {
                                                    curve0Ptr = null;
                                                }
                                            }
                                            else
                                            {
                                                curve1Ptr = null;
                                                bottomPtr = null;
                                                curve0Ptr = null;
                                            }

                                            continue;
                                        }

                                        I_1          = curve1Ptr->B;
                                        I_2          = I2val;
                                        r_1          = curve1Ptr->Row;
                                        r_2          = r;
                                        dr           = r_1 - r_2;
                                        intersection = r_2 - ((I_2 - I_1 - _squareLookup[dr]) / (dr << 1));

                                        if (intersection < 0)
                                        {
                                            break;
                                        }

                                        if (curve0Ptr == null || intersection < curve0Ptr->End)
                                        {
                                            curvesCount++;
                                            curve1Ptr->End = intersection;
                                            curve0Ptr      = curve1Ptr;
                                            curve1Ptr++;
                                            curve1Ptr->Row    = r;
                                            curve1Ptr->End    = -1;
                                            curve1Ptr->B      = I_2;
                                            curve1Ptr->Column = I2column;

                                            break;
                                        }

                                        curvesCount--;
                                        if (curvesCount > 0)
                                        {
                                            curve1Ptr--;
                                            if (curvesCount > 1)
                                            {
                                                curve0Ptr--;
                                            }
                                            else
                                            {
                                                curve0Ptr = null;
                                            }
                                        }
                                        else
                                        {
                                            curve1Ptr = null;
                                            bottomPtr = null;
                                            curve0Ptr = null;
                                        }
                                    }
                                }

                                if (curvesCount == 0)
                                {
                                    continue;
                                }
                                if (I2new == INFINITY)
                                {
                                    dr    = bottomPtr->Row - r;
                                    I2new = _squareLookup[dr] + bottomPtr->B;
                                }
                                if ((I2val == INFINITY && dtVal == 0) || I2new < dtVal)
                                {
                                    dtScan[0] = I2new;
                                    dtScan[1] = bottomPtr->Row;
                                    dtScan[2] = bottomPtr->Column;
                                    Debug.Assert(dtScan[0] == distance(r, c, dtScan[1], dtScan[2]));
                                }

                                if (bottomPtr->End == r)
                                {
                                    curvesCount--;
                                    bottomPtr++;
                                }
                            }
                        }
                        if (computeSquareRoot)
                        {
                            dtPtr = dtBuf;
                            for (r = rows; r != 0; r--)
                            {
                                for (c = columns; c != 0; c--, dtPtr += channels)
                                {
                                    *dtPtr = (int)Math.Sqrt(*dtPtr);
                                }
                            }
                        }
                    }
                }
            }

            return(dt);
        }