【计算机图形】分形维数法介绍以及python实现

分形维数法概念

分形维数法是一种用于描述和分析复杂形状和结构的方法。这些形状和结构可能看起来很不规则或混乱,但实际上,它们在某种程度上有一定的规律性。分形维数帮助我们量化这种规律性和复杂性。

具体展开来说,分形就是几何形状,它的某些部分与整体相似,即使放大了看,部分的形状依然和整体类似。例如,雪花、海岸线和树木的分枝都是一种分形。
传统的维数有一维(线)、二维(平面)和三维(立体)。分形维数是一种非整数维数,用来描述那些复杂度介于这些传统维数之间的形状。例如,一个分形的维数可能是1.5或2.7,这表示它比一条线复杂,但还没有达到一个平面的复杂程度。

分形维数可以用来描述自然界中的各种复杂形态,如山脉的轮廓、云的形状、植物的生长模式等;在图像处理、信号分析和材料科学等领域,分形维数可以分析和理解复杂系统和数据。

分形维数有多种计算方法,其中一种常见的方法是盒子计数法,这种方法通过在不同尺度下计算覆盖分形所需的盒子数量来估算维数。

Python程序实现

import numpy as np
import matplotlib.pyplot as plt
from skimage import io, color, filters
from matplotlib.widgets import RectangleSelector
from osgeo import gdal


def differential_box_counting(img, min_box_size=5, num_boxes=20):
    assert len(img.shape) == 2
    img = (img - img.min()) / (img.max() - img.min())
    N = img.shape[0]
    sizes = np.logspace(np.log2(min_box_size), np.log2(N), num=num_boxes, base=2).astype(int)
    counts = []

    for size in sizes:
        reduced_image = measure_block_counting(img, size)
        counts.append(reduced_image)

    counts = np.array(counts)
    coeffs = np.polyfit(np.log(sizes), np.log(counts), 1)
    return -coeffs[0], sizes, counts


def measure_block_counting(Z, box_size):
    block_count = 0
    for i in range(0, Z.shape[0], box_size):
        for j in range(0, Z.shape[1], box_size):
            block = Z[i:i + box_size, j:j + box_size]
            if np.any(block):
                block_count += 1
    return block_count


def read_tif_image(image_path):
    dataset = gdal.Open(image_path)
    band = dataset.GetRasterBand(1)
    image = band.ReadAsArray()
    return image


class SelectRegion:
    def __init__(self, ax, img):
        self.ax = ax
        self.img = img
        self.rect_selector = RectangleSelector(ax, self.onselect, interactive=True)
        self.selected_region = None

    def onselect(self, eclick, erelease):
        x1, y1 = int(eclick.xdata), int(eclick.ydata)
        x2, y2 = int(erelease.xdata), int(erelease.ydata)
        self.selected_region = self.img[y1:y2, x1:x2]
        self.rect_selector.set_active(False)
        plt.close()


def main():
    img_path = 'img path'  # 替换为你的TIF文件路径
    img = read_tif_image(img_path)
    if img.ndim == 3 and img.shape[2] == 4:
        img = img[:, :, :3]
    if img.ndim == 3:
        img = color.rgb2gray(img)

    # 保存原图用于显示
    original_img = img.copy()

    # 边缘提取
    img = filters.sobel(img)

    fig, ax = plt.subplots(1, 1, figsize=(8, 8))
    ax.imshow(original_img, cmap='gray')  # 显示原图
    select_region = SelectRegion(ax, original_img)

    plt.show()

    if select_region.selected_region is not None:
        selected_img = select_region.selected_region

        # 使用预处理后的图像进行分形维数计算
        selected_processed_img = filters.sobel(selected_img)

        fd, sizes, counts = differential_box_counting(selected_processed_img, min_box_size=5, num_boxes=20)

        print(f'Fractal Dimension: {fd}')

        fig, axs = plt.subplots(1, 2, figsize=(12, 6))
        axs[0].imshow(selected_img, cmap='gray')  # 显示选定的原图区域
        axs[0].set_title(f'Selected Region\nFractal Dimension: {fd}')

        axs[1].plot(np.log(sizes), np.log(counts), 'o-', label='Data')
        axs[1].plot(np.log(sizes), np.polyval(np.polyfit(np.log(sizes), np.log(counts), 1), np.log(sizes)), 'r--', label=f'Fit: D={fd:.2f}')
        axs[1].set_xlabel('log(Box Size)')
        axs[1].set_ylabel('log(Count)')
        axs[1].legend()
        axs[1].set_title('Fractal Dimension Fitting')

        plt.tight_layout()
        plt.show()


if __name__ == '__main__':
    main()

补充路径之后,程序的具体流程如下:
打开一张图片,锚定一个区域:
在这里插入图片描述
可以自动得出区域的分形维数和维数(斜率)随盒子尺寸变化的拟合情况:
在这里插入图片描述
xlabel是盒子的尺寸,也就是2的n次方。拿其中一个点说,盒子大小为2的4次方(16)个像素点时,对应的要覆盖这个分形结构的盒子数(二值化之后包含非0像素的盒子数)。(因为我的程序是打开一张图片截取感兴趣的区域这样的思路,所以横坐标用这样的方式来设置,也有一些程序横坐标是分数值,这样是针对真个图片来说的,比如四分之一,表示盒子的边长为整个图片的四分之一)。
具体的分形过程可视化两张过程图看看吧,直观一些。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
本文只介绍了盒计数分形法,比较常用。
具体原理和其他方法的介绍可以多看看相关文章。

吕泽昆.图像分形维数的计盒方法改进[J].电子技术与软件工程,2020,(11):144-145.
张志,董福安,伍友利.二维灰度图像的分形维数计算[J].计算机应用,2005,(12): 2853-2854

分形树丛是一种数学和计算机图形学的概念,它源自自然界中树木分支的自相似结构,如真实森林或植物的生长模式。在Python中,可以通过库如`matplotlib`、`numpy`以及一些专门用于生成分形图像的库,比如` fractal_art` 或 `pyfractal`,来创建这样的可视化效果。 通常,分形树丛的生成过程会使用递归算法,通过复制并缩放现有的形状,然后按照一定的规则分布开来。这种过程中,树枝不断细化,形成层次分明、复杂的几何结构。在程序中,我们可以设置初始的分支形状、迭代次数、缩放因子等参数,来控制生成树丛的细节和复杂度。 以下是创建一个简单分形树丛的Python示例代码片段: ```python import matplotlib.pyplot as plt from matplotlib.path import Path import numpy as np def draw_tree(x, y, scale=0.85): # 基本分支点 points = [(x, y)] path = Path(points) # 添加新枝 if len(points) > 4: points.append((x + scale * (points[-1][0] - points[0][0]), y + scale * (points[-1][1] - points[0][1]))) points.append((x + scale * (points[-1][0] - points[0][0]) / 3, y)) points.append((x + scale * (points[-1][0] - points[0][0]) / 3 + scale * (points[-2][0] - points[0][0]) / 3, y + scale * (points[-2][1] - points[0][1]) / 3)) return path, points # 初始化参数 num_trees = 100 scale_factor = 0.6 angle = 0.0 size = 800 shift = (size // 2, size // 2) # 创建画布 fig, ax = plt.subplots() for _ in range(num_trees): x, y = shift for _ in range(50): # 迭代次数 path, points = draw_tree(x, y, scale_factor) ax.add_patch(PathPatch(path, facecolor='none', edgecolor='black')) x, y = points[-1] plt.axis('off') plt.title('Fractal Tree Clump') plt.show()
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值