如何基于灰度值裁剪从低对比度灰度图像中提取的条纹区域
条纹高亮区域提取方案咨询
这是我此前低对比度灰度图像条纹提取问题的后续问询。
经过调研和梳理后,我当前需要解决的问题是对之前步骤提取得到的各条条纹进行裁剪处理。
我目前得到的条纹示例如下:

我需要裁剪保留其中的高亮区域,预期效果如下:

(部分像素因灰度值过低可能不可见)。
我尝试过使用OpenCV的otsu threshold处理,但因为绝大多数像素为黑色背景,效果不佳。另外由于光照不均,每条条纹的对比度都存在差异。
目前我认为该需求本质是识别标记出灰度值处于高位平稳区间的所有像素,剔除低于阈值的像素,但还未找到合适的实现方案。
恳请各位提供可行建议,非常感谢!
解答
1. 带掩码的Otsu阈值法(适配大量黑色背景场景)
你之前使用Otsu阈值效果不佳的核心原因是大量纯黑背景像素参与了阈值计算,拉低了全局最优阈值的结果,只要增加掩码过滤步骤即可解决:
- 首先生成非零像素掩码,过滤掉纯黑背景:
import cv2 import numpy as np img = cv2.imread("stripe.png", 0) mask = img > 0 # 仅保留非背景像素
- 仅对掩码覆盖的条纹区域执行Otsu阈值计算:
stripe_pixels = img[mask] ret, _ = cv2.threshold(stripe_pixels, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
- 用计算得到的阈值对整图做二值化,保留高亮区域:
result = np.where(img >= ret, img, 0)
2. 百分位动态阈值法(适配不同条纹的对比度差异)
针对每条条纹对比度不同的问题,可以直接基于单张图的灰度分布动态取高位区间像素,不需要固定阈值:
# 提取所有非零像素的灰度值 stripe_pixels = img[img > 0] # 取灰度值的85分位数作为阈值(可根据实际效果调整分位数值,范围0-100) threshold = np.percentile(stripe_pixels, 85) result = np.where(img >= threshold, img, 0)
该方案会自动适配每张图的灰度分布,不需要针对不同条纹单独调参。
3. 自适应阈值法(解决单条条纹内部光照不均问题)
如果单条条纹内部也存在光照明暗不均的情况,可以使用局部自适应阈值处理:
# 块大小和偏移量可根据条纹尺寸调整 thresh = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 3) result = cv2.bitwise_and(img, img, mask=thresh)
内容的提问来源于stack exchange,提问作者Xinlong Wang
相关产品推荐
相关产品推荐

