实验目的
- 掌握如何用Matlab来读取,存储图像,获取图像的大小、颜色、高度、宽度等相关信息,及图像的间的转换。
- 使用Matlab软件对图像进行彩色处理。
- 了解图像算术运算在数字图像处理中的初步应用。
- 体会图像算数运算处理过程和处理前后图像的变化。
实验原理
Matlab实现图像的基本操作。
一幅数字图像在Matlab中用一个矩阵来表示,对数字图像进行处理,实质上就是对特定的图像矩阵进行变换的过程
图像读取imread()
功能:从文件中读取图片
语法:
1. A = imread(filename, fmt)
2. [X, map] = imread(...)
3. [...] = imread(filename)
4. [...] = imread(URL, ...)
5. [...] = imread(..., Paream1, Val1, Para2, Val2...)
A = imread(filename, fmt)函数从filename中读取一张灰度图或彩色图像,fmt表示图像的格式,例如jpg、tif等。返回图像对应的矩阵并赋值给变量A。
[X, map] = imread(…)读取图片赋值给索引图像矩阵X,索引图像矩阵和colormap配合使用,用来显示图像的颜色信息。相关颜色colormap设置为colormap。colormap是一个N×3的向量,是由灰度映射到彩色的集合。Matlab中每一个像素点都经过colormap的映射显示到屏幕上。
图像的保存imwrite()
功能:将内存中的图像信息存储到存储介质(硬盘)中
语法:
1. imwrite(A, filename)
2. imwrite(A, map, filename)
3. imwrite(_, fmt)
4. imwrite(_, Name, Value)
imwrite(A, filename)将矩阵A对应的图像保存到文件filename中。
显示图像 imshow(), image()
功能:将图像信息显示在屏幕上
语法:
1. image(C)
2. image(x, y, C)
3. image(x, y, C, 'PropertyName', PropertyValue, ...)
4. image('PropertyName', PropertyValue, ...)
5. handle = image(...)
6.
7. imshow(I)
8. imshow(I, RI)
9. imshow(X, map)
10. imshow(X, RX, map)
11. imshow(filename)
image()和imshow()都实现了将图像显示出来,imshow()以图像原大小将图像显示出来,image()为了更好的显示图像将图像进行了一定比例的缩放。 不过在图像显示时两个函数默认的colormap不一样,需要指定colormap才能正常显示图片。
图像大小读取size()
功能:读取图像矩阵的信息
语法:
1. d = size(X)
2. [m, n] = size(X)
3. m = size(X, dim)
4. [d1, d2, d3, ..., dn] = size(X)
读取矩阵X的大小,如果X是一个向量返回向量的维数d,如果X是一个2维矩阵返回矩阵的行数m和列数n,m = size(X, dim) 指定矩阵的维数将返回矩阵信息的向量m。
改变图像大小imresize()
功能:改变图像尺寸
语法:
1. B = imresize(A, scale)
2. gpuarrayB = imresize(gpuarrayA, scale)
3. B = imresize(A, [numrows numcols])
B矩阵是返回值,返回矩阵A缩放scale大小后的新图像矩阵。如果scale属于[0, 1],B将比A小,缩小的比例为scale的大小。
图像信息获取 iffo = imfinf(filename)
功能:获取文件中图像的信息
语法:
“`
4. info = imfinfo(filename)
5. info = imfinfo(filename, fmt)
6. info = imfinfo(url)
“`
该函数可以从文件中或是url中获取图像信息,获取的图像信息将以下面的形式给出
1. info =
2. Filename: [1x56 char]
3. FileModDate: '09-Jun-2017 09:38:46'
4. FileSize: 11566
5. Format: 'jpg'
6. FormatVersion: ''
7. Width: 718
8. Height: 489
9. BitDepth: 24
10. ColorType: 'truecolor'
11. FormatSignature: ''
12. NumberOfSamples: 3
13. CodingMethod: 'Huffman'
14. CodingProcess: 'Sequential'
15. Comment: {}
包括图像的存储类型、文件更改时间、文件大小、文件格式、图像的尺寸以及编码方式等等。
图像的代数算数运算
代数运算是指两幅或多幅输入图像之间进行点对点的加、减、乘、除运算得到输出图像的过程。如果记输入图像为A(x, y)和B(x, y),输出图像为C(x, y),则有如下四种形式
实验内容和分析
1. 图像底片的制作
函数代码:
1. function re = Reverse(gray)
2. %图像反转,俗称底片
3. s = size(gray);
4. [m, n] = size(gray);
5. if size(s) == 3
6. fprintf('图片不是灰度图像,可能是彩色图像不能进行底片处理');
7. return;
8. end
9. for i = 1 : m
10. for j = 1 : n
11. gray(i, j) = 255 - gray(i, j);
12. end
13. end
14. re = gray;
2. 图像伪彩
伪彩色处理是指将灰度图像转换成彩色图象。因为人眼对于彩色的分辨能力远高于对灰度图像的分辨能力,所以将灰度图像转换成彩色可以提高人眼对图像细节的辨别能力。伪彩色并不能真实的反映图像像的彩色情况。图像伪彩的本质是从灰度级到彩色的一个映射。对于单通道灰度图转换成伪彩图像的方法是将一种灰度映射为一种颜色,而映射方式不唯一,可以根据需要自行设定,下面的代码使用的算法是我自己想出来的。
1. function re = FalseColorRGB(gray)
2. [m, n] = size(gray);
3. %I = im2double(gray);
4. falsecolor = zeros(m, n, 3);
5. for i = 1 : m
6. for j = 1 : n
7. falsecolor(i, j, 1) = uint8(gray(i, j) / 0.3);
8. falsecolor(i, j, 2) = uint8(gray(i, j) / 0.59);
9. falsecolor(i, j, 3) = uint8(gray(i, j) / 0.11);
10. for k = 1 : 3
11. if falsecolor(i, j, k) > 255
12. falsecolor(i, j, k) = 255;
13. end
14. end
15. end
16. end
17. %falsecolor = falsecolor .* 255;
18. re = uint8(falsecolor);
函数的原理是彩色影神成灰度值的逆变换,将彩色图像映射成灰度图,采用的映射方法是,将RGB三个通道进行先行加权,R通道的权值为0.50,G通道的权值是0.39,B通道的权值是0.11,所以伪彩函数我做了一个逆变换,将灰度值分别映射到三个通道上得下图的效果。
利用上面函数产生伪彩图像效果如下
从结果中我们看到图像的效果还是挺好的,经过函数映射出的图像有一种仙境的感觉。哈哈
3. 图像减法
减法的代码如下
1. cat = imread('./cat.jpg');
2. flower = imread('./flower.jpg');
3. [m, n, k] = size(cat);
4. flower = imresize(flower, [m, n]);
5. s = imsubtract( flower, cat);
6. figure(), imshow(s, []), title('图像相减');
这里我没有自己自己写减法的函数利用了matlab自带的减法函数
得到的效果图如下
4. 利用图像乘法进行图像ROI的提取
实验流程:
第一步:产生和原始图像一样大小的mask,在这个mask上设置感兴趣区域
第二步:感兴趣区域的设计,可以根据个人喜好和实际情况设计感兴趣的区域,这里我提取mask的感兴趣区域的是在图片中心为圆心半径为200个像素点的圆。在此区域的像素值为1,其他区域的像素值为0.
第三步:将原始图像和产生的mask进行图像乘法运算。
我写了两个主要函数来实现这个功能,第一个函数是产生模板函数CreateMyMask() 这个函数产生一个和原始图像同样尺寸的mask用于后面相乘操作。第二个函数为multiplication(mask, gray),它的功能是将模板和原始图像进行相乘操作。
函数CreateMyMask(gray)函数如下:
1. function re = CreateMyMask(gray)
2. [m, n] = size(gray)
3. pointx = m / 2;
4. pointy = n / 2;
5. mask = zeros(m, n);
6. radius = 200; %半径为200
7. for i = 1 : m
8. for j = 1 : n
9. if sqrt(double((pointx - i)^2 + (pointy - j)^2)) < radius
10. mask(i, j) = 1;
11. end
12. end
13. end
14. re = mask;
````
两幅图像相乘的函数multiplication(mask, gray)如下:
<div class="se-preview-section-delimiter"></div>
- function re = multiplication(mask, gray)
- [m, n] = size(gray);
- for i = 1 : m
- for j = 1 : n
- gray(i,j) = gray(i, j) * mask(i, j);
- end
- end
- re = gray;
“`
1. function re = multiplication(mask, gray)
2. [m, n] = size(gray);
3. for i = 1 : m
4. for j = 1 : n
5. gray(i,j) = gray(i, j) * mask(i, j);
6. end
7. end
8. re = gray;
实验结果如下图:
提取的ROI区域为
可以看出图像中心的圆被提取出来了,当然如果感兴趣区域是其他部分也可按此类方法进行操作,比如感兴趣的矩形区域,三角等等,甚至是任意区域,所以它才叫感兴趣区域,哈哈。
5. 图像叠加
这个实验我们通过图片叠加的操作将两幅不同信息的图片叠加到一起。实际操作是
将个性签名和个人帅气生活照叠加成一张图片
程序代码:
1. name = imread('./signal.PNG');
2. Abao = imread('./ziji.jpg');
3. namegray = RGBtoGray(name);
4. namegray = uint8(namegray);
5. namefoot = AddNameToPic(namegray, Abao);
6. figure(5);
7. imshow(namegray, []);
8. figure(6);
9. imshow(namefoot, []); title('将文字加到图像中');
核心函数:AddNameToPic(name, pic)
1. function re = AddNameToPic(name, pic)
2. %imshow(name, []);
3. [m2, n2] = size(pic);
4. name = imresize(name, 1.3);
5. %thre = graythresh(name)
6. name = im2bw(name, 0.5); % 二值化
7. %name = uint8(name);
8. %name = 255 - name;
9. imshow(name, []);
10. [m, n] = size(name);
11. k = 20
12. for i = 1 : m
13. for j = 1 : n
14. if name(i, j) < 1
15. pic(i + k, j, 1) = 160;
16. pic(i + k, j, 2) = 32;
17. pic(i + k, j, 3) = 240;
18. end
19. end
20. end
21. re = pic;
这里签名照命名为signal.png,自己的生活照命名为ziji.png,签名照可以到网上自己生成个性签名,要黑字白底的才可以,否则程序会出问题,生活照就随意了,但最好要帅气的,特别帅气的。
6. 图像的旋转
图像旋转是指图像以某一点为中心旋转一定的角度,形成一幅新的图像的过程。当然这个点通常就是图像的中心。既然是按照中心旋转,自然会有这样一个属性:旋转前和旋转后的点离中心的位置不变。
1. pic = imread('./haha.jpg');
2. rotate = imrotate(pic, 30);
3. resized = imresize(pic, 2);
4. figure(), imshow(pic, []); title('原始图像');
5. figure(), imshow(rotate); title('图像旋转');
图像旋转效果图:
可以从旋转后的图像中看出,旋转后的图像本质上是贴在了另一张黑色的底面上,这个矩形底面正好将旋转后的图像包住类似容器一样。
总结
本次实验通过学习Matlab图像处理的相关操作,对基本的图像变换进行了实验。并亲自完成了图像底片的生成(Reverse函数),图像ROI(CreateMyMask函数、Multiplication函数)提取和图像合成(AddNameToPic函数)的核心函数,通过自己努力完成核心函数的编写,一方面锻炼了自我编程能力,另一方面让我对图像处理的基本原理有了更深的理解和体会。