数字图像处理学习笔记#3(p17)

#对图像进行分段式灰度变换

% 对图像进行分段式灰度变换,MATLAB代码如下
close all;
clear all;
clc;

A = imread('peppers.png');%A与'peppers.png'在matlab中的区别是什么?为什么
%imfinfo可以作用于'peppers.png'却不能作用于A?用什么函数可以将已经被imread
%赋值的变量当做图像来读取信息?
info1=imfinfo('peppers.png');
B=rgb2gray(A);
imwrite(B,'peppers2.png');
info2=imfinfo('peppers2.png');
[M,N]=size(B);
for x=1:M
    for y=1:N
        if(B(x,y)<=35);
            C(x,y)=B(x,y)*10;
        elseif(B(x,y)>35&B(x,y)<=75);
            C(x,y)=(10/7)*[B(x,y)-5]+50;
        else(B(x,y)>75);
            C(x,y)=(105/180)*[B(x,y)-75]+150;
        end
    end
end

set(0,'defaultFigurePosition',[100,100,1000,500]);
set(0,'defaultFigureColor',[1 1 1]);
subplot(1,2,1),imshow(B);
subplot(1,2,2),imshow(C);
info1,info2

处理思路是循环遍历图像中的每一个像素,要注意的是,对于彩色图像,需要将24位的彩色图像转换为8位灰度图像,才能进行灰度调整,按照同样的思路,也可以分别对RGB三个通道每个通道分别进行灰度变换,因为灰度本身就是亮度,与通道无关。需要注意的一点是matlab中if后面的判断语句也要加分号,以及if语句和for语句的结束都需要一个end,输入之后会自动对齐缩进未解决的问题是,imfinfo函数可以通过输入文件名作为参数来读取图像文件的信息,但是例如A=imread(‘xxx.png’)这种已经将图像信息赋值给变量A的情况,若没有变量名参数,或者对A进行一定操作生成了变量B,如何读取B的信息?只能通过将B另存为图像文件吗?

#2 对图像进行非线性变换

% 对图像进行非线性灰度变换,MATLAB代码如下
close all;
clear all;
clc;

A = imread('peppers.png');%A与'peppers.png'在matlab中的区别是什么?为什么
%imfinfo可以作用于'peppers.png'却不能作用于A?用什么函数可以将已经被imread
%赋值的变量当做图像来读取信息?

B=rgb2gray(A);
C=double(B);%
D=(log(C+1))/10;

set(0,'defaultFigurePosition',[100,100,1000,500]);
set(0,'defaultFigureColor',[1 1 1]);
subplot(1,4,1),imshow(A);
subplot(1,4,2),imshow(B);
subplot(1,4,3),imshow(C);
subplot(1,4,4),imshow(D);

因为A变量中存储的是x,y,f信息,所以可以直接对f进行操作,需要注意的是中间步骤

C=double(B),取小数型,取小数的原因:

matlab_处理图像时为什么把数据转换为double型,及显示_图形处理时为什么要转换为双精度浮点数-CSDN博客

主要有两点:

1 有些函数支持double型,而不支持uint8的数据类型,所以要转换
2 精度问题了,因为uint8进行数据处理的时候,容易造成数据溢出或精度不够

 另外,之所以double之后的图像显示为纯白,什么也看不到,原因是:matlab中用imshow()显示double类型图像中出现的问题_matlab double类型矩阵是否只能显示灰色-CSDN博客

在matlab中,我们常使用imshow()函数来显示图像,而此时的图像矩阵可能经过了某种运算。在matlab中,为了保证精度,经过了运算的图像矩阵I其数据类型会从unit8型变成double型。如果直接运行imshow(I),我们会发现显示的是一个白色的图像。这是因为imshow()显示图像时对double型是认为在0~1范围内,即大于1时都是显示为白色,而imshow显示uint8型时是0~255范围。而经过运算的范围在0-255之间的double型数据就被不正常得显示为白色图像了。   

通过查询变量表可以确定,double后的灰度数据数值没有发生改变,只是数据类型发生了变化,而因为对于double类型的数据,imshow()函数默认灰度范围是0-1,而原本的unit8格式的灰度数据数值范围是0-255的整数,改变数据类型之后数值不变,这就导致几乎全部的新double类型数据的值都大于1,也就是显示为白色,所以导致图像全白,理论上来说如果有一幅灰度全0的黑色图像,那么经过double之后仍然可以显示为黑色图像,下面进行试验。

% 对图像进行非线性灰度变换,MATLAB代码如下
close all;
clear all;
clc;

A = imread('peppers.png');%A与'peppers.png'在matlab中的区别是什么?为什么
%imfinfo可以作用于'peppers.png'却不能作用于A?用什么函数可以将已经被imread
%赋值的变量当做图像来读取信息?

B=rgb2gray(A);
[M,N]=size(B);
for x=1:M
    for y=1:N
       C(x,y)=0;
    end
end
D=double(C);

set(0,'defaultFigurePosition',[100,100,1000,500]);
set(0,'defaultFigureColor',[1 1 1]);
subplot(1,4,1),imshow(A);
subplot(1,4,2),imshow(B);
subplot(1,4,3),imshow(C);
subplot(1,4,4),imshow(D);

试验成功。

#3 通过程序获取灰度图像的直方图

% 对图像进行非线性灰度变换,MATLAB代码如下
close all;
clear all;
clc;

A = imread('peppers.png');%A与'peppers.png'在matlab中的区别是什么?为什么
%imfinfo可以作用于'peppers.png'却不能作用于A?用什么函数可以将已经被imread
%赋值的变量当做图像来读取信息?

B=rgb2gray(A);
[r,c]=size(B);%统计图像尺寸,用于遍历函数
%也可以写作:
% r=size(B,1);
% c=size(B,2);
N=zeros(1,256);%生成一个向量,用于保存256个灰度值对应的数量
%遍历所有像素,统计不同灰度像素的数量
for x=1:r
    for y=1:c
       k=B(x,y);
       N(k+1)=N(k+1)+1;
    end
end

set(0,'defaultFigurePosition',[100,100,1000,500]);
set(0,'defaultFigureColor',[1 1 1]);

subplot(1,2,1),imshow(B);
subplot(1,2,2),bar(N);%使用bar()函数来显示条形图
axis tight;%使坐标系的最大值和最小值与数据范围一致

思路是遍历所有像素,然后依次统计灰度,核心函数是N(k+1)=N(k+1)+1; 因为灰度级分布在0-255,而创建的向量一定是从1-256,所以统计灰度级k时,应当对应向量横坐标k+1,例如统计灰度级0时放在坐标1,统计灰度级255时放在坐标256。

其次是matlab中的变量都是数组形式的,至少是一个一维向量,所以在需要存储变量之前要创建向量来存储,一般用zeros()函数来创建一个全0的向量要注意是zeros(1,256),返回一个1x256的数组,不是zeros(0,256)!!!!!!!

最后是使用bar()函数来显示条状图,axis tight;来使坐标系的最大值和最小值与数据范围统一

#3.1 尝试分别统计RGB三个通道的灰度直方图

close all;
clear all;
clc;
%分别统计RGB三个通道的灰度直方图
A=imread('peppers.png');  %读入图像
[R,G,B]=imsplit(A);%imsplit()函数分割图像之后会合成为一个,导致c变量值变为3倍!
%获取r和c来遍历每一个像素,三个图像大小相同,所以使用同一个变量
[r,c]=size(R);
%给每一个通道创建一个向量用于统计直方图
R_space=zeros(1,256); 
G_space=zeros(1,256);
B_space=zeros(1,256);
%循环遍历
for x=1:r
    for y=1:c
        R_count=R(x,y);
        R_space(R_count+1)=R_space(R_count+1)+1;
        G_count=G(x,y);
        G_space(G_count+1)=G_space(G_count+1)+1;
        B_count=B(x,y);
        B_space(B_count+1)=B_space(B_count+1)+1;
    end
end

figure,
%显示原图片
subplot(2,3,1),imshow(R),title('Red')
subplot(2,3,2),imshow(G),title('Green')
subplot(2,3,3),imshow(B),title('Blue')
%显示直方图
subplot(2,3,4),bar(R_space);title('Red bar');
subplot(2,3,5),bar(G_space);title('Green bar')
subplot(2,3,6),bar(B_space);title('Blue bar')

代码调试过程中出现过Index in position 2 exceeds array bounds. Index must not exceed 512.

索引值超出数组范围的报错,经过单步调试发现c值超出了图像范围,经过分析发现imsplit()函数在分割RGB三个通道之后合成为了一个数组,也就是将三幅图像横向拼接在了一起,导致代表列数的c值变为了原来的3倍,因此超出了数组范围。

#4 调整图像灰度级改变明暗度

%调整灰度范围
clear all;
close all;
clc;

A=imread('pout.tif');
%使用double函数将灰度值变为小数型,提高运算精度,防止精度不足
A=double(A);
%灰度变换公式,但是可能导致灰度值超出0-255范围,所以后续遍历对超出范围的数值进行调整
B=(A-80)*255/70;
[r,c]=size(A);
%对超出范围的数值进行调整
for x=1:r
    for y=1:c
        if B(x,y)<0
            B(x,y)=0;
        end
        if B(x,y)>255
            B(x,y)=255;
        end
    end
end

figure,
subplot(1,2,1),imshow(uint8(A));%使用uint8函数将double类型转换回来,否则
%imshow函数会将double类型的灰度默认为0-1范围进行显示,大于1的均认为是白色像素
% 从而导致图像几乎全白
subplot(1,2,2),imshow(uint8(B));

 

进行除法等多数会产生小数部分,或者比较精确运算的时候,需要将变量类型调整为double(),使用小数类型变量进行运算,同时,由于大部分情况下运算的数值是灰度值,最终如果使用imshow()函数进行显示的时候,需要再用uint8()函数将变量值转换回来,否则由于imshow函数对double类型的默认灰度范围为0-1,会导致图像显示几乎全白,详见p17-#2。

#5 使用imadjust()函数调整灰度范围

% 使用imadjust()函数调整灰度范围
clear all;
close all;
clc;

A=imread('pout.tif');
B=imadjust(A,[0.2,0.5],[0,1]);%调整图像灰度值
figure,
subplot(1,2,1),imshow(A);%使用uint8函数将double类型转换回来,否则
%imshow函数会将double类型的灰度默认为0-1范围进行显示,大于1的均认为是白色像素
% 从而导致图像几乎全白
subplot(1,2,2),imshow(uint8(B));

% 使用imadjust()函数调整灰度范围
clear all;
close all;
clc;

A=imread('pout.tif');
%经过灰度直方图统计,灰度值主要分布在0.29-0.69
B=imadjust(A,[0.3,0.7],[0,1]);%调整图像灰度值,将[0.2,0.5]映射到[0-1]
C=imadjust(A,[0,0.2],[0,1]);%调整几乎不存在的灰度,看效果
D=imadjust(A,[0.7,1],[0,1]);%调整几乎不存在的灰度,看效果
figure,
subplot(1,4,1),imshow(A),title('原图像');%使用uint8函数将double类型转换回来,否则
%imshow函数会将double类型的灰度默认为0-1范围进行显示,大于1的均认为是白色像素
% 从而导致图像几乎全白
subplot(1,4,2),imshow(uint8(B)),title('0.3-0.7');
subplot(1,4,3),imshow(uint8(C)),title('0-0.2');
subplot(1,4,4),imshow(uint8(D)),title('0.7-1');

可以理解为设定一个输入范围,小于左侧值的直黑,大于右侧值的直白,中间的映射到输出范围。

#6 使用brighten()函数来更改亮暗程度

%使用brighten()函数调整图像亮度,matlab代码如下
clear all;
close all;
clc;

A=imread('corn.bmp');
figure,imshow(A),title('原图');
figure,imshow(A);brighten(0.6);title('加亮');
figure,imshow(A);brighten(-0.6);title('变暗');

 

但是似乎不是对所有图像都有效 ,测试结果为对彩色图像无效,只对灰度图像生效,而且必须每个图单独figure一次,而不能用subplot,subplot会导致所有图像显示都一样 

#7 使用imhist()函数计算和显示图像灰度级图像

% 通过函数imhist()计算和显示灰度级图像的直方图,matlab代码如下
clear all;
close all;
clc;

I=imread('pout.tif');
subplot(1,2,1);
imshow(uint8(I));
subplot(1,2,2);
imhist(I);%统计直方图

#8 使用imhist()函数计算RGB彩色图像三个通道的直方图

% 通过函数imhist()计算和显示彩色图像RGB三个通道的直方图,matlab代码如下
clear all;
close all;
clc;

I=imread('onion.png');
subplot(1,4,1),imshow(uint8(I));
subplot(1,4,2),imhist(I(:,:,1)),title('R');%计算并显示R通道的直方图
subplot(1,4,3),imhist(I(:,:,2)),title('G');%计算并显示R通道的直方图
subplot(1,4,4),imhist(I(:,:,3)),title('B');%计算并显示R通道的直方图

#9 通过函数imhist()计算和显示彩色图像HSV分量的直方图

% 通过函数imhist()计算和显示彩色图像HSV分量的直方图,matlab代码如下
clear all;
close all;
clc;

I=imread('football.jpg');
J=rgb2hsv(I);%什么是HSV?
h=figure;%为什么不直接figure,而是要h=figure?因为后面要set图像的位置信息
set(h,'position',[200,200,1000,400]);
subplot(1,4,1),imshow(uint8(I));
subplot(1,4,2),imhist(J(:,:,1)),title('H');%计算并显示R通道的直方图
subplot(1,4,3),imhist(J(:,:,2)),title('S');%计算并显示R通道的直方图
subplot(1,4,4),imhist(J(:,:,3)),title('V');%计算并显示R通道的直方图

HSV是指hue(色相),saturation(饱和度),value(亮度)。

三分钟带你快速学习RGB、HSV和HSL颜色空间 - 知乎 (zhihu.com)

#10 通过函数histeq()对图像进行直方图均衡化处理,并对比前后的直方图

%通过函数histeq()对图像进行直方图均衡化处理,matlab代码如下;
clear all;
close all;
clc;

I=imread('tire.tif');
J=histeq(I);
figure;
subplot(2,2,1),imshow(uint8(I));
subplot(2,2,2),imshow(uint8(J));
subplot(2,2,3),imhist(I,64);
subplot(2,2,4),imhist(J,64);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值