mcpField
S
scikit-image

scikit-image

github.com/tondevrel数据与数据库2484 次安装39 周前更新
代码仓库

关于 scikit-image

scikit-image 是面向科研图像分析的 Python 库,以 NumPy 数组表示图像。它涵盖滤波、分割、特征检测、图像修复和对象测量等处理。

主要功能

  1. 01图像滤波与降噪
  2. 02分割与形态学处理
  3. 03特征和纹理检测
  4. 04图像修复与变换
  5. 05连通区域标记和测量

适用场景

  1. 01预处理含噪科研图像
  2. 02分割细胞或颗粒
  3. 03检测边缘、角点或纹理
  4. 04测量已标记对象的属性

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/tondevrel/scientific-agent-skills --skill scikit-image

安装后在 Claude Code 中输入/scikit-image确认已加载。

详细介绍

scikit-image - 科学图像处理

scikit-image 将图像视为 NumPy 数组。它提供了一套全面的算法,用于滤波、特征检测和对象测量,是研究级图像分析的标准工具。

适用场景

  • 预处理科学图像(降噪、增强对比度)。
  • 图像分割(分离细胞、颗粒或感兴趣区域)。
  • 特征提取(检测边缘、角点、斑点或纹理)。
  • 几何变换(缩放、旋转、扭曲)。
  • 形态学操作(细化、骨架化、填充孔洞)。
  • 测量对象属性(面积、周长、偏心率)。
  • 修复退化图像(反卷积、修复)。

参考文档

官方文档:https://scikit-image.org/
用户指南:https://scikit-image.org/docs/stable/user_guide.html
搜索模式:skimage.filters、skimage.segmentation、skimage.feature、skimage.morphology

核心原则

图像是 NumPy 数组

灰度图像是一个二维数组 (M, N)。彩色图像是一个三维数组 (M, N, 3)。多通道三维体数据的形状为 (P, M, N, C)。

坐标系

原点 (0, 0) 位于左上角。坐标始终表示为 (行, 列)。

数据类型和范围

scikit-image 支持多种具有特定范围的数据类型:

  • uint8:0 到 255
  • uint16:0 到 65535
  • float:-1 到 1 或 0 到 1

快速参考

安装
pip install scikit-image
标准导入
import numpy as np
import matplotlib.pyplot as plt
from skimage import io, filters, segmentation, feature, measure, morphology, color, util
基本模式 - 加载和滤波
from skimage import io, filters, color

# Load image
image = io.imread('data.png')

# Convert to grayscale if needed
gray_image = color.rgb2gray(image)

# Apply a filter (e.g., Gaussian blur)
blurred = filters.gaussian(gray_image, sigma=2.0)

# Display
io.imshow(blurred)
io.show()

关键规则

✅ 应该做
  • 使用实用函数进行转换 - 更改数据类型时,使用 util.img_as_float、util.img_as_ubyte 自动处理重新缩放。
  • 分析时使用灰度图 - 大多数特征提取和分割算法都需要二维灰度数组。
  • 检查图像形状 - 处理前务必检查 image.shape 和 image.dtype。
  • 使用向量化操作 - 使用 NumPy 操作,而不是循环遍历像素。
  • 先滤波再分割 - 降噪(高斯、中值)可显著改善分割效果。
  • 使用 label 统计对象 - measure.label 是识别连通分量的标准方法。
❌ 不应该做
  • 手动重新缩放数据类型 - 避免使用 image / 255.0;请使用 util.img_as_float。
  • 忽略“坐标警告” - 注意 (x, y) 与 (row, col) 的区别。scikit-image 使用 (row, col)。
  • 修改输入图像 - 大多数函数会返回新数组;如果需要修改,请使用副本。
  • 对灰度图应用颜色敏感型滤波器 - 某些滤波器在三维数组和二维数组上的行为不同。

反模式(绝对不要这样做)

# ❌ BAD: Manual dtype conversion (doesn't handle scaling)
image_float = image.astype(float) # Values stay 0-255 but as floats

# ✅ GOOD: Safe utility conversion
from skimage import util
image_float = util.img_as_float(image) # Values scaled to 0.0-1.0

# ❌ BAD: Looping over pixels
for r in range(rows):
    for c in range(cols):
        if image[r, c] > 128:
            image[r, c] = 255

# ✅ GOOD: Vectorized thresholding
image[image > 0.5] = 1.0

# ❌ BAD: Plotting multiple images without a shared axis
plt.imshow(img1); plt.show()
plt.imshow(img2); plt.show()

# ✅ GOOD: Using subplots for comparison
fig, ax = plt.subplots(1, 2)
ax[0].imshow(img1, cmap='gray')
ax[1].imshow(img2, cmap='gray')

滤波与修复(skimage.filters)

降噪和边缘检测
from skimage import filters

# Edge detection
edges_sobel = filters.sobel(image)
edges_canny = feature.canny(image, sigma=3)

# Denoising
denoised = filters.median(image, morphology.disk(3))

# Thresholding (Automatic)
val = filters.threshold_otsu(image)
binary = image > val

形态学(skimage.morphology)

形状处理和结构分析
from skimage import morphology

# Binary morphology
struct_element = morphology.disk(5)
eroded = morphology.erosion(binary, struct_element)
dilated = morphology.dilation(binary, struct_element)
opened = morphology.opening(binary, struct_element) # Erosion then Dilation

# Skeletonization (Reducing objects to 1-pixel width)
skeleton = morphology.skeletonize(binary)

# Removing small objects
clean_binary = morphology.remove_small_objects(binary, min_size=64)

分割(skimage.segmentation)

分离对象
from skimage import segmentation, color

# Watershed Segmentation (Marker-based)
from scipy import ndimage as ndi
distance = ndi.distance_transform_edt(binary)
coords = feature.peak_local_max(distance, footprint=np.ones((3, 3)), labels=binary)
mask = np.zeros(distance.shape, dtype=bool)
mask[tuple(coords.T)] = True
markers, _ = ndi.label(mask)
labels = segmentation.watershed(-distance, markers, mask=binary)

# SLIC (Superpixels)
segments = segmentation.slic(image, n_segments=100, compactness=10)
out = color.label2rgb(segments, image, kind='avg')

特征检测(skimage.feature)

关键点和纹理
from skimage import feature

# Local Binary Patterns (Texture analysis)
lbp = feature.local_binary_pattern(image, P=8, R=1)

# Corner detection (Harris)
coords = feature.corner_peaks(feature.corner_harris(image), min_distance=5)

# Blob detection (Difference of Gaussian)
blobs = feature.blob_dog(image, max_sigma=30, threshold=.1)
# blobs: array of [row, col, sigma]

测量(skimage.measure)

量化结果
from skimage import measure

# Label connected components
labels = measure.label(binary)

# Calculate properties
props = measure.regionprops(labels)

for prop in props:
    print(f"Label: {prop.label}")
    print(f"Area: {prop.area}")
    print(f"Centroid: {prop.centroid}")
    print(f"Eccentricity: {prop.eccentricity}")

# Find contours
contours = measure.find_contours(binary, 0.8)

实用工作流

1. 颗粒计数流程
def count_particles(image_path):
    # 1. Load and grayscale
    img = color.rgb2gray(io.imread(image_path))
    
    # 2. Denoise
    img_denoised = filters.gaussian(img, sigma=1)
    
    # 3. Threshold
    thresh = filters.threshold_otsu(img_denoised)
    binary = img_denoised < thresh # Assuming dark particles
    
    # 4. Morphological cleaning
    binary = morphology.remove_small_objects(binary, 50)
    binary = morphology.closing(binary, morphology.disk(3))
    
    # 5. Label and measure
    labels = measure.label(binary)
    return measure.regionprops(labels), labels

# properties, label_img = count_particles('samples.tif')
2. 显微图像分析(细胞核分割)
def segment_nuclei(dna_image):
    """Identify nuclei in a DAPI/Hoechst stained image."""
    # Local thresholding for uneven illumination
    local_thresh = filters.threshold_local(dna_image, block_size=35)
    binary = dna_image > local_thresh
    
    # Fill holes
    filled = ndi.binary_fill_holes(binary)
    
    # Separate touching nuclei
    distance = ndi.distance_transform_edt(filled)
    local_maxi = feature.peak_local_max(distance, indices=False, footprint=np.ones((15, 15)), labels=filled)
    markers = measure.label(local_maxi)
    labels = segmentation.watershed(-distance, markers, mask=filled)
    
    return labels
3. 变化检测(图像相减)
def detect_change(img_before, img_after, threshold=0.1):
    # Ensure float
    im1 = util.img_as_float(color.rgb2gray(img_before))
    im2 = util.img_as_float(color.rgb2gray(img_after))
    
    # Difference
    diff = np.abs(im1 - im2)
    
    # Filter noise in difference
    diff_clean = filters.median(diff, morphology.disk(2))
    
    return diff_clean > threshold

性能优化

使用 skimage.util.view_as_windows
from skimage.util import view_as_windows

# Create overlapping patches without copying data (using strides)
# Fast for local neighborhood calculations
patches = view_as_windows(image, (64, 64), step=32)
# Shape: (n_patches_r, n_patches_c, 64, 64)
并行处理
# Many skimage functions are already Cython-optimized.
# For batch processing, use standard joblib or multiprocessing.
from joblib import Parallel, delayed

results = Parallel(n_jobs=-1)(delayed(filters.gaussian)(img) for img in image_list)

常见问题及解决方案

处理多通道图像
# ❌ Problem: Filters failing on RGB images
# result = filters.median(rgb_image) # Raises error

# ✅ Solution: Filter per channel or convert
# filters.median(color.rgb2gray(rgb_image))
# OR apply to each channel
# result = np.stack([filters.median(rgb_image[..., i]) for i in range(3)], axis=-1)
label 的内存问题
# ❌ Problem: Large noisy images produce millions of 1-pixel labels
# ✅ Solution: Clear small noise before labeling
binary = morphology.remove_small_objects(binary, min_size=10)
labels = measure.label(binary)
坐标:(X, Y) 与 (Row, Col) 混淆
# ❌ Problem: Points appear swapped on plot
# Matplotlib: plt.plot(x, y)
# scikit-image: image[row, col]

# ✅ Solution: Explicitly swap for visualization
coords = feature.peak_local_max(img) # Returns [row, col]
plt.plot(coords[:, 1], coords[:, 0], 'r.') # Plot as [x, y]

scikit-image 提供了科学发现所需的严谨数学基础。借助 NumPy 生态系统,它让从原始传感器数据到可量化洞见的工作流畅通无阻。

评论

支持 Markdown