双目拼接摄像机中简单的色差校正原理

目录

[1. 原理](#1. 原理)

[2. 实现](#2. 实现)

[3. 核心说明](#3. 核心说明)

[4. 关键执行约束](#4. 关键执行约束)


基于双目中性灰点的 UV 偏差,推导正确的 RGain/BGain 修正公式

1. 原理

(1)YUV 与 RGB 的正确转换(BT601 为例,ISP 标配)
python 复制代码
RGB→YUV(8bit,UV范围[-128,127],需归一化到[0,255]):
Y = 16 + (65.738*R + 129.057*G + 25.064*B)/256
U = 128 + (-37.945*R - 74.494*G + 112.439*B)/256
V = 128 + (112.439*R - 94.154*G - 18.285*B)/256

逆推:中性灰(R=G=B)时,U=128,V=128(归一化后);
若RGain偏大 → R>G=B → V>128;
若BGain偏大 → B>G=B → U<128;
若RGain偏小 → R<G=B → V<128;
若BGain偏小 → B<G=B → U>128。
(2)正确的修正逻辑

双目场景下,左图作为参考(WB 已校准),右图 UV 偏差 = 硬件差异 + WB 增益偏差,需先剔除硬件差异,再修正 WB:

2. 实现

python 复制代码
import numpy as np

# 全局WB增益缓存队列(用于样本不足时的平滑,初始化默认值1.0)
wb_gain_queue = {
    "RGain": [1.0] * 10,  # 8.8定点数对应初始值256
    "BGain": [1.0] * 10
}

def uv_adjust_wb_gain(U_l, V_l, U_r, V_r, Y_l, Y_r, mask, RGain_old, BGain_old, yuv_standard="BT601"):
    """
    基于双目中性灰点UV偏差,调整右图WB的RGain/BGain(无冗余+工程化修正)
    :param U_l/V_l: 左图公共区域U/V通道(参考,8bit,归一化后[0,255])
    :param U_r/V_r: 右图公共区域U/V通道(待校正,8bit,归一化后[0,255])
    :param Y_l/Y_r: 左/右图公共区域Y通道(用于校验内容一致性,8bit)
    :param mask: 有效像素Mask(1=有效,0=无效)
    :param RGain_old/BGain_old: ISP当前的RGain/BGain(浮点数,GGain=1)
    :param yuv_standard: YUV色彩空间(BT601/BT709)
    :return: 新的RGain、BGain(16bit 8.8定点数,ISP可直接写入)
    """
    # 1. 严格筛选双目中性灰点(核心条件)
    # 条件:① 有效Mask ② 左右目UV均接近中性灰 ③ 左右目亮度差小(内容一致)
    mask_gray_l = ((np.abs(U_l - 128) <= 10) & (np.abs(V_l - 128) <= 10)).astype(np.uint8)
    mask_gray_r = ((np.abs(U_r - 128) <= 10) & (np.abs(V_r - 128) <= 10)).astype(np.uint8)
    mask_y_consist = (np.abs(Y_l - Y_r) <= 10).astype(np.uint8)  # 亮度一致=内容一致
    mask_final = mask & mask_gray_l & mask_gray_r & mask_y_consist
    
    # 2. 提取双目中性灰点的UV
    valid_U_l = U_l[mask_final == 1]
    valid_V_l = V_l[mask_final == 1]
    valid_U_r = U_r[mask_final == 1]
    valid_V_r = V_r[mask_final == 1]
    
    # 3. 样本量校验 + 空值保护(核心优化:样本不足时用历史平滑值)
    valid_pix_num = len(valid_U_l)
    if valid_pix_num < 50:
        # 样本不足:返回队列中位数(8.8定点数),避免增益突变
        stable_RGain = np.median(wb_gain_queue["RGain"])
        stable_BGain = np.median(wb_gain_queue["BGain"])
        RGain_new_fixed = int(stable_RGain * 256)
        BGain_new_fixed = int(stable_BGain * 256)
        return RGain_new_fixed, BGain_new_fixed
    
    # 4. 计算双目UV偏差(仅WB导致的偏差,剔除硬件差异)
    delta_U_wb = np.mean(valid_U_r) - np.mean(valid_U_l)  # 右图U - 左图U
    delta_V_wb = np.mean(valid_V_r) - np.mean(valid_V_l)  # 右图V - 左图V
    
    # 5. 正确推导RGain/BGain修正值(修正k值顺序)
    # 系数k:UV偏差→WB增益的转换系数(BT601更敏感,k更小)
    k = 0.0035 if yuv_standard == "BT601" else 0.004
    RGain_new = RGain_old * (1 - delta_V_wb * k)  # V偏多→RGain调小(减少红色)
    BGain_new = BGain_old * (1 + delta_U_wb * k)  # U偏多→BGain调大(增加蓝色)
    
    # 6. 增益钳位(ISP硬件限制:±20%调整范围)
    RGain_new = np.clip(RGain_new, 0.8, 1.2)
    BGain_new = np.clip(BGain_new, 0.8, 1.2)
    
    # 7. 更新WB增益缓存队列(用于后续样本不足时的平滑)
    wb_gain_queue["RGain"].pop(0)
    wb_gain_queue["RGain"].append(RGain_new)
    wb_gain_queue["BGain"].pop(0)
    wb_gain_queue["BGain"].append(BGain_new)
    
    # 8. ISP适配:转换为16bit 8.8定点数(整数部分8bit,小数部分8bit)
    # 示例:0.8→205 (0.8*256), 1.0→256, 1.2→307 (1.2*256)
    RGain_new_fixed = int(RGain_new * 256)
    BGain_new_fixed = int(BGain_new * 256)
    
    return RGain_new_fixed, BGain_new_fixed

3. 说明

错误点 修正前 修正后
中性灰筛选 仅单目右图 双目中性灰点(左 + 右),且亮度一致(内容无差异)
偏差计算 单目 UV-128 双目 UV 偏差(右图 - 左图),剔除硬件差异
公式符号 无区分色彩空间 按 BT601/BT709 定系数,符号完全匹配 UV 与 RGain/BGain 的映射关系
输出格式 浮点数 定点数(ISP 硬件仅支持整数 / 定点数)
干扰排除 未排除内容差异 加左右目亮度一致性约束,避免场景内容干扰 WB 调整

4. 关键执行约束

  • ✅ WB 增益调整时机:必须在 ISP 的 "AWB 模块" 之后、"RGB2YUV 模块" 之前执行 ------RGain/BGain 是对 Sensor 原始 RGB 数据的增益,仅作用于后续帧,无法对当前帧已转换的 YUV 回退调整(此前建议 "重新处理" 不符合 ISP 实际);
  • ✅ 执行频率:每 10~20 帧调整一次(避免频繁写入 ISP 寄存器导致画面闪烁);
  • ✅ 硬件映射:RGain/BGain 在 ISP 中为 16bit 定点数(如 8.8 格式),需将浮点数转换为整数后写入(如 1.0→256,0.8→205)。

相关推荐
qq_281684212 小时前
Transformer-XL:突破固定长度枷锁,重构长文本语言模型
人工智能·深度学习·语言模型·重构·transformer
CoovallyAIHub2 小时前
中文语音识别该用谁?6 个开源模型 + 2 个配套工具,一文理清
深度学习·算法·计算机视觉
铮铭2 小时前
开源!π0.6-MEM 机器人长时记忆架构完整实现——基于 Physical Intelligence 最新论文的工程落地
人工智能·具身智能·vla
星始流年2 小时前
AI Agent 开发系列 之 01 🔎重新认识 LLM
人工智能·llm·agent
会编程的土豆2 小时前
【数据结构与算法】 二叉树做题
开发语言·数据结构·c++·算法
Henrybit933682 小时前
Claude与OpenAI的差异
人工智能
树上有只程序猿2 小时前
OpenClaw确实好用,但你得明白自己想要什么
人工智能
木禾ali0th2 小时前
告别大模型“裸奔”:开源项目 ClawVault 架构与核心能力解析
算法·安全
Storynone2 小时前
【Day28】LeetCode:509. 斐波那契数,70. 爬楼梯,746. 使用最小花费爬楼梯
python·算法·leetcode