Example #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);
        }
Example #2
0
        /// <summary>
        /// Thresholds the provided image.  The <paramref name="lessThan"/> parameter will determine whether the pixels that are less than the
        /// threshold are set to true and the others "false" or vice versa.  The thresholding will be performed on the provided channel.
        /// channel.
        /// </summary>
        /// <typeparam name="T">The underlying type of the input image.  Must be of interface IComparable.</typeparam>
        /// <param name="image">The input image</param>
        /// <param name="threshold">The threshold to use</param>
        /// <param name="lessThan">Whether pixels less than the threshold are set to "true" and all others to "false", or vice versa</param>
        /// <param name="channel">The channel on which to perform thresholding</param>
        /// <returns>The thresholded image</returns>
        public static BinaryImage Threshold <T>(this IMultichannelImage <T> image, T threshold, bool lessThan, int channel) where T : IComparable <T>
        {
            T[, ,] data = image.RawArray;
            int         rows        = image.Rows;
            int         columns     = image.Columns;
            BinaryImage resultImage = new BinaryImage(rows, columns);

            bool[, ,] result = resultImage.RawArray;

            for (int r = 0; r < rows; r++)
            {
                for (int c = 0; c < columns; c++)
                {
                    result[r, c, 0] = data[r, c, channel].CompareTo(threshold) <= 0 ? lessThan : !lessThan;
                }
            }

            return(resultImage);
        }
Example #3
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);
        }
Example #4
0
        /// <summary>
        /// Performs connected components analysis.
        /// </summary>
        /// <param name="image">The image to analyze</param>
        /// <returns>The connected components image</returns>
        public static unsafe LabelImage Compute(BinaryImage image)
        {
            _current = 0;
            int   r, c;
            short currentLabel, currentSet;
            short label0, label1, label2, label3, set0, set1;
            short tl, t, tr, l;
            int   rows = image.Rows;
            int   columns = image.Columns;
            int   count, labelCount;

            short[]    equiv  = new short[rows * columns];
            LabelImage labels = new LabelImage(rows, columns);

            fixed(bool *imageBuf = image.RawArray)
            {
                fixed(short *labelsBuf = labels.RawArray, equivBuf = equiv)
                {
                    bool * imagePtr = imageBuf + columns + 1;
                    short *tlPtr = labelsBuf;
                    short *tPtr = tlPtr + 1;
                    short *trPtr = tPtr + 1;
                    short *lPtr = tlPtr + columns;
                    short *labelsPtr = lPtr + 1;
                    short *equivPtr = equivBuf;
                    short *set0Ptr, set1Ptr;

                    label0       = label1 = label2 = label3 = 0;
                    currentLabel = 1;
                    r            = rows - 2;
                    while (r-- != 0)
                    //for (r = 1; r < rows - 1; r++)
                    {
                        c = columns - 2;
                        // we are already at c+1
                        while (c-- != 0)
                        //for (c = 1; c < columns - 1; c++)
                        {
                            if (*imagePtr)
                            {
                                tl = *tlPtr;
                                t  = *tPtr;
                                tr = *trPtr;
                                l  = *lPtr;

                                labelCount = 0;

                                if (tl != 0)
                                {
                                    label0 = tl;
                                    labelCount++;
                                }

                                if (t != 0)
                                {
                                    if (labelCount == 0)
                                    {
                                        labelCount++;
                                        label0 = t;
                                    }
                                    else if (labelCount == 1 && t != label0)
                                    {
                                        labelCount++;
                                        label1 = t;
                                    }
                                }

                                if (tr != 0)
                                {
                                    if (labelCount == 0)
                                    {
                                        labelCount++;
                                        label0 = tr;
                                    }

                                    else if (labelCount == 1 && tr != label0)
                                    {
                                        labelCount++;
                                        label1 = tr;
                                    }
                                    else if (labelCount == 2 && tr != label0 && tr != label1)
                                    {
                                        labelCount++;
                                        label2 = tr;
                                    }
                                }

                                if (l != 0)
                                {
                                    if (labelCount == 0)
                                    {
                                        labelCount++;
                                        label0 = l;
                                    }
                                    else if (labelCount == 1 && l != label0)
                                    {
                                        labelCount++;
                                        label1 = l;
                                    }
                                    else if (labelCount == 2 && l != label0 && l != label1)
                                    {
                                        labelCount++;
                                        label2 = l;
                                    }
                                    else if (labelCount == 3 && l != label0 && l != label1 && l != label2)
                                    {
                                        labelCount++;
                                        label3 = l;
                                    }
                                }

                                if (labelCount == 0)
                                {
                                    *labelsPtr = currentLabel++;
                                }
                                else if (labelCount == 1)
                                {
                                    *labelsPtr = label0;
                                }
                                else if (labelCount == 2)
                                {
                                    *labelsPtr = label0;
                                    list_add(new LabelPair {
                                        Label1 = label0, Label2 = label1
                                    });
                                }
                                else if (labelCount == 3)
                                {
                                    *labelsPtr = label0;
                                    list_add(new LabelPair {
                                        Label1 = label0, Label2 = label1
                                    });
                                    list_add(new LabelPair {
                                        Label1 = label0, Label2 = label2
                                    });
                                    list_add(new LabelPair {
                                        Label1 = label1, Label2 = label2
                                    });
                                }
                                else if (labelCount == 4)
                                {
                                    *labelsPtr = label0;
                                    list_add(new LabelPair {
                                        Label1 = label0, Label2 = label1
                                    });
                                    list_add(new LabelPair {
                                        Label1 = label0, Label2 = label2
                                    });
                                    list_add(new LabelPair {
                                        Label1 = label0, Label2 = label3
                                    });
                                    list_add(new LabelPair {
                                        Label1 = label1, Label2 = label2
                                    });
                                    list_add(new LabelPair {
                                        Label1 = label1, Label2 = label3
                                    });
                                    list_add(new LabelPair {
                                        Label1 = label2, Label2 = label3
                                    });
                                }
                            }
                            imagePtr++;
                            tlPtr++;
                            tPtr++;
                            trPtr++;
                            lPtr++;
                            labelsPtr++;
                        }
                        // get to c+1
                        imagePtr  += 2;
                        tlPtr     += 2;
                        tPtr      += 2;
                        trPtr     += 2;
                        lPtr      += 2;
                        labelsPtr += 2;
                    }

                    // resolve equivalencies
                    count = currentLabel;
                    while (count-- != 0)
                    {
                        *equivPtr++ = 0;
                    }
                    currentSet = 1;
                    fixed(LabelPair *nodeBuf = _nodes)
                    {
                        LabelPair *nodePtr = nodeBuf;

                        while (_current-- != 0)
                        {
                            LabelPair current = *nodePtr++;

                            set0Ptr = equivBuf + current.Label1;
                            set1Ptr = equivBuf + current.Label2;
                            bool contain1 = *set0Ptr != 0;
                            bool contain2 = *set1Ptr != 0;
                            if (contain1 && contain2)
                            {
                                set0 = *set0Ptr;
                                set1 = *set1Ptr;
                                if (set0 != set1)
                                {
                                    equivPtr = equivBuf;
                                    count    = currentLabel;
                                    while (count-- != 0)
                                    {
                                        if (*equivPtr == set1)
                                        {
                                            *equivPtr = set0;
                                        }
                                        equivPtr++;
                                    }
                                }
                            }
                            else if (contain1)
                            {
                                *set1Ptr = *set0Ptr;
                            }
                            else if (contain2)
                            {
                                *set0Ptr = *set1Ptr;
                            }
                            else
                            {
                                *set0Ptr = currentSet;
                                *set1Ptr = currentSet;
                                currentSet++;
                            }
                        }
                    }

                    labelsPtr = labelsBuf;
                    count     = rows * columns;
                    while (count-- != 0)
                    {
                        currentLabel = *labelsPtr;

                        if (currentLabel == 0)
                        {
                            labelsPtr++;
                            continue;
                        }

                        equivPtr = equivBuf + currentLabel;
                        if (*equivPtr == 0)
                        {
                            *equivPtr = currentSet++;
                        }
                        *labelsPtr++ = *equivPtr;
                    }
                }
            }

            return(labels);
        }