我认为获得有关金属池所需信息的最佳方法是对其进行分段。由于图像嘈杂,我认为图形切割是更好的选择。
我使用垂直 Scharr 过滤估计池边界,并使用它们来计算图形弧权重。

由此,我使用图像的上下边界作为图形切割算法的源和接收器(这些像素将属于不同的标签)。
执行第二次分割以获得没有池的水平线并计算它们的差异以获得最终结果。
beta
必须调整参数,随着它的增加,它会更符合您的权重(嘈杂的边界)。我发现 50 得到了很好的结果,但你应该玩它。
import numpy as np
from skimage import io, filters, measure
import skimage.morphology as morph
import matplotlib.pyplot as plt
import maxflow
def normalize(im):
im -= im.min()
return im / im.max()
def graph_cut(weights):
g = maxflow.GraphFloat()
nodeids = g.add_grid_nodes(weights.shape)
structure = maxflow.vonNeumann_structure(ndim=2, directed=True)
g.add_grid_edges(nodeids, weights, structure=structure, symmetric=True)
g.add_grid_tedges(nodeids[1, :], 0, 1e16)
g.add_grid_tedges(nodeids[-1, :], 1e16, 0)
g.maxflow()
return g.get_grid_segments(nodeids)
def get_largest(label):
label = measure.label(label)
largest = label == np.argmax(np.bincount(label.flat)[1:])+1
return largest
def main():
im = io.imread("example.png")
im = filters.median(im, morph.disk(5))
# pool segmentation
beta = 50 # parameter
aux = filters.scharr_v(im)
aux = normalize(np.abs(aux))
weights = np.exp(-beta * aux)
pool = graph_cut(weights)
# end
# surface segmentation
aux = np.abs(filters.scharr(im))
aux = normalize(aux)
weights = np.exp(-aux)
surf = graph_cut(weights)
# end
# result
res = pool ^ surf # xor
res = get_largest(res)
contours = measure.find_contours(res, 0.5)
fig, ax = plt.subplots()
ax.imshow(im, cmap='gray')
for contour in contours:
ax.plot(contour[:, 1], contour[:, 0], linewidth=1, c = 'red')
plt.show()
if __name__ == "__main__":
main()
结果:

