/// <summary> /// Computes a scale-space pyramid from the source image. /// </summary> /// <param name="source">Source image</param> /// <param name="levels">Number of levels per octave</param> /// <param name="sigma">Sigma for the initial convolution Gaussian</param> /// <returns>A scale-space pyramid</returns> public static ScaleSpacePyramid <T> Compute(T source, int levels, float sigma) { List <T> octaves = new List <T>(); T current = Convolution.ConvolveGaussian <T>(source, sigma); while (current.Width >= MIN_SIZE && current.Height >= MIN_SIZE) { octaves.Add(current); current = Convolution.ConvolveGaussian <T>(current, 2 * sigma, 2); } T[,] pyramid = new T[octaves.Count, levels]; float multiplier = (float)Math.Sqrt(Math.Pow(2, 2.0 / levels) - 1); for (int o = 0; o < octaves.Count; o++) { pyramid[o, 0] = octaves[o]; float currentSigma = multiplier * sigma; for (int l = 1; l < levels; l++) { pyramid[o, l] = Convolution.ConvolveGaussian <T>(pyramid[o, l - 1], currentSigma); currentSigma *= multiplier; } } return(new ScaleSpacePyramid <T>(pyramid, sigma)); }
/// <summary> /// Computes the eigensystem image from the second moment image provided. /// </summary> /// <param name="moments">Contains the second moments used to compute the eigensystem image.</param> /// <param name="sigma">The sigma to use when convolving the second moment image</param> /// <returns>the eigensystem image</returns> public static unsafe EigensystemImage Compute(SecondMomentImage moments, float sigma) { moments = Convolution.ConvolveGaussian <SecondMomentImage>(moments, sigma); int rows = moments.Rows; int columns = moments.Columns; float[, ,] data = new float[rows, columns, 6]; fixed(float *src = moments.RawArray, dst = data) { float *srcPtr = src; float *dstPtr = dst; int length = rows * columns; while (length-- > 0) { float a11 = *srcPtr++; float a22 = *srcPtr++; float a12 = *srcPtr++; float a21 = a12; float sqrt = (float)Math.Sqrt(4 * a12 * a21 + Math.Pow(a11 - a22, 2)); float sum = a11 + a22; float eigen1 = sum + sqrt; float eigen2 = sum - sqrt; float x1, y1; findEigenvector(a11, a12, a21, a22, eigen1, out x1, out y1); float x2, y2; findEigenvector(a11, a12, a21, a22, eigen2, out x2, out y2); *dstPtr++ = eigen1; *dstPtr++ = eigen2; *dstPtr++ = x1; *dstPtr++ = y1; *dstPtr++ = x2; *dstPtr++ = y2; } } EigensystemImage image = new EigensystemImage(); image.SetData(data); return(image); }
/// <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); }