分水岭分割后的标签分配不正确(Python)



我正在使用skimage.segmentation.watershed分割一些粒子。这非常有效,我设法将它们适当地分离(见图(。分割后的图像。然而,当我使用ndi.label标记不同的区域时,并不是所有的片段都会被分离,有些片段在标记指定后会被指定相同的标签(即使使用分水岭,它们也被正确分割((图像2,例如左上角的粒子(。请注意,先前分离的粒子是如何被指定相同的标签的。我对Python还比较陌生,不知道还能做些什么来解决这个问题。如果你能给我任何帮助,我将不胜感激。提前感谢:(

我使用的代码是(我把它放在for循环中,因为我想同时自动分析几个图像(:

#import hyperspy for reading directly ser or emd files
import hyperspy.api as hs
#The scikit image library will be used for segmenting the images
from skimage.exposure import histogram
from skimage.color import label2rgb
from skimage import data, io, filters
from skimage.filters import threshold_local, threshold _yen, threshold_li
from skimage.filters import try_all_threshold
from skimage.filters import gaussian
from skimage.feature import peak_local_max
from skimage.feature import canny
from skimage import measure
from skimage.morphology import label
from skimage.morphology import remove_small_objects
from skimage.draw import ellipse
from skimage.measure import label, regionprops, regionprops_table
from skimage.transform import rotate
from skimage.segmentation import watershed
#matplotlib for performing plots
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
#Basic packages (math and statistics)
import pandas as pd
import numpy as np
from scipy import ndimage as ndi
from scipy import stats
import math
import glob
import seaborn as sns
#load data
s=hs.load(folder+'*.emi',stack=True)
#threshold
thresh=threshold_li(s.data)
binary=s>thresh
#Cleaning
cleaned=remove_small_objects(binary.data, min_size=5)

分割本身

#Define variables needed
dist=np.zeros([cleaned.shape[1],cleaned.shape[1]])
water=np.zeros([cleaned.shape[0],cleaned.shape[1],cleaned.shape[1]])
mask=np.zeros(dist.shape, dtype=bool)
markers,_=ndi.label(mask)
water_particles=np.zeros([cleaned.shape[0],cleaned.shape[1],cleaned.shape[1]])
eq_diam_total=np.array([])
#for loop for segmenting all the images using watershed. 
#I will use the commented "for i in range (cleaned.shape[0])" 
#once I manage to solve the segmentation issue:

#for i in range (cleaned.shape[0]):
for i in range(2,3):
dist = ndi.distance_transform_edt(cleaned[i,:,:]) #make distance map
maxima=peak_local_max(gaussian(dist, sigma=1.5),threshold_rel=None, 
min_distance=5)  # find local maxima
print('maxima',maxima.shape)
mask[tuple(maxima.T)]=True
markers,_=ndi.label(mask)
print('markers',markers.shape)

#segment
water[i,:,:]=watershed(-dist, markers,mask=cleaned[i,:,:])
print('water', water.shape)

#label each particle
water_particles[i,:,:], water_labels = ndi.label(water[i,:,:])
print('water_particles',water_particles.shape)
print('water_labels',water_labels)


分割后的绘图

%matplotlib inline  
from skimage import color
fig,axes=plt.subplots(1, 2, sharey=True)  
axes[0].imshow(color.label2rgb(water[i,:,:]))
axes[0].axis('off')
axes[0].set_title('After watershed segmentation')               

axes[1].imshow(color.label2rgb(water_particles[i,:,:]))
axes[1].axis('off')
axes[1].set_title('After label')

skimage.segmentation.watershed的输出是一个标记的图像,它可以直接进入测量功能(regionprops(。

此外,分水岭函数将把所有局部极小值作为标记,你不需要自己找到这些。简化代码:

from scipy import ndimage as ndi
from skimage.segmentation import watershed
# ...
dist = ndi.distance_transform_edt(cleaned[i,:,:]) #make distance map
water_particles[i,:,:] = watershed(-dist, markers,mask=cleaned[i,:,:])

如果您想要接收一个可以标记自己的图像(无论出于何种原因(,请添加watershed_line=True参数。这将在每个区域(盆地(之间保持分离,以便标记算法能够识别它们。

最新更新