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

如何基于轮廓凹部在OpenCV中分割不同尺寸单色目标

基于distanceTransform的1-bit图像凹部分割实现方案

针对无噪声1-bit黑白图像中白色目标的凹部分割需求,尤其是目标尺寸差异大、椭圆或挤压变形的场景,用distanceTransform结合分水岭的方案可以解决传统分水岭种子选取失效的问题,核心思路是通过距离变换生成自适应尺寸的前景种子,再引导分水岭完成精准分割。

核心逻辑

distanceTransform能计算前景像素到最近背景的距离,目标内部的距离值从中心到边缘递减,凹部位置的距离值会明显低于周围凸区域。基于这个特征,我们可以提取每个子目标的核心作为分割种子,这些种子的大小会自适应目标尺寸,不会因为目标大小差异导致种子丢失或重叠。

分步实现

  • 1. 提取前景Mask
    直接从输入的1-bit图像中提取白色目标的二值Mask(白色为前景,值为1;黑色为背景,值为0),因为无噪声,无需额外降噪处理:

    mask = (img == 255).astype(np.uint8)
    
  • 2. 计算距离变换图
    使用L2距离类型计算距离变换,卷积核选5x5适配多数目标尺寸,输出32位浮点型距离图:

    dist_transform = cv2.distanceTransform(mask, cv2.DIST_L2, 5)
    

    距离图中,目标中心区域距离值最大,凹部区域距离值显著降低。

  • 3. 生成自适应前景种子
    用相对阈值提取距离图中高值区域作为确定前景(种子),阈值取距离最大值的70%(经验值,可根据凹部深浅调整):

    ret, sure_fg = cv2.threshold(dist_transform, 0.7 * dist_transform.max(), 255, 0)
    sure_fg = sure_fg.astype(np.uint8)
    

    这个相对阈值能自适应不同尺寸的目标:大目标的距离最大值高,种子区域范围合理;小目标的距离最大值低,种子也能精准定位核心。

  • 4. 确定背景与不确定区域
    对原始Mask做膨胀操作,得到覆盖凹部外侧的确定背景;再用背景减去前景种子,得到凹部所在的不确定区域:

    sure_bg = cv2.dilate(mask, np.ones((3,3), np.uint8), iterations=2)
    unknown = cv2.subtract(sure_bg, sure_fg)
    
  • 5. 标记连通区域
    对前景种子做连通区域标记,调整标记值避免与背景(0)混淆,再将不确定区域设为0:

    ret, markers = cv2.connectedComponents(sure_fg)
    markers = markers + 1  # 背景标记为1,前景种子从2开始编号
    markers[unknown == 255] = 0
    
  • 6. 应用分水岭分割
    将灰度图转为3通道图(分水岭要求输入为3通道),执行分水岭算法:

    img_color = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
    markers = cv2.watershed(img_color, markers)
    

    最终markers中,值为-1的是分割线,不同正整数对应不同的分割区域。

优化细节

  • 若凹部极浅,可降低阈值比例(如0.5),或用局部极大值检测替代阈值:通过对距离变换图做膨胀,再与原图对比提取局部极大点,得到更精准的种子。
  • 针对挤压变形的目标,可选用DIST_L1距离类型,计算更快且对变形区域的中心定位依然准确。
  • 若目标存在极小的凸起,可对前景种子做一次开运算,去除小的干扰连通区域。

内容的提问来源于stack exchange,提问作者김은수

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 07:35:24