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

如何用OpenCV或传统方法提取亮度不均的钢材灰度图轮廓?

钢材灰度图像轮廓提取优化(适配高亮度/亮度不均场景)

问题背景

手头有大量钢材灰度图像,部分亮度偏高,还有些存在亮度不均的问题,目前的轮廓提取效果有缺陷,想找更靠谱的处理方案。

现有尝试

先通过确定左右边界裁剪来减少背景噪声,裁剪后的处理代码如下:

m=img.shape[0]//2
count=mayregion
if clip_top:
    last_row = img_three[-1, :]  
    mid_row= img_three[m, :]  
    mean_pixel = (np.mean(last_row)+np.mean(mid_row))//2
    count=(np.sum(last_row > 240)+np.sum(mid_row>240))
else:
    last_row = img_three[0, :]  
    mid_row = img_three[m, :]  
    mean_pixel = (np.mean(last_row) + np.mean(mid_row)) // 2
    count = (np.sum(last_row > 240) + np.sum(mid_row > 240))
if mean_pixel>240:
    k=100
elif mean_pixel>210:
    k=80
else:
    k=30
img_three_color = cv2.cvtColor(img_three, cv2.COLOR_GRAY2BGR)
img_three = cv2.GaussianBlur(img, (7, 7), 1)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
img_open = cv2.morphologyEx(img_three, cv2.MORPH_OPEN, kernel)
img_close = cv2.morphologyEx(img_open, cv2.MORPH_CLOSE, kernel)
_, binary = cv2.threshold(img_close, k, 255, cv2.THRESH_BINARY)

contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

filtered_contours = [cnt for cnt in contours if cv2.contourArea(cnt) >= 100]
cv2.drawContours(img_three_color, filtered_contours, -1, (0, 255, 0), 10)

但用这个方法提取的轮廓还是有不少问题。

优化方向

针对高亮度和亮度不均的核心问题,可以从这几个点调整:

  • 用自适应阈值替代全局阈值:全局阈值在亮度不均的图里要么丢细节要么留噪声,cv2.adaptiveThreshold能根据局部区域的像素分布算阈值,适配不同区域的亮度变化,替换原全局阈值代码:
    binary = cv2.adaptiveThreshold(img_close, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2)
    
    其中11是局部块大小(需为奇数),2是阈值偏移量,可根据你的图像实际情况微调。
  • 换用双边滤波替代高斯模糊:高斯模糊容易把边缘糊掉,双边滤波能在滤除噪声的同时保留边缘细节,适合钢材这种需要清晰边缘的场景:
    img_three = cv2.bilateralFilter(img, d=9, sigmaColor=75, sigmaSpace=75)
    
  • 优化形态学操作参数:当前的(3,3)椭圆核可能太细,试试调大到(5,5),或者增加形态学梯度操作强化边缘:
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
    img_grad = cv2.morphologyEx(img_open, cv2.MORPH_GRADIENT, kernel)
    
  • 改进阈值计算逻辑:原逻辑只取两行像素的均值来定阈值,样本量太小容易误判。可以改用Otsu自动阈值法,它能根据图像直方图自动找到最优分割阈值:
    _, binary = cv2.threshold(img_close, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    
  • 增强轮廓后处理:除了面积过滤,还可以加长宽比过滤,剔除不符合钢材形态的噪声轮廓:
    filtered_contours = []
    for cnt in contours:
        area = cv2.contourArea(cnt)
        if area < 100:
            continue
        x, y, w, h = cv2.boundingRect(cnt)
        aspect_ratio = w / h
        # 根据你的钢材实际形态设定合理范围,这里只是示例
        if 0.2 < aspect_ratio < 5:
            filtered_contours.append(cnt)
    

实操建议

优先试自适应阈值+双边滤波的组合,先解决亮度不均的核心问题;再根据轮廓的具体缺陷(比如断边、噪声轮廓多)调整形态学参数和过滤规则,逐步优化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 16:21:00