彩色图像处理
一、RGB图像
一幅RGB图像是一个MN3的彩色像素数组,其中每个彩色色素是一个三值组,这三个值分别对应一个特定空间位置处RGB图像的红,绿,蓝分量。
RGB也可以视为三幅灰度图像形成的“堆叠”,当将他们分别送到彩色显示器的红,绿,蓝输入端时,会在屏幕上生成一幅彩色图像。分量图像的数据类决定了他们的取值范围。用来表示这些分量图像像素值的比特数决定了一幅图像的比特深度。图像的颜色数为;(2b)3,其中b是每幅图像的比特数。
使用cat运算符可以堆叠出RGB图像:
rgb_image=cat(3,fR,fG,fB)
该运算中,要求图像按顺序放置。cat运算符的语法为;
rgb_image=cat(dim,A1,A2,…) 沿指定的方向来连接各个数组。如果dim=1,那么这些数组垂直排列,dim=2,则这些数组水平排列,dim=3,则在第三个方向排列。
如果所有分量图像都是一样的,那么结果是一幅灰度图像。
提取彩色图像的三幅分量图像:
fR=f(:,:,1);
>> fG=f(:,:,2);
>> fB=f(:,:,3);
rgb_red=cat(3,fR,zeros(size(fR)),zeros(size(fR)));
rgb_green=cat(3,zeros(size(fR)),fG,zeros(size(fR)));
rgb_blue=cat(3,zeros(size(fR)),zeros(size(fR)),fB);
RGB彩色空间通常以图解的方式显示一个RGB彩色立方体,立方体的顶点是光的原色(红,绿,蓝)和二次色(青,红紫,黄)。
为从任意角度查看该彩色立方体,可以定义M函数rgbcube
function rgbcube(vx,vy,vz)
vertices_matrix=[0 0 0;0 0 1;0 1 0;0 1 1;1 0 0;1 0 1;1 1 0;1 1 1];
faces_matrix=[1 5 6 2;1 3 7 5;1 2 4 3;2 4 8 6;3 7 8 4;5 6 8 7];
colors=vertices_matrix;
patch('Vertices',vertices_matrix,'Faces',faces_matrix,'FaceVertexCData',colors,'FaceColor','interp','EdgeAlpha',0)
if nargin==0
vx=10;vy=10;vz=4;
elseif nargin~=3
error('wrong number of input')
end
axis off
view([vx,vy,vz])
axis square
实验总结:
在RGB彩色模型中表示的图像由三个分量图像组成,每种原色一幅分量图像。当送入RGB监视器时,这3幅图像在屏幕上混合生成一幅彩色图像。RGB彩色立方体是实心的,在24比特RGB图像中,它由(28)3=16 777 216种颜色组成。
二、索引图像
索引图像有两个分量:一个整数数据矩阵X和一个彩色映射矩阵map。矩阵map是一个大小为m*3的double数组,其值是区间[0,1]上的浮点数。map的长度m等于其定义的颜色数。map的每一行指定单一颜色的红,绿,蓝分量(如果map的三列相等,则彩色映射就成为灰度图)。索引图像将像素的灰度值“直接映射”到彩色值。通过将相应整数矩阵X的值作为指向map的一个索引,来确定每个像素的颜色。如果 X是double类型, 那么值 1 指向 map 的第一行,值 2 指向第二行,等等。如果 X是uint8或uint16类型,那么值 0 指向 map 的第一行。
要显示一幅索引图像,可以写出
imshow(X,map)
或者,
image(X)
colormap(map)
彩色映射使用索引图像来存储,使用imread加载索引图像时,彩色映射会自动和图像一起载入。
有时需要用具有较少颜色的映射去近似一个索引映射。为此使用imapprox,语法为:
[Y,newmap]=imapprox(X,map,n)
该函数使用彩色映射newmap返回一个数组Y,它最多有n种颜色。输入数组X的类型可以 是uint8、uint16或double。如果n小于等于256,那么输出Y是uint8类;如果n大于 256,那么Y是double类。
指定一个彩色映射的方法之一是:
map(k,:)=[r(k) g(k) b(k)];
其中,[r(k) g(k) b(k)]是RGB值,它指定彩色映射的一行,改变k的值就可以将映射填满。
名称 | RGB值 |
---|---|
黑(k) | [0 0 0] |
青(c) | [0 1 1] |
红(r) | [1 0 0] |
蓝(b) | [0 0 1] |
绿(g) | [0 1 0 ] |
深红(m) | [1 0 1] |
黄(Y) | [1 1 0] |
白(w) | [1 1 1] |
上表列出了一些基本颜色的RGB值,表中三种格式的任何一种都可以用来指定颜色。
例如
whitebg('g');
whitebg('green');
whitebg([0 1 0]);
运行代码后得到
MTLAB提供了几个预定义的彩色映射,
colormap(map_name);
它将彩色映射设置为矩阵map_name。
例如
colormap(copper)
其中copper是一个MATLAB彩色映射函数。该映射中的颜色会从黑色平稳地变为紫铜色。
三、处理RGB和索引图像的函数
函数 | 目的 |
---|---|
dither | 采用抖动从RGB图像创建索引图像 |
gray2ind | 从灰度图像创建索引图象 |
ind2gray | 从索引图象创建灰度图像 |
rgb2ind | 从RGB图像创建索引图像 |
grayslice | 采用阈值处理从灰度图像创建索引图像 |
ind2rgb | 从索引图像创建RGB图像 |
rgb2gray | 从RGB图像创建灰度图像 |
函数dither既适用于灰度图像,也适用于彩色图像。在灰度图像的情况下,抖动试图用通过在白色背景上生成黑点的二值图像来得到灰色调。点的大小可以从明亮区域的小点逐渐变化到黑暗区域的大点。实现“抖动”算法,关键问题是,要折中考虑视觉感受的精确性和计算复杂度。
1,dither函数用于灰度图像的语法;
bw=dither(gray_image)
其中,gray_image是一幅灰度图像,bw是抖动处理过的二值图像(logical类)。
处理彩色图像时,“抖动”主要是与函数rgb2ind联合使用,以减少图像中的颜色数。
对灰度图像的处理
bw=dither(gray_image);
对彩色图像的处理
RGB=imread(' C:/experiment/fangzi.jpg');
>> [X,map]=rgb2ind(RGB,8,'nodither');
>> subplot(1,2,1),imshow(X,map);
>> title('未抖动的索引图像');
>> [x1,map1] = rgb2ind(RGB,8,'dither');
>> subplot(1,2,2),imshow(x1,map1)
>> title('抖动处理的彩色索引图像')
2,函数grayslice的语法:
X=grayslice(gray_image,n)
该函数使用如下阈值对灰度图像进行阈值处理,生成一幅索引图象:
1/n,2/n,3/n,…,(n-1)/n
使用带有适合长度的映射命令,可以查看导致的索引图像。
另一种语法为:
X=grayslice(gray_image,v)
其中,v是一个用于阈值gray_image的向量(取值范围为[0,1])。函数grayslice是伪彩色图像处理的基本工具,伪彩色处理时,指定的灰度带被赋予了不同的颜色。输入图像可以时uint8类,uint16类或者double类。即使输入图像时uint8类或uint16类,v中阈值的取值范围必须是[0,1]。该函数执行了必要的缩放。
X=grayslice(gray_image,16);
X1=grayslice(gray_image,8);
subplot(131),imshow(gray_image),title('灰度图像');
subplot(132),imshow(X,jet(16)),title('n=16时索引图像');
>> subplot(133),imshow(X1,jet(8)),title('n=8时索引图像');
四、彩色空间转换
1,NTSC彩色空间
NTSC彩色制适用于模拟电视。这种形式的一个主要的优点是,灰度信息和彩色数据是分离的,所以同一个信号既可以使用于彩色电视机,也可以用于黑白电视机。在NTSC格式中,图像数据由三个分量组成:亮度(Y),色调(I)和饱和度(Q),其中字母YIQ的选择遵从惯例。亮度分量表示灰度信息,其他两个分量携带电视信号和彩色信息。YIQ分量是使用如下线性变换从RGB图像中得到的:
其中,第一行个元素之和为1,下两行元素之和为0,因为对于一幅灰度图像,所有RGB分量是相等的,I,Q分量应该为0。
函数rgb2ntsc执行上述变换;
yiq_image=rgb2ntsc(rgb_image)
其中,输入的RGB图像可以是uint8类,uint16类或double类。输出图像是大小为MN3的double类图像。类似的,RGB分量可以利用下面的线性变换从 YIQ分量得到:
函数ntsc2rgb执行上述变换;
rgb_image = ntsc2rgb(yiq_image)
输入输出都是double类。
rgb_image=imread(' C:/experiment/mingren.jpeg');
>> yiq_image=rgb2ntsc(rgb_image);
>> fY = yiq_image(:,:,1);
>> fI = yiq_image(:,:,2);
>> fQ = yiq_image(:,:,3);
>> subplot(3, 2, 1), imshow(rgb_image);title('原图像');
>> subplot(3, 2, 2), imshow(yiq_image);title('NTSC彩色空间图像');
>> subplot(3, 2, 3), imshow(fY);title('NTSC亮度');
>> subplot(3, 2, 4), imshow(fI);title('NTSC色度');
>> subplot(3, 2, 5), imshow(fQ) ;title('NTSC饱和度');
输出都是double类图像。
2,YCbCr彩色空间
YCbCr彩色空间广泛应用于数字视频中,在这种格式中,亮度信息用单个分量Y来表示,彩色信息存储为两个色差分量Cb和Cr。分量Cb是蓝色分量和参考值的差,分量Cr是红色分量和参考值的差。实现RGB到YCbCr处理手段是;
执行上述的操作是:
ycbcr_image = rgb2ycbcr(rgb_image)
输入的 RGB 图像可以是 uint8、uint16 或 double类。输出图像和输入图像的类型相同。使用类似的变换可以从 YCbCr 转换回 RGB:
rgb_image = ycbcr2rgb(ycbcr_image)
3,HSV彩色空间
HSV(色调,饱和度,数值)是人们从颜色轮或调色板中挑选颜色(即颜料或油墨)时所用的几种彩色系统之一。这种彩色系统与RGB系统相比,更加接近于人们的经验和描述彩色感觉时所用的方式。
HSV彩色空间可以沿RGB彩色立方体的灰度轴(这些轴连接黑色和白色顶点)明确表达,得出六边形彩色调色板。
当沿图中垂直灰轴移动时,与该轴垂直的六边形平面的大小是变化的。
轴V=0端为黑色,V=1端为白色,位于全彩色六边形的中心,这样,该轴就表示了灰度所有的深浅,饱和度由距离V轴的距离来度量。
从RGB转换为HSV的MATLAB函数是rgb2hsv,语法为;
hsv_image=rgb2hsv(rgb_image)
同样,反变换函数是:
rgb_image = hsv2rgb (hsv_image)
4,CMY和CMYK彩色空间
青色,深红色和黄色是光的二次色,或颜料的原色。当用光照射涂有青色颜料的表面时,表面不会反射红光,青色颜料从表面反射的光中减去了红光。使用如下公式执行一个近似的转换;
其中,假设所有的颜色值已被归一化到区间【0,1】。这个公式证明了前段的陈述,即纯青色涂覆的表面反射的光中不包含红色。在理论上,等量的颜料原色,将青色、紫红色和黄色混合会产生黑色。在实践中,将这些颜色混合印刷会生成模糊不清的黑色。所以,为了生成纯正的黑色(打印中主要的颜色),第 4 种颜色——黑色便添加进来了,从而给出提升的 CMYK彩色模型。这种模式的文件大,占用的磁盘和内存大,一般在印刷时使用。
5,HSI彩色空间
人们在观察和描述彩色物体时,常用色调、饱和度和亮度进行描述。色调是描述纯色的颜色属性,饱和度则是纯色被白光冲淡程度的度量,而亮度是一种主观感觉,无法度量。HSI模型将强度分量与从一幅彩色图像中承载的彩色信息分开。
1.将颜色从 RGB 转换为 HSI
给出一幅RGB彩色格式的图像,每个RGB像素的H分量可由下面的式子得到,
其中
饱和度由下面的式子给出:
亮度由下面式子给出:
将从 H 的公式中得出的所有结果除以 360°,即可将色调归一化在[0,1]之间。 如果给出的 RGB值在[0,1]之间,那么其他的两个 HSI 分量就已经在[0,1]之间了。
实现的函数:
function hsi = rgb2hsi(rgb)
rgb = im2double(rgb);
r = rgb(:, :, 1);
g = rgb(:, :, 2);
b = rgb(:, :, 3);
num = 0.5*((r - g) + (r - b));
den = sqrt((r - g).^2 + (r - b).*(g - b));
theta = acos(num./(den + eps));
H = theta;
H(b > g) = 2*pi - H(b > g);
H = H/(2*pi);
num = min(min(r, g), b);
den = r + g + b;
den(den == 0) = eps;
S = 1 - 3.* num./den;
H(S == 0) = 0;
I = (r + g + b)/3;
hsi = cat(3, H, S, I);
2.将颜色从HSI 转换为RGB
用360°乘以H,将色调的值还原成原来的范围——[0°,360°]。
RG区域(0≤H≤120 )如果 H在这个区域内,那么 RGB分量由下式给出:
和
GB区域(120°≤H<240°):如果给出的H值在这个区域内,我们就先从中减去120°:
这时 RGB分量是:
BR区域(240°≤H≤360°):
hsi转换为rgb的函数为:
function rgb = hsi2rgb(hsi)
H = hsi(:, :, 1) * 2 * pi;
S = hsi(:, :, 2);
I = hsi(:, :, 3);
R = zeros(size(hsi, 1), size(hsi, 2));
G = zeros(size(hsi, 1), size(hsi, 2));
B = zeros(size(hsi, 1), size(hsi, 2));
idx = find( (0 <= H) & (H < 2*pi/3));
B(idx) = I(idx) .* (1 - S(idx));
R(idx) = I(idx) .* (1 + S(idx) .* cos(H(idx)) ./cos(pi/3 - H(idx)));
G(idx) = 3*I(idx) - (R(idx) + B(idx));
idx = find( (2*pi/3 <= H) & (H < 4*pi/3) );
R(idx) = I(idx) .* (1 - S(idx));
G(idx) = I(idx) .* (1 + S(idx) .* cos(H(idx) - 2*pi/3) ./cos(pi - H(idx)));
B(idx) = 3*I(idx) - (R(idx) + G(idx));
idx = find( (4*pi/3 <= H) & (H <= 2*pi));
G(idx) = I(idx) .* (1 - S(idx));
B(idx) = I(idx) .* (1 + S(idx) .* cos(H(idx) - 4*pi/3) ./cos(5*pi/3 - H(idx)));
R(idx) = 3*I(idx) - (G(idx) + B(idx));
rgb = cat(3, R, G, B);
rgb = max(min(rgb, 1), 0);
在RGB模型和CMY模型中创建颜色并从一种模型转换到另一种模型的过程很简单。另外RGB系统能很好地吻合人眼强烈感知红,绿,蓝三原色的事实。但是,RGB模型,CMY模型和其他类似的颜色模型都不太适合用于颜色的直观描述,即人类实际上解释颜色的方式。
观察物体时,使用色调,饱和度,亮度来描述物体,使用HSI模型描述对人来说自然且直观。