Skip to content

SciPy - Ndimage

SciPy - 多维图像处理(scipy.ndimage)

Section titled “SciPy - 多维图像处理(scipy.ndimage)”

scipy.ndimage 模块专注于 N 维图像处理。它提供了广泛的功能,用于对 NumPy 数组进行滤波、插值、测量、形态学操作以及其他常见的图像处理任务。

使用 scipy.ndimage 可以完成的常见图像处理任务包括:

  • 读写图像(通常借助 Matplotlib 或 ImageIO 等其他库)。
  • 基本操作:裁剪、翻转、旋转。
  • 图像滤波:去噪、锐化、模糊(例如,高斯滤波)。
  • 形态学操作:腐蚀、膨胀、开运算、闭运算。
  • 对象测量:查找质心、标记特征。
  • 插值和几何变换。

对于更高级的图像分析(例如,SIFT/SURF 等特征检测、复杂分割算法),通常会结合使用或替代 scipy.ndimage 使用 scikit-image、OpenCV 或 Mahotas 等库。

SciPy 本身不侧重于图像输入/输出 (I/O)。scipy.datasets.face() 提供了一个示例彩色图像(一只浣熊),以 NumPy 数组形式呈现。对于通用图像加载,推荐使用 matplotlib.image 或 imageio 等库。

from scipy import datasets # For the sample image
import matplotlib.pyplot as plt
import numpy as np
# Load the sample 'face' image (a racoon)
# It's a 3D NumPy array (height, width, color_channels)
# 加载示例 'face' 图像(一只浣熊)
# 这是一个 3D 的 NumPy 数组(高、宽、颜色通道)
face_color = datasets.face()
# Load a grayscale version if available, or convert
# face_gray = datasets.face(gray=True) # This was an option in older scipy.misc
# For current datasets.face(), convert manually if needed:
# 如果可用,加载灰度版本,或进行转换
# face_gray = datasets.face(gray=True) # 这是旧版本 scipy.misc 中的一个选项
# 对于当前的 datasets.face(),如果需要,请手动转换:
face_gray = np.mean(face_color, axis=2).astype(np.uint8)
# Display the image using Matplotlib
# 使用 Matplotlib 显示图像
fig, axes = plt.subplots(1, 2, figsize=(10, 5))
axes[0].imshow(face_color)
axes[0].set_title('Color Face Image')
axes[0].axis('off')
axes[1].imshow(face_gray, cmap='gray')
axes[1].set_title('Grayscale Face Image')
axes[1].axis('off')
plt.tight_layout()
# plt.show()
# Description: This code loads a sample image of a racoon, once in color and
# once converted to grayscale. It then displays both side-by-side using Matplotlib.
# 描述:此代码加载一只浣熊的示例图像,一次是彩色的,一次是转换为灰度的。
# 然后使用 Matplotlib 将两者并排显示。

图像在其原始数字形式中本质上是一个 NumPy 数组,其中像素值表示强度或颜色。对于灰度图像,它通常是一个 2D 数组。对于彩色图像(例如,RGB),它是一个 3D 数组(高、宽、3 个通道)。

基本图像统计信息:

from scipy import datasets
import numpy as np
face = datasets.face() # Color image
# face = datasets.face() # 彩色图像
print(f"Image shape: {face.shape}") # 图像形状
print(f"Data type: {face.dtype}") # 数据类型
print(f"Mean pixel value (overall): {face.mean():.2f}") # 平均像素值(整体)
print(f"Max pixel value: {face.max()}") # 最大像素值
print(f"Min pixel value: {face.min()}") # 最小像素值

输出(根据 SciPy 版本/数据集的具体情况会略有差异):

Image shape: (768, 1024, 3)
Data type: uint8
Mean pixel value (overall): 114.51
Max pixel value: 255
Min pixel value: 0

由于图像是 NumPy 数组,因此可以使用数组切片进行基本的变换,例如裁剪。scipy.ndimage 提供了用于更复杂变换的功能,例如旋转和缩放。

from scipy import datasets
import matplotlib.pyplot as plt
import numpy as np
face_gray = np.mean(datasets.face(), axis=2).astype(np.uint8)
height, width = face_gray.shape
# Crop the central part of the image
# Remove 1/4th from each side (top, bottom, left, right)
# 裁剪图像的中心部分
# 从每一侧(上、下、左、右)各移除 1/4
crop_start_h, crop_end_h = height // 4, height - height // 4
crop_start_w, crop_end_w = width // 4, width - width // 4
cropped_face = face_gray[crop_start_h:crop_end_h, crop_start_w:crop_end_w]
plt.figure(figsize=(5, 5))
plt.imshow(cropped_face, cmap='gray')
plt.title('Cropped Grayscale Face') # 裁剪后的灰度图像标题
plt.axis('off') # 关闭坐标轴
# plt.show()
# Description: This code will display the central cropped portion of the grayscale racoon image.
# 描述:此代码将显示灰度浣熊图像的中心裁剪部分。

NumPy 的 flipud(上下翻转)和 fliplr(左右翻转)非常有用。

from scipy import datasets
import numpy as np
import matplotlib.pyplot as plt
face_color = datasets.face()
# Flip upside down
# 上下翻转
flipped_ud_face = np.flipud(face_color)
plt.figure(figsize=(5,5))
plt.imshow(flipped_ud_face)
plt.title('Up-Down Flipped Face') # 上下翻转图像标题
plt.axis('off') # 关闭坐标轴
# plt.show()
# Description: This code will display the racoon image flipped vertically.
# 描述:此代码将垂直翻转并显示浣熊图像。

scipy.ndimage.rotate() 函数按指定角度(以度为单位)旋转图像。

from scipy import datasets, ndimage
import matplotlib.pyplot as plt
face_color = datasets.face()
# Rotate the image by 45 degrees. By default, fills outside areas with 0.
# 'reshape=False' keeps original image dimensions, cropping rotated parts.
# 将图像旋转 45 度。默认情况下,外部区域填充 0。
# 'reshape=False' 保留原始图像尺寸,裁剪旋转后的部分。
rotated_face = ndimage.rotate(face_color, 45, reshape=False)
plt.figure(figsize=(5,5))
plt.imshow(rotated_face)
plt.title('Rotated Face (45 degrees)') # 旋转后的图像标题 (45 度)
plt.axis('off') # 关闭坐标轴
# plt.show()
# Description: This code will display the racoon image rotated by 45 degrees clockwise,
# with parts of the image outside the original bounds cropped.
# 描述:此代码将显示顺时针旋转 45 度的浣熊图像,
# 裁剪掉超出原始边界的图像部分。

滤波根据像素的邻域修改像素值,用于平滑、锐化和边缘检测等任务。

高斯滤波器可以平滑图像并减少噪声。scipy.ndimage.gaussian_filter(input, sigma) 应用此操作。sigma 是高斯核的标准差;sigma 越大,模糊越多。

from scipy import datasets, ndimage
import matplotlib.pyplot as plt
import numpy as np
face_gray = np.mean(datasets.face(), axis=2).astype(np.uint8)
# Apply Gaussian filter with sigma = 3
# 应用 sigma = 3 的高斯滤波器
blurred_face = ndimage.gaussian_filter(face_gray, sigma=3)
# Apply Gaussian filter with sigma = 7 for more blur
# 应用 sigma = 7 的高斯滤波器,以获得更多模糊
more_blurred_face = ndimage.gaussian_filter(face_gray, sigma=7)
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
axes[0].imshow(face_gray, cmap='gray')
axes[0].set_title('Original Grayscale') # 原始灰度图像标题
axes[0].axis('off') # 关闭坐标轴
axes[1].imshow(blurred_face, cmap='gray')
axes[1].set_title('Blurred (sigma=3)') # 模糊 (sigma=3) 图像标题
axes[1].axis('off') # 关闭坐标轴
axes[2].imshow(more_blurred_face, cmap='gray')
axes[2].set_title('More Blurred (sigma=7)') # 更模糊 (sigma=7) 图像标题
axes[2].axis('off') # 关闭坐标轴
plt.tight_layout()
# plt.show()
# Description: This code displays the original grayscale image alongside two versions
# blurred with a Gaussian filter using different sigma values (3 and 7).
# The image with sigma=7 will appear more blurred.
# 描述:此代码显示原始灰度图像以及使用不同 sigma 值(3 和 7)
# 应用高斯滤波器模糊的两个版本。
# sigma=7 的图像将显得更模糊。

边缘检测旨在识别亮度的显著变化,这通常对应于对象的边界。

Sobel 滤波器是一种常见的基于梯度的边缘检测器。scipy.ndimage.sobel(input, axis, output) 沿给定轴计算 Sobel 滤波器。通常将 X 轴和 Y 轴的结果组合起来以获得整体边缘幅度。

from scipy import ndimage, datasets
import numpy as np
import matplotlib.pyplot as plt
# Create a simple synthetic image for clear edge detection
# 创建一个简单的合成图像用于清晰的边缘检测
image = np.zeros((128, 128))
image[32:-32, 32:-32] = 1 # A white square on a black background # 黑色背景上的白色方块
# Add some noise and blur to make it more realistic
# 添加一些噪声和模糊使其更逼真
image = image + 0.1 * np.random.rand(128,128)
image = ndimage.gaussian_filter(image, sigma=2)
# Apply Sobel filter along x-axis (axis=1 for columns/horizontal gradient)
# 沿 X 轴应用 Sobel 滤波器(axis=1 表示列/水平梯度)
sobel_x = ndimage.sobel(image, axis=1, mode='reflect')
# Apply Sobel filter along y-axis (axis=0 for rows/vertical gradient)
# 沿 Y 轴应用 Sobel 滤波器(axis=0 表示行/垂直梯度)
sobel_y = ndimage.sobel(image, axis=0, mode='reflect')
# Combine to get edge magnitude
# 组合以获得边缘幅度
sobel_magnitude = np.hypot(sobel_x, sobel_y)
fig, axes = plt.subplots(1, 4, figsize=(16, 4))
axes[0].imshow(image, cmap='gray')
axes[0].set_title('Original Synthetic Image') # 原始合成图像标题
axes[0].axis('off') # 关闭坐标轴
axes[1].imshow(sobel_x, cmap='gray')
axes[1].set_title('Sobel X (Horizontal Edges)') # Sobel X(水平边缘)标题
axes[1].axis('off') # 关闭坐标轴
axes[2].imshow(sobel_y, cmap='gray')
axes[2].set_title('Sobel Y (Vertical Edges)') # Sobel Y(垂直边缘)标题
axes[2].axis('off') # 关闭坐标轴
axes[3].imshow(sobel_magnitude, cmap='gray')
axes[3].set_title('Sobel Magnitude (Edges)') # Sobel 幅度(边缘)标题
axes[3].axis('off') # 关闭坐标轴
plt.tight_layout()
# plt.show()
# Description: This code generates a synthetic image of a square, then applies the
# Sobel filter to detect its horizontal and vertical edges, and finally shows the
# combined edge magnitude. The last image highlights the boundaries of the square.
# 描述:此代码生成一个正方形的合成图像,然后应用 Sobel 滤波器
# 检测其水平和垂直边缘,最后显示组合的边缘幅度。
# 最后一张图像突出显示了正方形的边界。

scipy.ndimage 提供了许多其他功能,包括形态学操作(例如,binary_erosion、binary_dilation)、特征测量(center_of_mass、label)和插值(zoom、map_coordinates)。有关详细信息,请查阅官方 SciPy ndimage 文档。