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.

ifs3.py 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import random
  2. import time
  3. import copy
  4. import numpy as np
  5. from skimage.restoration import estimate_sigma
  6. from .expr import *
  7. from .fractdim import *
  8. class IFS3(object):
  9. """ @brief 1 Variable IFS with R,G,B,A X,Y decomposition """
  10. #height=width=1024
  11. height=width=768
  12. #height=width=512
  13. def __init__(self, nexpr=4, init_sz=1, world=None):
  14. self._nexpr = nexpr
  15. self._expr = [RpnExpr(sz=init_sz, nvar=1)
  16. for _ in range(nexpr)]
  17. self._world = world
  18. if self._world is None:
  19. self._world = self.get_world()
  20. self._position = [random.randint(0, self.height-1),
  21. random.randint(0, self.width-1)]
  22. @classmethod
  23. def get_world(cls):
  24. return np.zeros((cls.height,cls.width,4), dtype=np.uint8)
  25. def raz_world(self):
  26. for i in range(self.height):
  27. for j in range(self.width):
  28. self._world[i][j] = [0,0,0,0]
  29. def __str__(self):
  30. return ";".join([str(e) for e in self._expr])
  31. def __copy__(self):
  32. ret = IFS3(nexpr=self._nexpr, world=self._world)
  33. ret._expr = [copy.copy(e) for e in self._expr]
  34. #ret._world = copy.deepcopy(self._world)
  35. return ret
  36. def get_image(self):
  37. return self._world
  38. def mutation(self, n=1, rand=True):
  39. n = 1 if n <= 1 else random.randint(1,n)
  40. for _ in range(n):
  41. random.choice(self._expr).mutation()
  42. def step(self):
  43. r,g,b,a = [int(e)
  44. for e in self._world[self._position[0]][self._position[1]]]
  45. arg = r
  46. arg <<= 8
  47. arg += g
  48. arg <<= 8
  49. arg += b
  50. arg <<= 8
  51. arg += a
  52. arg <<=16
  53. arg += self._position[0]
  54. arg <<=16
  55. arg += self._position[1]
  56. ret = int(random.choice(self._expr).eval(arg))
  57. dr, dg, db, da = r,g,b,a
  58. #self._position[1] = (ret & 0xFFFF)%self.width
  59. self._position[1] = ((ret & 0xFFFF)*self.width)//0x10000
  60. ret >>= 16
  61. self._position[0] = ((ret & 0xFFFF)*self.height)//0x10000
  62. ret >>= 16
  63. a = ret & 0xFF
  64. ret >>= 8
  65. b = ret & 0xFF
  66. ret >>= 8
  67. g = ret & 0xFF
  68. ret >>= 8
  69. r = ret & 0xFF
  70. sa = a/255
  71. outa = (a + da*(1-sa))/255
  72. if outa == 0:
  73. ro,go,bo = 0,0,0
  74. else:
  75. ro, go, bo = [(c*(a/255)+dc*da*(1-sa))/outa
  76. for c, dc in ((r,dr), (g, dg), (b, db))]
  77. r,g,b,a = [int(e) for e in (ro,go,bo,outa*255)]
  78. self._world[self._position[0]][self._position[1]] = [r,g,b,a]
  79. def score(self):
  80. start = time.time()
  81. colcount = len(np.unique(np.reshape(self._world[:,:,:3], (-1,3)),
  82. axis=0))
  83. #sigma = estimate_sigma(self._world, multichannel=True, average_sigmas=True)
  84. sigmas = estimate_sigma(self._world[:,:,:3], multichannel=True,
  85. average_sigmas=False)
  86. scores = [fractal_dimension(self._world[:,:,i]*self._world[:,:,3]/255)
  87. for i in range(3)]
  88. #alpha score
  89. #scores += [fractal_dimension(self._world[:,:,3])]
  90. gray = rgb2gray(self._world)
  91. graysigma = estimate_sigma(gray)
  92. grayscore = fractal_dimension(gray)
  93. del(gray)
  94. sigmas += [graysigma]*3
  95. sigmas = [0 if np.isnan(sigma) else sigma for sigma in sigmas]
  96. scores += [grayscore]*3
  97. sigma = sum(sigmas)/len(sigmas)
  98. mod = abs(scores[0]-scores[1])
  99. mod += abs(scores[0]-scores[2])
  100. mod += abs(scores[0]-scores[3])
  101. mod += abs(scores[1]-scores[2])
  102. mod += abs(scores[1]-scores[3])
  103. mod /= 5
  104. score = sum(scores)/len(scores)
  105. score += mod
  106. if sigma and sigma > 0:
  107. score -= sigma/100
  108. colscore = abs(colcount-1024) / 1e5
  109. score -= colscore
  110. printscore = lambda arr: '['+(', '.join(['%1.3f' % e for e in arr]))+']'
  111. print("colscore %3.3f (%4d colors) scores time %5.2fs" % (colscore,
  112. colcount,
  113. time.time() - start))
  114. print("SIGMAS : %s SIGMA : %f " % (printscore(sigmas), sigma))
  115. print("SCORES : %s SCORE : %r" % (printscore(scores), score))
  116. return score