Skip to content

Instantly share code, notes, and snippets.

@caiofcm
Forked from rougier/fractal-dimension.py
Created January 18, 2021 17:54
Show Gist options
  • Save caiofcm/462f1177b7252df6755c5fc6a3ed1a7c to your computer and use it in GitHub Desktop.
Save caiofcm/462f1177b7252df6755c5fc6a3ed1a7c to your computer and use it in GitHub Desktop.
Fractal dimension computing
# -----------------------------------------------------------------------------
# From https://en.wikipedia.org/wiki/Minkowski–Bouligand_dimension:
#
# In fractal geometry, the Minkowski–Bouligand dimension, also known as
# Minkowski dimension or box-counting dimension, is a way of determining the
# fractal dimension of a set S in a Euclidean space Rn, or more generally in a
# metric space (X, d).
# -----------------------------------------------------------------------------
import cv2
import numpy as np
import imageio
def fractal_dimension(Z, threshold=0.9):
# Only for 2d image
assert(len(Z.shape) == 2)
# From https://github.com/rougier/numpy-100 (#87)
def boxcount(Z, k):
S = np.add.reduceat(
np.add.reduceat(Z, np.arange(0, Z.shape[0], k), axis=0),
np.arange(0, Z.shape[1], k), axis=1)
# We count non-empty (0) and non-full boxes (k*k)
return len(np.where((S > 0) & (S < k*k))[0])
# Transform Z into a binary array
Z = (Z < threshold)
# Minimal dimension of image
p = min(Z.shape)
# Greatest power of 2 less than or equal to p
n = 2**np.floor(np.log(p)/np.log(2))
# Extract the exponent
n = int(np.log(n)/np.log(2))
# Build successive box sizes (from 2**n down to 2**1)
sizes = 2**np.arange(n, 1, -1)
# Actual box counting with decreasing size
counts = []
for size in sizes:
counts.append(boxcount(Z, size))
# Fit the successive log(sizes) with log (counts)
coeffs = np.polyfit(np.log(sizes), np.log(counts), 1)
return -coeffs[0]
def main_01():
filename = 'Koch_curve2.png' #'sierpinski2.png' #'t02.jpg'
originalImage = cv2.imread(filename)
I = cv2.cvtColor(originalImage, cv2.COLOR_BGR2GRAY)/256.0
# Koch curve should be 1.26
EXPECTEDS = {
'koch': 1.26,
'sierpinski': 1.5849
}
Db = fractal_dimension(I, 0.9)
print("Minkowski–Bouligand dimension (computed): ", Db)
# print("Theoretical: ", (np.log(3)/np.log(2)))
return
if __name__ == "__main__":
main_01()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment