色彩特性实验
第一章 要求
数字成像的作业,当时做的时候查了很多资料,现在把过程记录一下。
用matlab模拟Imatest的“colorcheck”模块编写一个色差处理程序。要求实现最基本功能:读入相机拍摄的色卡图像,用鼠标拖选单个色块区域,手动输入色块编号,程序可以自动计算色差ΔEab和ΔCab。24个色块的标准值选用爱色丽色卡的sRGB标称值,经XYZ空间转换到CIE Lab均匀颜色空间,在D65照明体下比较和显示色差。
第二章 色彩空间
2.1 色彩空间
所谓色彩空间,即一定的色彩范围,这是一种色彩模型。sRGB、AdobeRGB、ProPhotoRGB、CMYK等都是不同的色彩空间。它们都以可见光谱为基础,但分别包含不同的色彩范围。
2.2 sRGB色彩空间
sRGB色彩空间是惠普与微软于1996年一起开发的用于显示器、打印机以及因特网的一种标准RGB色彩空间。这种标准得到了W3C、Exif、英特尔、Pantone、Corel以及其它许多业界厂商的支持,在GIMP这样的开放源代码软件也支持这种标准,另外一些专有的或者像SVG这样的开放图形文件格式中也有应用。
sRGB定义了红色、绿色与蓝色三原色的颜色,即在其它两种颜色值都为零时该颜色的最大值。在CIE xy颜色坐标系中红色位于[0.6400, 0.3300]、绿色位于[0.3000, 0.6000]、蓝色位于[0.1500, 0.0600]、白色是位于[0.3127,0.3290]的D65。对于任何的RGB色彩空间来说,非负的R、G、B都不可能表示超出原色定义的三角形即色域范围,它刚好在人眼的色彩感知范围之内。
2.3 CIE Lab色彩空间
CIE(Commission International del’Eclairage)国际标准照明委员会于1931年建立了一系列表示可见光谱的颜色空间标准。它有三个基本量,用X、Y、Z表示,通过X、Y、Z能够表示任何一种颜色,X、Y、Z的值能够利用R、G、B线性表示出来,相对于RGB颜色空间,XYZ颜色空间几乎能包含人类能够感觉到的所有颜色,但XYZ颜色空间仍然是一种不均匀的颜色空间。因此在CIE-XYZ颜色空间的基础上又有了CIE-Lab,CIE-Luv等颜色空间。
国际照明委员会制定了Lab颜色空间,人类所能感觉到的任何颜色都可以在Lab颜色空间中表示出来,其颜色空间比RGB颜色空间还大,可以直接使用欧几里德距离来衡量两种颜色的差异性。这种模式是以数字化的方式来描述人的视觉感觉,它与显示器的色移、输出设备以及其他设备无关。Lab系统是一个优秀的亮度和彩色分离器,它在图像压缩方面很有用。其中L代表亮度,a的正方向代表红色,负方向代表绿色,b的正方向代表黄色,负方向代表蓝色。Lab颜色空间由XYZ转换而得
任意颜色在LAB空间都会有一个准确的数值表示而且和设备无关,任何单一色调背景下,用通道抠有明显颜色区别的部分,用LAB模式很快能完成;LAB模式下对明度(L)通道做任何操作(如锐化、模糊等)不会影响到色相;适合RGB通道抠的图大部分LAB模式能完成,反之不成立。
2.4 sRGB与CIE Lab的转换
2.4.1 sRGB到CIE XYZ的变换
首先对sRGB像素进行归一化处理(式2-1),在将归一化后的sRGB像素进行线性化。
将线性化的sRGB像素值转化为归一化的XYZ(D65)空间,根据IEC61922-2-1定义得:
2.4.2 CIE XYZ到CIE Lab的转换
其中
第三章 实验代码
3.1 流程图
3.2 爱色丽色卡
爱色丽色卡的sRGB、CIE Lab数值如图所示。
程序代码
首先建立色卡类,用来存放色卡的sRGB、CIE Lab数值及其其他属性。
classdef COLORCARD
%COLORCARD-色卡
%存放sRGB值 和 CIE Lab值
properties
%保持读入待检验色卡的数据
card;
%爱色丽色卡标准值
sRGB = [ 115,82,68; 194,150,130; 98,122,157; 87,108,67; 133,128,177; 103,189,170;
214,126,44; 80,91,166; 193,90,99; 94,60,108; 157,188,64; 224,163,46;
56,61,150; 70,148,73; 175,54,60; 231,199,31; 187,86,149; 8,133,161;
243,243,242; 200,200,200; 160,160,160; 122,122,121; 85,85,85; 52,52,52 ];
CIE_Lab = [ 37.986,13.555,14.059; 65.711,18.13,17.81; 49.927,-4.88,-21.925; 43.139,-13.095,21.905;
55.112,8.844,-25.399; 70.719,-33.397,-0.199; 62.661,36.067,57.096; 40.02,10.41,-45.964;
51.124,48.239,16.248; 30.325,22.976,-21.587; 72.532,-23.709,57.255; 71.941,19.363,67.857;
28.778,14.179,-50.297; 55.261,-38.342,31.37; 42.101,53.378,28.19; 81.733,4.039,79.819;
51.935,49.986,-14.574; 51.038,-28.631,-28.638;96.539,-0.425,1.186; 81.257,-0.638,-0.335;
66.766,-0.734,-0.504; 50.867,-0.153,-0.27; 35.656,-0.421,-1.231;20.461,-0.079,-0.973 ];
value = cell(1,24);%存放每个色块的编号、选框左上和右下点的坐标、数据
Cab = zeros(1,24);%Cab = (a^2+b^2)^(1/2)
end
end
绘制爱色丽色卡
standard_color = COLORCARD;%创建爱色丽色卡对象
I = standard_color.sRGB ./ 255;%sRGB归一化
%绘制爱色丽色卡
figure('NumberTitle','off','name','屏幕图样:Colorchecker(sRGB)')
daspect([1,1,1]);%设置图像比例
set(gca,'xlim',[0,740]);%设置x坐标轴范围
set(gca,'ylim',[0,500]);%设置y坐标轴范围
axis off %关闭坐标轴
rectangle('position',[0,0,740,500],'FaceColor',[0,0,0]);%绘制740*500的黑色背景
%在黑色背景上绘制24个色块
w = 100;%色块的尺寸
h = 20;%色块之间的距离
m = 1;%定义色块起始编号
x = 20 : w + h :620;
y = 380: - w - h:20;
for y = 380: - w - h:20
for x = 20 : w + h :620
rectangle('position',[x,y,w,w],'FaceColor',I(m,:));
m = m + 1;
end
end
saveas(gcf, 'standard_color', 'jpg');%保存爱色丽色卡
运行程序得到标准色卡图样。
计算标准色卡的Ca * b *:
L_standrand = standard_color.CIE_Lab(:,1);
a_standrand = standard_color.CIE_Lab(:,2);
b_standrand = standard_color.CIE_Lab(:,3);
Cab_standrand = sqrt(a_standrand.^2 + b_standrand.^2);
3.3 拍摄色卡
用老师提供的拍摄色卡,记为测试色卡进行测试。
程序代码
%创建测试色卡对象
test_color = COLORCARD;
%选择图片路径
[filename,filepath] = uigetfile({'*'},'选择图片');
%合成路径
Fullfile = [filepath,filename];
%读取色卡,数据存放在card属性中
test_color.card = imread(Fullfile);
if isempty(test_color.card) %读取色卡失败
h=dialog('name','关于...','position',[200 200 200 70]);
uicontrol('parent',h,'style','text','string','读取色卡失败,请重新读取!','position',[50 40 120 20],'fontsize',12);
uicontrol('parent',h,'style','pushbutton','position',[80 10 50 20],'string','确定','callback','delete(gcbf)');
movegui(h,'center');
else %读取色卡成功
h=dialog('name','关于...','position',[200 200 200 70]);
uicontrol('parent',h,'style','text','string','读取色卡成功!','position',[50 40 120 20],'fontsize',12);
uicontrol('parent',h,'style','pushbutton','position',[80 10 50 20],'string','确定','callback','delete(gcbf)');
movegui(h,'center');
%显示图片
figure('NumberTitle','off','name','Colorchecke-selection')
imshow(test_color.card);
end
显示读取的色卡
3.4 测试色卡的两次框选
3.4.1 第一次框选
方便对测试色卡的后续处理,进行第一次整体框选。
%显示图片
figure('NumberTitle','off','name','Colorchecke-selection')
imshow(test_color.card);
%整体框选
card = imcrop(test_color.card);
test_color.card = [];
test_color.card = card;
open('ImatestColorCheck2.fig');
3.4.2 第二次框选
按照要求,手动框选24个色块并进行编号,计算色块的sRGB、CIE Lab值。对单个色块框选后进行sRGB、CIE Lab的计算,直到完成全部色块的处理。
for i = 1:24
%手动框选24个色块并编号,得到每个色块的平均sRGB作为该色块的sRGB
[sRGB,value] = color_number(test_color.card);
test_color.sRGB(i,:) = sRGB; %把每个sRGB值存放在测试色卡test_color.sRGB属性中
test_color.value{i} = value; %把每个value的值存放在测试色卡test_color.value属性中
test_color.CIE_Lab(i,:) = sRGB2CIE_Lab(sRGB); %sRGB转换为CIE_Lab,
%把每个CIE_Lab的值存放在测试色卡test_color.CIE_Lab属性中
%判断24个色块是否框选完成,完成后进行提示
if i == 24
h=dialog('position',[200 200 200 70]);
movegui(h,'center');
uicontrol('parent',h,'style','text','string','已完成24个色块的框选!','position',[50 40 120 20],'fontsize',12);
uicontrol('parent',h,'style','pushbutton','string','确定','callback','delete(gcbf)','position',[80 10 50 20]);
end
end
在该程序中有两个函数:
(1)单个色块的处理函数:function [sRGB,value] = color_number(card)
函数输出参数为单个色块的平均sRGB值,输入参数为第一次整体截取的测试测卡图像。
具体函数程序如下
function [sRGB,value] = color_number(card)
waitforbuttonpress; % 等待鼠标按下
point1 = get(gca,'CurrentPoint'); % 鼠标按下
rbbox;
point2 = get(gca,'CurrentPoint'); % 鼠标松开
point1 = floor(point1(1,1:2)); %提取出两个点
point2 = floor(point2(1,1:2));
offset = abs(point1-point2);%offset(1)为x方向的距离,offset(2)为y方向的距离
%判断单个色块的框选是否成功,若没有成功则提示重新框选
while offset(1,1) == 0 || offset(1,2) == 0
uiresume;
h=dialog('position',[200 200 200 100]);
movegui(h,'center');
uicontrol('parent',h,'style','text','string','未完成拖选,请重新选择!','position',[30 40 150 30],'fontsize',9);
uicontrol('parent',h,'style','pushbutton','string','确定','callback','delete(gcf)','position',[80 10 50 20]);
set(h, 'WindowStyle', 'modal');%设为模态对话框
uiwait;
a = 0;
waitforbuttonpress; % 等待鼠标按下
point1 = get(gca,'CurrentPoint'); % 鼠标按下
rbbox;
point2 = get(gca,'CurrentPoint'); % 鼠标松开
point1 = floor(point1(1,1:2)); % 提取出两个点
point2 = floor(point2(1,1:2));
offset = abs(point1-point2);
end
hold on %防止plot时闪烁
rectangle('position',[point1(1),point1(2),offset(1),offset(2)],'EdgeColor','r');%绘制选框
number = inputdlg('请输入色块编号');%框选完成后出现提示框:输入编号
%value为元胞数组,value(1,1)保存编号,value(2,1)保存鼠标拖选矩形框的左上和右下点的坐标,value(3,1)保存该色块数据
value(1,1) = number;%保存编号
value(2,1) = {[point1(1) point1(2) point2(1) point2(2)]};%保存鼠标拖选矩形框的左上和右下点的坐标
j = 1;
color_val = zeros((offset(1)+ 1)*(offset(2)+1),3);%根据选中色块像素数量创建矩阵,存放色块的数据
for n = point1(1):point2(1)
for m = point1(2):point2(2)
color_val(j,1) = card(m,n,1);%所有的sR
color_val(j,2) = card(m,n,2);%所有的sG
color_val(j,3) = card(m,n,3);%所有的sB
j = j + 1;
end
end
value(3,1) = {color_val}; %保存单个色块数据
R = mean(color_val(:,1));%该色块的平均sR
G = mean(color_val(:,2));%该色块的平均sG
B = mean(color_val(:,3));%该色块的平均sB
sRGB = [R,G,B];
end
(2)sRGB转换为CIE Lab函数:function CIE_Lab = sRGB2CIE_Lab(sRGB)
函数输出参数为色块的平均sRGB值对应的CIE Lab,输入参数为单个色块的平均sRGB值。该函数是先将色块的sRGB值转换为CIE XYZ值,再将CIE XYZ值转换为CIE Lab值。
function CIE_Lab = sRGB2CIE_Lab(sRGB)
%归一化sRGB被线性化
%归一化sRGB(除以255)
sRGB_normal = sRGB./255;
%线性化
%归一化后的sR值
if sRGB_normal(1) <= 0.0405
sR(1) = sRGB_normal(1) / 12.95;
else
sR(1) = ((0.055+sRGB_normal(1)) / 1.055)^2.4;
end
%归一化后的sG值
if sRGB_normal(2) <= 0.0405
sG(1) = sRGB_normal(2) / 12.95;
else
sG(1) = ((0.055+sRGB_normal(2)) / 1.055)^2.4;
end
%归一化后的sB值
if sRGB_normal(3) <= 0.0405
sB(1) = sRGB_normal(3) / 12.95;
else
sB(1) = ((0.055+sRGB_normal(3)) / 1.055)^2.4;
end
sRGB = [sR,sG,sB];
sRGB = sRGB';
%将线性化的sRGB值转换到归一化的XYZ(D65)空间
A = [0.4124,0.3576,0.1805;%变换矩阵
0.2126,0.7152,0.0722;
0.0193,0.1192,0.9505];
XYZ = A * sRGB;
%从sRGB到CIE_Lab的变换(以CIE XYZ为中介)
%Xn,Yn,Zn为D65照明体下参考白点坐标
Xn = 0.9505;
Yn = 1.0000;
Zn = 1.0890;
X = XYZ(1);
Y = XYZ(2);
Z = XYZ(3);
if X/Xn > 0.008856
fX = (X / Xn)^(1/3);
else
fX = 7.787*(X/Xn) + 16/116;
end
if Y/Yn > 0.008856
fY = (Y / Yn)^(1/3);
L = 116 * fY - 16;%计算L*
else
fY = 7.787*(Y/Yn) + 16/116;
L = 903.3 * (Y/Yn);%计算L*
end
if Z/Zn > 0.008856
fZ = (Z / Zn)^(1/3);
else
fZ = 7.787*(Z/Zn) + 16/116;
end
a = 500 * (fX - fY);%计算a*
b = 200 * (fY - fZ);%计算b*
CIE_Lab = [L,a,b];
end
3.5 计算Ca * b *
L_test = test_color.CIE_Lab(:,1);
a_test = test_color.CIE_Lab(:,2);
b_test = test_color.CIE_Lab(:,3);
Cab_test = sqrt(a_test.^2 + b_test.^2);
3.6 计算色差
CIE (国际照明委员会)Lab颜色空间简单介绍:L:(亮度)轴 表示黑白,0为黑 100为白。a:(红绿)轴 正值为红,负值为绿,0为中性。b:(黄蓝)轴正值为黄,负值为蓝,0为中性。
△L为正,说明测试样比标准样浅(偏白)△L为负,说明测试样比标准样深(偏黑)。△a为正,说明测试样比标准样红(偏红)△a为负,说明测试样比标准样绿(偏绿)。△b为正,说明测试样比标准样黄(偏黄)△b为负,说明测试样比标准样蓝(偏蓝)。△Eab为总色差,值越大说明色差越大。
色差公式:
△E=[(△L)2 (△a)2 (△b)2]^(1/2)。
具体程序代码如下:
%计算Eab Cab
L_test = test_color.CIE_Lab(:,1);
a_test = test_color.CIE_Lab(:,2);
b_test = test_color.CIE_Lab(:,3);
Cab_test = sqrt(a_test.^2 + b_test.^2);
standard_color = COLORCARD;
L_standrand = standard_color.CIE_Lab(:,1);
a_standrand = standard_color.CIE_Lab(:,2);
b_standrand = standard_color.CIE_Lab(:,3);
Cab_standrand = sqrt(a_standrand.^2 + b_standrand.^2);
cL = L_test - L_standrand;
ca = a_test - a_standrand;
cb = b_test - b_standrand;
d_Eab = sqrt(cL.^2 + ca.^2 + cb.^2);
d_Cab = Cab_test - Cab_standrand ;
3.7 显示色差
a_standard = standard_color.CIE_Lab(:,2);
b_standard = standard_color.CIE_Lab(:,3);
a_test = test_color.CIE_Lab(:,2);
b_test = test_color.CIE_Lab(:,3);
d_Eab_mean = mean(d_Eab);
d_Eab_max = max(d_Eab);
d_Cab_mean = mean(abs(d_Cab));
d_Cab_max = max(abs(d_Cab));
figure
xlabel = 'a*';
ylabel = 'b*';
for i = 1:24
plot([a_standard(i),a_test(i)],[b_standard(i),b_test(i)]);
hold on;
text(a_standard(i),b_standard(i),'o','color','g');
hold on;
text(a_test(i),b_test(i),'o','color','r');
hold on;
end
hold off;
daspect([1,1,1]);
第四章 图形用户界面及实验结果
4.1 图形用户界面
模拟Imatest的colorcheck模块,进行色差处理实验。
新建两个fig页面:ImatestColorCheck.fig、ImatestColorCheck2.fig
屏幕图样的回调函数为加载爱色丽色卡,ColorCheck则是进行色差处理:加载测试图片、第一次框选、打开ImatestColorCheck2.fig。
Axes2显示第一次框选后的图并进行第二次框选:对24个色块进行拖选、输入编号并进行sRGB、CIE Lab、Cab、△Cab、△Eab的计算。“是的,继续”的回调函数是显示色差并计算△Cab和△Eab的平均值和最大值。
4.2 图形用户界面操作流程及实验结果
开始界面如下所示:
点击屏幕图样得到爱色丽色卡。
点击Color Check进行色差处理,首先导入测试图片,出现选择图片浏览框。
读取成功后出现读取成功提示框并显示图像,反之提示失败。
对读入的图像进行整体框选,双击得到框选后的图片:
进行第二次框选,进入该页面后直接用鼠标手动拖选色块,并输入编号。
对24个色块拖选并输入编码,计算每个色块的sRGB和CIE Lab的值及完成对Cab、Eab的自动计算。
完成后如下图所示。
计算得到色差为:
序号 | △Eab | △Cab |
---|---|---|
1 | 5.55143434864324 | 4.73406748967801 |
2 | 6.94565796095100 | -3.93451489823245 |
3 | 5.69803843845297 | -0.704309327814165 |
4 | 12.0551415565656 | 10.4625414092679 |
5 | 7.90863719490411 | 4.40144235915420 |
6 | 10.4578006379024 | -9.26571932844358 |
7 | 11.5721667592339 | -4.35644839495931 |
8 | 12.5572087734804 | 7.45005075054171 |
9 | 5.43307201560013 | 4.31230540273475 |
10 | 5.55490512919290 | 0.395183864825807 |
11 | 7.93701635743434 | -6.32267735709571 |
12 | 13.5539202225103 | -3.47158710088395 |
13 | 15.4631015946848 | 9.78415349125530 |
14 | 3.09505584044692 | -2.56271077996743 |
15 | 10.4681895310704 | 8.18254913143394 |
16 | 16.4556837862032 | -13.1433642150267 |
17 | 3.37089097077980 | 2.44642530172536 |
18 | 16.2333430815614 | -9.54014768002860 |
19 | 7.59842052815809 | 1.75832540409464 |
20 | 2.53211832226216 | 1.12136825330515 |
21 | 3.46078587882271 | 1.14717730278684 |
22 | 2.75871624261633 | 0.787104610254210 |
23 | 5.34602729596054 | -0.154927353098391 |
24 | 8.08200634373610 | -0.100256065415188 |
点击确定,关闭提示框,点击“是的,继续”显示色差图。绿色圆圈代表理想值,红色圆圈代表测试值。
这里可以在sRGB的背景图上显示色差,我没有弄……
△Cab_mean =4.605806553000977
△Cab_max = 13.143364215026693
△Eab_mean = 8.337055783798895
△Eab_max = 16.455683786203150
△Cab<0时,测试色比标准色色彩饱和度低;△Cab>0时,测试色比标准色色彩饱和度高。总体来看测试色饱和度较低。△Eab是Lab空间下的标准偏差。
参考文献
[1]杨超,刘本永. 基于Lab颜色空间纹理特征的图像前后景分离[J]. 激光与光电子学进展, 2019, 56(12): 59-64.
[2]徐志成. 一个色彩空间转换系统的设计与实现[D]. 东南大学, 2017.
[3]赵军辉,吴玉峰,胡坤融,等. 基于Lab色彩空间和色调映射的彩色图像增强算法[J]. 计算机科学, 2018, 45(2): 297-300.
[4]李伟斌,马洪林,易贤,等. 基于色彩空间变换的彩色图像分割方法[J]. 计算机工程与应用, 2019, 55(9): 162-167.
[5]王可,陆长德,乐万德,等. 基于Lab均匀色彩空间的色彩调和系统[J]. 西北工业大学学报, 2004, 卷缺失(6): 695-699.
[6]郑元林,杨淑蕙,周世生,等. CIE 1976 LAB色差公式的均匀性研究[J]. 包装工程, 2005, 卷缺失(2): 48-49, 65.