Fast IFS using RPN notation
python
c
x86-64
nasm
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.

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import random
  2. import copy
  3. import numpy as np
  4. from skimage.restoration import estimate_sigma
  5. from .expr import *
  6. from .fractdim import *
  7. alpha=32
  8. calpha = lambda n, c=255, a=10: -int(((c*a/255)-c)*(1-(1-a/255)**n))
  9. calphas = [[calpha(i, c, alpha) for i in range(0x1000)]
  10. for c in range(256)]
  11. class IFS2(object):
  12. """ @brief 1 Variable IFS with X,Y decomposition """
  13. #height=width=1024
  14. height=width=512
  15. def __init__(self, nexpr=4, init_sz=1, world=None, alpha=16):
  16. self._alpha = alpha
  17. self._nexpr = nexpr
  18. self._expr = [RpnExpr(sz=init_sz, nvar=1)
  19. for _ in range(nexpr)]
  20. self._world = world
  21. if self._world is None:
  22. self._world = self.get_world()
  23. #self._position = [random.randint(0, self.height-1),
  24. # random.randint(0, self.width-1)]
  25. self._position = [self.height//2, self.width//2]
  26. @classmethod
  27. def get_world(cls):
  28. return np.zeros((cls.height,cls.width), dtype=np.uint32)
  29. def raz_world(self):
  30. for i in range(self.height):
  31. for j in range(self.width):
  32. self._world[i][j] = 0
  33. def __str__(self):
  34. return ";".join([str(e) for e in self._expr])
  35. def __copy__(self):
  36. ret = IFS2(nexpr=self._nexpr, world=self._world)
  37. ret._expr = [copy.copy(e) for e in self._expr]
  38. #ret._world = copy.deepcopy(self._world)
  39. return ret
  40. def mutation(self, n=1, rand=True):
  41. n = 1 if n <= 1 else random.randint(1,n)
  42. for _ in range(n):
  43. random.choice(self._expr).mutation()
  44. def step(self):
  45. arg = self._position[0]
  46. arg <<=32
  47. arg += self._position[1]
  48. ret = int(random.choice(self._expr).eval(arg))
  49. self._position[1] = (ret & 0xFFFFFFFF)%self.width
  50. ret >>= 32
  51. self._position[0] = (ret & 0xFFFFFFFF)%self.height
  52. self._world[self._position[0]][self._position[1]] += 1
  53. def get_image(self, color=(0,0xFF,0x0)):
  54. return np.array([[[calpha(n, c, self._alpha) if n and c else 0 for c in color]
  55. for n in line]
  56. for line in self._world], dtype=np.uint8)
  57. def score(self):
  58. #maxi = self._world.max()
  59. #mini = self._world.min()
  60. #gray = np.array((self._world - mini)/(maxi-mini)*255, dtype=np.uint8)
  61. gray = np.array([[calpha(n, 255, self._alpha) if n else 0
  62. for n in line]
  63. for line in self._world], dtype=np.uint8)
  64. sigma = estimate_sigma(gray, multichannel=False, average_sigmas=True)
  65. sigma = 0 if np.isnan(sigma) else sigma
  66. score = fractal_dimension(gray, 128)
  67. if sigma and sigma > 5:
  68. score /= sigma/5
  69. return score