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

数组点分组实现整组操作 OpenCV检测二值图白点遮挡

基于二值图像的LED孔洞白点遮挡检测方案

问题背景

我目前正在开发一款程序,可读取二值图像,自动识别图中是否存在被遮挡的白点:即程序预设应为白色的点位,实际在图像中呈现为黑色,采集场景为LED光线透过孔洞形成白色光点,相关参考图如下:

  • 二值化处理后示例图:二值化示例图
  • 原始采集图:原始采集图

当前实现代码

现有代码仅能在理想无干扰场景下生效,实现如下:

import cv2
import numpy as np

img = cv2.imread('bwimg.jpg')
pixels = np.asarray(img)
pixels = np.nonzero(pixels)
xpixels = pixels[1] # x coordinate of each white pixel
ypixels = pixels[0] # y coordinate of each white pixel

# example estimations for the center coordinates of some of the points (can be calibrated further, just an example)
xcoords = [60, 160, 255, 350, 445]
ycoords = [410, 405, 400, 395, 390]

for coo in range(0,4):
   indexList = np.ravel(np.asarray(xpixels == xcoords[coo]).nonzero())
   for y in range(0,4):
      for x in indexList:
         if ypixels[x] == ycoords[y]:
            print(x, xcoords[coo], ycoords[y])

优化需求

现有方案仅判定白点中心单个像素的颜色,鲁棒性极差,需要在以下异常场景下保持检测有效性:

  • 白点仅被半遮挡
  • 碎屑落在白点上导致少量像素被误判为黑色

预设优化思路:不再仅判定白点中心单个像素的颜色,而是以预设的白点中心坐标为圆心,划定固定半径的检测区域,若区域内白色像素占比超过50%,则判定该白点未被遮挡。已知可借助OpenCV或scipy实现该类数组点分组、整组区域判定的逻辑,求具体实现方法。

附注:我不常于平台发帖,不确定添加scipy标签是否符合板块规范,若不合适我会及时移除该标签。


实现方案

直接用OpenCV的掩码操作即可实现圆形区域的像素统计,不需要额外依赖scipy,计算效率高且逻辑稳定:

  1. 读取图像时直接转单通道灰度图,避免三通道冗余计算
  2. 针对每个预设白点坐标生成对应尺寸的圆形掩码,半径可根据实际白点大小标定(建议取白点实际半径的80%~90%)
  3. 用掩码截取对应检测区域,统计白色像素(值为255)占掩码总有效像素的比例,和设定阈值做对比即可输出判定结果

可直接运行的优化后代码

import cv2
import numpy as np

# 可根据实际场景标定的参数
DETECT_RADIUS = 8  # 检测区域圆形半径,匹配实际白点大小调整
WHITE_THRESHOLD = 0.5  # 白色像素占比阈值,超过则判定为正常未遮挡
EXPECTED_POINTS = list(zip([60, 160, 255, 350, 445], [410, 405, 400, 395, 390]))  # 预设白点中心坐标格式(x,y)

# 读取图像 直接加载为单通道灰度图
img = cv2.imread('bwimg.jpg', cv2.IMREAD_GRAYSCALE)
h, w = img.shape

# 可选:针对碎屑噪点做小半径形态学开运算,进一步提升鲁棒性
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
img = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)

for idx, (cx, cy) in enumerate(EXPECTED_POINTS):
    # 边界校验 避免预设坐标越界导致报错
    if cx - DETECT_RADIUS < 0 or cx + DETECT_RADIUS >= w or cy - DETECT_RADIUS <0 or cy + DETECT_RADIUS >=h:
        print(f"点位{idx} 坐标({cx},{cy})超出图像边界,判定为异常")
        continue
    # 生成圆形检测区域掩码
    mask = np.zeros((h,w), dtype=np.uint8)
    cv2.circle(mask, (cx, cy), DETECT_RADIUS, 255, thickness=-1)
    # 统计区域内总有效像素、白色像素数量
    total_pixels = cv2.countNonZero(mask)
    target_area = cv2.bitwise_and(img, img, mask=mask)
    white_pixels = cv2.countNonZero(target_area)
    white_ratio = white_pixels / total_pixels
    
    if white_ratio >= WHITE_THRESHOLD:
        print(f"点位{idx} 坐标({cx},{cy}) 正常,白色像素占比{white_ratio:.1%}")
    else:
        print(f"点位{idx} 坐标({cx},{cy}) 被遮挡,白色像素占比{white_ratio:.1%}")

调优提示

  • 检测半径不要设置过大,避免把相邻白点的像素纳入当前检测区域造成误判
  • 如果预设坐标存在标定偏移,可以先对每个预设点周围做小范围质心计算,将检测圆心对齐到实际白点的质心后再做占比统计,可进一步降低标定误差的影响
  • 阈值可根据现场遮挡的实际情况调整,半遮挡场景较多可适当下调阈值到0.30.4,要求严格可上调到0.60.7

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 13:33:22