Last active
August 13, 2024 10:35
-
-
Save rougier/e5eafc276a4e54f516ed5559df4242c0 to your computer and use it in GitHub Desktop.
Fractal dimension computing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# ----------------------------------------------------------------------------- | |
# 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 scipy.misc | |
import numpy as np | |
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] | |
I = scipy.misc.imread("sierpinski.png")/256.0 | |
print("Minkowski–Bouligand dimension (computed): ", fractal_dimension(I)) | |
print("Haussdorf dimension (theoretical): ", (np.log(3)/np.log(2))) |
Hi delton137!
I used another simple line that I generated, and then with altering the number of boxes, and then after iterating and computing the mean, I believe I got a better estimate. For this other curve, the box-count dimension was 1.06 ish. And it was well within the 95% CI range when I compared it to the FD from the one measured by the software.
I think I hopefully solved my own problem. I came across some papers re: optimal sizes of boxes. I will need to see how to implement that!
Also, I saw that you are also working in medical imaging. It is very inspiring to see interest in fractals and medical imaging. I am but a mere medical student currently, I hope to see a lot more fractals in the future, and a lot more collaboration!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
FWIW the calculation is approximate.. also look at my comment above, there might still be a subtle issue with this code.