版权声明:本文为博主原创文章,未经博主允许不得转载。如果你非要转载,麻烦加上我的原网址,谢谢。http://blog.csdn.net/qinglingLS https://blog.csdn.net/qinglingLS/article/details/84900399
废话不说,先上图,
实现方式:matlab
实现功能:
实验目标
- 了解图像颜色空间的转换关系。
- 了解图像的文件结构。
实验内容 - 完成如下颜色空间的转换。(4 Points)
- RGB -> YIQ
- RGB -> HSI
- RGB -> YCbCr
- RGB -> XYZ
选做:
自己实现对 BMP 文件头的读取,并解析 BMP 图像文件。 (2.5 Points)
补充说明
程序从命令行中读取文件路径,并输出 4 个文件,文件名如下:
图像原始文件名-学号-YIQ.bmp
图像原始文件名-学号-HSI.bmp
图像原始文件名-学号-YCbCr.bmp
图像原始文件名-学号-XYZ.bmp
- 了解图像的文件结构。
读取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