【颜色空间转换大集合】RGB到YIQ,RGB到HSI和HSI到RGB,RGB到YcbCr,RGB到XYZ颜色转换matlab代码的Demo,含详细的解释

版权声明:本文为博主原创文章,未经博主允许不得转载。如果你非要转载,麻烦加上我的原网址,谢谢。http://blog.csdn.net/qinglingLS https://blog.csdn.net/qinglingLS/article/details/84900399

废话不说,先上图,
实现方式:matlab
在这里插入图片描述

在这里插入图片描述

实现功能:

实验目标

  1. 了解图像颜色空间的转换关系。
  2. 了解图像的文件结构。
    实验内容
  3. 完成如下颜色空间的转换。(4 Points)
  1. RGB -> YIQ
  2. RGB -> HSI
  3. RGB -> YCbCr
  4. RGB -> XYZ
    选做:
    自己实现对 BMP 文件头的读取,并解析 BMP 图像文件。 (2.5 Points)
    补充说明
    程序从命令行中读取文件路径,并输出 4 个文件,文件名如下:
    图像原始文件名-学号-YIQ.bmp
    图像原始文件名-学号-HSI.bmp
    图像原始文件名-学号-YCbCr.bmp
    图像原始文件名-学号-XYZ.bmp
  1. 了解图像的文件结构。

读取BMP文件头:
效果图:
在这里插入图片描述
输出文件:
在这里插入图片描述

调用代码demo需要csdn积分下载。

在这里插入图片描述
全部文件网址:
https://download.csdn.net/download/qinglingls/10837786
demo单独文件下载网址如下:
https://download.csdn.net/download/qinglingls/10837783
谢谢大家支持。。给我分享资源的动力叭!!!。^ o^
分享了那么多代码,但是我已经到没积分了。。
另外附一份实验报告的参考网址:
https://download.csdn.net/download/qinglingls/10837790

下面演示下代码效果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

自实现的BMP函数代码文件:
bmpReader.m

function rgb=bmpReader(bmpName)
%	自己实现的BMP文件读取函数
%	输入:bmp文件名字
%	输出:rgb格式的矩阵,
%		  大小:图像高*宽*3
%
BITMAPFILEHEADER=14; %根据BMP格式定义BMP文件头大小和头信息文件大小
BITMAPINFOHEADER=40;
fid = fopen(bmpName, 'rb');%大端法读取
if fid<=0
    fprintf('出现错误,没有这个文件');
    return;
end
%% 按照格式读取bmp文件头
fhead.bfType=fread(fid,2,'bit8');
if fhead.bfType(1)~=66||fhead.bfType(2)~=77
    fprintf('Wrong!!It is not a .BMP file!!!!!\n');
    return;
end
fhead.bfSize=fread(fid,1,'uint32');
fhead.bfReserved1=fread(fid,1,'uint16');
fhead.bfReserved2=fread(fid,1,'uint16');
fhead.bfOffBits=fread(fid,1,'uint32');

fprintf('BITMAPFILEHEADER 大小为:%d\n', BITMAPFILEHEADER);
fprintf('BITMAPINFOHEADER 大小为:%d\n', BITMAPINFOHEADER);
fprintf('%s\t\t-- bfType: 位图文件的类型,必须为\n', fhead.bfType);
fprintf('%d\t\t-- bfSize:  位图文件的大小,以字节为单位\n', fhead.bfSize);
fprintf('%d\t\t--bfReserved1:  位图文件保留字,必须为0\n', fhead.bfReserved1);
fprintf('%d\t\t-- bfReserved2:位图文件保留字,必须为0\n', fhead.bfReserved2);
fprintf('%d\t\t-- bfOffBits:  位图数据的起始位置,以相对于位图文件头的偏移量表示,以字节为单位\n', fhead.bfOffBits);
%% 按照格式读取bmp头信息大小
%fseek(fid,BITMAPFILEHEADER,'eof');%跳过位图文件头结构BITMAPFILEHEADER寻找结尾
Ihead.biSize=fread(fid,1,'uint32');%读取数据到data里,原始16bit8采样
Ihead.biWidth=fread(fid,1,'uint32');
Ihead.biHeight=fread(fid,1,'uint32');
Ihead.biPlanes=fread(fid,1,'uint16');
Ihead.biBitCount=fread(fid,1,'uint16');
Ihead.biCompression=fread(fid,1,'uint32');
Ihead.biSizeImage=fread(fid,1,'uint32');
Ihead.biXPelsPerMeter=fread(fid,1,'uint32');
Ihead.biYPelsPerMeter=fread(fid,1,'uint32');
Ihead.biClrUsed=fread(fid,1,'uint32');
Ihead.biClrImportant=fread(fid,1,'uint32');

fprintf('%d\t\t-- biSize:本结构所占用字节数\n', Ihead.biSize);
fprintf('%d\t\t-- biWidth: 位图的宽度,以像素为单位\n', Ihead.biWidth);
fprintf('%d\t\t--biHeight\n: ', Ihead.biHeight);
fprintf('%d\t\t--biPlanes\n:  ', Ihead.biPlanes);
fprintf('%d\t\t--biBitCount:  每个像素所需的位数,必须是1(双色), 4(16色),8(256色)或24(真彩色)之一\n', Ihead.biBitCount);
fprintf('%d\t\t-- biCompression: 位图压缩类型,必须是 0(不压缩), 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一\n', Ihead.biCompression);
fprintf('%d\t\t-- biSizeImage:  位图的大小,以字节为单位\n', Ihead.biSizeImage);
fprintf('%d\t\t--biXPelsPerMeter: 位图水平分辨率,每米像素数\n', Ihead.biXPelsPerMeter);
fprintf('%d\t\t-- biYPelsPerMeter: 位图垂直分辨率,每米像素数\n', Ihead.biYPelsPerMeter);
fprintf('%d\t\t--biClrUsed:  位图实际使用的颜色表中的颜色数\n', Ihead.biClrUsed);
fprintf('%d\t\t-- biClrImportant:  位图显示过程中重要的颜色数\n', Ihead.biClrImportant);
%%
% 1,4,8位图像才会使用调色板数据,16,24,32位图像不需要调色板数据,即调色板最多只需要256项(索引0 - 255)。
% 颜色表的大小根据所使用的颜色模式而定:2色图像为8字节;16色图像位64字节;256色图像为1024字节。
% 其中,每4字节表示一种颜色,并以B(蓝色)、G(绿色)、R(红色)、alpha(32位位图的透明度值,一般不需要)。
% 即首先4字节表示颜色号1的颜色,接下来表示颜色号2的颜色,依此类推。
% 颜色表中RGBQUAD结构数据的个数有biBitCount来确定,当biBitCount=1,4,8时,分别有2,16,256个表项。
% 当biBitCount=1时,为2色图像,BMP位图中有2个数据结构RGBQUAD,一个调色板占用4字节数据,所以2色图像的调色板长度为2*4为8字节。
% 当biBitCount=4时,为16色图像,BMP位图中有16个数据结构RGBQUAD,一个调色板占用4字节数据,所以16像的调色板长度为16*4为64字节。
% 当biBitCount=8时,为256色图像,BMP位图中有256个数据结构RGBQUAD,一个调色板占用4字节数据,所以256色图像的调色板长度为256*4为1024字节。
% 当biBitCount=16,24或32时,没有颜色表。
if Ihead.biBitCount==16||Ihead.biBitCount==256
    ctTable.rgbBlue=fread(fid,1,'uint8');
    ctTable.rgbGreen=fread(fid,1,'uint8');
    ctTable.rgbRed=fread(fid,1,'uint8');
    ctTable.rgbReserved=fread(fid,1,'uint8');
end

%24位图像使用3字节保存颜色值,每一个字节代表一种颜色,按红、绿、蓝排列。
if Ihead.biBitCount==24  %24真彩色图像每点占24位(3字节)
    buffer=fread(fid,'uint8');%全读取为uint8
    %一个扫描行所占的字节数计算方法:
    dataSizePerLine=(Ihead.biWidth*Ihead.biBitCount)/8;
    % 一个扫描行所占的字节数
    dataSizePerLine= dataSizePerLine/4*4; %字节数必须是4的倍数
    %位图数据的大小(不压缩情况下):
    DataSize= dataSizePerLine* Ihead.biHeight;
    if DataSize==Ihead.biSizeImage
        fprintf('DataSize==biSizeImage,成功解析\n');
    else
        fprintf('Wrong,格式错误!!不是24色真彩色图像\n');
    end
    %有填充的直接算作顺序,因为
    pitch=mod(Ihead.biWidth,4);
    if pitch~=0
       fprintf('wrong!\n');
       return;
    end
    %b g r,下面转换为正常顺序
    if Ihead.biHeight>0
        %height>0 表示图片颠倒,
        for i=0:1:Ihead.biHeight-1
            for  j=0:1:Ihead.biWidth-1
                %测试图片大小:250*252*3
                b=buffer((i*Ihead.biWidth+j)*3+1);
                g=buffer((i*Ihead.biWidth+j)*3+1+1);
                r=buffer((i*Ihead.biWidth+j)*3+2+1);
                rgb(Ihead.biHeight-i,j+1,1)=r;
                rgb(Ihead.biHeight-i,j+1,2)=g;
                rgb(Ihead.biHeight-i,j+1,3)=b;
                %  pDC->SetPixel(j,height-i,RGB(r,g,b));
            end
        end
    end
    %rgb=cat(3,r,g,b);
    rgb=uint8(rgb);
    figure;
    imshow(rgb);title('自实现函数原图BMP读取显示')
elseif Ihead.biBitCount==1  %2彩色图像每点占8位(1字节)
    buffer=fread(fid,'bit1'); 
    %带调色板的模式,现在不怎么用了,似乎。。所以就不做测试了。。。
    %首先4字节表示颜色号1的颜色,接下来表示颜色号2的颜色,依此类推。
    for i=0:1:Ihead.biHeight-1
        for  j=0:1:Ihead.biWidth-1
            b=buffer((i*Ihead.biWidth+j)*4+1);
            g=buffer((i*Ihead.biWidth+j)*4+1+1);
            r=buffer((i*Ihead.biWidth+j)*4+2+1);
            rgb(Ihead.biHeight-i,j+1,1)=r;
            rgb(Ihead.biHeight-i,j+1,2)=g;
            rgb(Ihead.biHeight-i,j+1,3)=b;
        end
    end
    rgb=uint8(rgb);
    figure
    imshow(rgb);
    title('自实现函数原图BMP读取显示')
end
end

自实现的RGB2HSI和HSI2RGB
这个参考了别人的代码。。但是找不到原网址了。。
rgb2hsi.m文件

%hsi2rgb
function hsi = rgb2hsi(rgb) 
%  	实现从RGB到HSI的转换
%	输入:rgb向量矩阵
%	输出:hsi向量矩阵
rgb = im2double(rgb); 
r = rgb(:, :, 1); 
g = rgb(:, :, 2); 
b = rgb(:, :, 3); 
% Implement the conversion equations. 
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;
% Combine all three results into an hsi image. 
hsi = cat(3, H, S, I);


%HSI2RGB
function rgb = hsi2rgb(hsi) 
% Extract the individual HSI component images. 
H = hsi(:, :, 1) * 2 * pi; 
S = hsi(:, :, 2); 
I = hsi(:, :, 3); 
% Implement the conversion equations. 
R = zeros(size(hsi, 1), size(hsi, 2)); 
G = zeros(size(hsi, 1), size(hsi, 2)); 
B = zeros(size(hsi, 1), size(hsi, 2)); 
% RG sector (0 <= H < 2*pi/3). 
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)); 
% BG sector (2*pi/3 <= H < 4*pi/3). 
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)); 

% BR sector. 
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); 

rgb2XYZ.m文件

function rgb2XYZ(filename)
%	RGB到XYZ的转换
%	输入:文件名
%	无输出,直接打印图像并写入文件
%
rgb = imread(filename);  
subplot(2,3,1),imshow(rgb,'InitialMagnification','fit');title('原图像');  
rgb =double(rgb);%双精度化(0-255)  
x = 0.412453*rgb(:,:,1)+0.357580*rgb(:,:,2)+0.180423*rgb(:,:,3);  
x = mat2gray(x);%把矩阵转化为灰度图像  
y = 0.212671*rgb(:,:,1)+0.715160*rgb(:,:,2)+0.072169*rgb(:,:,3);  
y = mat2gray(y);  
z = 0.019334*rgb(:,:,1)+0.119193*rgb(:,:,2)+0.950227*rgb(:,:,3);  
z = mat2gray(z);  
xyz = cat(3,x,y,z);%把x,y,z连在一起  
subplot(2,3,3),imshow(xyz);title('XYZ图像');  
subplot(2,3,4),imshow(x);title('X图像');  
subplot(2,3,5),imshow(y);title('Y图像');  
subplot(2,3,6),imshow(z);title('Z图像');  
imwrite(xyz,strcat(filename,'-1160300910-XYZ.bmp'));
end

rgb2YCbCr.m

function rgb2YCbCr(filename)
%
%	RGB到YCbCr的转换
%	输入:文件名
%	无输出,直接打印图像并写入文件
%
ima = imread(filename); %读取一张名为abc.bmp的图片
ima_ycbcr = rgb2ycbcr(ima);%将rgb格式转为ycbcr格式
subplot(2,3,1); 
imshow(ima_ycbcr(:,:,1)); 
title('Y'); 
subplot(2,3,2); 
imshow(ima_ycbcr(:,:,2)); 
title('Cb') 
subplot(2,3,3); 
imshow(ima_ycbcr(:,:,3)); 
title('Cr') 
subplot(2,3,4); 
x = cat(3, ima_ycbcr(:,:,1), ima_ycbcr(:,:,2), ima_ycbcr(:,:,3));
imshow(x); 
title('ima_ycbcr')
subplot(2,3,5); 
imshow(ima); 
title('原图');
imwrite(ima,strcat(filename,'-1160300910-YCbCr.bmp'));
end

rgb2yiq_func.m

%
rgb=imread(fileName); 
RGB=(rgb); 
r=RGB(:,:,1); 
g=RGB(:,:,2); 
b=RGB(:,:,3); 
 
Y=0.299*r+0.587*g+0.114*b; 
I=0.596*r-0.274*g-0.322*b; 
Q=0.211*r-0.523*g+0.312*b; 

figure
subplot(2,3,1); 
imshow(Y); 
title('YRGB'); 
subplot(2,3,2); 
imshow(I); 
title('IRGB') 
subplot(2,3,3); 
imshow(Q); 
title('QRGB') 
subplot(2,3,4); 
imshow(RGB); 
title('RGB')
subplot(2,3,5); 
img_YIQ=cat(3,Y,I,Q);
imwrite(img_YIQ,strcat(fileName,'-1160300910-YIQ.bmp'));
imshow(img_YIQ);
title('RGB2YIQ图像');
end

我觉得看到最后的小孩应该有奖励。
gitlab代码开源地址:https://gitlab.com/Koadaky/digital-image-color-change-project

猜你喜欢

转载自blog.csdn.net/qinglingLS/article/details/84900399