# IFS fractal dimension calculation using box-counting method # http://en.wikipedia.org/wiki/Iterated_function_system # http://en.wikipedia.org/wiki/Fractal_dimension # http://en.wikipedia.org/wiki/Box-counting_dimension # http://en.wikipedia.org/wiki/Simple_linear_regression # FB - 20120211 import math import random from PIL import Image imgx = 512 imgy = 512 # will be auto-re-adjusted according to aspect ratio of the fractal maxIt = imgx * imgy * 2 fractalName = "Barnsley Fern" mat=[[0.0, 0.0, 0.0, 0.16, 0.0, 0.0, 0.01], [0.85, 0.04, -0.04, 0.85, 0.0, 1.6, 0.85], [0.2, -0.26, 0.23, 0.22, 0.0, 1.6, 0.07], [-0.15, 0.28, 0.26, 0.24, 0.0, 0.44, 0.07]] ##fractalName = "Centipede" ##mat = [[0.824074, 0.281482, -0.212346, 0.864198, -1.882290, -0.110607, 0.787473], ## [0.088272, 0.520988, -0.463889, -0.377778, 0.785360, 8.095795, 0.212527]] ##fractalName = "Levy C curve" ##mat = [[0.5, -0.5, 0.5, 0.5, 0.0, 0.0, 0.5], ## [0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5]] ##fractalName = "Dragon curve" ##mat = [[0.5, -0.5, 0.5, 0.5, 0.0, 0.0, 0.5], ## [-0.5, -0.5, 0.5, -0.5, 1.0, 0.0, 0.5]] ##fractalName = "Sierpinski Triangle" ##mat = [[0.5, 0.0, 0.0, 0.5, 0.0, 0.0, 0.33], ## [0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.33], ## [0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.33]] ##fractalName = "Sierpinski Carpet" ##mat = [[0.333, 0.0, 0.0, 0.333, 0.000, 0.999, 0.125], ## [0.333, 0.0, 0.0, 0.333, 0.333, 0.999, 0.125], ## [0.333, 0.0, 0.0, 0.333, 0.666, 0.999, 0.125], ## [0.333, 0.0, 0.0, 0.333, 0.000, 0.666, 0.125], ## [0.333, 0.0, 0.0, 0.333, 0.666, 0.666, 0.125], ## [0.333, 0.0, 0.0, 0.333, 0.000, 0.333, 0.125], ## [0.333, 0.0, 0.0, 0.333, 0.333, 0.333, 0.125], ## [0.333, 0.0, 0.0, 0.333, 0.666, 0.333, 0.125]] m = len(mat) # number of IFS transformations # find xmin, xmax, ymin, ymax of the fractal using IFS algorithm x = mat[0][4] y = mat[0][5] xa = x xb = x ya = y yb = y for k in range(maxIt): i = random.randint(0, m - 1) if random.random() <= mat[i][6]: x0 = x * mat[i][0] + y * mat[i][1] + mat[i][4] y = x * mat[i][2] + y * mat[i][3] + mat[i][5] x = x0 if x < xa: xa = x if x > xb: xb = x if y < ya: ya = y if y > yb: yb = y imgy = int(imgy * (yb - ya) / (xb - xa)) # auto-re-adjust the aspect ratio image = Image.new("RGB", (imgx, imgy)) pixels = image.load() # drawing using IFS algorithm theColor = (255, 255, 255) x=0.0 y=0.0 for k in range(maxIt): i = random.randint(0, m - 1) if random.random() <= mat[i][6]: x0 = x * mat[i][0] + y * mat[i][1] + mat[i][4] y = x * mat[i][2] + y * mat[i][3] + mat[i][5] x = x0 jx = int((x - xa) / (xb - xa) * (imgx - 1)) jy = (imgy - 1) - int((y - ya) / (yb - ya) * (imgy - 1)) if jx >= 0 and jx < imgx and jy >= 0 and jy < imgy: pixels[jx, jy] = theColor image.save(fractalName + " fractal.png", "PNG") # fractal dimension calculation using box-counting method b = 2 # initial box size in pixels f = 2 # box scaling factor n = 3 # number of graph points for simple linear regression gx = [] # x coordinates of graph points gy = [] # y coordinates of graph points for ib in range(n): bs = b * f ** ib # box size in pixels bnx = int(imgx / bs) # of boxes in x direction of image bny = int(imgy / bs) # of boxes in y direction of image boxCount = 0 for by in range(bny): for bx in range(bnx): # if there are any pixels in the box then increase box count foundPixel = False for ky in range(bs): for kx in range(bs): if pixels[bs * bx + kx, bs * by + ky] == theColor: foundPixel = True boxCount += 1 break if foundPixel: break gx.append(math.log(1.0 / bs)) gy.append(math.log(boxCount)) # simple linear regression x_ = 0.0 y_ = 0.0 x2_ = 0.0 xy_ = 0.0 for j in range(n): x_ += gx[j] y_ += gy[j] x2_ += gx[j] ** 2 xy_ += gx[j] * gy[j] x_ = x_ / n y_ = y_ / n x2_ = x2_ / n xy_ = xy_ / n b = (xy_ - x_ * y_) / (x2_ - x_ ** 2) # slope of the regression line # a = y_ - b * x_ print "Fractal Name: " + fractalName print "Estimated Fractal Dimension: " + str(b)