public static PNM ApplyPixelFunction(this PNM image, int matrixLength, Func <PNM, int, Pixel> func) { PNM newImage = PNM.Copy(image); int padding = matrixLength / 2; Pad(newImage, padding); newImage = ApplyConvolutionFunctionCore(newImage, matrixLength, func); Trim(newImage, padding); return(newImage); }
public static PNM ApplyConvolutionMatrix(this PNM image, float[] matrix, float weight, float shift) { int length = (int)Math.Sqrt(matrix.Length); if (Math.Pow(length, 2) != matrix.Length || (length / 2) * 2 == length) { throw new ArgumentException("matrix"); } PNM newImage = PNM.Copy(image); int padding = length / 2; Pad(newImage, padding); newImage = ApplyConvolutionMatrixCore(newImage, matrix, length, weight, shift); Trim(newImage, padding); return(newImage); }
public static PNM ApplyHeightMapFunction(this PNM image, int matrixLength, Func <int, int, float[], int, Pixel> func) { PNM newImage = PNM.Copy(image); int padding = matrixLength / 2; Pad(newImage, padding); int newImageSize = newImage.Width * newImage.Height; float[] heightmap = new float[newImageSize]; byte r, g, b; for (int i = 0; i < newImageSize; i++) { newImage.GetPixel(i, out r, out g, out b); heightmap[i] = PNM.RGBToLuminosity(r, g, b) / 255f; } newImage = ApplyHeightMapFunctionCore(newImage.Width, newImage.Height, heightmap, matrixLength, func); Trim(newImage, padding); return(newImage); }
//this should be rewritten to ApplyConvolutionFunction public static PNM ApplyGradientEdgesDetection(this PNM image) { PNM workImage = PNM.Copy(image); Pad(workImage, 1); Tuple <float[], float[], float[]> xraster = ApplyConvolutionUnbound(workImage, new float[] { -1, 0, 1, -1, 0, 1, -1, 0, 1 }, 3); Tuple <float[], float[], float[]> yraster = ApplyConvolutionUnbound(workImage, new float[] { 1, 1, 1, 0, 0, 0, -1, -1, -1 }, 3); PNM newImage = new PNM(image.Width, image.Height); int size = image.Width * image.Height; Parallel.For(0, size, i => { byte r = Coerce(Math.Sqrt(Math.Pow(xraster.Item1[i], 2) + Math.Pow(yraster.Item1[i], 2))); byte g = Coerce(Math.Sqrt(Math.Pow(xraster.Item2[i], 2) + Math.Pow(yraster.Item2[i], 2))); byte b = Coerce(Math.Sqrt(Math.Pow(xraster.Item3[i], 2) + Math.Pow(yraster.Item3[i], 2))); newImage.SetPixel(i, r, g, b); }); return(newImage); }
public static PNM ApplyHarrisDetector(this PNM image) { // gaussian window float[] gaussian = new float[] { 0, 0.01F, 0.02F, 0.01F, 0, 0.01F, 0.06F, 0.1F, 0.06F, 0.01F, 0.02F, 0.1F, 0.16F, 0.1F, 0.02F, 0.01F, 0.06F, 0.1F, 0.06F, 0.01F, 0, 0.01F, 0.02F, 0.01F, 0 }; // greyscale PNM workImage = PNM.Copy(image).ApplyPointProcessing(Color.ToGrayscale); Filter.Pad(workImage, 1); // integrate with prewitt double[] normalizedWorkImage = workImage.raster.Where((b, idx) => idx % 3 == 0).Select(b => b / 255d).ToArray(); double[] xraster = RunConvolution(normalizedWorkImage, workImage.Width, workImage.Height, Edges.SobelX, 3); double[] yraster = RunConvolution(normalizedWorkImage, workImage.Width, workImage.Height, Edges.SobelY, 3); double[] rasterA = new double[xraster.Length]; double[] rasterB = new double[xraster.Length]; double[] rasterC = new double[xraster.Length]; for (int i = 0; i < xraster.Length; i++) { rasterA[i] = Math.Pow(xraster[i], 2); rasterB[i] = Math.Pow(yraster[i], 2); rasterC[i] = xraster[i] * yraster[i]; } rasterA = Filter.PadWithZeros(rasterA, image.Width, image.Height, 2, 2); rasterB = Filter.PadWithZeros(rasterB, image.Width, image.Height, 2, 2); rasterC = Filter.PadWithZeros(rasterC, image.Width, image.Height, 2, 2); // calculate the matrices double[][] matrices = new double[image.Width * image.Height][]; int maxHeight = image.Height + 2; int maxWidth = image.Width + 2; int newWidth = image.Width + 4; int width = image.Width; for (int i = 2; i < maxHeight; i++) { //Parallel.For(2, maxHeight, (i) => //{ for (int j = 2; j < maxWidth; j++) { // apply convolution double accumulatorA = 0; double accumulatorB = 0; double accumulatorC = 0; int mi = 0; for (int x0 = -2; x0 <= 2; x0++) { for (int y0 = -2; y0 <= 2; y0++) { accumulatorA += gaussian[mi] * rasterA[(i + x0) * newWidth + j + y0]; accumulatorB += gaussian[mi] * rasterB[(i + x0) * newWidth + j + y0]; accumulatorC += gaussian[mi] * rasterC[(i + x0) * newWidth + j + y0]; mi++; } } int realPosition = (i - 2) * width + (j - 2); matrices[realPosition] = new double[] { accumulatorA, accumulatorB, accumulatorC }; } //}); } // do the part 2 and 3 double[] cornerness = new double[image.Width * image.Height]; for (int i = 0; i < matrices.Length; i++) { double det = (matrices[i][0] * matrices[i][1]) - (matrices[i][2] * matrices[i][2]); double trace = matrices[i][0] + matrices[i][1]; double corner = det - (HarrisK * (trace * trace)); if (corner >= HarrisThreshold) { cornerness[i] = corner; } } //return ToPNM(cornerness, image.Width, image.Height); CenteredNonMaximumSuppression(cornerness, image.Width, image.Height, 3); // draw corners PNM newImage = PNM.Copy(image); for (int i = 0; i < cornerness.Length; i++) { if (cornerness[i] == 0) { continue; } MarkPixel(newImage, i); } return(newImage); }