import random import copy import numpy as np from skimage.restoration import estimate_sigma from .expr import * from .fractdim import * alpha=32 calpha = lambda n, c=255, a=10: -int(((c*a/255)-c)*(1-(1-a/255)**n)) calphas = [[calpha(i, c, alpha) for i in range(0x1000)] for c in range(256)] class IFS2(object): """ @brief 1 Variable IFS with X,Y decomposition """ #height=width=1024 height=width=512 def __init__(self, nexpr=4, init_sz=1, world=None, alpha=16): self._alpha = alpha self._nexpr = nexpr self._expr = [RpnExpr(sz=init_sz, nvar=1) for _ in range(nexpr)] self._world = world if self._world is None: self._world = self.get_world() #self._position = [random.randint(0, self.height-1), # random.randint(0, self.width-1)] self._position = [self.height//2, self.width//2] @classmethod def get_world(cls): return np.zeros((cls.height,cls.width), dtype=np.uint32) def raz_world(self): for i in range(self.height): for j in range(self.width): self._world[i][j] = 0 def __str__(self): return ";".join([str(e) for e in self._expr]) def __copy__(self): ret = IFS2(nexpr=self._nexpr, world=self._world) ret._expr = [copy.copy(e) for e in self._expr] #ret._world = copy.deepcopy(self._world) return ret def mutation(self, n=1, rand=True): n = 1 if n <= 1 else random.randint(1,n) for _ in range(n): random.choice(self._expr).mutation() def step(self): arg = self._position[0] arg <<=32 arg += self._position[1] ret = int(random.choice(self._expr).eval(arg)) self._position[1] = (ret & 0xFFFFFFFF)%self.width ret >>= 32 self._position[0] = (ret & 0xFFFFFFFF)%self.height self._world[self._position[0]][self._position[1]] += 1 def get_image(self, color=(0,0xFF,0x0)): return np.array([[[calpha(n, c, self._alpha) if n and c else 0 for c in color] for n in line] for line in self._world], dtype=np.uint8) def score(self): #maxi = self._world.max() #mini = self._world.min() #gray = np.array((self._world - mini)/(maxi-mini)*255, dtype=np.uint8) gray = np.array([[calpha(n, 255, self._alpha) if n else 0 for n in line] for line in self._world], dtype=np.uint8) sigma = estimate_sigma(gray, multichannel=False, average_sigmas=True) sigma = 0 if np.isnan(sigma) else sigma score = fractal_dimension(gray, 128) if sigma and sigma > 5: score /= sigma/5 return score