图像处理(一)

读取和显示图像

  • 读取图像: imread()
  • 显示图像: imshow()

例如:

1
2
3
clear, close all
I = imread('pout.tif'); %read
imshow(I); %show

其中pout.tif为matlab内置图像, 所以不需要外部导入图像就可以执行上面的代码.

执行代码后, I 矩阵存储了pout.tif的灰度值信息,矩阵中每个元素的类型是uint8类型, 范围是 0~255 , 也就是说每个像素需要使用一个字节来存储, 因此, 矩阵的大小就是图像的大小. imshow()函数把矩阵显示成图像的形式.

image-20200711145908621

imshow()的显示结果:

image-20200711145949851

可以使用imageinfo()函数来查看图像的详细信息. 例如执行imageinfo('pout.tif'):

image-20200711150309506

使用imtool()函数可以图像打开时看到图像的像素点灰度信息. 比如执行 imtool('pout.tif')后 , 在弹出窗口中点击红色方框中的按钮, 即可查看每个位置的像素的灰度值信息.

image-20200711150924655

image-20200711150939615

图像处理

既然图像就是矩阵, 那么图像处理实际上就是对矩阵的处理, 改变矩阵中的数值, 就可以改变图像的灰度信息, 实现对图像的处理.

1
2
3
4
5
6
7
8
9
I = imread('pout.tif');
for ii=1:size(I,1)
for jj=1:size(I,2)
if (rem(ii,2)==0 && rem(jj,2)==0 )
I(ii,jj)=0;
end
end
end
imshow(I)

上述代码就可以理解为是对图像的一种处理方式, 代码实现了把图像的偶数行, 偶数列的像素点的灰度值置0. 其执行效果如下:

image-20200711152124190

图像处理技术要远比上述代码高端, 可以使用滤波器对图像进行处理, 这里给出滤波器的使用效果, 暂时不对滤波器进行介绍.

image-20200711152528588

四则运算

这里首先介绍图像的四则运算 , 图像的四则运算是一种很简单的图像处理方式, 其中包括 加 减 乘 除 等, 需要使用的matlab命令大概如下:

  • imabsdiff: 两个图像的绝对差
  • imadd: Add two images or add constant to image
  • imapplymatrix: Linear combination of color channels
  • imcomplement: Complement image
  • imdivide: Divide one image into another or divide image by constant
  • imlincomb: Linear combination of images
  • immultiply: Multiply two images or multiply image by constant
  • imsubtract: 从一个图像中减去另一个图像或从图像中减去常量

图像的乘法示例, 图像乘法使用immultiply()函数, immultiply()函数可以达到使图像对比度增强或者对比度降低的效果, 如果将原图像的灰度值乘以一个大于一的数, 会导致各个灰度值之间的差距被拉开, 因此实现了对比度增强的效果. 反之, 乘以一个小于一的数值, 就实现了对比度降低的效果. 下面给出一个示例代码:

1
2
3
4
I=imread('rice.png');
subplot(1,2,1); imshow(I);
J=immultiply(I, 1.5); % 将原矩阵的像素灰度值乘以1.5
subplot(1,2,2); imshow(J);

效果图:

image-20200711154009094

可以看到, 图像的整体颜色效果是变亮的, 与此同时, 原来亮的部分亮度的增加程度也更大.

使用imadd()函数可以使两个图像对应点处的灰度值相加, 当然, 矩阵相加的前提是矩阵的大小应该相同.

1
2
3
4
5
I=imread('rice.png');
J=imread('cameraman.tif'); K=imadd(I,J);
subplot(1,3,1); imshow(I);
subplot(1,3,2); imshow(K);
subplot(1,3,3); imshow(J);

效果图:

image-20200711154318038


练习:

  1. 写一个function, 实现immultiply()函数的效果.
  2. 调整rice.png使图像的亮度增加或对比度增加.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
% 第一题: 对图像进行遍历调整
function J=immultiply_m(I,x)
if x<=0
disp('输入的数值不能小于0');
return;
end
for ii = 1:size(I,1)
for jj = 1:size(I,2)
if(I(ii,jj)*x <= 255)
J(ii,jj)=I(ii,jj)*x;
else
J(ii,jj)=255;
end
end
end

测试代码:

1
2
3
4
5
6
I=imread('pout.tif');
J=immultiply_m(I,1.5);
subplot(1,2,1);
imshow(I);
subplot(1,2,2);
imshow(J);

效果图:

image-20200711160515901

1
2
3
4
5
6
7
8
9
10
% 第二题
I=imread('rice.png');
X=uint8(ones(size(I,1),size(I,2))*50); % 元素都是50, 大小和原图相同的矩阵, 用于相加提升亮度
J=imadd(I,X);
K=immultiply(I,1.5); % 使用内置函数提升对比度
M=immultiply_m(I,1.5); % 使用我的函数提升对比度 对比效果
subplot(2,2,1); imshow(I);
subplot(2,2,2); imshow(J);
subplot(2,2,3); imshow(K);
subplot(2,2,4); imshow(M);

效果图:

image-20200711161513139


直方图均衡化

下面介绍imhist()函数, imhist函数用来显示图像灰度分布直方图.

执行示例:

1
2
I=imread('pout.tif');
imhist(I);

image-20200711162339950

可以看到, 图像的灰度值主要分布在75到170之间, 从整体来看, 图像的对比度较差. 我们可以来看一下执行乘法后的灰度分布直方图.

1
2
J=immultiply(I,1.5);
imhist(J);

image-20200711162628170

灰度值整体上是提高的趋势, 灰度值之间的差距也得到了一定程度的拉开. 但是从图中可以看出, 这种乘法不是最好的提高对比度的方式, 原因在于使用乘法后的图像灰度值较小的区域都没有使用到. 优秀的对比度提升算法应该使得图像的整体灰度分布比较均匀, 而不是整体偏高, 偏低, 或者集中在某一范围内. 使灰度值的分布均匀的过程又叫做直方图的均衡化 , matlab提供了内置函数来实现直方图的均衡化. 直方图均衡化的函数是histeq.

histeq函数使用示例:

1
2
3
4
5
I = imread('pout.tif'); I2 = histeq(I);
subplot(2,2,1); imhist(I);
subplot(2,2,2); imshow(I);
subplot(2,2,3); imhist(I2);
subplot(2,2,4); imshow(I2);

执行效果:

image-20200711163343685


练习: 写一个自己的function, 实现histeq函数的功能.

算法提示: 首先找到原图的最小灰度值min和最大灰度值max. 将其缩小和放大为0和255, 根据其他像素值在其原区间的比例, 得出该像素点在新区间的灰度值.

1
2
3
4
5
6
7
8
9
function J=histeq_m(I)
max0=max(max(I));
min0=min(min(I));
sub=double(max0-min0);
for ii=1:size(I,1)
for jj=1:size(I,2)
J(ii,jj)=uint8(double((I(ii,jj)-min0))/sub*255);
end
end

测试代码:

1
2
3
4
5
6
7
8
9
10
clear
I=imread('rice.png');
J1=histeq(I);
J2=histeq_m(I);
subplot(3,2,1); imhist(J1);
subplot(3,2,2); imhist(J2);
subplot(3,2,3); imshow(J1);
subplot(3,2,4); imshow(J2);
subplot(3,2,5); imshow(I);
title('原图');

效果对比图:

image-20200711165644698

看来我的代码还是比较一般, 欢迎批评指正.


图像的位置变换

图像的位置变换可以分为图像平移, 旋转, 图像的放大与缩小, 以及图像形状的变化. 通常实现这些变化需要和矩阵相乘, 下图给出一些变换对应的矩阵.

image-20200711170216645

matlab中对于这些操作有许多内置的函数, 比如imrotate()函数实现图像的旋转. 示例代码:

1
2
3
4
5
I = imread('rice.png'); subplot(1,2,1);
imshow(I); J = imrotate(I, 35, 'bilinear'); % 图像旋转35度
subplot(1,2,2); imshow(J);
size(I)
size(J)

结果图:

image-20200711170951812

从图中看, 似乎旋转后的图像和原图像恶大小是相等的, 但是通过命令行窗口的结果可以看出, 旋转后的图像实际上是比原图更大一些, 因为加入了许多黑色的像素点.

image-20200711171505309

图像存储

上面介绍了怎么读取图像, 显示图像. 接下来介绍如何存储图像. matlab中使用imwrite()函数来把一个表示图像的矩阵来保存成图像. 支持的保存格式 bmp,gif,hdf,jpg,jpeg,jp2,jpx,pcx,pnm,ras,tif,tiff,xwd等等.

示例代码:

1
2
3
I=imread('pout.tif');
J=histeq(I);
imwrite(J,'pout2.png');

执行代码后, pout2.png 会被保存在当前matlab的工作目录中.

资料链接

参考视频 参考讲义