Matlab数字图像处理学习记录【1】——准备与基本原理

零.准备与环境

因为以前有过图像处理的基础:PythonCV学习记录1——如何安装Opencv库并在Python中调用
所以有些细节不会记录很很很详细。
同时,MATLAB的版本是2018b,也就是v9.5,也写过安装教程:Ubuntu18.04安装Matlab2018a
Matlab的使用介绍也不用多介绍了。书里是用的Matlab的图像处理工具箱IPT,感觉语法有些像OpenCV
最后,学习是基于冈萨雷斯的数字图像处理MATLAB版第三版

一.数字图像的表示

1.1 坐标约定

Matlab的坐标不像Python或者C++里的方式,它的原点是(1,1)。且规定元组的组成为(M,N) M是行 N是列
另外:IPT工具箱里有可能有少部分以(row,col)的表示方法,看源码的时候要注意
在这里插入图片描述

1.2 矩阵表示

Python中可等同于numpy的数组,而C++里是Mat,而听说Matlab是一个面向数组的语言???所以它本身就可以支持数组变量,且构成如下:
在这里插入图片描述
有:1 × N的矩阵为行向量,M × 1的矩阵为列向量,1 × 1的矩阵则为标量
Matlab里的变量由字母开头,且只能由字母、数字和下划线组成。

二. 读取图像

Matlab支持读取以下格式的图像:
在这里插入图片描述
语法类似CV:

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: {}

五.数据类

没啥看的,按位宽定的数据类型
在这里插入图片描述

六.图像类型

6.1分类

工具箱支持以下四种图像类型:

  • 亮度图像
  • 二值图像
  • 索引图像
  • RGB图像

6.2亮度图像

亮度图像中,它的亮度由uint8和uint16表示,在灰度图中,灰度即亮度;在其他图中,亮度是各通道得加权值

6.3二值图像

顾名思义,就0或1组成的图像。但注意Matlab里,要被认为是二值图像的话,数据类型必须是logical类。

七.图像和数据类转换

7.1数据类的转换

单纯的数据类的转换,直接使用对应的函数,即可完成数据类型间的转换:

B = ClassName(A)

类型名是前面那个表格里的。

7.2图像类和类型间的转换

在这里插入图片描述
通过一些函数转换,一般来说,对超出部分会直接取新范围的最大最小值,或者说将归一化的值除以新范围的最大值。
就比如这里给出一个亮度图转归一化的灰度图再二值化的过程:

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);

在这里插入图片描述
使用RGB的效果也差不多,但有一些差异:
在这里插入图片描述

尽管语句支持嵌套,但看起来Matlab是不如Python和C++的OpenCV方便的样子。

八.数组索引

这一部分就类似于Python的数组切片,而且代码都类似。

8.1向量索引

形如这样:

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
%%

切片:

  1. matrix(首索引:数量) 同时支持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
%%
  1. 自定义步长:matrix(首索引:步长:数量)
v = [0 1 2 3 4 5];
v(1:2:end)
v(end:-2:1)
%%
ans =
     0     2     4
ans =
     5     3     1
%%
  1. 切片矩阵:matrix([matrix])
v = [0 1 2 3 4 5];
v([1 3 5])
%%
ans =
     0     2     4
%%

8.2矩阵索引

同理,切片支持在高维矩阵中,书上以二维为标准:

  1. 构造与简单的下标访问
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
%%
  1. 行列切片
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);

在这里插入图片描述

8.3选择数组维数

很多操作,其实可以在后面跟上其所操作的维度数:

size(A, dim)

比如该函数,dim=1则是给出size的行数,dim=2则是列数。

九.一些重要的标准数组

其实和Numpy的生成一些特殊矩阵的代码类似,所以直接放图:
在这里插入图片描述

十.运算符

也直接放图,和其他编程语言大同小异。所以看一看,记住就行了:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

十一.流控制

11.1if语句

if expre1
	statement1
elseif expre2
	statement2
else
	statement3
end

这神奇的结构,我能感觉这玩意儿是多少种编程语言的结合体。。。

11.2for语句

for index = start:increment:end
	statements
end

例如:

cnt = 0;
for j=0:1:10
   cnt = cnt + 1; 
end
cnt
%%
cnt = 
		11
%%

11.3While

while expre
	statements
end

同时,支持continuebreak

11.4switch

switch expre
	case condition1
		statement
	case condition2
		statement
	otherwise
		statement
end

十二.向量化

前面说Matlab是面向矩阵的语言,看了这部分可能是在编写的时候像Numpy那样,添加了很多优化矩阵的代码,甚至用GPU并行计算矩阵吧,所以单纯用for的效率会远远不及矩阵操作。所以一般来说值得传递也可以给向量或者矩阵,这里就举一个例子:
通过tictoc包裹的语块,可以统计时间。这里给出一个该函数的构造:
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)=Asin(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

得到图片
在这里插入图片描述
和时间t1=0.0051
矩阵版:

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

十三.IO流

输出,使用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
%%

猜你喜欢

转载自blog.csdn.net/u011017694/article/details/112762081