任务
在应用傅里叶变换算法时,首先对彩色RGB图像进行处理,转换为灰度图像,调用系统函数rgb2gray()
。下面通过对各通道的取值进行自写函数实现。
过程
本函数的核心是将三维的数组通过一定规则的运算得到一维的数组,参考文章什么是灰度图可以得到不同方法的运算。最终代码如下:
RGB值和灰度的转换,实际上是人眼对于彩色的感觉到亮度感觉的转换,这是一个心理学问题,有一个公式:
Grey = 0.299*R + 0.587*G + 0.114*B
RGB 转换灰度图像原理
%% RGB彩图转灰度图
% Function:将rgb三通道图像Img通过不同方式的运算得到灰度图grayImg
% Date:2020/9/24
% Author:leezeeyee
function grayImg=rgb2grayL(Img,way)
% 判断传入函数参数个数nargin是否指明方式way
if nargin<2
% 未提供方式参数way,默认选择方式1
way=1;
end
% 得到传入图像Img的长M、高N与维度D
[M,N,D]=size(Img);
if D==3
% 维度为3,RGB图像,进行转换操作
R=Img(:,:,1);
G=Img(:,:,2);
B=Img(:,:,3);
% 1.浮点算法:Gray = R*0.3 + G*0.59 + B*0.11
if way==1
grayImg=R*0.3 + G*0.59 + B*0.11;
% 2.整数方法:Gray = (R*30+G*59+B*11)/100
elseif way==2
grayImg=uint8((uint16(R)*30+uint16(G)*59+uint16(B)*11)/100);
% 3.移位方法:Gray =(R*28+G*151+B*77)>> 8
elseif way==3
grayImg=uint8(bitshift(uint16(R)*28+uint16(G)*151+uint16(B)*77,-8));
% 4.平均值法:Gray = (R+G+B)/3
elseif way==4
grayImg=(R+G+B)/3;
% 5.仅取绿色:Gray = G
elseif way==5
grayImg=G;
end
end
这里的代码是经过数据类型的转换,可以直接应用于图像处理,具体的修改原因见下文分析。
问题与解决方法
性能测试
测试不同算法的运行时间,首先通过随机函数生成范围在1~255以内的200*200*3的矩阵.
Img=randi([1,255],200,200,3);
测试代码
Img=randi([1,255],200,200,3);
tic
gray1=rgb2grayL(Img);
disp(['浮点算法运行时间: ',num2str(toc)]);
tic
gray2=rgb2grayL(Img,2);
disp(['整数算法运行时间: ',num2str(toc)]);
tic
gray3=rgb2grayL(Img,3);
disp(['移位算法运行时间: ',num2str(toc)]);
tic
gray4=rgb2grayL(Img,4);
disp(['均值算法运行时间: ',num2str(toc)]);
tic
gray5=rgb2grayL(Img,5);
disp(['单通道算法运行时间: ',num2str(toc)]);
subplot(2,3,1);imshow(gray1,[]);
title('浮点算法','fontname','Adobe 黑体 Std R' ,'Color','k','FontSize',12);
hold on;
subplot(2,3,2);imshow(gray2,[]);
title('整数算法','fontname','Adobe 黑体 Std R' ,'Color','k','FontSize',12);
hold on;
subplot(2,3,3);imshow(gray3,[]);
title('移位算法','fontname','Adobe 黑体 Std R' ,'Color','k','FontSize',12);
hold on;
subplot(2,3,4);imshow(gray4,[]);
title('均值算法','fontname','Adobe 黑体 Std R' ,'Color','k','FontSize',12);
hold on;
subplot(2,3,5);imshow(gray5,[]);
title('单通道提取算法','fontname','Adobe 黑体 Std R' ,'Color','k','FontSize',12);
hold on;
结果如下所示:
浮点算法运行时间: 0.0048435 整数算法运行时间: 0.0022653 移位算法运行时间: 0.0044984 均值算法运行时间: 0.0027857 单通道算法运行时间: 0.0026629
为避免单次结果的随机性,每种算法在1000*1000*3维度矩阵数据循环100次的结果如下
浮点算法运行时间: 3.2572s 整数算法运行时间: 3.0417s 移位算法运行时间: 3.5805s 均值算法运行时间: 3.0893s 单通道算法运行时间: 2.3045s
为了避免if-else
判断分支位置对消耗时间带来的影响,我将第5分支提前到第2位置后的两次结果分别为2.2873s
于2.3787s
,可见并非影响时间的主要因素。
分析
用浮点数进行运算与移位运算的时长是其他方法的近2倍,其中:
- 浮点数由于精度高,需要时间长是能够理解的。
- 但移位运算方式本身对于底层的语言是更快速,并且matlab的官方文档中也明确指出。但在我的一些测试中,并没有体现出它的优势,也许matlab本身对运算的优化已经足够高效。这个问题有待进一步探索——如用更加底层的C语言实现
- 整数运算与均值运算属于同一类型,时间相近。
- 单通道即仅提取RGB中某特定通道的值,只有一步数据装载的操作。
白加黑
但将相同的算法应用于实际图像时,问题来了——出现了白图与黑图,如下所示:
查看储存整数算法与移位算法得到的灰度图像,里面的数据分别为清一色的3
与清一色的0
,首先想到的是数据类型的原因。
数据类型
通过matlab内置函数class
可以查看某个变量的数据类型,在图像中,数据类型为uint8
,则最大可表示范围为0~255
,这在整数算法和移位算法中都超出这一范围。
以整数算法为例,数据在计算(R*30+G*59+B*11)
时在255处截断,再进行100的除法运算,四舍五入后等于最终结果3.
经过运算,255*100=25500<65535=2^16-1
,则可以用uint16
类型进行装载,因此分别对整数算法和移位算法中的数据类型进行转换后的处理与显示,具体改动为:
% 2.整数方法:Gray = (R*30+G*59+B*11)/100
elseif way==2
% grayImg=(R*30+G*59+B*11)/100;
grayImg=uint8((uint16(R)*30+uint16(G)*59+uint16(B)*11)/100);
% 3.移位方法:Gray =(R*28+G*151+B*77)>> 8
elseif way==3
% grayImg=bitshift(R*28+G*151+B*77,-8);
grayImg=uint8(bitshift(uint16(R)*28+uint16(G)*151+uint16(B)*77,-8));
结果展示
此时,运行不同的运算方法或方式得到如下结果。
但存在的问题是,由于增加了数据类型转换的步骤,因此整数算法与移位算法的用时增加,如下所示:
浮点算法运行时间: 0.0079022 整数算法运行时间: 0.012094 移位算法运行时间: 0.010768 均值算法运行时间: 0.0039739 单通道算法运行时间: 0.012084
浮点算法在同一种算法的三种方式中夺得头魁,这种结果应当是matlab中的独特体现。
非常实用的网站,非常感谢李佬的分享!!
谢谢支持!期待你的分享~