scikit-image について
scikit-imageは、画像をNumPy配列として扱う研究・科学向けのPython画像解析ライブラリです。フィルタリング、セグメンテーション、特徴検出、復元、測定の機能を備えています。
主な機能
- 01画像のフィルタリングとノイズ除去
- 02セグメンテーションとモルフォロジー処理
- 03特徴とテクスチャの検出
- 04画像の復元と変換
- 05ラベリングとオブジェクト測定
活用シーン
- 01科学画像のノイズ除去
- 02細胞や粒子のセグメンテーション
- 03エッジ、コーナー、テクスチャの検出
- 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 ~ 255uint16: 0 ~ 65535float: -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 エコシステムを基盤としているため、生のセンサーデータから定量的な知見を得るまでのワークフローをシームレスに実現できます。
コメント
Markdown 対応