Python 图像分割和提取

Python Image segementation and extraction

我想弄清楚如何从具有矿物颗粒的灰度图像中提取多个对象。我需要分割不同的颗粒,然后提取它们中的每一个以保存为单独的图像文件。 在做研究时,我发现每个人都使用 skimage。我担心有些谷物不会被提取(mineralgrains)。

有没有人处理过类似的问题?

我不完全确定这张图片中的矿物颗粒是什么,但是使用 skimage 算法分割和标记连接的组件非常简单。

据我所知,最简单的方法分为两个主要步骤:

  1. 生成二值图像。最直接的方法是使用基于阈值的方法,例如此处详述的方法:https://scikit-image.org/docs/dev/auto_examples/segmentation/plot_thresholding.html
  2. 分离连接的对象。这通常是通过使用此处详述的分水岭算法来完成的:https://scikit-image.org/docs/stable/auto_examples/segmentation/plot_watershed.html

假设矿物颗粒是示例图像中较大的物体,第一遍方法可能如下所示

import numpy as np
from scipy import ndimage as ndi
from skimage import io
from skimage.filters import gaussian, threshold_li
from skimage.morphology import remove_small_holes, remove_small_objects
from skimage.segmentation import watershed
from skimage.feature import peak_local_max
from skimage.measure import label

# read in the image
img = io.imread('fovAK.png', as_gray=True)

gauss_sigma = 1 # standard deviation for Gaussian kernel for removing a bit of noise from image
obj_min_size = 5000 # minimum # of pixels for labeled objects
min_hole_size = 5000 # The maximum area, in pixels, of a contiguous hole that will be filled
watershed_footprin = 100 # size of local region within which to search for peaks for watershed

#########################
#make a binary image using threshold
#########################

img_blurred = gaussian(img, gauss_sigma) # remove a bit of noise from image 
img_thresh = threshold_li(img_blurred) # use histogram based method to determine intensity threshold
img_binary = img_blurred > img_thresh # make a binary image 


# make a border around the image so that holes at edge are not filled
ydims, xdims = img.shape
img_binary[0, :] = 0
img_binary[ydims-1, :] = 0
img_binary[:, 0] = 0
img_binary[:, xdims-1] = 0

img_rsh = remove_small_holes(img_binary, min_hole_size) # removes small holdes in binary image
img_rso = remove_small_objects(img_rsh, obj_min_size) # removes small objects in binary image

#############################
#use watershed algorithm to seperate connected objects
####################################

distance = ndi.distance_transform_edt(img_rso) # distance transform of image
coords = peak_local_max(distance, labels=img_rso, footprint=np.ones((ws_footprint, ws_footprint))) # local pead distances
mask = np.zeros(distance.shape, dtype=bool) # mask for watershed
mask[tuple(coords.T)] = True
markers, _ = ndi.label(mask)
labels = watershed(-distance, markers, mask=img_rso)

这绝对是您示例图像的第一遍,绝不是完美的。您可能需要使用不同的阈值算法或调整其他参数,但希望这能让您朝着正确的方向前进。

从那里您可以遍历标记的对象并保存单个图像。

对于这类问题肯定有更复杂的方法,从边缘检测器和带通滤波器一直到使用基于 ML 的方法,但希望这能让您朝着正确的方向前进。