Image manipulation/filter using pixelsort and canny edge detection. Based on opencv.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

120 lines
3.2KB

  1. import cv2
  2. import random
  3. def glitchsort(filename: str, outputname: str, lower_canny: int=100, higher_canny: int=200, sorting_length=0, vertical: bool=True):
  4. """
  5. Wrapper function for glitchsort_x and glitchsort_y
  6. :param filename:
  7. :param outputname:
  8. :param lower_canny:
  9. :param higher_canny:
  10. :param sorting_length:
  11. :param vertical:
  12. :return:
  13. """
  14. new_img = None
  15. if vertical:
  16. new_img = __glitchsort_x(filename, lower_canny, higher_canny, sorting_length)
  17. else:
  18. new_img = __glitchsort_y(filename, lower_canny, higher_canny, sorting_length)
  19. print("Writing output...")
  20. cv2.imwrite(outputname, new_img)
  21. print("Done!")
  22. def __glitchsort_x(filename: str, lower_canny: int=100, higher_canny: int=200, sorting_length=0):
  23. """
  24. Apply pixel sorting to the given image using canny edge detection to stop sorting.
  25. Sorting length varies a bit averaging around sorting_length (0 for endless)
  26. :param filename:
  27. :param lower_canny:
  28. :param higher_canny:
  29. :param sorting_length:
  30. :return:
  31. """
  32. img = cv2.imread(filename)
  33. width, height, depth = img.shape
  34. canny = cv2.Canny(img, lower_canny, higher_canny)
  35. new_img = img.copy()
  36. print("Sorting...")
  37. for x in range(width): # search for first edge
  38. for y in range(height):
  39. if canny[x, y] == 255:
  40. length = int(sorting_length+random.randint(-1, 1)*0.3)
  41. pixelsort(img, new_img, x, y, dx=0, dy=-1, length=length)
  42. continue
  43. return new_img
  44. def __glitchsort_y(filename: str, lower_canny: int=100, higher_canny: int=200, sorting_length=0):
  45. """
  46. Apply pixel sorting to the given image using canny edge detection to stop sorting.
  47. Sorting length varies a bit averaging around sorting_length (0 for endless)
  48. :param filename:
  49. :param lower_canny:
  50. :param higher_canny:
  51. :param sorting_length:
  52. :return:
  53. """
  54. img = cv2.imread(filename)
  55. width, height, depth = img.shape
  56. canny = cv2.Canny(img, lower_canny, higher_canny)
  57. new_img = img.copy()
  58. print("Sorting...")
  59. for y in range(height): # search for first edge
  60. for x in range(width):
  61. if canny[x, y] == 255:
  62. length = int(sorting_length+random.randint(-1, 1)*0.3)
  63. pixelsort(img, new_img, x, y, dx=-1, dy=0, length=length)
  64. continue
  65. return new_img
  66. def pixelsort(img, new_img, x, y, dx=0, dy=1, length=-1):
  67. """
  68. Pixelsort from point (x,y) in direction (dx,dy) for length long (-1 means until end of picture).
  69. :param img:
  70. :param new_img:
  71. :param x:
  72. :param y:
  73. :param dx:
  74. :param dy:
  75. :return:
  76. """
  77. assert(dx != 0 or dy != 0)
  78. width, height, depth = img.shape
  79. pixels = []
  80. todo = length
  81. while todo is not 0:
  82. pixels.append([x, y])
  83. x += dx
  84. y += dy
  85. todo -= 1
  86. if x >= width or x <= 0 or y >= height or y <= 0: # ran out of bounds
  87. break
  88. def get_value(pixel):
  89. return img[pixel[0], pixel[1], 0]
  90. sorted_pixels = sorted(pixels, key=get_value)
  91. for i in range(len(pixels)):
  92. new_img[pixels[i][0], pixels[i][1]] = img[sorted_pixels[i][0], sorted_pixels[i][1]]