基于像素强度的多区域图像分割

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

我试图根据像素强度将灰度图像分割成三个区域。由于照明和斑点,这项任务比我预期的更具挑战性......

这是原始图像

明亮区域占据了图像的大部分。在它的下面,有一个灰色区域,黑色区域占据了图像底部的狭窄部分。

多 Otsu 阈值处理不是很有效,因为直方图没有显示尖锐的峰值...

from skimage.filters import threshold_multiotsu

thresholds = threshold_multiotsu(image)
plt.hist(image.ravel(), bins=255)
for thresh in thresholds:
    plt.axvline(thresh, color='r')

regions = np.digitize(image, bins=thresholds)
plt.imshow(regions, cmap='jet')

我认为我需要的是具有多个标签的大规模自适应阈值,但我不知道如何实现这一点。

(编辑)

在阈值化之前应用模糊显示出更有希望的结果。

blur = cv2.GaussianBlur(image, (0, 0), 8)

thresholds = threshold_multiotsu(blur)
regions = np.digitize(blur, bins=thresholds)
plt.imshow(regions, cmap='jet')

但是

x > 1100
中的“白色”和“灰色”区域之间的边界仍然不准确。

同时,对模糊图像应用 Sobel 滤波器会返回相当准确的边界。

grad_x = cv2.Sobel(blur, cv2.CV_16S, 1, 0, ksize=3)
grad_y = cv2.Sobel(blur, cv2.CV_16S, 0, 1, ksize=3)
abs_grad_x = cv2.convertScaleAbs(grad_x)
abs_grad_y = cv2.convertScaleAbs(grad_y)
grad = cv2.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0)
plt.imshow(grad, cmap="gray")

那么问题就变成了:如何结合Sobel结果和Otsu结果来获得准确的mask?

python image-processing image-segmentation scikit-image
1个回答
0
投票

使用 k 均值聚类怎么样?如有必要,您可以在聚类之前应用平滑过滤器。下面,我使用了您在聚类之前使用的相同平滑过滤器。我不确定我是否满足了您使用 sobel 和 otsu 的真正要求。只是想提出另一种可能的分割方式。

import numpy as np
import cv2 as cv

img = cv.imread('input.png')

img = cv.GaussianBlur(img, (0, 0), 8)

Z = img.reshape((-1,3))
# convert to np.float32
Z = np.float32(Z)
# define criteria, number of clusters(K) and apply kmeans()
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 10, 1.0)
K = 3
ret,label,center=cv.kmeans(Z,K,None,criteria,10,cv.KMEANS_RANDOM_CENTERS)
# Now convert back into uint8, and make original image
center = np.uint8(center)
res = center[label.flatten()]
res2 = res.reshape((img.shape))

cv.imwrite('output.png', res2)

分段:

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