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

如何用OpenCV检测图像中被白色区域包围的黑色区域轮廓

黑色区域检测与分割方案

针对你提供的预处理后图像,要检测被上下白色区域(顶部白色可能不连通)包围的黑色区域,可采用以下两种实用方案:

方案一:基于连通分量分析

利用连通分量识别上下白色区域,再提取中间黑色区域:

  1. 提取白色连通域
    用OpenCV的连通分量分析工具,找出图像中所有白色区域的位置与属性:

    import cv2
    import numpy as np
    
    # 读入灰度图并确保二值化
    img = cv2.imread('your_image.jpg', cv2.IMREAD_GRAYSCALE)
    _, binary = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
    
    # 分析白色连通域(connectivity=8表示8邻域连通)
    num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(binary, connectivity=8)
    
  2. 筛选上下白色区域
    根据连通域的垂直位置,将顶部和底部的白色区域分类:

    h, w = binary.shape
    upper_threshold = h // 3  # 顶部区域阈值,可根据实际调整
    lower_threshold = h * 2 // 3  # 底部区域阈值
    
    upper_labels = []
    lower_labels = []
    for i in range(1, num_labels):
        y = stats[i][1]  # 连通域外接矩形的顶部y坐标
        height = stats[i][3]
        # 筛选顶部白色区域
        if y + height < upper_threshold:
            upper_labels.append(i)
        # 筛选底部白色区域
        if y > lower_threshold:
            lower_labels.append(i)
    
  3. 生成掩码并提取黑色区域
    合并上下白色区域生成掩码,再提取中间的黑色区域:

    # 创建上下白色区域的掩码
    upper_mask = np.zeros_like(binary)
    for label in upper_labels:
        upper_mask[labels == label] = 255
    
    lower_mask = np.zeros_like(binary)
    for label in lower_labels:
        lower_mask[labels == label] = 255
    
    combined_mask = cv2.bitwise_or(upper_mask, lower_mask)
    
    # 提取中间黑色区域
    inverted = cv2.bitwise_not(binary)
    black_region = cv2.bitwise_and(inverted, cv2.bitwise_not(combined_mask))
    
  4. 检测黑色区域轮廓
    提取目标区域的轮廓并可视化:

    contours, _ = cv2.findContours(black_region, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    # 在原图上绘制绿色轮廓
    result = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
    cv2.drawContours(result, contours, -1, (0, 255, 0), 2)
    

方案二:基于水平投影分析

通过统计每行的白色像素占比,快速定位上下白色区域的边界,适合顶部白色不连通的场景:

  1. 计算水平投影
    统计图像每行的白色像素数量:

    row_sum = np.sum(binary == 255, axis=1)
    
  2. 定位上下边界
    找到顶部白色区域的最低行,以及底部白色区域的最高行:

    # 找顶部白色区域的底部边界
    upper_bottom = np.max(np.where(row_sum > 0)[0][np.where(row_sum > 0)[0] < h//3])
    # 找底部白色区域的顶部边界
    lower_top = np.min(np.where(row_sum > 0)[0][np.where(row_sum > 0)[0] > h*2//3])
    
  3. 提取中间黑色区域
    直接截取上下边界之间的区域,再检测轮廓:

    # 截取中间区域
    middle_region = binary[upper_bottom:lower_top, :]
    # 反向后找黑色区域轮廓(此时黑色已转为白色)
    inverted_middle = cv2.bitwise_not(middle_region)
    contours, _ = cv2.findContours(inverted_middle, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    

注意事项

  • 若图像存在噪声小斑点,可先执行形态学开操作去除:binary = cv2.morphologyEx(binary, cv2.MORPH_OPEN, np.ones((3,3), np.uint8))
  • 方案二对顶部白色不连通的场景鲁棒性更强,无需关心白色块的数量;方案一更适合需要精确区分上下白色区域的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 14:51:04