4. 水下图像光照不均与后向散射的判读预处理

为什么先处理光照与后向散射

ROV 在浑水或斜向照明条件下拍摄的管体图像,常见两类退化:一是光照不均——补光灯中心亮、边缘暗,形成大尺度亮度梯度;二是后向散射——水中悬浮颗粒把灯光反射回镜头,在画面上叠加一层低对比度的“雾”,使暗部细节被抬亮、边缘被抹平。两者都会让判读员把亮度梯度误认为涂层色差,或把散射雾中的纹理噪声误判为裂纹。因此预处理的目标不是“把图修好看”,而是压平大尺度亮度场、抑制散射雾、保留并锐化真实边缘,同时不引入伪边缘。

处理链与参数选择

本例采用一条可复现的四步链:通道分解 → 大尺度背景估计与光照校正 → 散射雾抑制(暗通道先验去雾)→ 局部对比度增强与边缘保护。关键参数含义如下:

  • 背景估计尺度:用大核高斯或形态学闭运算估计低频亮度场,核尺寸应明显大于缺陷尺寸(示例取 61 像素),否则会把缺陷本身当成背景减掉。
  • 校正增益上限:除法校正后限制增益(示例 2.5 倍),防止暗角区域噪声被过度放大。
  • 去雾强度 ω:暗通道先验中保留多少雾,示例取 0.85;ω 越大去雾越强,但过强会在高亮反光处产生色偏与光晕。
  • 引导滤波半径与 ε:用于细化透射率图,半径 41、ε=1e-3,保证边缘处透射率不跳变。
  • CLAHE 裁剪限幅与网格:clipLimit=2.0、tile=8×8,提升局部纹理对比而不放大噪声。
判读前先做一次“参数敏感性”检查:同一帧用两组参数各出一版,若疑似缺陷在两组结果中位置与形态一致、仅清晰度不同,则该特征可信;若只在某一组参数下出现,多半是增强伪影。
光照不均 + 后向散射 → 校正 → 判读可用性对比 原始帧:中心过曝 / 边缘暗 散射雾叠加,纹理对比度低 ① 通道分解 B/G/R 分离 ② 背景估计 大核高斯 61px ③ 光照校正 除法校正,增益≤2.5 ④ 去雾 暗通道 ω=0.85 ⑤ 局部增强 CLAHE 2.0 / 8×8 低频亮度场 仅含光照梯度 透射率图 t(x) 引导滤波细化 校正帧:亮度均匀、雾感下降 疑似缺陷边界可辨(红圈) 处理前判读风险 · 暗角被误读为涂层色差 · 散射雾掩盖细裂纹 · 高亮反光处漏判 · 边界模糊,范围难圈定 处理后判读改善 · 亮度场压平,色差可信 · 纹理与边缘对比提升 · 疑似缺陷可圈定边界 · 需复核增强伪影 判读结论:疑似缺陷在两组参数下位置一致 → 可信 若仅单组参数出现 → 判为增强伪影,需回看原始帧

可执行的预处理实现

下面给出与上图处理链一致的 Python 实现(OpenCV + NumPy),输入为单帧 BGR 图像,输出为校正帧与中间产物,便于逐环节检查。

import cv2
import numpy as np

def estimate_illumination(bgr, ksize=61):
    # 大核高斯估计低频亮度场,核尺寸需远大于缺陷尺寸
    gray = cv2.cvtColor(bgr, cv2.COLOR_BGR2GRAY).astype(np.float32)
    bg = cv2.GaussianBlur(gray, (ksize, ksize), 0)
    return np.maximum(bg, 1.0)

def correct_illumination(bgr, bg, gain_max=2.5):
    out = bgr.astype(np.float32)
    for c in range(3):
        ch = out[:, :, c]
        gain = np.clip(bg / np.maximum(ch, 1.0), 1.0, gain_max)
        out[:, :, c] = np.clip(ch * gain, 0, 255)
    return out.astype(np.uint8)

def dark_channel(img, radius=7):
    b, g, r = cv2.split(img.astype(np.float32))
    min_ch = np.minimum(np.minimum(b, g), r)
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2*radius+1, 2*radius+1))
    return cv2.erode(min_ch, kernel)

def dehaze(bgr, omega=0.85, radius=7, t0=0.1, guide_r=41, eps=1e-3):
    img = bgr.astype(np.float32) / 255.0
    dc = dark_channel(bgr, radius) / 255.0
    # 大气光:暗通道最亮的前 0.1% 像素对应原图均值
    flat = dc.ravel()
    idx = flat.argsort()[-max(1, int(flat.size * 0.001)):]
    A = np.mean(img.reshape(-1, 3)[idx], axis=0)
    A = np.maximum(A, 1e-3)
    norm = img / A
    t = 1.0 - omega * dark_channel((norm * 255).astype(np.uint8), radius) / 255.0
    t = np.clip(t, t0, 1.0).astype(np.float32)
    # 引导滤波细化透射率,避免边缘光晕
    gray = cv2.cvtColor(bgr, cv2.COLOR_BGR2GRAY).astype(np.float32) / 255.0
    t = cv2.ximgproc.guidedFilter(gray, t, guide_r, eps)
    t = np.clip(t, t0, 1.0)[..., None]
    J = (img - A) / t + A
    return np.clip(J * 255, 0, 255).astype(np.uint8), t[..., 0]

def enhance(bgr, clip=2.0, tile=8):
    lab = cv2.cvtColor(bgr, cv2.COLOR_BGR2LAB)
    l, a, b = cv2.split(lab)
    clahe = cv2.createCLAHE(clipLimit=clip, tileGridSize=(tile, tile))
    l2 = clahe.apply(l)
    return cv2.cvtColor(cv2.merge([l2, a, b]), cv2.COLOR_LAB2BGR)

def preprocess(frame):
    bg = estimate_illumination(frame)
    corrected = correct_illumination(frame, bg)
    dehazed, tmap = dehaze(corrected)
    final = enhance(dehazed)
    return final, {"bg": bg, "corrected": corrected, "tmap": tmap}

if __name__ == "__main__":
    frame = cv2.imread("rov_frame_0001.png")
    final, mid = preprocess(frame)
    cv2.imwrite("out_final.png", final)
    cv2.imwrite("out_corrected.png", mid["corrected"])
    cv2.imwrite("out_tmap.png", (mid["tmap"] * 255).astype(np.uint8))

结果判读与验证

处理完成后按以下顺序核对,避免把增强伪影带入缺陷记录:

  1. 亮度均匀性:观察校正帧四角与中心,管体同一材质区域灰度差应明显缩小;若暗角处出现块状噪声,说明增益上限过高,回调至 2.0 左右。
  2. 雾感与色偏:去雾后水体背景应更暗、更透,但管体颜色不应偏蓝或偏黄;出现色偏时降低 ω 至 0.7 附近。
  3. 边缘真实性:将疑似缺陷边界与原始帧逐点对照,真实缺陷在原始帧中应有可追溯的灰度或颜色突变;仅在增强帧出现的“边缘”判为伪影。
  4. 参数一致性:同一缺陷用两组参数(如 ω=0.75 与 0.85)各处理一次,位置与形态一致方可进入缺陷圈定。
暗通道先验假设“无雾图像局部存在暗像素”,对高反光金属管体与强补光区域并不总成立,容易在镜面反光处产生光晕。此类区域应结合原始帧人工复核,不可仅凭去雾结果判定缺陷。

判读记录要点

记录项示例值作用
帧号 / 里程0001 / K3+120缺陷定位回溯
背景估计核61 px复现光照校正
增益上限2.5控制暗角噪声放大
去雾 ω / t00.85 / 0.1复现去雾强度
CLAHE 参数2.0 / 8×8复现局部增强
双参数一致性一致排除增强伪影
疑似缺陷位置管体 10 点钟方向供后续圈定与复拍

完成上述步骤后,校正帧即可作为后续缺陷识别与范围圈定的输入;原始帧与中间产物(亮度场、透射率图)应一并归档,以便复核时区分真实特征与处理引入的变化。