色彩平衡公式数学原理解析及影调分区调整参数设置
色彩平衡实现公式逻辑与影调调整参数说明
我找到了一份色彩平衡(Color Balance)功能的实现参考,希望有人能解释下述公式的推导逻辑:
float DR=(1-cr_val)*R1+(cr_val)*R2-0.5; float DG=(1-cr_val)*G1+(cr_val)*G2-0.5; float DB=(1-cr_val)*B1+(cr_val)*B2-0.5;
该实现的完整代码如下:
#include <iostream> #include <vector> #include <stdio.h> #include <functional> #include <algorithm> #include <numeric> #include <cstddef> #include "opencv2/opencv.hpp" using namespace std; using namespace cv; int val_Cyan_Red=0; int val_Magenta_Green=0; int val_Yellow_Blue=0; Mat result; Mat Img; void on_trackbar( int, void* ) { float SH=0.1; // 缩放系数,对应阴影/中间调/高光不同调整模式 float cr_val=(float)val_Cyan_Red/255.0; float mg_val=(float)val_Magenta_Green/255.0; float yb_val=(float)val_Yellow_Blue/255.0; // 青-红通道调整 float R1=0; float G1=1; float B1=1; float R2=1; float G2=0; float B2=0; float DR=(1-cr_val)*R1+(cr_val)*R2-0.5; float DG=(1-cr_val)*G1+(cr_val)*G2-0.5; float DB=(1-cr_val)*B1+(cr_val)*B2-0.5; result=Img+(Scalar(DB,DG,DR)*SH); // 洋红-绿通道调整 R1=1; G1=0; B1=1; R2=0; G2=1; B2=0; DR=(1-mg_val)*R1+(mg_val)*R2-0.5; DG=(1-mg_val)*G1+(mg_val)*G2-0.5; DB=(1-mg_val)*B1+(mg_val)*B2-0.5; result+=(Scalar(DB,DG,DR)*SH); // 黄-蓝通道调整 R1=1; G1=1; B1=0; R2=0; G2=0; B2=1; DR=(1-yb_val)*R1+(yb_val)*R2-0.5; DG=(1-yb_val)*G1+(yb_val)*G2-0.5; DB=(1-yb_val)*B1+(yb_val)*B2-0.5; result+=(Scalar(DB,DG,DR)*SH); imshow("Result",result); waitKey(10); } int main( int argc, char** argv ) { namedWindow("Image",cv::WINDOW_NORMAL); namedWindow("Result"); Img=imread("D:\ImagesForTest\cat2.jpg",1); Img.convertTo(Img,CV_32FC1,1.0/255.0); createTrackbar("CyanRed", "Image", &val_Cyan_Red, 255, on_trackbar); createTrackbar("MagentaGreen", "Image", &val_Magenta_Green, 255, on_trackbar); createTrackbar("YellowBlue", "Image", &val_Yellow_Blue, 255, on_trackbar); imshow("Image",Img); waitKey(0); }

另外原实现提到,修改trackbar的缩放系数可以分别针对阴影(Shadows)、中间调(Midtones)、高光(Highlights)区域生效,想知道调整这三个不同影调区间时,对应的参数应该设置为多少。
公式推导逻辑解释
- 核心是基于色轮互补色的线性插值:色彩平衡的三个调整轴分别是青-红、洋红-绿、黄-蓝,每一组都是互补色对,滑块拉到两端对应纯色偏,拉到中间位置无调整。
- 以青-红轴为例:
R1/G1/B1 = 0/1/1对应青色(红通道值为0,绿、蓝通道满值),R2/G2/B2 = 1/0/0对应红色(红通道满值,绿、蓝通道值为0),(1-cr_val)*基色1 + cr_val*基色2就是在青色、红色两个端点之间做0-1范围的线性插值,得到当前滑块位置对应的目标色偏值。 - 末尾减0.5是做归零偏移:当滑块处在中间位置(cr_val=0.5)时,插值结果为(0.5,0.5,0.5),减0.5后得到(0,0,0),也就是不添加任何色偏,符合滑块居中无调整的交互逻辑。注意OpenCV默认是BGR通道顺序,代码里叠加色偏时传入Scalar的顺序是蓝、绿、红偏移量,和DB/DG/DR的计算顺序对应,不存在通道顺序错误。
- 最后计算结果乘缩放系数SH叠加到原图像素值上,就是最终的色偏调整效果,三个互补色轴的计算逻辑完全一致。
不同影调的参数设置
你贴的是简化版实现,固定SH值只能做全局色彩调整,原代码里“修改SH对应不同影调”的注释并不完全准确——要实现分影调调整,不能只改固定SH值,需要先给每个像素根据自身亮度计算调整权重,再把固定SH替换成对应权重即可:
- 阴影调整:权重和像素亮度成反比,亮度越低权重越高,常用权重公式为
shadow_weight = 1 - pixel_luma,对应基础SH取值建议0.08~0.15,权重越高暗部色偏调整强度越大 - 中间调调整:权重围绕亮度0.5呈类高斯分布,亮度越接近中灰权重越高,常用权重公式为
midtone_weight = 1 - abs(pixel_luma - 0.5)*2,对应基础SH取值建议0.1~0.2 - 高光调整:权重和像素亮度成正比,亮度越高权重越高,常用权重公式为
highlight_weight = pixel_luma,对应基础SH取值建议0.08~0.15
如果只做最简效果验证,不需要逐像素算权重的话,固定SH可以参考:阴影模式设0.1、中间调设0.15、高光设0.1,调整强度和Photoshop色彩平衡的默认参数接近。
内容的提问来源于stack exchange,提问作者Distinct_Cabinet
相关产品推荐
相关产品推荐

