分水岭算法

问题描述 投票:0回答:1

我尝试使用“分水岭”算法来分割颅骨和肿瘤。

这是我的代码:

import numpy as np
import matplotlib.pyplot as plt
from skimage import io, filters, color
from skimage.segmentation import active_contour, watershed
from skimage.morphology import disk
from skimage.filters import rank

# Bild laden
image = io.imread('brain.png')

# Falls das Bild im RGBA-Format vorliegt, extrahiere die RGB-Kanäle
if image.shape[2] == 4:
    image_rgb = image[:, :, :3]
else:
    image_rgb = image

# Konvertiere das Bild in Graustufen
image_gray = color.rgb2gray(image_rgb)

# Gradientenbild berechnen
gradient = filters.sobel(image_gray)

# Initialisiere die Kontur mit einer Ellipse für das Gehirn
brain_s = np.linspace(0, 3*np.pi, 200)
brain_x = 200 + 60*np.cos(brain_s)
brain_y = 135 + 60*np.sin(brain_s)
brain_init = np.array([brain_x, brain_y]).T

# Aktive Kontur für das Gehirn anwenden
brain_snake = active_contour(gradient, brain_init, alpha=0.1, beta=8.4, gamma=0.12)

# Manuelle Marker für das Gehirn für die Watershed-Transformation festlegen
brain_markers = np.zeros_like(image_gray, dtype=np.uint8)
brain_markers[50, 50] = 1
brain_markers[100, 150] = 2

# Watershed-Transformation für das Gehirn durchführen
brain_segmentation = watershed(gradient, brain_markers, mask=image_gray)

# Initialisiere die Kontur mit einer Ellipse für den Schädel
skull_s = np.linspace(0, 3*np.pi, 340)
skull_x = 200 + 165*np.cos(skull_s)
skull_y = 135 + 300*np.sin(skull_s)
skull_init = np.array([skull_x, skull_y]).T

# Aktive Kontur für den Schädel anwenden
skull_snake = active_contour(gradient, skull_init, alpha=0.1, beta=2.0, gamma=0.22)

# Manuelle Marker für den Schädel für die Watershed-Transformation festlegen
skull_markers = np.zeros_like(image_gray, dtype=np.uint8)
skull_markers[150, 200] = 1
skull_markers[180, 250] = 2

# Watershed-Transformation für den Schädel durchführen
skull_segmentation = watershed(gradient, skull_markers, mask=image_gray)

# Ergebnisse anzeigen
fig, axes = plt.subplots(nrows=2, ncols=4, figsize=(20, 10))
axes[0, 0].imshow(image, cmap=plt.cm.gray)
axes[0, 0].set_title('Original Image')

axes[0, 1].imshow(gradient, cmap=plt.cm.gray)
axes[0, 1].plot(brain_snake[:, 0], brain_snake[:, 1], '-b', lw=3)
axes[0, 1].set_title('Brain: Gradient Image with Active Contour')

axes[0, 2].imshow(brain_markers, cmap=plt.cm.nipy_spectral)
axes[0, 2].set_title('Brain: Markers for Watershed')

axes[0, 3].imshow(brain_segmentation, cmap=plt.cm.nipy_spectral)
axes[0, 3].set_title('Brain: Watershed Segmentation Result')

axes[1, 1].imshow(gradient, cmap=plt.cm.gray)
axes[1, 1].plot(skull_snake[:, 0], skull_snake[:, 1], '-b', lw=3)
axes[1, 1].set_title('Skull: Gradient Image with Active Contour')

axes[1, 2].imshow(skull_markers, cmap=plt.cm.nipy_spectral)
axes[1, 2].set_title('Skull: Markers for Watershed')

axes[1, 3].imshow(skull_segmentation, cmap=plt.cm.nipy_spectral)
axes[1, 3].set_title('Skull: Watershed Segmentation Result')

for ax_row in axes:
    for ax in ax_row:
        ax.axis('off')

plt.show()

目前看起来像这样:

how it looks atm

但最终我想要这样:

how it should look

有人可以帮我设置参数吗?我尝试了很多不同的数字,但我从来没有得到完整的头骨。

python numpy scikit-image watershed
1个回答
0
投票

头骨和肿瘤比其他部分更亮,因此找到合适的阈值并对图像进行二值化可能会更容易。

所以,这是我解决问题的方法:

from skimage import morphology, filters

t = filters.threshold_mean(image) # or you can hardcode threhsold to be 100, i.e. t = 100, or you can also try filters.threshold_li(image)

y, x, c = np.where(image > t)
blank = np.zeros_like(image)
blank[y, x, c] = 1
blank = blank.sum(axis=-1) > 3 # if image has 4 channels, to be more generic image.shape[-1]-1 can be used instead 3
blank = morphology.remove_small_objects(blank, 400) # will remove objects, which has area smaller than 400, you may play with it
labels = measure.label(blank)
plt.imshow(labels)

你应该得到这样的东西: 分段头骨和肿瘤

© www.soinside.com 2019 - 2024. All rights reserved.