【python】纤维宽度分布分析与可视化

根据五张显微镜图片(11-1.tif ~ 11-5.tif),统计纤维宽度分布,并画出直方图+正态分布拟合曲线

主要步骤

  1. 读取图片
  1. 图像预处理(灰度化、二值化、去噪等)
  1. 边缘检测/骨架提取
  1. 测量纤维宽度
  1. 统计宽度分布,绘制直方图和正态分布拟合曲线

图片

代码

import cv2
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm
from skimage import measure

def measure_fiber_width(image_path, pixel_per_um):
    # 读取图片
    img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
    # 二值化
    _, binary = cv2.threshold(img, 0, 255, cv2.THRESH_OTSU)
    # 反色(确保纤维为白色)
    binary = 255 - binary
    # 去噪
    binary = cv2.medianBlur(binary, 5)
    # 连通域分析
    labels = measure.label(binary, connectivity=2)
    props = measure.regionprops(labels)
    widths = []
    for prop in props:
        # 只考虑较大的区域,过滤噪声
        if prop.area > 100:
            minr, minc, maxr, maxc = prop.bbox
            width = max(maxr - minr, maxc - minc) / pixel_per_um
            widths.append(width)
    return widths

def remove_outliers(data, n_std=2):
    mu = np.mean(data)
    std = np.std(data)
    filtered = [x for x in data if (mu - n_std*std) <= x <= (mu + n_std*std)]
    return filtered

def plot_width_distribution(widths, ax, title):
    widths = remove_outliers(widths, n_std=1)
    # 直方图
    n, bins, patches = ax.hist(widths, bins=7, color='cyan', edgecolor='black', alpha=0.7, density=True)
    # 拟合正态分布
    mu, std = norm.fit(widths)
    xmin, xmax = ax.get_xlim()
    x = np.linspace(xmin, xmax, 100)
    p = norm.pdf(x, mu, std)
    ax.plot(x, p, 'r-', lw=2)
    ax.set_xlabel('Width (μm)')
    ax.set_ylabel('Percentage (%)')
    ax.set_title(f'{title}\nW={mu:.2f}±{std:.2f}')
    ax.grid(False)

# 假设每像素代表的微米数(需根据标尺换算)
# pixel_per_um = 2.0  # 你需要根据图片标尺换算

file_list = ['11-1.tif', '11-2.tif', '11-3.tif', '11-4.tif', '11-5.tif']
titles = ['e', 'f', 'g', 'h', 'i']
pixel_per_ums = [(1255-798)/50.0,(1255-748)/20.0,(1255-748)/10.0,(1255-798)/5.0,(1255-849)/2.0]

fig, axs = plt.subplots(1, 5, figsize=(20, 4))
for i, (file, title,pixel_per_um) in enumerate(zip(file_list, titles,pixel_per_ums)):
    widths = measure_fiber_width(file, pixel_per_um)
    plot_width_distribution(widths, axs[i], title)
plt.tight_layout()
plt.show()

结果

注意

  • pixel_per_um 需要你根据图片标尺自行换算(如50μm对应多少像素)。

步骤

1.在图片中找到标尺

比如图片上有一条标注为“50 μm”的标尺。

2.用图像软件测量标尺长度(像素)

用如 ImageJ、Photoshop、画图、或 Python 脚本等工具,测量这条标尺在图片中占多少像素(比如 200 像素)。

3.计算每微米对应的像素数

例如:标尺为 50 μm,测得长度为 200 像素,则

也就是 1 μm = 4 像素。

4.计算每像素对应的微米数(pixel_per_um)

你的代码需要的是“每像素对应的微米数”,即

你的代码里 pixel_per_um 实际上是“每微米多少像素”,所以用第一个公式。

ImageJ

下载

起始像素

结束像素

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Z_W_H_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值