Measuring fractal dimension by box-counting#

Theory#

The term fractal dimension was introduced by Benoit Mandelbrot in 1967 to explain self-similarity of a pattern. A fractal dimension is defined as a ratio of the change in detail to the change in scale. It is used as an index that quantifies the complexity of a fractal pattern.

Famously, fractal dimensions have been used to analyze the length of the British coastline. A coastline’s measured length is observed to change depending on the length of the measuring stick used. In 2-D and 3-D, this notion can be extended to the length of a measuring pixel or voxel, respectively.

image

Box Counting Method#

One way to determine fractal dimension of an image is the box counting method. Boxes of various sizes are laid over the image in a fixed grid pattern. The number of boxes that span the edge of the pattern (i.e. partially 1 and partially 0) are tallied as a function of box size. This count is then used to calculate the fractal dimension .

Mathematical Definition#

The relationship of a pattern’s fractal dimension and its measuring element can be expressed as:

\[N \propto \frac{1}{D^F}\]
\[F = \lim_{D \to 0} \frac{-log N(D)}{log(D)}\]

where:

  • N: number of boxes of side D that span an edge

  • D: size of the boxes

  • F: fractal dimension

Example#

A Sierpinski carpet has a known fractal dimension of 1.8928. Performing the box counting method found its fractal dimension as approximately 1.8 ~ 1.9.

First, import the needed packages.

import matplotlib.pyplot as plt
import porespy as ps
ps.visualization.set_mpl_style()
[03:18:40] ERROR    PARDISO solver not installed, run `pip install pypardiso`. Otherwise,          _workspace.py:56
                    simulations will be slow. Apple M chips not supported.                                         

Generate a sierpinski carpet and visualize.

im = ps.generators.sierpinski_foam(4, 5)
plt.imshow(im);
../../../_images/336ab464d3423d71e465d9f3048fd0011ab3f947beead66503af7fd724be8a9d.png

Finally, apply the box count function and visualize.

data = ps.metrics.boxcount(im)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4))
ax1.set_yscale('log')
ax1.set_xscale('log')
ax1.set_xlabel('box edge length')
ax1.set_ylabel('number of boxes spanning phases')
ax2.set_xlabel('box edge length')
ax2.set_ylabel('slope')
ax2.set_xscale('log')
ax1.plot(data.size, data.count,'-o')
ax2.plot(data.size, data.slope,'-o');
../../../_images/52dcd211f4c0fce40aea49755e77d016eaf3924e6b2b33a68f64f1fc6a9376ff.png

The horizontal portion of the slope vs box edge length curve, between \(10^1\) and \(10^2\) is a flat line with a value of approximately 1.9. Beyond a box edge length of \(10^2\) the analysis becomes impacted by the finite image size so the result begins to diverge.