>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> import scipy as sp

1.5.11.4. 图像处理练习的解决方案示例:玻璃中的未熔颗粒

../../../_images/MV_HFV_012.jpg
  1. 打开图像文件 MV_HFV_012.jpg 并显示它。浏览 imshow 文档字符串中的关键字参数,以“正确”的方向显示图像(原点在左下角,而不是像标准数组那样在左上角)。

    >>> dat = plt.imread('data/MV_HFV_012.jpg')
    
  2. 裁剪图像以去除带有测量信息的底部面板。

    >>> dat = dat[:-60]
    
  3. 使用中值滤波器稍微滤波图像,以细化其直方图。检查直方图如何变化。

    >>> filtdat = sp.ndimage.median_filter(dat, size=(7,7))
    
    >>> hi_dat = np.histogram(dat, bins=np.arange(256))
    >>> hi_filtdat = np.histogram(filtdat, bins=np.arange(256))
    ../../../_images/exo_histos.png
  4. 使用滤波图像的直方图,确定允许定义沙子像素、玻璃像素和气泡像素掩码的阈值。其他选项(作业):编写一个函数,根据直方图的最小值自动确定阈值。

    >>> void = filtdat <= 50
    
    >>> sand = np.logical_and(filtdat > 50, filtdat <= 114)
    >>> glass = filtdat > 114
  5. 显示一个图像,其中三个相位用三种不同的颜色着色。

    >>> phases = void.astype(int) + 2*glass.astype(int) + 3*sand.astype(int)
    
    ../../../_images/three_phases.png
  6. 使用数学形态学来清理不同的相位。

    >>> sand_op = sp.ndimage.binary_opening(sand, iterations=2)
    
  7. 为所有气泡和沙粒分配标签,并从沙子掩码中去除小于 10 个像素的颗粒。为此,使用 sp.ndimage.sumnp.bincount 计算颗粒尺寸。

    >>> sand_labels, sand_nb = sp.ndimage.label(sand_op)
    
    >>> sand_areas = np.array(sp.ndimage.sum(sand_op, sand_labels, np.arange(sand_labels.max()+1)))
    >>> mask = sand_areas > 100
    >>> remove_small_sand = mask[sand_labels.ravel()].reshape(sand_labels.shape)
    ../../../_images/sands.png
  8. 计算气泡的平均尺寸。

    >>> bubbles_labels, bubbles_nb = sp.ndimage.label(void)
    
    >>> bubbles_areas = np.bincount(bubbles_labels.ravel())[1:]
    >>> mean_bubble_size = bubbles_areas.mean()
    >>> median_bubble_size = np.median(bubbles_areas)
    >>> mean_bubble_size, median_bubble_size
    (np.float64(1699.875), np.float64(65.0))