public static Pixel Mirror(PNM image, int index) { byte r, g, b; int x = index % image.Width; int y = index / image.Width; if (x < image.Width / 2d) { image.GetPixel((y * image.Width) + (image.Width - x - 1), out r, out g, out b); } else { image.GetPixel((y * image.Width) + x, out r, out g, out b); } /* * image.ToPolar(index, out radius, out angle); * double newX = image.Width * angle/Math.PI*2; * double newY = image.Height * radius / maxR; * int newIndex = ((int)newX * image.Width) + (int)newY; * // correct for pixels outside the image * if(newIndex < 0 || newIndex >= image.Width * image.Height) * newIndex = index; * image.GetPixel(radius, angle + radius, out r, out g, out b); * */ return(new Pixel(r, g, b)); }
// assume k = -0.2 and R = 15x15 // needs 1 pixel width padding public static Pixel Niblack(PNM image, int index, double k = -0.2, int length = 15, int padding = 7) { byte r, g, b; float[] surrounding = new float[length * length]; int i = 0; for (int m = 0; m < length; m++) { for (int n = 0; n < length; n++) { image.GetPixel(index - ((padding - m) * image.Width) - (padding - n), out r, out g, out b); surrounding[i] = PNM.RGBToLuminosity(r, g, b); i++; } } float mean = surrounding.Average(); double threshold = mean + (k * (mean / surrounding.Length)); image.GetPixel(index, out r, out g, out b); byte luminosity = PNM.RGBToLuminosity(r, g, b); if (luminosity < threshold) { return(Pixel.Black); } return(Pixel.White); }
public static Pixel Erosion(PNM image, int index) { int length = 3; int padding = 1; byte r = 0, g = 0, b = 0; byte tempR, tempG, tempB; for (int m = 0; m < length; m++) { for (int n = 0; n < length; n++) { image.GetPixel(index - ((padding - m) * image.Width) - (padding - n), out tempR, out tempG, out tempB); // check for "white pixel" if (tempR > 127) r = 255; if (tempG > 127) g = 255; if (tempB > 127) b = 255; } if (r != 0 && g != 0 && b != 0) break; } return new Pixel(r, g, b); }
// assume mask 3x3, image is already 1 pixel padded public static Pixel Median(PNM image, int index) { byte[] workArrayR = new byte[9]; byte[] workArrayG = new byte[9]; byte[] workArrayB = new byte[9]; int length = 3; int padding = 1; byte r, g, b; int i = 0; for (int m = 0; m < length; m++) { for (int n = 0; n < length; n++) { image.GetPixel(index - ((padding - m) * image.Width) - (padding - n), out r, out g, out b); workArrayR[i] = r; workArrayG[i] = g; workArrayB[i] = b; i++; } } Array.Sort(workArrayR); Array.Sort(workArrayG); Array.Sort(workArrayB); return new Pixel(workArrayR[4], workArrayG[4], workArrayB[4]); }
public static Pixel Dilation(PNM image, int index) { int length = 3; int padding = 1; byte r = 255, g = 255, b = 255; byte tempR, tempG, tempB; for (int m = 0; m < length; m++) { for (int n = 0; n < length; n++) { image.GetPixel(index - ((padding - m) * image.Width) - (padding - n), out tempR, out tempG, out tempB); // check for "black pixel" if (tempR < 128) r = 0; if (tempG < 128) g = 0; if (tempB < 128) b = 0; } if (r == 0 && g == 0 && b == 0) break; } return new Pixel(r, g, b); }
// assume mask 3x3, image is already 1 pixel padded public static Pixel Median(PNM image, int index) { byte[] workArrayR = new byte[9]; byte[] workArrayG = new byte[9]; byte[] workArrayB = new byte[9]; int length = 3; int padding = 1; byte r, g, b; int i = 0; for (int m = 0; m < length; m++) { for (int n = 0; n < length; n++) { image.GetPixel(index - ((padding - m) * image.Width) - (padding - n), out r, out g, out b); workArrayR[i] = r; workArrayG[i] = g; workArrayB[i] = b; i++; } } Array.Sort(workArrayR); Array.Sort(workArrayG); Array.Sort(workArrayB); return(new Pixel(workArrayR[4], workArrayG[4], workArrayB[4])); }
private static void HysteresisConnect(PNM image, int index, int width, int height, byte lowValue, byte highValue) { int x = index % width; int y = index / height; for (int x0 = x - 1; x0 < x + 1; x0++) { for (int y0 = y - 1; y0 < y + 1; y0++) { int currentIndex = (width * y0) + x0; if (!IsPixelOnEdge(currentIndex, width, height)) { byte l; image.GetPixel(currentIndex, out l, out l, out l); if (l != 255) { if (l >= lowValue) { image.SetPixel(currentIndex, 255, 255, 255); HysteresisConnect(image, currentIndex, width, height, lowValue, highValue); } } } } } }
public static Pixel Dilation(PNM image, int index) { int length = 3; int padding = 1; byte r = 255, g = 255, b = 255; byte tempR, tempG, tempB; for (int m = 0; m < length; m++) { for (int n = 0; n < length; n++) { image.GetPixel(index - ((padding - m) * image.Width) - (padding - n), out tempR, out tempG, out tempB); // check for "black pixel" if (tempR < 128) { r = 0; } if (tempG < 128) { g = 0; } if (tempB < 128) { b = 0; } } if (r == 0 && g == 0 && b == 0) { break; } } return(new Pixel(r, g, b)); }
public static Pixel Oil(PNM image, int index) { int length = 7; int padding = length / 2; byte[] rvalues = new byte[length * length]; byte[] gvalues = new byte[length * length]; byte[] bvalues = new byte[length * length]; byte r, g, b; int i = 0; for (int m = 0; m < length; m++) { for (int n = 0; n < length; n++) { image.GetPixel(index - ((padding - m) * image.Width) - (padding - n), out r, out g, out b); rvalues[i] = r; gvalues[i] = g; bvalues[i] = b; i++; } } return(new Pixel(rvalues.GroupBy(p => p).OrderByDescending(gr => gr.Count()).First().Key, gvalues.GroupBy(p => p).OrderByDescending(gr => gr.Count()).First().Key, bvalues.GroupBy(p => p).OrderByDescending(gr => gr.Count()).First().Key)); }
public static Pixel Erosion(PNM image, int index) { int length = 3; int padding = 1; byte r = 0, g = 0, b = 0; byte tempR, tempG, tempB; for (int m = 0; m < length; m++) { for (int n = 0; n < length; n++) { image.GetPixel(index - ((padding - m) * image.Width) - (padding - n), out tempR, out tempG, out tempB); // check for "white pixel" if (tempR > 127) { r = 255; } if (tempG > 127) { g = 255; } if (tempB > 127) { b = 255; } } if (r != 0 && g != 0 && b != 0) { break; } } return(new Pixel(r, g, b)); }
internal static int[][] HoughVote(PNM image, int maxW) { // initialize voting board int[][] votingBoard = new int[180][]; for (int i = 0; i < 180; i++) { votingBoard[i] = new int[maxW * 2]; } int size = image.Width * image.Height; for (int i = 0; i < size; i++) { byte l; image.GetPixel(i, out l, out l, out l); if (l < 255) { continue; } double centeredX = i % image.Width - (image.Width / 2d); double centeredY = (image.Height / 2d) - i / image.Width; // pixel is white - vote in all directions for (int angle = 0; angle < 180; angle++) { double radianAngle = Math.PI * angle / 180d; double w = centeredX * Math.Cos(radianAngle) + centeredY * Math.Sin(radianAngle); votingBoard[angle][(int)w + maxW]++; } } return(votingBoard); }
public static Pixel Negative(PNM image, int index) { byte r, g, b; image.GetPixel(index, out r, out g, out b); return(new Pixel((byte)(255 - r), (byte)(255 - g), (byte)(255 - b))); }
internal static Pixel ConvoluteWithModule(PNM image, int index, float[] matrix1, float[] matrix2, int length, int padding) { float sumR1 = 0; float sumR2 = 0; float sumG1 = 0; float sumG2 = 0; float sumB1 = 0; float sumB2 = 0; byte r, g, b; for (int m = 0; m < length; m++) { for (int n = 0; n < length; n++) { image.GetPixel(index - ((padding - m) * image.Width) - (padding - n), out r, out g, out b); float coeff1 = matrix1[(m * length) + n]; float coeff2 = matrix2[(m * length) + n]; sumR1 += r * coeff1; sumR2 += r * coeff2; sumG1 += g * coeff1; sumG2 += g * coeff2; sumB1 += b * coeff1; sumB2 += b * coeff2; } } return(new Pixel(Filter.Coerce(Module(sumR1, sumR2)), Filter.Coerce(Module(sumG1, sumG2)), Filter.Coerce(Module(sumB1, sumB2)))); }
private static double[][] ToInitialDistanceMap(PNM image, ref int pixelCount) { double[][] distanceMap = new double[image.Width][]; for (int i = 0; i < image.Width; i++) { distanceMap[i] = new double[image.Height]; } byte l; for (int i = 0; i < image.Width; i++) { for (int j = 0; j < image.Height; j++) { image.GetPixel(i, j, out l, out l, out l); if (l == 255) { distanceMap[i][j] = 0; pixelCount++; } else { distanceMap[i][j] = Double.PositiveInfinity; } } } return(distanceMap); }
private static Pixel FishEye(PNM image, int index, double maxR) { byte r,g,b; double radius, angle; image.ToPolar(index, out radius, out angle); image.GetPixel((radius * radius) / maxR, angle, out r, out g, out b); return new Pixel(r, g, b); }
private static Pixel FishEye(PNM image, int index, double maxR) { byte r, g, b; double radius, angle; image.ToPolar(index, out radius, out angle); image.GetPixel((radius * radius) / maxR, angle, out r, out g, out b); return(new Pixel(r, g, b)); }
public static Pixel Mirror(PNM image, int index) { byte r, g, b; int x = index % image.Width; int y = index / image.Width; if (x < image.Width / 2d) image.GetPixel((y * image.Width) + (image.Width - x - 1), out r, out g, out b); else image.GetPixel((y * image.Width) + x, out r, out g, out b); /* image.ToPolar(index, out radius, out angle); double newX = image.Width * angle/Math.PI*2; double newY = image.Height * radius / maxR; int newIndex = ((int)newX * image.Width) + (int)newY; // correct for pixels outside the image if(newIndex < 0 || newIndex >= image.Width * image.Height) newIndex = index; image.GetPixel(radius, angle + radius, out r, out g, out b); * */ return new Pixel(r, g, b); }
public static Pixel Oil(PNM image, int index) { int length = 7; int padding = length / 2; byte[] rvalues = new byte[length * length]; byte[] gvalues = new byte[length * length]; byte[] bvalues = new byte[length * length]; byte r, g, b; int i = 0; for (int m = 0; m < length; m++) { for (int n = 0; n < length; n++) { image.GetPixel(index - ((padding - m) * image.Width) - (padding - n), out r, out g, out b); rvalues[i] = r; gvalues[i] = g; bvalues[i] = b; i++; } } return new Pixel(rvalues.GroupBy(p => p).OrderByDescending(gr => gr.Count()).First().Key, gvalues.GroupBy(p => p).OrderByDescending(gr => gr.Count()).First().Key, bvalues.GroupBy(p => p).OrderByDescending(gr => gr.Count()).First().Key); }
private static IEnumerable <Tuple <float, float>[]> MaskedHoughVote(PNM image, int center, bool[] mask, int dmax, int dmin, int padding) { double angleStep = (Math.PI * 3) / (4d * dmax); int angles = (int)Math.Floor(Math.PI / angleStep); double distanceStep = 3 / 4d; int distances = (int)Math.Ceiling(dmax / distanceStep); int[][] votingBoard = new int[angles][]; for (int i = 0; i < angles; i++) { votingBoard[i] = new int[distances]; } int maskSize = mask.Length; int maskIndex = 0; for (int i = -dmax / 2; i <= dmax / 2; i++) { for (int j = -dmax / 2; j <= dmax / 2; j++) { if (!mask[maskIndex++]) { continue; } int x = center % image.Width + i; int y = center / image.Width - j; int realIndex = (y * image.Width) + x; byte l; image.GetPixel(realIndex, out l, out l, out l); if (l < 255) { continue; } for (int angle = 0; angle < angles; angle++) { double radianAngle = angle * angleStep; double w = i * Math.Cos(radianAngle) + j * Math.Sin(radianAngle); double normalizedW = w + (dmax / 2d); int steppedW = (int)(normalizedW / distanceStep); votingBoard[angle][steppedW]++; } } } // votingboard is full - enhance it now List <double[]> peaks = EnhanceHoughVotingBoard(votingBoard, dmax, dmin, angleStep, distanceStep); List <Tuple <int, int, double> > extendedPeaks = new List <Tuple <int, int, double> >(peaks.Count / 2); for (int i = 0; i < peaks.Count; i++) { for (int j = i + 1; j < peaks.Count; j++) { if (Math.Abs(peaks[i][0] - peaks[j][0]) < AngularThreshold && Math.Abs(peaks[i][1] + peaks[j][1]) < DistanceThreshold && Math.Abs(peaks[i][2] - peaks[j][2]) < NormalizedThreshold * (peaks[i][2] + peaks[j][2]) / 2) { extendedPeaks.Add(Tuple.Create(i, j, 0.5 * (peaks[i][0] + peaks[j][0]))); } } } // extendedPeaks now holds Tuples of (i, j, ak), where i and j are indices of paired peaks and their alpha_k List <Tuple <double[][], double[][]> > finalPairs = new List <Tuple <double[][], double[][]> >(); for (int i = 0; i < extendedPeaks.Count; i++) { for (int j = i + 1; j < extendedPeaks.Count; j++) { if (Math.Abs(Math.Abs(extendedPeaks[i].Item3 - extendedPeaks[j].Item3) - (Math.PI / 2)) < AngularThreshold) { // we got pairs of peak pairs finalPairs.Add(Tuple.Create(new double[][] { peaks[extendedPeaks[i].Item1], peaks[extendedPeaks[i].Item2] }, new double[][] { peaks[extendedPeaks[j].Item1], peaks[extendedPeaks[j].Item2] })); } } } return(finalPairs.Select(pair => new Tuple <double, double>[] { PolarLineIntersection(pair.Item1[0][0], pair.Item1[0][1], pair.Item2[0][0], pair.Item2[0][1]), PolarLineIntersection(pair.Item1[1][0], pair.Item1[1][1], pair.Item2[0][0], pair.Item2[0][1]), PolarLineIntersection(pair.Item1[0][0], pair.Item1[0][1], pair.Item2[1][0], pair.Item2[1][1]), PolarLineIntersection(pair.Item1[1][0], pair.Item1[1][1], pair.Item2[1][0], pair.Item2[1][1]) }) .Select(tups => new Tuple <float, float>[] { CorrectCoordinates(tups[0].Item1, tups[0].Item2, center, image.Width, image.Height, padding), CorrectCoordinates(tups[1].Item1, tups[1].Item2, center, image.Width, image.Height, padding), CorrectCoordinates(tups[2].Item1, tups[2].Item2, center, image.Width, image.Height, padding), CorrectCoordinates(tups[3].Item1, tups[3].Item2, center, image.Width, image.Height, padding) })); }
private static double[][] ToInitialDistanceMap(PNM image, ref int pixelCount) { double[][] distanceMap = new double[image.Width][]; for(int i =0; i< image.Width; i++) { distanceMap[i] = new double[image.Height]; } byte l; for (int i = 0; i < image.Width; i++) { for (int j = 0; j < image.Height; j++) { image.GetPixel(i, j, out l, out l, out l); if (l == 255) { distanceMap[i][j] = 0; pixelCount++; } else { distanceMap[i][j] = Double.PositiveInfinity; } } } return distanceMap; }
private static IEnumerable<Tuple<float, float>[]> MaskedHoughVote(PNM image, int center, bool[] mask, int dmax, int dmin, int padding) { double angleStep = (Math.PI * 3) / (4d * dmax); int angles = (int)Math.Floor(Math.PI / angleStep); double distanceStep = 3/4d; int distances = (int)Math.Ceiling(dmax / distanceStep); int[][] votingBoard = new int[angles][]; for (int i = 0; i < angles; i++) votingBoard[i] = new int[distances]; int maskSize = mask.Length; int maskIndex = 0; for (int i = -dmax/2; i <= dmax/2; i++) { for (int j = -dmax / 2; j <= dmax/2; j++) { if (!mask[maskIndex++]) continue; int x = center % image.Width + i; int y = center / image.Width - j; int realIndex = (y * image.Width) + x; byte l; image.GetPixel(realIndex, out l, out l, out l); if (l < 255) continue; for (int angle = 0; angle < angles; angle++) { double radianAngle = angle * angleStep; double w = i * Math.Cos(radianAngle) + j * Math.Sin(radianAngle); double normalizedW = w + (dmax / 2d); int steppedW = (int)(normalizedW / distanceStep); votingBoard[angle][steppedW]++; } } } // votingboard is full - enhance it now List<double[]> peaks = EnhanceHoughVotingBoard(votingBoard, dmax, dmin, angleStep, distanceStep); List<Tuple<int, int, double>> extendedPeaks = new List<Tuple<int, int, double>>(peaks.Count / 2); for (int i = 0; i < peaks.Count; i++) { for (int j = i + 1; j < peaks.Count; j++) { if (Math.Abs(peaks[i][0] - peaks[j][0]) < AngularThreshold && Math.Abs(peaks[i][1] + peaks[j][1]) < DistanceThreshold && Math.Abs(peaks[i][2] - peaks[j][2]) < NormalizedThreshold * (peaks[i][2] + peaks[j][2]) / 2) extendedPeaks.Add(Tuple.Create(i, j, 0.5 * (peaks[i][0] + peaks[j][0]))); } } // extendedPeaks now holds Tuples of (i, j, ak), where i and j are indices of paired peaks and their alpha_k List<Tuple<double[][], double[][]>> finalPairs = new List<Tuple<double[][], double[][]>>(); for (int i = 0; i < extendedPeaks.Count; i++) { for (int j = i + 1; j < extendedPeaks.Count; j++) { if (Math.Abs(Math.Abs(extendedPeaks[i].Item3 - extendedPeaks[j].Item3) - (Math.PI / 2)) < AngularThreshold) // we got pairs of peak pairs finalPairs.Add(Tuple.Create( new double[][] {peaks[extendedPeaks[i].Item1], peaks[extendedPeaks[i].Item2] }, new double[][] { peaks[extendedPeaks[j].Item1], peaks[extendedPeaks[j].Item2] })); } } return finalPairs.Select(pair => new Tuple<double, double>[] { PolarLineIntersection(pair.Item1[0][0], pair.Item1[0][1], pair.Item2[0][0], pair.Item2[0][1]), PolarLineIntersection(pair.Item1[1][0], pair.Item1[1][1], pair.Item2[0][0], pair.Item2[0][1]), PolarLineIntersection(pair.Item1[0][0], pair.Item1[0][1], pair.Item2[1][0], pair.Item2[1][1]), PolarLineIntersection(pair.Item1[1][0], pair.Item1[1][1], pair.Item2[1][0], pair.Item2[1][1])}) .Select(tups => new Tuple<float, float>[]{ CorrectCoordinates(tups[0].Item1, tups[0].Item2, center, image.Width, image.Height, padding), CorrectCoordinates(tups[1].Item1, tups[1].Item2, center, image.Width, image.Height, padding), CorrectCoordinates(tups[2].Item1, tups[2].Item2, center, image.Width, image.Height, padding), CorrectCoordinates(tups[3].Item1, tups[3].Item2, center, image.Width, image.Height, padding)}); }
internal static Pixel ConvoluteWithModule(PNM image, int index, float[] matrix1, float[] matrix2, int length, int padding) { float sumR1 = 0; float sumR2 = 0; float sumG1 = 0; float sumG2 = 0; float sumB1 = 0; float sumB2 = 0; byte r, g, b; for (int m = 0; m < length; m++) { for (int n = 0; n < length; n++) { image.GetPixel(index - ((padding - m) * image.Width) - (padding - n), out r, out g, out b); float coeff1 = matrix1[(m * length) + n]; float coeff2 = matrix2[(m * length) + n]; sumR1 += r * coeff1; sumR2 += r * coeff2; sumG1 += g * coeff1; sumG2 += g * coeff2; sumB1 += b * coeff1; sumB2 += b * coeff2; } } return new Pixel(Filter.Coerce(Module(sumR1, sumR2)), Filter.Coerce(Module(sumG1, sumG2)), Filter.Coerce(Module(sumB1, sumB2))); }
internal static int[][] HoughVote(PNM image, int maxW) { // initialize voting board int[][] votingBoard = new int[180][]; for (int i = 0; i < 180; i++) votingBoard[i] = new int[maxW * 2]; int size = image.Width * image.Height; for (int i = 0; i < size; i++) { byte l; image.GetPixel(i, out l, out l, out l); if (l < 255) continue; double centeredX = i % image.Width - (image.Width / 2d); double centeredY = (image.Height / 2d) - i / image.Width; // pixel is white - vote in all directions for (int angle = 0; angle < 180; angle++) { double radianAngle = Math.PI * angle / 180d; double w = centeredX * Math.Cos(radianAngle) + centeredY * Math.Sin(radianAngle); votingBoard[angle][(int)w + maxW]++; } } return votingBoard; }
public static Pixel Negative(PNM image, int index) { byte r, g, b; image.GetPixel(index, out r, out g, out b); return new Pixel((byte)(255 - r), (byte)(255 - g), (byte)(255 - b)); }
// assume k = -0.2 and R = 15x15 // needs 1 pixel width padding public static Pixel Niblack(PNM image, int index, double k = -0.2, int length = 15, int padding = 7) { byte r, g, b; float[] surrounding = new float[length * length]; int i = 0; for (int m = 0; m < length; m++) { for (int n = 0; n < length; n++) { image.GetPixel(index - ((padding - m) * image.Width) - (padding - n), out r, out g, out b); surrounding[i] = PNM.RGBToLuminosity(r, g, b); i++; } } float mean = surrounding.Average(); double threshold = mean + (k* (mean / surrounding.Length)); image.GetPixel(index, out r, out g, out b); byte luminosity = PNM.RGBToLuminosity(r,g,b); if (luminosity < threshold) return Pixel.Black; return Pixel.White; }