Morphology.cs 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using PixiEditor.Models.Position;
  5. namespace PixiEditor.Models.ImageManipulation
  6. {
  7. public class Morphology
  8. {
  9. public static Coordinates[] ApplyDilation(Coordinates[] points, int kernelSize, int[,] mask)
  10. {
  11. int kernelDim = kernelSize;
  12. //This is the offset of center pixel from border of the kernel
  13. int kernelOffset = (kernelDim - 1) / 2;
  14. int margin = kernelDim;
  15. byte[,] byteImg = GetByteArrayForPoints(points, margin);
  16. byte[,] outputArray = byteImg.Clone() as byte[,];
  17. Coordinates offset = new Coordinates(points.Min(x => x.X) - margin, points.Min(x => x.Y) - margin);
  18. int width = byteImg.GetLength(0);
  19. int height = byteImg.GetLength(1);
  20. for (int y = kernelOffset; y < height - kernelOffset; y++)
  21. for (int x = kernelOffset; x < width - kernelOffset; x++)
  22. {
  23. byte value = 0;
  24. //Apply dilation
  25. for (int ykernel = -kernelOffset; ykernel <= kernelOffset; ykernel++)
  26. for (int xkernel = -kernelOffset; xkernel <= kernelOffset; xkernel++)
  27. if (mask[xkernel + kernelOffset, ykernel + kernelOffset] == 1)
  28. value = Math.Max(value, byteImg[x + xkernel, y + ykernel]);
  29. else
  30. continue;
  31. //Write processed data into the second array
  32. outputArray[x, y] = value;
  33. }
  34. return ToCoordinates(outputArray, offset).Distinct().ToArray();
  35. }
  36. private static Coordinates[] ToCoordinates(byte[,] byteArray, Coordinates offset)
  37. {
  38. List<Coordinates> output = new List<Coordinates>();
  39. int width = byteArray.GetLength(0);
  40. for (int y = 0; y < byteArray.GetLength(1); y++)
  41. for (int x = 0; x < width; x++)
  42. if (byteArray[x, y] == 1)
  43. output.Add(new Coordinates(x + offset.X, y + offset.Y));
  44. return output.ToArray();
  45. }
  46. private static byte[,] GetByteArrayForPoints(Coordinates[] points, int margin)
  47. {
  48. Tuple<int, int> dimensions = GetDimensionsForPoints(points);
  49. int minX = points.Min(x => x.X);
  50. int minY = points.Min(x => x.Y);
  51. byte[,] array = new byte[dimensions.Item1 + margin * 2, dimensions.Item2 + margin * 2];
  52. //Debug.Write("----------\n");
  53. for (int y = 0; y < dimensions.Item2 + margin; y++)
  54. for (int x = 0; x < dimensions.Item1 + margin; x++)
  55. {
  56. Coordinates cords = new Coordinates(x + minX, y + minY);
  57. array[x + margin, y + margin] = points.Contains(cords) ? (byte) 1 : (byte) 0;
  58. }
  59. //for (int y = 0; y < array.GetLength(1); y++)
  60. //{
  61. // for (int x = 0; x < array.GetLength(0); x++)
  62. // {
  63. // Debug.Write($"{array[x, y]} ");
  64. // }
  65. // Debug.Write("\n");
  66. //}
  67. return array;
  68. }
  69. private static Tuple<int, int> GetDimensionsForPoints(Coordinates[] points)
  70. {
  71. int width = points.Max(x => x.X) - points.Min(x => x.X);
  72. int height = points.Max(x => x.Y) - points.Min(x => x.Y);
  73. return new Tuple<int, int>(width + 1, height + 1);
  74. }
  75. }
  76. }