Python编程:色温

色温(Color Temperature)是一个用来描述光源颜色特征的物理量,通常用开尔文温度(K)表示。它并不是指灯泡或光源的实际温度,而是以绝对黑体辐射为参照的一种度量方式。当一个理想的黑体被加热到特定温度时,它会发出特定颜色的光,这个颜色与光源的颜色相匹配时,该黑体的温度即为该光源的色温。

色温范围及其对应的光色:

  • 低于3000K:暖白色,给人以温暖、舒适的感觉,类似于烛光或者白炽灯。
  • 3000K至4500K:中性白色,较为柔和,适用于大多数室内环境。
  • 4500K至6500K:自然白色或冷白色,接近于日光,能提供清晰明亮的照明效果。
  • 高于6500K:日光色,非常冷的色调,常用于需要高度集中注意力的地方如办公室或医院手术室等。

色温计算是白平衡处理的核心环节,用于量化光源的颜色特性。以下是色温计算的完整技术解析和Python实现:

色温计算基本原理

  1. 色温定义

    • 表示光源颜色的物理量,单位开尔文(K)

    • 黑体辐射理论:当黑体加热时,其发光颜色随温度变化的轨迹称为普朗克轨迹

  2. 计算流程

关键算法实现

1. RGB到色温的转换
import numpy as np
import cv2

def rgb_to_cct(r, g, b):
    """
    通过RGB值估算色温(K)
    基于Robertson方法实现
    :param r,g,b: 归一化的RGB值(0-1)
    :return: 色温(K)
    """
    # 转换为XYZ色彩空间
    x = 0.4124564*r + 0.3575761*g + 0.1804375*b
    y = 0.2126729*r + 0.7151522*g + 0.0721750*b
    z = 0.0193339*r + 0.1191920*g + 0.9503041*b
    
    # 计算色度坐标
    x_chroma = x / (x + y + z)
    y_chroma = y / (x + y + z)
    
    # 计算色温(McCamy公式)
    n = (x_chroma - 0.3320) / (0.1858 - y_chroma)
    cct = 449 * n**3 + 3525 * n**2 + 6823.3 * n + 5520.33
    
    return int(cct)
2. 图像色温估计(完整实现)
def estimate_image_cct(img, method='robertson'):
    """
    估计图像整体色温
    :param img: BGR格式图像
    :param method: 计算方法('robertson'|'kang')
    :return: 色温(K)
    """
    # 转换为RGB并归一化
    rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) / 255.0
    
    # 计算图像平均色
    avg_color = np.mean(rgb, axis=(0,1))
    r, g, b = avg_color
    
    if method == 'kang':
        # Kang算法(高精度)
        x = 0.4124564*r + 0.3575761*g + 0.1804375*b
        y = 0.2126729*r + 0.7151522*g + 0.0721750*b
        z = 0.0193339*r + 0.1191920*g + 0.9503041*b
        
        u = (4*x) / (x + 15*y + 3*z)
        v = (6*y) / (x + 15*y + 3*z)
        
        # 查找最近的黑体辐射点
        # 这里使用简化计算,实际应使用查找表
        cct = 1000000 / (0.27487*u**2 - 2.0915*u + 4.2586)
    else:
        # Robertson算法(默认)
        cct = rgb_to_cct(r, g, b)
    
    return np.clip(cct, 2000, 15000)  # 限制在合理范围

色温计算优化

1. 基于色域的精确计算
def precise_cct(x, y):
    """
    高精度色温计算(需预计算查找表)
    :param x,y: CIE1931色度坐标
    :return: 色温(K)
    """
    # 等温线插值计算
    # 实际实现应包含完整查找表和插值算法
    u = (4*x) / (-2*x + 12*y + 3)
    v = (6*y) / (-2*x + 12*y + 3)
    
    # 计算与普朗克轨迹的最小距离
    # 此处为示例,实际需要完整实现
    distance = np.sqrt((u - 0.292)**2 + (v - 0.24)**2)
    return int(1/(0.0001*distance + 0.0000001))
2. 区域加权色温计算
def zonal_cct(img, weights=None):
    """
    分区加权色温计算
    :param img: 输入图像
    :param weights: 区域权重矩阵(与img同尺寸)
    :return: 加权色温(K)
    """
    if weights is None:
        # 默认中心加权
        h, w = img.shape[:2]
        weights = np.zeros((h,w))
        cv2.circle(weights, (w//2,h//2), min(w,h)//2, 1, -1)
    
    # 转换为LAB色彩空间
    lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
    l, a, b = cv2.split(lab)
    
    # 计算权重归一化
    weights = weights / np.sum(weights)
    
    # 计算加权平均色
    weighted_rgb = np.zeros(3)
    for i in range(3):
        weighted_rgb[i] = np.sum(img[:,:,i] * weights)
    
    return rgb_to_cct(*weighted_rgb/255)

色温计算的实际应用

1. 自动白平衡增益计算
def calculate_wb_gains(cct):
    """
    根据色温计算白平衡增益
    :param cct: 色温(K)
    :return: (r_gain, g_gain, b_gain)
    """
    # 基于黑体辐射模型的近似计算
    if cct < 4000:
        # 暖光环境
        r_gain = 1.0
        b_gain = 0.5 + (cct / 8000)
    elif cct > 7000:
        # 冷光环境
        r_gain = 1.0 - (cct - 7000) / 20000
        b_gain = 1.0
    else:
        # 中性光
        r_gain = 1.0
        b_gain = 1.0
    
    # 保持G通道不变
    return (r_gain, 1.0, b_gain)
2. 色温可视化工具
def visualize_cct(img):
    """色温可视化工具"""
    cct = estimate_image_cct(img)
    
    # 创建色温条
    gradient = np.linspace(1000, 10000, 256)
    colors = []
    for temp in gradient:
        r, g, b = color_from_cct(temp)
        colors.append([b, g, r])  # OpenCV使用BGR
    
    color_bar = np.array(colors, dtype=np.uint8)
    color_bar = cv2.resize(color_bar, (100, img.shape[0]))
    
    # 标记当前色温位置
    pos = int((cct - 1000) / (10000-1000) * 255)
    cv2.line(color_bar, (0, pos), (100, pos), (0,0,0), 2)
    
    # 合并显示
    result = np.hstack([img, color_bar])
    cv2.putText(result, f"CCT: {cct}K", (10,30), 
               cv2.FONT_HERSHEY_SIMPLEX, 1, (255,255,255), 2)
    
    return result

def color_from_cct(cct):
    """根据色温生成对应颜色(简化版)"""
    if cct < 2000:
        return (255, 150, 50)
    elif cct < 4000:
        return (255, 200, 150)
    elif cct < 6000:
        return (255, 255, 200)
    elif cct < 8000:
        return (200, 220, 255)
    else:
        return (150, 180, 255)

性能优化技巧

  1. 查找表预计算

    # 预计算色温查找表
    cct_lut = np.zeros((256,256,256))
    for r in range(256):
        for g in range(256):
            for b in range(256):
                cct_lut[r,g,b] = rgb_to_cct(r/255, g/255, b/255)
  • GPU加速计算

    import cupy as cp
    
    def gpu_cct(img):
        """GPU加速的色温计算"""
        img_gpu = cp.asarray(img)
        rgb_gpu = img_gpu / 255.0
        
        # 并行计算每个像素
        x = 0.4124564*rgb_gpu[:,:,0] + 0.3575761*rgb_gpu[:,:,1] + 0.1804375*rgb_gpu[:,:,2]
        y = 0.2126729*rgb_gpu[:,:,0] + 0.7151522*rgb_gpu[:,:,1] + 0.0721750*rgb_gpu[:,:,2]
        z = 0.0193339*rgb_gpu[:,:,0] + 0.1191920*rgb_gpu[:,:,1] + 0.9503041*rgb_gpu[:,:,2]
        
        x_chroma = x / (x + y + z)
        y_chroma = y / (x + y + z)
        
        n = (x_chroma - 0.3320) / (0.1858 - y_chroma)
        cct_map = 449 * n**3 + 3525 * n**2 + 6823.3 * n + 5520.33
        
        return int(cp.mean(cct_map).get())

评估与验证

  1. 色温计算精度测试

    def test_cct_accuracy():
        """测试色温计算精度"""
        test_cases = [
            # (RGB值, 预期色温)
            ((0.95, 0.88, 0.75), 3000),  # 白炽灯
            ((0.90, 0.95, 1.00), 6500),  # 日光
            ((0.80, 0.85, 0.95), 7500),  # 阴天
        ]
        
        for rgb, expected in test_cases:
            calculated = rgb_to_cct(*rgb)
            error = abs(calculated - expected) / expected
            print(f"RGB{rgb}: 计算{calculated}K, 预期{expected}K, 误差{error*100:.1f}%")
  • 实际图像测试流程

    img = cv2.imread('test_image.jpg')
    cct = estimate_image_cct(img)
    gains = calculate_wb_gains(cct)
    
    print(f"估计色温: {cct}K")
    print(f"建议白平衡增益: R={gains[0]:.2f}, G={gains[1]:.2f}, B={gains[2]:.2f}")
    
    # 应用白平衡
    balanced = img.copy().astype('float32')
    balanced[:,:,0] *= gains[2]  # B
    balanced[:,:,1] *= gains[1]  # G
    balanced[:,:,2] *= gains[0]  # R
    balanced = np.clip(balanced, 0, 255).astype('uint8')
    
    cv2.imshow('Original vs Balanced', np.hstack([img, balanced]))
    cv2.waitKey(0)

通过以上方法,可以实现精确高效的色温计算,为白平衡处理提供可靠的基础数据。实际应用中建议结合多种方法,并根据具体场景进行参数优化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值