/// <summary> /// Converts this image to a grayscale image. /// </summary> /// <returns>A grayscale image</returns> public unsafe GrayscaleImage ToGrayscale() { int rows = Rows; int columns = Columns; GrayscaleImage grayscale = new GrayscaleImage(rows, columns); fixed(int *src = _handler.RawArray) { fixed(float *dst = grayscale.RawArray) { int * srcPtr = src; float *dstPtr = dst; int count = rows * columns; while (count-- != 0) { *dstPtr = *srcPtr; dstPtr++; srcPtr++; } } } grayscale.Normalize(); return(grayscale); }
/// <summary> /// Saves the image to a file, using the provided minimum and maximum values for scaling. /// </summary> /// <param name="image">The image to save</param> /// <param name="filename">The destination filename</param> /// <param name="min">The value to map to 0</param> /// <param name="max">The value to map to 255</param> public static void Save(GrayscaleImage image, string filename, float min, float max) { BitmapEncoder encoder = IO.GetEncoder(filename); encoder.Frames.Add(BitmapFrame.Create(image.ToBitmap(min, max))); encoder.Save(filename); }
/// <summary> /// Returns a GrayscaleImage representing the edge magnitude at each pixel. /// </summary> /// <returns>A magnitude map</returns> public unsafe GrayscaleImage ToMagnitudeMap() { GrayscaleImage mono = new GrayscaleImage(Rows, Columns); fixed(float *src = RawArray, dst = mono.RawArray) { float *srcPtr = src; float min = float.MaxValue; float max = float.MinValue; int length = Rows * Columns; for (int i = 0; i < length; i++, srcPtr += 4) { min = Math.Min(min, *srcPtr); max = Math.Max(max, *srcPtr); } float scale = max - min; srcPtr = src; float *dstPtr = dst; while (length-- > 0) { float val = *srcPtr; val -= min; val /= scale; *dstPtr++ = val; srcPtr += 4; } } return(mono); }
/// <summary> /// Writes <paramref name="image"/> to <paramref name="filename"/> using the PGM file format. /// </summary> /// <param name="image">Image to write</param> /// <param name="filename">Path to write to</param> public static unsafe void Write(GrayscaleImage image, string filename) { FileStream output = File.OpenWrite(filename); int rows = image.Height; int columns = image.Width; string header = string.Format("P5\n{0} {1}\n255\n", columns, rows); byte[] buf = Encoding.ASCII.GetBytes(header); output.Write(buf, 0, buf.Length); fixed(float *src = image.RawArray) { float *ptr = src; for (int r = 0; r < rows; r++) { byte[] row = new byte[columns]; for (int c = 0; c < columns; c++) { row[c] = (byte)(*ptr++ *255); } output.Write(row, 0, columns); } } output.Close(); }
/// <summary> /// Reads a PGM file from <paramref name="filename"/>. /// </summary> /// <param name="filename">The location of the PGM file</param> /// <returns>An object encapsulating the image data</returns> public static unsafe GrayscaleImage Read(string filename) { FileStream stream = File.OpenRead(filename); StreamReader input = new StreamReader(stream); string magicNumber = input.ReadLine(); if (magicNumber != "P5") { return(null); } string[] dims = input.ReadLine().Split(); string depth = input.ReadLine(); if (depth != "255") { return(null); } int columns = int.Parse(dims[0]); int rows = int.Parse(dims[1]); GrayscaleImage gray = new GrayscaleImage(rows, columns); fixed(float *src = gray.RawArray) { float *ptr = src; byte[] scanline = new byte[columns]; float norm = 1f / 255; for (int r = 0; r < rows; r++) { int count = 0; while (count < columns) { count += stream.Read(scanline, count, columns - count); } for (int c = 0; c < columns; c++) { float val = scanline[c] * norm; * ptr++ = val; } } } return(gray); }
/// <summary> /// Converts the distance transform image to a grayscale representation. /// </summary> /// <returns>A grayscale representation of the distance transform</returns> public unsafe GrayscaleImage ToGrayscale() { GrayscaleImage gray = new GrayscaleImage(Rows, Columns); fixed(float *dst = gray.RawArray) { fixed(int *src = RawArray) { int * srcPtr = src; float *dstPtr = dst; for (int length = Rows * Columns; length > 0; length--, dstPtr++, srcPtr += Channels) { *dstPtr = *srcPtr; } } } return(gray); }
/// <summary> /// Returns a grayscale version of this image, with 1 for "true" and 0 for "false". /// </summary> /// <returns>A grayscale version of the image</returns> public unsafe GrayscaleImage ToGrayscale() { GrayscaleImage mono = new GrayscaleImage(Rows, Columns); fixed(float *dst = mono.RawArray) { fixed(bool *src = RawArray) { float *dstPtr = dst; bool * srcPtr = src; int length = Rows * Columns; while (length-- > 0) { bool edge = *srcPtr++; * dstPtr++ = edge ? 1 : 0; } } } return(mono); }
/// <summary> /// Extracts a channel as a Grayscale image. Uses the <see cref="M:IArrayHandler.ExtractChannel"/> method. /// </summary> /// <param name="handler">The image upon which to operate</param> /// <param name="channel">The channel to extract</param> /// <returns>An image representation of the channel</returns> public static unsafe GrayscaleImage ExtractChannelAsImage(this IArrayHandler <float> handler, int channel) { float[,] buffer = handler.ExtractChannel(channel); int rows = handler.Rows; int columns = handler.Columns; float[, ,] data = new float[rows, columns, 1]; fixed(float *channelSrc = buffer, dataSrc = data) { float *channelPtr = channelSrc; float *dataPtr = dataSrc; int count = rows * columns; while (count-- > 0) { *dataPtr++ = *channelPtr++; } } GrayscaleImage gray = new GrayscaleImage(); gray.SetData(data); return(gray); }
/// <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); }
/// <summary> /// Computes a gradient image. /// </summary> /// <param name="image">Source image</param> /// <param name="blurImage">Whether to blur the source image before computing the gradient</param> /// <returns>Gradient image</returns> public static GradientImage Compute(GrayscaleImage image, bool blurImage) { return(Compute(image, blurImage ? SIGMA : 0f)); }
/// <summary> /// Computes a gradient image from the source image using the default sigma value. /// </summary> /// <param name="image">Source image</param> /// <returns>Gradient image</returns> public static GradientImage Compute(GrayscaleImage image) { return(Compute(image, SIGMA)); }