Beispiel #1
0
        /// <summary>
        /// Extracts corners from the gradient image.  The method used here is one which uses the eigensystem at each
        /// pixel (computed from the smoothed second moments) to determine whether a corner is present.  A corner is
        /// one in which both eigenvalues are above the threshold.
        /// </summary>
        /// <param name="grad">Gradient image of source</param>
        /// <param name="threshold">Threshold used to determine corners</param>
        /// <returns>A list of corners</returns>
        public static unsafe Vector[] Extract(GradientImage grad, float threshold)
        {
            EigensystemImage eigen  = EigensystemImage.Compute(SecondMomentImage.Compute(grad));
            List <Vector>    points = new List <Vector>();
            int rows    = eigen.Rows;
            int columns = eigen.Columns;

            fixed(float *src = eigen.RawArray)
            {
                float *srcPtr   = src;
                int    channels = eigen.Channels;

                for (int r = 0; r < rows; r++)
                {
                    for (int c = 0; c < columns; c++, srcPtr += channels)
                    {
                        float lambda1 = srcPtr[0];
                        float lambda2 = srcPtr[1];
                        if (lambda1 > threshold && lambda2 > threshold)
                        {
                            points.Add(new DenseVector(new float[] { c, r }));
                        }
                    }
                }
            }

            return(points.ToArray());
        }
        /// <summary>
        /// Computes the second moments at each pixel based on the provided gradient image.
        /// </summary>
        /// <param name="grad">The gradient of the source image</param>
        /// <returns>The second moment image</returns>
        public static unsafe SecondMomentImage Compute(GradientImage grad)
        {
            int rows    = grad.Rows;
            int columns = grad.Columns;

            float[, ,] data = new float[rows, columns, 3];
            fixed(float *src = grad.RawArray, dst = data)
            {
                float *srcPtr = src;
                float *dstPtr = dst;
                int    length = rows * columns;

                for (int i = 0; i < length; i++, srcPtr += 4)
                {
                    float ix       = srcPtr[2];
                    float iy       = srcPtr[3];
                    *     dstPtr++ = ix * ix;
                    *     dstPtr++ = iy * iy;
                    *     dstPtr++ = ix * iy;
                }
            }

            SecondMomentImage image = new SecondMomentImage();

            image.SetData(data);
            return(image);
        }
Beispiel #3
0
        /// <summary>
        /// Computes DiscreteContours at the samples provided.
        /// </summary>
        /// <param name="samples">Samples to compute contours at</param>
        /// <param name="pyramid">Image pyramid to use for samples</param>
        /// <returns>DiscreteContours</returns>
        public static List <Keypoint> Compute(List <ScaleSpaceSample> samples, ScaleSpacePyramid <GrayscaleImage> pyramid)
        {
            GradientImage[,] grads = new GradientImage[pyramid.Octaves, pyramid.Levels];

            List <Keypoint> points = new List <Keypoint>();

            foreach (ScaleSpaceSample sample in samples)
            {
                if (grads[sample.Octave, sample.Level] == null)
                {
                    grads[sample.Octave, sample.Level] = GradientImage.Compute(pyramid[sample.Octave, sample.Level], false);
                }

                points.Add(Compute(sample, grads[sample.Octave, sample.Level], pyramid.ComputeSigma(sample.Octave, sample.Level)));
            }

            return(points);
        }
Beispiel #4
0
        /// <summary>
        /// Compute the Discrete Contour descriptor from the provided patch.  This match must be of gradients and
        /// of the size specified by <see cref="RequiredPatchSize"/>.  A raw image patch, or a patch of different
        /// dimensions, will not work.
        /// </summary>
        /// <param name="sample">Sample to compute DiscreteContour at</param>
        /// <param name="gradImage">Gradient image to use</param>
        /// <param name="scale">The scale of the sample (the value returned by ComputeSigma() in ScaleSpacePyramid)</param>
        /// <returns>Discrete Contour descriptor</returns>
        public static unsafe Keypoint Compute(ScaleSpaceSample sample, GradientImage gradImage, float scale)
        {
            Keypoint point = new Keypoint(sample.X, sample.Y, sample.ImageScale, scale, 0);

            float[] desc = new float[DESCRIPTOR_LENGTH];

            int startR   = sample.Row - SQUARE_SIZE / 2;
            int startC   = sample.Column - SQUARE_SIZE / 2;
            int rows     = gradImage.Rows;
            int columns  = gradImage.Columns;
            int channels = gradImage.Channels;
            int stride   = columns * channels;

            fixed(int *mask = MASK)
            {
                fixed(float *patch = gradImage.RawArray)
                {
                    int *maskPtr = mask;

                    float *patchPtr;

                    if (startR < 0)
                    {
                        if (startC < 0)
                        {
                            patchPtr = patch;
                        }
                        else
                        {
                            patchPtr = patch + startC * channels;
                        }
                    }
                    else if (startC < 0)
                    {
                        patchPtr = patch + startR * stride;
                    }
                    else
                    {
                        patchPtr = patch + startR * stride + startC * channels;
                    }
                    for (int r = 0; r < SQUARE_SIZE; r++)
                    {
                        int    rr        = startR + r;
                        float *patchScan = patchPtr;
                        if (rr >= 0 && rr < rows - 1)
                        {
                            patchPtr += stride;
                        }
                        for (int c = 0; c < SQUARE_SIZE; c++, maskPtr++)
                        {
                            int bin = *maskPtr;       //MASK[rr, cc];

                            float mag = patchScan[0]; //gradientPatch[rr, cc, 0];
                            float dir = patchScan[1]; //gradientPatch[rr, cc, 1];
                            int   cc  = startC + c;
                            if (cc >= 0 && cc < columns - 1)
                            {
                                patchScan += channels;
                            }
                            //if (mag != gradImage[Math.Max(0, Math.Min(rr, rows - 1)), Math.Max(0, Math.Min(cc, columns - 1)), 0])
                            //    throw new Exception("testing");


                            if (bin < BINS)
                            {
                                addValue(bin, dir, mag * 2, desc);
                            }
                            else
                            {
                                bin -= BINS;
                                int bin1 = HALF[bin, 0];
                                int bin2 = HALF[bin, 1];
                                addValue(bin1, dir, mag, desc);
                                addValue(bin2, dir, mag, desc);
                            }
                        }
                    }
                }
            }

            point.Descriptor = desc;
            return(point);
        }
Beispiel #5
0
 /// <summary>
 /// Extracts corners from the gradient image using the default threshold.
 /// </summary>
 /// <param name="grad">Gradient image of source</param>
 /// <returns>A list of corners</returns>
 public static Vector[] Extract(GradientImage grad)
 {
     return(Extract(grad, EigensystemImage.SENSITIVITY));
 }
Beispiel #6
0
        /// <summary>
        /// Computes a gradient image from the source image.
        /// </summary>
        /// <param name="sigma">The sigma to use when blurring the source image.</param>
        /// <param name="image">Source image</param>
        /// <returns>Gradient image</returns>
        public static unsafe GradientImage Compute(GrayscaleImage image, float sigma)
        {
            int rows    = image.Rows;
            int columns = image.Columns;

            if (sigma > 0)
            {
                image = Convolution.ConvolveGaussian <GrayscaleImage>(image, sigma);
            }
            float[, ,] data = new float[rows, columns, 4];
            fixed(float *src = image.RawArray, dst = data)
            {
                float *srcPtr  = src;
                float *srcPtrP = srcPtr + 1;
                float *dstPtr  = dst;

                dstPtr += 2;
                // X derivative
                for (int r = 0; r < rows; r++)
                {
                    *dstPtr = *srcPtrP - *srcPtr;
                    dstPtr += 4;
                    srcPtrP++;
                    for (int c = 1; c < columns - 1; c++, srcPtr++, srcPtrP++, dstPtr += 4)
                    {
                        *dstPtr = *srcPtrP - *srcPtr;
                    }
                    srcPtrP--;
                    *dstPtr = *srcPtrP - *srcPtr;
                    dstPtr  += 4;
                    srcPtr  += 2;
                    srcPtrP += 2;
                }
                srcPtr  = src;
                srcPtrP = srcPtr + columns;
                dstPtr  = dst;
                dstPtr += 3;
                int stride = 4 * columns;

                for (int c = 0; c < columns; c++, srcPtr++, srcPtrP++, dstPtr += 4)
                {
                    float *srcScan  = srcPtr;
                    float *srcScanP = srcPtrP;
                    float *dstScan  = dstPtr;
                    *      dstScan  = *srcScanP - *srcScan;
                    dstScan  += stride;
                    srcScanP += columns;
                    for (int r = 1; r < rows - 1; r++, dstScan += stride, srcScan += columns, srcScanP += columns)
                    {
                        *dstScan = *srcScanP - *srcScan;
                    }
                    srcScanP -= columns;
                    *dstScan = *srcScanP - *srcScan;
                }
                dstPtr = dst;
                int length = rows * columns;

                for (int i = 0; i < length; i++, dstPtr += 4)
                {
                    setData(dstPtr);
                }
            }

            GradientImage result = new GradientImage();

            result.SetData(data);
            return(result);
        }