色彩增强不同于彩色图像增强,图像增强的一般处理方式为直方图均衡化等,目的是为了增强图像局部以及整体对比度。而色彩增强的目的是为了使的原有的不饱和的色彩信息变得饱和、丰富起来。对应于Photoshop里面的“色相/饱和度”调节选项里面对饱和度的操作。色彩增强的过程,并不改变原有彩色图像的颜色以及亮度信息。
在我的色彩增强算法模块里面,始终只针对色彩饱和度(Saturation)信息做研究,调整。这样的话,那就不得不介绍HSV颜色空间了,H代表Hue(色彩),S代表Saturation(饱和度),V代表Value,也可用B表示(Brightness,明度),HSV空间也可称作HSB空间。
HSV空间在wikipedia上的介绍,https://en.wikipedia.org/wiki/HSL_and_HSV
下面根据自己的理解介绍一下HSV空间,以及其各通道在Matlab和OpenCV中的不同。
HSV的圆柱模型
HSV的圆锥模型
从上图可以看出,在HSV空间中,Hue通道的取值从0-360°变化时,颜色从红->黄->绿->青->蓝逐步变化。Saturation从0->1变化时,色彩逐渐加深变成纯色(pure)。Value值从0->1变化时,图像整体亮度增加,V值为0时,图像为全黑,V值为1时,图像为全白。
Matlab RGB色彩空间向HSV转换,采用函数rgb2hsv,转换后的hsv各通道的元素取值范围为[0,1];OpenCV中彩色图像向HSV空间中转换,cvtColor(src,srcHsv,CV_BGR2HSV),转换后H的取值范围为[0,180],S,V的取值范围为[0,255].
下面介绍自己的算法处理思路,后面会给出完整的Matlab代码:
步骤一、给出一张原图src,用PS进行饱和度(Saturation)+40处理后另存为src_40;
步骤二、将以上两张图像分别转换到hsv空间,提取出饱和度信息,分别为S,S_40;
步骤三、统计饱和度增加40后,原色彩饱和度与饱和度增量之间的对应关系,即S -- (S_40-S);
步骤四、对关系S -- (S_40-S)进行二次多项式曲线拟合,得到二次曲线f(x) = p1*x^2 + p2*x + p3;
为什么是二次?1.对应关系呈现出抛物线形状;2.更高次曲线并没有明显改善拟合性能,且计算消耗会变高。
步骤五、任意给定输出图像input,根据其色彩饱和度信息,即可进行色彩增强40处理,新的饱和度信息可以表示为S'(x) = S(x) + f(x),得到增强后的色彩信息后返回RGB图像输出;
步骤六、分别对原图+20,+40,+60后进行饱和度信息统计,并得到相应拟合参数,设置为色彩增强的低、中、高三挡,在实际处理过程中,根据输入图像input自身色彩饱和度信息(均值)自适应选取相应参数进行色彩增强;
步骤七、按需对某一单独颜色通道进行色彩增强处理,例如绿色范围为105°-135°,在对该范围进行增强的同时,还需对75°-105°,135°-165°进行一半强度的增强,这样才会保证色彩的连续性,不会出现色斑;
步骤八、按需对色彩(Hue)进行转换;
代码部分:第一部分用作估计拟合参数,在Curve fitting tool里面对X,Y进行拟合,得到曲线参数。
% Color Enhancement
clc,clear,close all
src1 = imread('src.bmp');
src2 = imread('src_40.bmp');
src1_hsv = rgb2hsv(src1);
src2_hsv = rgb2hsv(src2);
h1 = src1_hsv(:,:,1);
s1 = src1_hsv(:,:,2);
v1 = src1_hsv(:,:,3);
h2 = src2_hsv(:,:,1);
s2 = src2_hsv(:,:,2);
v2 = src2_hsv(:,:,3);
%
meanS1 = mean(s1();
varS1 = std2(s1);
%
meanS2 = mean(s2();
varS2 = std2(s2);
%
deltaS = s2 - s1;
deltaV = v2 - v1;
%% test1 : 观测“原饱和度-饱和度调整增量”的关系 saturation and delta saturation
figure;
oriS = zeros(101,2);
s3 = s1;
j = 1;
for i = 0: 0.01 : 1
oriS(j,1) = i + 0.01;
oriS(j,2) = mean(deltaS(find(s1 > i & s1< i + 0.01)));
j = j + 1;
end
X = oriS(:,1);
Y = oriS(:,2);
XX = oriS(:,1) * 255;
YY = oriS(:,2) * 255;
plot(XX,YY)
第二部分,对输入图像进行高、中、低三级自适应增强处理
-
%% Color Enhancement Module -- Authored by HuangDao,08/17/2015
-
% functions: input a image of type BMP or PNG, the program will decide to
-
% do the Color Enhancement choice for you.There are four types of Enhanced
-
% intensity - 20,40,60,80.The larger number stands for stronger
-
% enhancement.
-
% And we can also choose the simple color channel(eg.R,G,B) to do the
-
% enhancement.There are also four different types of enhanced intensity.
-
%
-
% parameters table
-
% ------------------------------------------------------------------------
-
% | Enhanced | MATLAB params | OpenCV params |
-
% | intensity |p1 p2 p3 | p1 p2 p3 |
-
% | 20 |-0.1661 0.2639 -0.003626 |-0.0006512 0.2639 -0.9246|
-
% | 40 |-0.4025 0.6238 -0.0005937 |0.001578 0.6238 -0.1514|
-
% | 60 |1.332 1.473 -0.01155 |-0.005222 1.473 -2.946 |
-
% | 80 |-4.813 3.459 -0.004568 |-0.01887 3.459 -1.165 |
-
% ------------------------------------------------------------------------
-
-
clc; clear ;close all
-
% 载入文件夹
-
pathName = '.\';
-
fileType = '*.bmp';
-
files = dir([pathName fileType]);
-
len = length(files);
-
-
for pic = 5%1:1:len
-
srcName = files(pic).name;
-
srcImg = imread(srcName);
-
srcHSV = rgb2hsv(srcImg);
-
srcH = srcHSV(:,:,1);
-
srcS = srcHSV(:,:,2);
-
srcV = srcHSV(:,:,3);
-
meanS = mean(srcS(:));
-
varS = std2(srcS);
-
%图像整体进行色彩增强处理
-
if (meanS >= 0.5)
-
p1 = 0;p2 = 0;p3 = 0;
-
else if (meanS >= 0.35 && meanS
< 0.5)
-
p1 =
-0.1661;p2 =
0.2639;p3 =
-0.003626;
-
else
if (
meanS >=0.2 && meanS
<0.35)
-
p1 = -0.4025;p2 = 0.6238;p3 = -0.0005937;
-
else
-
p1 = 1.332;p2 = 1.473;p3 = -0.01155;
-
end
-
end
-
end
-
dstS = srcS + p1*srcS.*srcS + p2*srcS + p3 ;
-
dstHSV = srcHSV;
-
dstHSV(:,:,2) = dstS;
-
dstImg = hsv2rgb(dstHSV);
-
figure;imshow(srcImg);
-
figure;imshow(dstImg);
-
%指定R,G,B通道进行色彩增强处理,红色范围([225-255]),绿色范围(75-[105-135]-165),蓝色范围([-15-15])
-
p11 = -0.4025;p21 = 0.6238;p31 = -0.0005937;%周边杂色调整系数,40
-
p12 = 1.332; p22 = 1.473; p32 = -0.01155; %纯色区域调整系数,60
-
compHue = srcH;
-
GcompS = dstS;
-
RcompS = dstS;
-
BcompS = dstS;
-
channel = 'B';
-
switch channel
-
case 'G'
-
I1 = find(compHue > 0.2083 & compHue
<0.2917);
-
GcompS(
I1) =
dstS(I1) +
dstS(
I1)
.*
dstS(
I1)*
p11 +
dstS(
I1)*
p21 +
p31;
-
I2 =
find(compHue >= 0.2917 & compHue
<= 0.3750);
-
GcompS(
I2) =
dstS(I2) +
dstS(
I2)
.*
dstS(
I2)*
p12 +
dstS(
I2)*
p22 +
p32;
-
I3 =
find(compHue > 0.3750 & compHue
<0.4583);
-
GcompS(
I3) =
dstS(I3) +
dstS(
I3)
.*
dstS(
I3)*
p11 +
dstS(
I3)*
p21 +
p31;
-
compHSV =
dstHSV;
-
compHSV(
:,
:,
2) =
GcompS;
-
dstImgG =
hsv2rgb(compHSV);
-
figure;
imshow(
dstImgG);
-
case '
R'
-
I1 =
find(compHue > 0.875 & compHue
<0.9583);
-
RcompS(
I1) =
dstS(I1) +
dstS(
I1)
.*
dstS(
I1)*
p11 +
dstS(
I1)*
p21 +
p31;
-
I2 =
find(compHue >= 0.9583 | compHue
<= 0.0417);
-
RcompS(
I2) =
dstS(I2) +
dstS(
I2)
.*
dstS(
I2)*
p12 +
dstS(
I2)*
p22 +
p32;
-
I3 =
find(compHue > 0.0417 & compHue
<0.125);
-
RcompS(
I3) =
dstS(I3) +
dstS(
I3)
.*
dstS(
I3)*
p11 +
dstS(
I3)*
p21 +
p31;
-
compHSV =
dstHSV;
-
compHSV(
:,
:,
2) =
RcompS;
-
dstImgR =
hsv2rgb(compHSV);
-
figure;
imshow(
dstImgR);
-
case '
B'
-
I1 =
find(compHue > 0.5417 & compHue
<0.625);
-
BcompS(
I1) =
dstS(I1) +
dstS(
I1)
.*
dstS(
I1)*
p11 +
dstS(
I1)*
p21 +
p31;
-
I2 =
find(compHue >= 0.625 & compHue
<= 0.7083);
-
BcompS(
I2) =
dstS(I2) +
dstS(
I2)
.*
dstS(
I2)*
p12 +
dstS(
I2)*
p22 +
p32;
-
I3 =
find(compHue > 0.7083 & compHue
<0.7917);
-
BcompS(
I3) =
dstS(I3) +
dstS(
I3)
.*
dstS(
I3)*
p11 +
dstS(
I3)*
p21 +
p31;
-
compHSV =
dstHSV;
-
compHSV(
:,
:,
2) =
BcompS;
-
dstImgB =
hsv2rgb(compHSV);
-
figure;
imshow(
dstImgB);
-
end
-
%进行
R,
G,
B通道之间的互换
-
convH =
zeros(size(srcH,1),size(srcH,2)); %
convert
-
deltaHue =
240;
-
switch
deltaHue
-
case
120
-
disp('
R
-> G')
-
convH = srcH + 1/3;
-
convH(find(convH >= 1)) = convH(find(convH >= 1)) - 1;
-
case 240
-
disp('R -> B')
-
convH = srcH + 2/3;
-
convH(find(convH >= 1)) = convH(find(convH >= 1)) - 1;
-
end
-
convHSV = dstHSV;
-
convHSV(:,:,1) = convH;
-
convImg = hsv2rgb(convHSV);
-
figure;imshow(convImg)
-
pause();
-
end
添加OpenCV代码段:
-
Mat srcHSV,sat,satAdj,dstMerge,dst;
//sat - saturation饱和度分量
-
Mat imageAwb = imread(
"m_ImageAwb.bmp");
-
vector
channels,channels1;
-
double p1,p2,p3;
-
-
cvtColor(imageAwb,srcHSV,CV_BGR2HSV);
-
split(srcHSV,channels);
-
split(srcHSV,channels1);
-
sat = channels.at(
1);
-
Scalar m = mean(sat);
-
-
if (m(
0) <=
51.5)
-
{p1 =
-0.002714 , p2 =
0.9498, p3 =
-0.5073; AfxMessageBox(
"High Color Enhancement!"); }
//高
-
else
if (m(
0) >
38.5 && m(
0) <=
89.5)
-
{p1 =
-0.001578 , p2 =
0.6238, p3 =
-0.1514;AfxMessageBox(
"Middle Color Enhancement!"); }
//中
-
else
if (m(
0) >
89.5 && m(
0) <=
127.5)
-
{p1 =
-0.0006512, p2 =
0.2639, p3 =
-0.9246;AfxMessageBox(
"Low Color Enhancement!");}
//低
-
else
-
{p1 =
0,p2 =
0,p3 =
0;AfxMessageBox(
"No Color Enhancement!");}
-
-
satAdj = sat;
-
for (
int i =
0 ; i < sat.rows;i ++)
-
{
-
for (
int j =
0;j < sat.cols;j ++)
-
{
-
uchar val = sat.at
(i,j);
-
satAdj.at
(i,j) = (val + p1 * val * val + p2 * val + p3) ;
-
}
-
}
-
-
channels1.at(
1) = satAdj;
-
merge(channels1,dstMerge);
-
cvtColor(dstMerge,dst,CV_HSV2BGR);
-
imwrite(
"m_ImageCE.bmp",dst);
最后给出算法效果图:
Group1.原图->增强后
Group2.原图->R通道增强->颜色通道改变R2B
Group3.原图->增强后->颜色通道改变R2B
完!下篇讲Local Tone Mapping。