mcpField
S
scikit-image

scikit-image

github.com/tondevrelデータ・データベース2484 回インストール38 週間前に更新
リポジトリ

scikit-image について

scikit-imageは、画像をNumPy配列として扱う研究・科学向けのPython画像解析ライブラリです。フィルタリング、セグメンテーション、特徴検出、復元、測定の機能を備えています。

主な機能

  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 配列です

グレースケール画像は 2D 配列(M, N)です。カラー画像は 3D 配列(M, N, 3)です。マルチチャンネルの 3D ボリュームは(P, M, N, C)です。

座標系

原点(0, 0)は左上隅です。座標は常に(行, 列)として表されます。

データ型と範囲

scikit-image は、特定の範囲を持つさまざまな dtype を扱います。

  • 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()

重要なルール

✅ すべきこと
  • 変換にはユーティリティ関数を使う - dtype を変更するときは、util.img_as_float、util.img_as_ubyte を使って自動的に再スケーリングします。
  • 解析にはグレースケールを使う - ほとんどの特徴抽出アルゴリズムとセグメンテーションアルゴリズムは、2D グレースケール配列を想定しています。
  • 画像の形状を確認する - 処理の前に必ず image.shape と image.dtype を確認します。
  • ベクトル化する - ピクセル単位のループではなく、NumPy の演算を使います。
  • セグメンテーションの前にフィルタを適用する - ノイズ除去(ガウシアン、メディアン)によって、セグメンテーションの結果が大幅に改善します。
  • オブジェクトのカウントにはラベル付けを使う - measure.label は連結成分を特定する標準的な方法です。
❌ してはいけないこと
  • dtype を手動で再スケーリングする - image / 255.0 は避け、util.img_as_float を使います。
  • 「座標に関する注意」を無視する - (x, y)と(row, col)の違いに注意してください。scikit-image は(row, col)を使います。
  • 入力画像を変更する - ほとんどの関数は新しい配列を返します。変更する必要がある場合はコピーを使います。
  • グレースケール画像に色依存のフィルタを適用する - フィルタによっては、3D 配列と 2D 配列で動作が異なります。

アンチパターン(絶対に避ける)

# ❌ 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 エコシステムを基盤としているため、生のセンサーデータから定量的な知見を得るまでのワークフローをシームレスに実現できます。

コメント