因为以前有过图像处理的基础:PythonCV学习记录1——如何安装Opencv库并在Python中调用
所以有些细节不会记录很很很详细。
同时,MATLAB的版本是2018b,也就是v9.5,也写过安装教程:Ubuntu18.04安装Matlab2018a
Matlab的使用介绍也不用多介绍了。书里是用的Matlab的图像处理工具箱IPT
,感觉语法有些像OpenCV
最后,学习是基于冈萨雷斯的数字图像处理MATLAB版第三版
Matlab
的坐标不像Python
或者C++
里的方式,它的原点是(1,1)
。且规定元组的组成为(M,N) M是行 N是列
。
另外:IPT工具箱里有可能有少部分以(row,col)的表示方法,看源码的时候要注意
在Python
中可等同于numpy
的数组,而C++
里是Mat
,而听说Matlab
是一个面向数组的语言???
所以它本身就可以支持数组变量,且构成如下:
有:1 × N
的矩阵为行向量,M × 1
的矩阵为列向量,1 × 1
的矩阵则为标量
Matlab里的变量由字母开头,且只能由字母、数字和下划线组成。
f = imread('filename');
它可以是绝对路径,也可以是相对路径。
记得加;
可以使命令行窗口,不输出f的值,否则看着很乱。
矩阵f
的属性可以这样获取:
[m, n] = size(f)
或者:
whos f
显示图像和CV的语法有些差别:
imshow(f)
当然,如果这幅图像是灰度图的话,可以添加灰阶级数矩阵G作为滤波:
imshow(f, [low high])
其中低于low的值为灰色,高于high的值为白色,之间的值为中等亮度值。
当然,也可以用figure
创建窗体,显示多个图片。
保存图片按道理来说应该用的不多,记一下即可:
imwrite(f, 'filename')
imwrite(f,'filename.jpg', 'quality', q)
接触过JPG图像的话,应该知道jpg可以压缩,q是压缩率 0~100
还可以用imfinfo
来查看图像的各种信息,返回的是一个结构体,可以用.
访问,结构体组成如下:
Filename: 'D:\Matlab_WS\test.jpg'
FileModDate: '17-Mar-2018 21:50:22'
FileSize: 302838
Format: 'jpg'
FormatVersion: ''
Width: 1090
Height: 1090
BitDepth: 24
ColorType: 'truecolor'
FormatSignature: ''
NumberOfSamples: 3
CodingMethod: 'Huffman'
CodingProcess: 'Sequential'
Comment: {}
工具箱支持以下四种图像类型:
亮度图像中,它的亮度由uint8和uint16表示,在灰度图中,灰度即亮度;在其他图中,亮度是各通道得加权值
顾名思义,就0或1组成的图像。但注意Matlab里,要被认为是二值图像的话,数据类型必须是logical
类。
单纯的数据类的转换,直接使用对应的函数,即可完成数据类型间的转换:
B = ClassName(A)
类型名是前面那个表格里的。
通过一些函数转换,一般来说,对超出部分会直接取新范围的最大最小值,或者说将归一化的值除以新范围的最大值。
就比如这里给出一个亮度图转归一化的灰度图再二值化的过程:
f = imread('.\gray.jpg');
double_f = im2double(f);
gray_f = mat2gray(double_f);
gb_f = im2bw(gray_f, 0.6);
subplot(1,2,1);
imshow(f);
subplot(1,2,2);
imshow(gb_f);
尽管语句支持嵌套,但看起来Matlab是不如Python和C++的OpenCV方便的样子。
这一部分就类似于Python的数组切片,而且代码都类似。
形如这样:
v = [0 1 2 3 4 5];
v(1)
ans显示为ans=0
所以Matlab的数组是从1开始
转置操作符 .'
v = [0 1 2 3 4 5];
v = v.'
%%
v =
0
1
2
3
4
5
%%
切片:
end
v = [0 1 2 3 4 5];
v(1:3)
v(1:end)
%%
ans =
0 1 2
ans =
0 1 2 3 4 5
%%
v = [0 1 2 3 4 5];
v(1:2:end)
v(end:-2:1)
%%
ans =
0 2 4
ans =
5 3 1
%%
v = [0 1 2 3 4 5];
v([1 3 5])
%%
ans =
0 2 4
%%
同理,切片支持在高维矩阵中,书上以二维为标准:
v = [0 1 2; 3 4 5; 6 7 8]
v(2,2)
%%
v =
0 1 2
3 4 5
6 7 8
ans =
4
%%
v = [0 1 2; 3 4 5; 6 7 8];
v(1:end, 2)
v(2,:)
%%
ans =
1
4
7
ans =
3 4 5
%%
还可以直接赋值,还不用考虑是否行列对应,这玩意儿会自动转换,甚至标量也可以:
v = [0 1 2; 3 4 5; 6 7 8];
v(:, 2) = [1 2 3];
v(2,:) = 0;
v
%%
v =
0 1 2
0 0 0
6 3 8
%%
所以可以这样提取图片的roi
或者行列扫描线:
f = imread('.\gray.jpg');
roi = f(1:256, 1:256);
line = f(:,256);
subplot(1,2,1);
imshow(roi);
subplot(1,2,2);
plot(line);
很多操作,其实可以在后面跟上其所操作的维度数:
size(A, dim)
比如该函数,dim=1则是给出size的行数,dim=2则是列数。
其实和Numpy
的生成一些特殊矩阵的代码类似,所以直接放图:
也直接放图,和其他编程语言大同小异。所以看一看,记住就行了:
if expre1
statement1
elseif expre2
statement2
else
statement3
end
这神奇的结构,我能感觉这玩意儿是多少种编程语言的结合体。。。
for index = start:increment:end
statements
end
例如:
cnt = 0;
for j=0:1:10
cnt = cnt + 1;
end
cnt
%%
cnt =
11
%%
while expre
statements
end
同时,支持continue
和break
switch expre
case condition1
statement
case condition2
statement
otherwise
statement
end
前面说Matlab
是面向矩阵的语言,看了这部分可能是在编写的时候像Numpy
那样,添加了很多优化矩阵的代码,甚至用GPU并行计算矩阵吧,所以单纯用for的效率会远远不及矩阵操作。所以一般来说值得传递也可以给向量或者矩阵,这里就举一个例子:
通过tic
和toc
包裹的语块,可以统计时间。这里给出一个该函数的构造:
f ( x , y ) = A ⋅ s i n ( u 0 x + v 0 y ) f(x,y)=A\cdot sin(u_0x+v_0y) f(x,y)=A⋅sin(u0x+v0y)
假设u0和v0等于1/(4*pi),A=1,图片大小也就是0<=x,y<=256
for循环版
u0 = 1/(4*pi);
v0 = u0;
f = [];
tic
for r = 1:256
u0x = u0*(r-1);
for c = 1:256
v0y = v0*(c-1);
f(r,c) = sin(u0x+v0y);
end
end
t1 = toc;
imshow(f);
t1
u0 = 1/(4*pi);
v0 = u0;
f = []
tic
r = 0:255;
c = 0:255;
[C, R] = meshgrid(c, r);
g = sin(u0*R + v0*C);
t1 = toc;
g = mat2gray(g);
imshow(g);
t1
图一样,而时间缩短到了:t1 = 0.0011
输出,使用disp( )
即可
输入则类似于Python
t=input('message out')
这个就类似于Python
的数组了,啥类型都可以添加,但是这里面的值不会被修改。
c = {'A', 'BC', [1 2], [1 2; 3 4], 5}
c{1}
c{2}
c{3}
c{4}
c{5}
%%
c =
1×5 cell 数组
{'A'} {'BC'} {1×2 double} {2×2 double} {[5]}
ans =
'A'
ans =
'BC'
ans =
1 2
ans =
1 2
3 4
ans =
5
%%
或者我们可以声明结构体:
S.age = 5;
S.name = 'kanna';
S.matrix = [1 2; 3 4];
T = S;
T.matrix = T.matrix + S.matrix;
T.matrix
%%
ans =
2 4
6 8
%%