/// <summary> /// Get the average rgb-values from an image in a given rectangle /// By default the function calculate the average rgb-values from the whole image /// </summary> /// <example> /// <code> /// <![CDATA[ /// ImageData Img = new ImageData(...); /// double[] AverageColor = CommonFunctions.AverageRGBValues(img); /// int left = 0; /// int top = 5; /// double[] AverageColorShifted = CommonFunctions.AverageRGBValues(img,left,top); /// int width = 50; /// int height = 100; /// double[] AverageColorRectangle = CommonFunctions.AverageRGBValues(img,left,top,width,height); /// ]]> /// </code> /// </example> /// <param name="Img">Image</param> /// <param name="Left">left of rectangle (default=0)</param> /// <param name="Top">top of rectangle (default=0)</param> /// <param name="Width">width of rectangle (default=full width)</param> /// <param name="Height">height of rectangle (default=full height)</param> /// <returns>averag rgb-values</returns> static public double[] AverageRGBValues(ImageData Img, int Left = 0, int Top = 0, int Width = -1, int Height = -1) { Color CurrentColor; long[] totals = new long[] { 0, 0, 0 }; if (Width == -1) { Width = Img.Width; } if (Height == -1) { Height = Img.Height; } for (int x = Left; x < Left + Width; x++) { for (int y = Top; y < Top + Height; y++) { CurrentColor = Img.GetPixel(x, y); totals[0] += CurrentColor.R; totals[1] += CurrentColor.G; totals[2] += CurrentColor.B; } } int count = Width * Height; double[] retvar = new double[] { (totals[0] / (double)count), (totals[1] / (double)count), (totals[2] / (double)count) }; return(retvar); }
/// <summary> /// calculate the similarity of image A in a given rectangle and a reference image B /// </summary> /// <param name="Img">image A</param> /// <param name="Reference">image B</param> /// <param name="Left">offset from left of image A</param> /// <param name="Top">offset from top of image A</param> /// <param name="Width">width of rectangle (default: full width)</param> /// <param name="Height">height of rectangle (default: full height)</param> /// <returns>similarity (1=exact,0=none)</returns> static public double Similarity(ImageData Img, ImageData Reference, int Left = 0, int Top = 0, int Width = -1, int Height = -1, int OffsetLeft = 0, int OffsetTop = 0) { double sim = 0.0; Width = (Width == -1) ? Img.Width - Left : Width; Height = (Height == -1) ? Img.Height - Top : Height; if ((Img.Width == Reference.Width) && (Img.Height == Reference.Height)) { for (Int32 column = Left; column < Left + Width; column++) { for (Int32 row = Top; row < Top + Height; row++) { Color a = Img.GetPixel(OffsetLeft + column, OffsetTop + row); Color b = Reference.GetPixel(column, row); int cr = Math.Abs(a.R - b.R); int cg = Math.Abs(a.G - b.G); int cb = Math.Abs(a.B - b.B); sim += (cr + cg + cb) / 3; } } sim /= 255.0; sim /= (Img.Height * Img.Width); } return(1 - sim); }
/// <summary> /// Calculates the similarity of image "img" in a given rectangle and a reference image "reference" /// </summary> /// <example> /// <code> /// <![CDATA[ /// ImageData Screenshot = new ImageData(...); /// ImageData Coin = new ImageData(...); /// // do magic or using a clipped region of screenshot (500px from left and 100px from top) /// int left_region = 500; /// int top_region = 100; /// double measure = Similarity(Screenshot,Coin,left_region,top_region); /// ]]> /// </code> /// </example> /// <param name="img">Image A</param> /// <param name="reference">Image B</param> /// <param name="left">The offset from left of image A</param> /// <param name="top">The offset from top of image A</param> /// <param name="width">The width of the rectangle (default: full width)</param> /// <param name="height">The height of the rectangle (default: full height)</param> /// <param name="offsetLeft">The left offset</param> /// <param name="offsetTop">The top offset</param> /// <returns>The similarity result (1=exact, 0=none)</returns> public static double Similarity(ImageData img, ImageData reference, int left = 0, int top = 0, int width = -1, int height = -1, int offsetLeft = 0, int offsetTop = 0) { double sim = 0.0; width = (width == -1) ? img.Width - left : width; height = (height == -1) ? img.Height - top : height; if ((img.Width == reference.Width) && (img.Height == reference.Height)) { for (Int32 column = left; column < left + width; column++) { for (Int32 row = top; row < top + height; row++) { Color a = img.GetPixel(offsetLeft + column, offsetTop + row); Color b = reference.GetPixel(column, row); int cr = Math.Abs(a.R - b.R); int cg = Math.Abs(a.G - b.G); int cb = Math.Abs(a.B - b.B); sim += (cr + cg + cb) / 3; //TODO: Fix possible loss of fraction } } sim /= 255.0; sim /= (img.Height * img.Width); } return(1 - sim); }
/// <summary> /// Get the average rgb-values from an image in a given rectangle /// By default the function calculate the average rgb-values from the whole image /// </summary> /// <example> /// <code> /// <![CDATA[ /// ImageData Img = new ImageData(...); /// double[] AverageColor = CommonFunctions.AverageRGBValues(img); /// int left = 0; /// int top = 5; /// double[] AverageColorShifted = CommonFunctions.AverageRGBValues(img,left,top); /// int width = 50; /// int height = 100; /// double[] AverageColorRectangle = CommonFunctions.AverageRGBValues(img,left,top,width,height); /// ]]> /// </code> /// </example> /// <param name="Img">Image</param> /// <param name="Left">left of rectangle (default=0)</param> /// <param name="Top">top of rectangle (default=0)</param> /// <param name="Width">width of rectangle (default=full width)</param> /// <param name="Height">height of rectangle (default=full height)</param> /// <returns>averag rgb-values</returns> public static double[] AverageRGBValues(ImageData Img, int Left = 0, int Top = 0, int Width = -1, int Height = -1) { Color CurrentColor; long[] totals = new long[] { 0, 0, 0 }; if (Width == -1) Width = Img.Width; if(Height==-1) Height = Img.Height; for (int x = Left; x < Left + Width; x++) { for (int y = Top; y < Top + Height; y++) { CurrentColor = Img.GetPixel(x, y); totals[0] += CurrentColor.R; totals[1] += CurrentColor.G; totals[2] += CurrentColor.B; } } int count = Width * Height; double[] retvar = new double[] { (totals[0] / (double)count), (totals[1] / (double)count), (totals[2] / (double)count) }; return retvar; }
/// <summary> /// Gets the average RGB values from a given rectangle in an image /// By default the average RGB values from the whole image are calculated /// </summary> /// <remarks> /// to detect the color of bubbles or coins this function can be helpful in connection with IdentifyColor() /// </remarks> /// <example> /// <code> /// <![CDATA[ /// ImageData Img = new ImageData(...); /// // average color in whole image /// double[] AverageColor = CommonFunctions.AverageRGBValues(img); /// int left = 0; /// int top = 5; /// // average color in clipped image /// double[] AverageColorShifted = CommonFunctions.AverageRGBValues(img,left,top); /// int width = 50; /// int height = 100; /// // average color in predefined rectangle /// double[] AverageColorRectangle = CommonFunctions.AverageRGBValues(img,left,top,width,height); /// ]]> /// </code> /// </example> /// <param name="img">The image to process</param> /// <param name="left">The left of the rectangle (default=0)</param> /// <param name="top">The top of the rectangle (default=0)</param> /// <param name="width">The width of the rectangle (default=full width)</param> /// <param name="height">The height of the rectangle (default=full height)</param> /// <returns>The average RGB values</returns> public static double[] AverageRGBValues(ImageData img, int left = 0, int top = 0, int width = -1, int height = -1) { long[] totals = { 0, 0, 0 }; if (width == -1) { width = img.Width; } if (height == -1) { height = img.Height; } for (int x = left; x < left + width; x++) { for (int y = top; y < top + height; y++) { Color currentColor = img.GetPixel(x, y); totals[0] += currentColor.R; totals[1] += currentColor.G; totals[2] += currentColor.B; } } int count = width * height; double[] retvar = { (totals[0] / (double)count), (totals[1] / (double)count), (totals[2] / (double)count) }; return(retvar); }
/// <summary> /// identify the color of a part(rectangle) from an image by a given list of reference colors (majority vote) /// </summary> /// <remarks> /// this tests every pixel in the given rectangle and majority votes the color from the given dictionary of possible colors /// </remarks> /// <param name="Img">image to look in</param> /// <param name="statReference">list of possible colors</param> /// <param name="Left">left of rectangle (default: 0)</param> /// <param name="Top">top of rectangle (default: 0)</param> /// <param name="Width">width of rectangle (default: full width)</param> /// <param name="Height">height of rectangle (default: full height)</param> /// <returns>Color</returns> static public Color IdentifyColorByVoting(ImageData Img, Dictionary <Color, List <double> > statReference, int Left = 0, int Top = 0, int Width = -1, int Height = -1) { double[] av = CommonFunctions.AverageRGBValues(Img, Left, Top, Width, Height); Color Foo = Color.White; int[] votes = Enumerable.Repeat(0, statReference.Count).ToArray(); if (Width == -1) { Width = Img.Width; } if (Height == -1) { Height = Img.Height; } for (int x = Left; x < Left + Width; x++) { for (int y = Top; y < Top + Height; y++) { // color from image Color CurrentColor = Img.GetPixel(x, y); int best_dist = 255 * 50; int best_idx = 0; for (int i = 0; i < statReference.Count; i++) { List <double> RGB = statReference.ElementAt(i).Value; // from from dictionary Color CCol = Color.FromArgb(Convert.ToInt32(RGB.ElementAt(0)), Convert.ToInt32(RGB.ElementAt(1)), Convert.ToInt32(RGB.ElementAt(2))); // distance int current_dist = Math.Abs(CCol.R - CurrentColor.R) + Math.Abs(CCol.G - CurrentColor.G) + Math.Abs(CCol.B - CurrentColor.B); if (current_dist < best_dist) { best_dist = current_dist; best_idx = i; } } votes[best_idx]++; } } // this is faster than LINQ int m = -1; int ans = 0; for (int i = 0; i < votes.Length; i++) { if (votes[i] > m) { m = votes[i]; ans = i; } } return(statReference.ElementAt(ans).Key); }
/// <summary> /// Identifies the colors of the pixels in a rectangle and compares them with those from an image by a given list of /// reference colors (majority vote) /// </summary> /// <remarks> /// This tests every pixel in the given rectangle and majority votes the color from the given dictionary of possible /// colors. Each pixel votes for a color. /// /// if the image patch is /// /// " red red " /// " red blue " /// /// then 4 pixels vote for similary colors to red and one pixel votes for a similar color to blue /// /// </remarks> /// <example> /// <code> /// <![CDATA[ /// ImageData Screenshot = new ImageData(...); /// Dictionary<Color, List<double>> Choose = new Dictionary<Color, List<double>> (); /// Choose.Add(Color.Red, new List<double> { 255, 144.23, 140.89 }); /// Choose.Add(Color.White, new List<double> { 218, 219, 222 }); /// Choose.Add(Color.Blue, new List<double> { 21, 108, 182 }); /// Choose.Add(Color.Green, new List<double> { 86, 191, 50 }); /// Choose.Add(Color.Yellow, new List<double> { 233, 203, 118 }); /// Choose.Add(Color.Orange, new List<double> { 246, 122, 11 }); /// Choose.Add(Color.Black, new List<double> { 94, 98, 98 }); /// Choose.Add(Color.Violet, new List<double> { 223, 80, 195 }); /// Choose.Add(Color.MediumSeaGreen, new List<double> { 106, 227, 216 }); /// // ... /// Color PieceColor = CommonFunctions.IdentifyColorByVoting(Screenshot,Choose,leftoffset,topoffset,width,height); /// ]]> /// </code> /// </example> /// <param name="img">The image to look in</param> /// <param name="statReference">The list of possible colors</param> /// <param name="left">The left of the rectangle (default: 0)</param> /// <param name="top">The top of the rectangle (default: 0)</param> /// <param name="width">The width of the rectangle (default: full width)</param> /// <param name="height">The height of the rectangle (default: full height)</param> /// <returns>The best matching color</returns> public static Color IdentifyColorByVoting(ImageData img, Dictionary <Color, List <double> > statReference, int left = 0, int top = 0, int width = -1, int height = -1) { int[] votes = Enumerable.Repeat(0, statReference.Count).ToArray(); if (width == -1) { width = img.Width; } if (height == -1) { height = img.Height; } for (int x = left; x < left + width; x++) { for (int y = top; y < top + height; y++) { // color from image Color currentColor = img.GetPixel(x, y); int bestDist = 255 * 50; int bestIndex = 0; for (int i = 0; i < statReference.Count; i++) { List <double> RGB = statReference.ElementAt(i).Value; // from from dictionary Color cCol = Color.FromArgb(Convert.ToInt32(RGB.ElementAt(0)), Convert.ToInt32(RGB.ElementAt(1)), Convert.ToInt32(RGB.ElementAt(2))); // distance int currentDist = Math.Abs(cCol.R - currentColor.R) + Math.Abs(cCol.G - currentColor.G) + Math.Abs(cCol.B - currentColor.B); if (currentDist < bestDist) { bestDist = currentDist; bestIndex = i; } } votes[bestIndex]++; } } // this is faster than LINQ int m = -1; int ans = 0; for (int i = 0; i < votes.Length; i++) { if (votes[i] > m) { m = votes[i]; ans = i; } } return(statReference.ElementAt(ans).Key); }
/// <summary> /// get the red channel as array /// </summary> /// <param name="Img">image</param> /// <returns>array[] of red channel</returns> static public uint[,] ExtractRedChannel(ImageData Img) { uint[,] red = new uint[Img.Width, Img.Height]; for (Int32 column = 0; column < Img.Width; column++) { for (Int32 row = 0; row < Img.Height; row++) { Color c = Img.GetPixel(column, row); red[column, row] = c.R; } } return(red); }
/// <summary> /// Finds all pixels matching a specified color /// </summary> /// <example> /// <code> /// <![CDATA[ /// List<Point> WaterPixel = CommonFunctions.FindColors(ScreenShot.create(),Color.Blue,20); /// ]]> /// </code> /// </example> /// <param name="img">The image to look in</param> /// <param name="searchColor">The color to look for</param> /// <param name="tolerance">The tolerance to use</param> /// <returns></returns> public static List <Point> FindColors(ImageData img, Color searchColor, uint tolerance) { var collection = new List <Point>(); for (int column = 0; column < img.Width; column++) { for (int row = 0; row < img.Height; row++) { if (ColorsSimilar(img.GetPixel(column, row), searchColor, tolerance)) { collection.Add(new Point(column, row)); } } } return(collection); }
/// <summary> /// find first occurence of color with tolerance /// </summary> /// <param name="Img">image to look in</param> /// <param name="SearchColor">color to look for</param> /// <param name="Tolerance">tolerance</param> /// <returns></returns> static public bool[,] FindColors(ImageData Img, Color SearchColor, uint Tolerance) { bool[,] grid = new bool[Img.Width, Img.Height]; for (Int32 column = 0; column < Img.Width; column++) { for (Int32 row = 0; row < Img.Height; row++) { if (CommonFunctions.ColorsSimilar(Img.GetPixel(column, row), SearchColor, Tolerance)) { grid[column, row] = true; } else { grid[column, row] = false; } } } return(grid); }
/// <summary> /// Finds all pixels matching a specified color /// /accelerated/ /// </summary> /// <remarks> /// this function skips in both dimension (x and y) a predefined amount of pixels in each iteration. /// You can use this function to test every n-th pixel /// </remarks> /// <param name="img">The image to look in</param> /// <param name="searchColor">The color to look for</param> /// <param name="skipX">The X pixels to skip each time</param> /// <param name="skipY">The Y pixels to skip each time</param> /// <param name="tolerance">The tolerance to use</param> /// <returns></returns> public static List <Point> FindColors(ImageData img, Color searchColor, uint tolerance, int skipX = 1, int skipY = 1) { if (skipX < 1 && skipY < 1) { return(null); // Cannot be non-positive numbers } var collection = new List <Point>(); for (int column = 0; column < img.Width; column = column + skipX) { for (int row = 0; row < img.Height; row = row + skipY) { if (ColorsSimilar(img.GetPixel(column, row), searchColor, tolerance)) { collection.Add(new Point(column, row)); } } } return(collection); }
/// <summary> /// Gets the average RGB values from a given rectangle in an image /// By default the average RGB values from the whole image are calculated /// </summary> /// <remarks> /// to detect the color of bubbles or coins this function can be helpful in connection with IdentifyColor() /// </remarks> /// <example> /// <code> /// <![CDATA[ /// ImageData Img = new ImageData(...); /// // average color in whole image /// double[] AverageColor = CommonFunctions.AverageRGBValues(img); /// int left = 0; /// int top = 5; /// // average color in clipped image /// double[] AverageColorShifted = CommonFunctions.AverageRGBValues(img,left,top); /// int width = 50; /// int height = 100; /// // average color in predefined rectangle /// double[] AverageColorRectangle = CommonFunctions.AverageRGBValues(img,left,top,width,height); /// ]]> /// </code> /// </example> /// <param name="img">The image to process</param> /// <param name="left">The left of the rectangle (default=0)</param> /// <param name="top">The top of the rectangle (default=0)</param> /// <param name="width">The width of the rectangle (default=full width)</param> /// <param name="height">The height of the rectangle (default=full height)</param> /// <returns>The average RGB values</returns> public static double[] AverageRGBValues(ImageData img, int left = 0, int top = 0, int width = -1, int height = -1) { long[] totals = {0, 0, 0}; if (width == -1) width = img.Width; if (height == -1) height = img.Height; for (int x = left; x < left + width; x++) { for (int y = top; y < top + height; y++) { Color currentColor = img.GetPixel(x, y); totals[0] += currentColor.R; totals[1] += currentColor.G; totals[2] += currentColor.B; } } int count = width*height; double[] retvar = {(totals[0]/(double) count), (totals[1]/(double) count), (totals[2]/(double) count)}; return retvar; }
/// <summary> /// Calculates the similarity of image "img" in a given rectangle and a reference image "reference" /// </summary> /// <example> /// <code> /// <![CDATA[ /// ImageData Screenshot = new ImageData(...); /// ImageData Coin = new ImageData(...); /// // do magic or using a clipped region of screenshot (500px from left and 100px from top) /// int left_region = 500; /// int top_region = 100; /// double measure = Similarity(Screenshot,Coin,left_region,top_region); /// ]]> /// </code> /// </example> /// <param name="img">Image A</param> /// <param name="reference">Image B</param> /// <param name="left">The offset from left of image A</param> /// <param name="top">The offset from top of image A</param> /// <param name="width">The width of the rectangle (default: full width)</param> /// <param name="height">The height of the rectangle (default: full height)</param> /// <param name="offsetLeft">The left offset</param> /// <param name="offsetTop">The top offset</param> /// <returns>The similarity result (1=exact, 0=none)</returns> public static double Similarity(ImageData img, ImageData reference, int left = 0, int top = 0, int width = -1, int height = -1, int offsetLeft = 0, int offsetTop = 0) { double sim = 0.0; width = (width == -1) ? img.Width - left : width; height = (height == -1) ? img.Height - top : height; if ((img.Width == reference.Width) && (img.Height == reference.Height)) { for (Int32 column = left; column < left + width; column++) { for (Int32 row = top; row < top + height; row++) { Color a = img.GetPixel(offsetLeft + column, offsetTop + row); Color b = reference.GetPixel(column, row); int cr = Math.Abs(a.R - b.R); int cg = Math.Abs(a.G - b.G); int cb = Math.Abs(a.B - b.B); sim += (cr + cg + cb)/3; //TODO: Fix possible loss of fraction } } sim /= 255.0; sim /= (img.Height*img.Width); } return 1 - sim; }
/// <summary> /// Get the pattern of the magics match sticks /// </summary> /// <param name="Image">image of character</param> /// <returns>pattern</returns> public float[] GetMagicMatchSticksState(ImageData Image) { int Width = Image.Width; // width of image int Height = Image.Height; // height of image int n = Num(); // num of magicsticks float[] Pattern = new float[n]; // state int lastx = -1, lasty = -1; int tmpx = -1, tmpy = -1; for (int i = 0; i < n; i++) { Pattern[i] = 0.0f; } for (int y = 0; y < Height; y++) { for (int x = 0; x < Width; x++) { // is the pixel black? if (Image.GetPixel(x, y).R == 0) { tmpx = Convert.ToInt16(x * 100 / Width); tmpy = Convert.ToInt16(y * 100 / Height); if ((tmpx != lastx) || (tmpy != lasty)) { lastx = tmpx; lasty = tmpy; for (int i = 0; i < n; i++) { // skip already activated receptors if (Pattern[i] == 1.0f) continue; if (MagicStickList[i].GetMagicMatchStickState(tmpx, tmpy)) Pattern[i] = 1.0f; } } } } } return Pattern; }
/// <summary> /// Finds all pixels matching a specified color /// /accelerated/ /// </summary> /// <remarks> /// this function skips in both dimension (x and y) a predefined amount of pixels in each iteration. /// You can use this function to test every n-th pixel /// </remarks> /// <param name="img">The image to look in</param> /// <param name="searchColor">The color to look for</param> /// <param name="skipX">The X pixels to skip each time</param> /// <param name="skipY">The Y pixels to skip each time</param> /// <param name="tolerance">The tolerance to use</param> /// <returns></returns> public static List<Point> FindColors(ImageData img, Color searchColor, uint tolerance, int skipX = 1, int skipY = 1) { if (skipX < 1 && skipY < 1) return null; // Cannot be non-positive numbers var collection = new List<Point>(); for (int column = 0; column < img.Width; column = column + skipX) { for (int row = 0; row < img.Height; row = row + skipY) { if (ColorsSimilar(img.GetPixel(column, row), searchColor, tolerance)) { collection.Add(new Point(column, row)); } } } return collection; }
/// <summary> /// Identifies the colors of the pixels in a rectangle and compares them with those from an image by a given list of /// reference colors (majority vote) /// </summary> /// <remarks> /// This tests every pixel in the given rectangle and majority votes the color from the given dictionary of possible /// colors. Each pixel votes for a color. /// /// if the image patch is /// /// " red red " /// " red blue " /// /// then 4 pixels vote for similary colors to red and one pixel votes for a similar color to blue /// /// </remarks> /// <example> /// <code> /// <![CDATA[ /// ImageData Screenshot = new ImageData(...); /// Dictionary<Color, List<double>> Choose = new Dictionary<Color, List<double>> (); /// Choose.Add(Color.Red, new List<double> { 255, 144.23, 140.89 }); /// Choose.Add(Color.White, new List<double> { 218, 219, 222 }); /// Choose.Add(Color.Blue, new List<double> { 21, 108, 182 }); /// Choose.Add(Color.Green, new List<double> { 86, 191, 50 }); /// Choose.Add(Color.Yellow, new List<double> { 233, 203, 118 }); /// Choose.Add(Color.Orange, new List<double> { 246, 122, 11 }); /// Choose.Add(Color.Black, new List<double> { 94, 98, 98 }); /// Choose.Add(Color.Violet, new List<double> { 223, 80, 195 }); /// Choose.Add(Color.MediumSeaGreen, new List<double> { 106, 227, 216 }); /// // ... /// Color PieceColor = CommonFunctions.IdentifyColorByVoting(Screenshot,Choose,leftoffset,topoffset,width,height); /// ]]> /// </code> /// </example> /// <param name="img">The image to look in</param> /// <param name="statReference">The list of possible colors</param> /// <param name="left">The left of the rectangle (default: 0)</param> /// <param name="top">The top of the rectangle (default: 0)</param> /// <param name="width">The width of the rectangle (default: full width)</param> /// <param name="height">The height of the rectangle (default: full height)</param> /// <returns>The best matching color</returns> public static Color IdentifyColorByVoting(ImageData img, Dictionary<Color, List<double>> statReference, int left = 0, int top = 0, int width = -1, int height = -1) { int[] votes = Enumerable.Repeat(0, statReference.Count).ToArray(); if (width == -1) width = img.Width; if (height == -1) height = img.Height; for (int x = left; x < left + width; x++) { for (int y = top; y < top + height; y++) { // color from image Color currentColor = img.GetPixel(x, y); int bestDist = 255*50; int bestIndex = 0; for (int i = 0; i < statReference.Count; i++) { List<double> RGB = statReference.ElementAt(i).Value; // from from dictionary Color cCol = Color.FromArgb(Convert.ToInt32(RGB.ElementAt(0)), Convert.ToInt32(RGB.ElementAt(1)), Convert.ToInt32(RGB.ElementAt(2))); // distance int currentDist = Math.Abs(cCol.R - currentColor.R) + Math.Abs(cCol.G - currentColor.G) + Math.Abs(cCol.B - currentColor.B); if (currentDist < bestDist) { bestDist = currentDist; bestIndex = i; } } votes[bestIndex]++; } } // this is faster than LINQ int m = -1; int ans = 0; for (int i = 0; i < votes.Length; i++) { if (votes[i] > m) { m = votes[i]; ans = i; } } return statReference.ElementAt(ans).Key; }
/// <summary> /// Finds all pixels matching a specified color /// </summary> /// <example> /// <code> /// <![CDATA[ /// List<Point> WaterPixel = CommonFunctions.FindColors(ScreenShot.create(),Color.Blue,20); /// ]]> /// </code> /// </example> /// <param name="img">The image to look in</param> /// <param name="searchColor">The color to look for</param> /// <param name="tolerance">The tolerance to use</param> /// <returns></returns> public static List<Point> FindColors(ImageData img, Color searchColor, uint tolerance) { var collection = new List<Point>(); for (int column = 0; column < img.Width; column++) { for (int row = 0; row < img.Height; row++) { if (ColorsSimilar(img.GetPixel(column, row), searchColor, tolerance)) { collection.Add(new Point(column, row)); } } } return collection; }
/// <summary> /// Retrieves the red channel as an array /// </summary> /// <param name="img">image</param> /// <returns>The red channel as an array</returns> public static uint[,] ExtractRedChannel(ImageData img) { var red = new uint[img.Width, img.Height]; for (Int32 column = 0; column < img.Width; column++) { for (Int32 row = 0; row < img.Height; row++) { Color c = img.GetPixel(column, row); red[column, row] = c.R; } } return red; }
/// <summary> /// find first occurence of color with tolerance /// </summary> /// <param name="Img">image to look in</param> /// <param name="SearchColor">color to look for</param> /// <param name="Tolerance">tolerance</param> /// <returns></returns> public static bool[,] FindColors(ImageData Img, Color SearchColor, uint Tolerance) { bool[,] grid = new bool[Img.Width, Img.Height]; for (Int32 column = 0; column < Img.Width; column++) { for (Int32 row = 0; row < Img.Height; row++) { if (CommonFunctions.ColorsSimilar(Img.GetPixel(column, row), SearchColor, Tolerance)) { grid[column, row] = true; } else { grid[column, row] = false; } } } return grid; }
/// <summary> /// calculate the similarity of image A in a given rectangle and a reference image B /// </summary> /// <param name="Img">image A</param> /// <param name="Reference">image B</param> /// <param name="Left">offset from left of image A</param> /// <param name="Top">offset from top of image A</param> /// <param name="Width">width of rectangle (default: full width)</param> /// <param name="Height">height of rectangle (default: full height)</param> /// <returns>similarity (1=exact,0=none)</returns> public static double Similarity(ImageData Img, ImageData Reference, int Left = 0, int Top = 0, int Width = -1, int Height = -1, int OffsetLeft = 0, int OffsetTop = 0) { double sim = 0.0; Width = (Width == -1) ? Img.Width - Left : Width; Height = (Height == -1) ? Img.Height - Top : Height; if ((Img.Width == Reference.Width) && (Img.Height == Reference.Height)) { for (Int32 column = Left; column < Left + Width; column++) { for (Int32 row = Top; row < Top + Height; row++) { Color a = Img.GetPixel(OffsetLeft + column, OffsetTop + row); Color b = Reference.GetPixel(column, row); int cr = Math.Abs(a.R - b.R); int cg = Math.Abs(a.G - b.G); int cb = Math.Abs(a.B - b.B); sim += (cr + cg + cb) / 3; } } sim /= 255.0; sim /= (Img.Height * Img.Width); } return 1 - sim; }
/// <summary> /// identify the color of a part(rectangle) from an image by a given list of reference colors (majority vote) /// </summary> /// <remarks> /// this tests every pixel in the given rectangle and majority votes the color from the given dictionary of possible colors /// </remarks> /// <param name="Img">image to look in</param> /// <param name="statReference">list of possible colors</param> /// <param name="Left">left of rectangle (default: 0)</param> /// <param name="Top">top of rectangle (default: 0)</param> /// <param name="Width">width of rectangle (default: full width)</param> /// <param name="Height">height of rectangle (default: full height)</param> /// <returns>Color</returns> public static Color IdentifyColorByVoting(ImageData Img, Dictionary<Color, List<double>> statReference, int Left = 0, int Top = 0, int Width = -1, int Height = -1) { double[] av = CommonFunctions.AverageRGBValues(Img, Left, Top, Width, Height); Color Foo = Color.White; int[] votes = Enumerable.Repeat(0, statReference.Count).ToArray(); if (Width == -1) Width = Img.Width; if (Height == -1) Height = Img.Height; for (int x = Left; x < Left + Width; x++) { for (int y = Top; y < Top + Height; y++) { // color from image Color CurrentColor = Img.GetPixel(x, y); int best_dist = 255*50; int best_idx = 0; for (int i = 0; i < statReference.Count;i++ ) { List<double> RGB = statReference.ElementAt(i).Value; // from from dictionary Color CCol = Color.FromArgb(Convert.ToInt32(RGB.ElementAt(0)), Convert.ToInt32(RGB.ElementAt(1)), Convert.ToInt32(RGB.ElementAt(2))); // distance int current_dist = Math.Abs(CCol.R - CurrentColor.R) + Math.Abs(CCol.G - CurrentColor.G) + Math.Abs(CCol.B - CurrentColor.B); if (current_dist < best_dist) { best_dist = current_dist; best_idx = i; } } votes[best_idx]++; } } // this is faster than LINQ int m=-1; int ans = 0; for (int i=0;i<votes.Length;i++) { if(votes[i]>m){ m=votes[i]; ans=i; } } return statReference.ElementAt(ans).Key; }