komiamiko

Nearest Blend - Colour Manipulation Filter

May 5th, 2021
791
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. # imports
  2. from PIL import Image
  3. import numpy as np
  4. import numpy.linalg as npl
  5.  
  6. # filter
  7. def nearest_blend(filepath, palette, proxy_palette=None, blend_factor=0.2):
  8.     # if separate proxy palette is not provided, use same as actual palette
  9.     if proxy_palette is None:
  10.         proxy_palette = palette
  11.     # convert palettes
  12.     palette = np.array(palette)
  13.     nt, _ = palette.shape
  14.     palette = palette.reshape((1, 1, nt, 3))
  15.     proxy_palette = np.array(proxy_palette).reshape((1, 1, nt, 3))
  16.     # load the image
  17.     im = Image.open(filepath)
  18.     pix = np.array(im)
  19.     # remove alpha channel, if any
  20.     pix = pix[:,:,0:3]
  21.     # get image size
  22.     ny, nx, _ = pix.shape
  23.     # reshape image to (Y, X, tone, channel)
  24.     pix = pix.reshape((ny, nx, 1, 3))
  25.     # use float type
  26.     pix = np.array(pix, dtype=np.float32)
  27.     # compute distances using proxy palette
  28.     proxy_delta = pix - proxy_palette
  29.     proxy_dist = npl.norm(proxy_delta, axis=3, keepdims=True) # (Y, X, T, 1)
  30.     # softmin
  31.     proxy_xdist = np.exp(-proxy_dist*blend_factor)
  32.     proxy_xmul = 1/np.sum(proxy_xdist, axis=2, keepdims=True) # (Y, X, 1, 1)
  33.     weights = proxy_xdist * proxy_xmul # (Y, X, T, 1)
  34.     # blend
  35.     newpix = weights * palette # (Y, X, T, 3)
  36.     newpix = np.sum(newpix, axis=2) # (Y, X, 3)
  37.     newpix = np.round(newpix)
  38.     newpix = np.maximum(0, newpix)
  39.     newpix = np.minimum(255, newpix)
  40.     newpix = np.array(newpix, dtype=np.uint8)
  41.     # save image
  42.     newim = Image.fromarray(newpix)
  43.     newim.save(filepath+'.nb.png')
  44.  
  45. # flag conversion utilities
  46. def hex_to_array(s):
  47.     return np.array([int(s[i:i+2],16) for i in range(0, len(s), 2)])
  48.  
  49. def flag_hex_to_array(s):
  50.     return np.array(list(map(hex_to_array,s.strip().split())))
  51.  
  52. # sample palettes
  53. nonbinary = flag_hex_to_array('2c2c2c 9c59d1 fcfcfc fcf434')
  54. genderfluid = flag_hex_to_array('333ebd 000000 be18d6 ffffff ff75a2')
  55. aroace = flag_hex_to_array('223756 62aedd ffffff eccd00 e28d00')
  56. bigender = flag_hex_to_array('6c83cf 9ac7e8 d5c7e8 ffffff eca6cb c479a0')
  57. bigender_ext = flag_hex_to_array('000000 6c83cf 9ac7e8 d5c7e8 ffffff eca6cb c479a0')
  58. bigender_ext_proxy = flag_hex_to_array('000000 115f5f 3197cd bd99f7 ffffff dd5f76 72510d')
  59. lesbian = flag_hex_to_array('a30262 d362a4 ffffff ff9a56 d52d00')
  60. lesbian_ext = flag_hex_to_array('a30262 d362a4 ffffff ff9a56 d52d00 000000')
  61. lesbian_ext_proxy = flag_hex_to_array('3c3f9a d362a4 ffffff ff9a56 485f10 000000')
  62. agender = flag_hex_to_array('b8f483 ffffff b9b9b9 000000')
  63. agender_proxy = flag_hex_to_array('7dc242 ffffff b7224c 000000')
  64.  
  65. # sample usage
  66. nearest_blend('test.png', nonbinary)
  67. nearest_blend('test.png', nonbinary, blend_factor=0.03)
  68. nearest_blend('test.png', aroace)
  69. nearest_blend('test.png', bigender)
  70. nearest_blend('test.png', bigender, blend_factor=0.03)
  71. nearest_blend('test.png', bigender_ext)
  72. nearest_blend('test.png', bigender_ext, blend_factor=0.03)
  73. nearest_blend('test.png', bigender_ext, bigender_ext_proxy)
  74. nearest_blend('test.png', bigender_ext, bigender_ext_proxy, blend_factor=0.03)
  75. nearest_blend('test.png', lesbian)
  76. nearest_blend('test.png', lesbian, blend_factor=0.03)
  77. nearest_blend('test.png', lesbian_ext)
  78. nearest_blend('test.png', lesbian_ext, blend_factor=0.03)
  79. nearest_blend('test.png', lesbian_ext, lesbian_ext_proxy)
  80. nearest_blend('test.png', lesbian_ext, lesbian_ext_proxy, blend_factor=0.03)
  81. nearest_blend('test.png', genderfluid)
  82. nearest_blend('test.png', genderfluid, blend_factor=0.03)
  83. nearest_blend('test.png', agender)
  84. nearest_blend('test.png', agender, agender_proxy, blend_factor=0.03)
RAW Paste Data