You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenCV中K-Means二聚类分割后如何提取目标区域二值掩码

问题根源

调用cv2.kmeans时使用cv2.KMEANS_RANDOM_CENTERS参数会随机选择初始聚类中心,每次运行后标签0、1对应的前景/背景类别会随机互换,没有固定对应关系,因此无法稳定提取目标区域。

实现逻辑

要稳定生成可用于面积计算的左心耳掩码,按以下流程处理即可:

  • 聚类完成后匹配目标类别:原始图像中左心耳腔体区域亮度显著低于周围亮背景,将两个BGR格式的聚类中心转为灰度值,灰度值更小的类别即为左心耳区域。如果要降低聚类结果的随机波动,可将初始化参数替换为cv2.KMEANS_PP_CENTERS,使用kmeans++算法选择初始中心,结果一致性更好。
  • 生成标准二值掩码:将聚类得到的标签数组与目标类别值做相等判断,生成的布尔数组转为uint8格式,目标区域赋值255、背景赋值0,即可得到单通道二值掩码。
  • 面积计算:直接统计掩码中非零像素的数量,即可得到左心耳的像素面积;如果需要实际物理面积,乘以DICOM文件中存储的像素间距参数即可。
完整实现代码
import numpy as np
import cv2

# 读取原始图像
img = cv2.imread('1_LA.jpg')
pixel_values = np.float32(img.reshape((-1, 3)))

# 设置K-means聚类参数
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
K = 2
# 若要更稳定的聚类结果,可将下面的cv2.KMEANS_RANDOM_CENTERS替换为cv2.KMEANS_PP_CENTERS
_, labels, centers = cv2.kmeans(pixel_values, K, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
labels = labels.reshape(img.shape[:-1])

# 匹配暗区域(左心耳)对应的标签
center_gray = []
for c in centers:
    # 将BGR格式的聚类中心转为灰度值
    gray_val = cv2.cvtColor(np.uint8([[c]]), cv2.COLOR_BGR2GRAY)[0][0]
    center_gray.append(gray_val)
target_label = np.argmin(center_gray)

# 生成二值掩码
mask = np.uint8(labels == target_label) * 255

# 计算像素面积
area_pixel = cv2.countNonZero(mask)
print(f"左心耳像素面积:{area_pixel}")

# 保存掩码文件
cv2.imwrite('laa_mask.png', mask)

# 可选:生成分割叠图验证效果
mask_3channel = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)
overlay = cv2.addWeighted(img, 0.7, mask_3channel, 0.3, 0)
cv2.imwrite('segmentation_verify.jpg', overlay)
结果说明

运行代码后生成的laa_mask.png为单通道二值掩码,目标区域值为255、背景值为0,和需求的目标掩码格式完全一致,可直接用于后续面积计算、形态学操作等任务。
如果后续测试的图像中目标区域为高亮度区域,只需将代码中np.argmin替换为np.argmax即可正确匹配目标类别。


内容的提问来源于stack exchange,提问作者TseHsien

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 04:45:40