Reading | 《数字图像处理原理与实践(MATLAB版)》(未完待续)

时间:2023-03-09 01:01:09
Reading | 《数字图像处理原理与实践(MATLAB版)》(未完待续)

一、前言

1、MATLAB or C++

用MATLAB进行图像处理编程,无需考虑内存分配和回收的问题,开发难度小一些;

相比之下,Visual C++需要考虑的问题比较多,但在工业开发中更实用,效率更高。

只用MATLAB容易忽视底层问题,比如读取图片等。

2、图像文件

图像文件一般由文件头、调色板数据和像素数据三部分组成。

文件头

存放图像的各种参数,包括图像类型、宽度、像素位数、压缩类型、有无调色板等。

文件头中的参数可以是固定的,也可以是灵活的。

如BMP格式,不仅参数类型固定,而且每个参数的位数也是固定的。

而有些图像文件格式中存在自定义参数,参数在文件中的存储位置也不固定。

调色板

图像的颜色索引表。

调色板仅存在于二值、16色、256色图像中,真彩色图像是没有调色板的。

GIF就不支持真彩色图像,因此在GIF文件中必然存在调色板。

像素数据

像素数据可以是压缩的,也可以是非压缩的。

不压缩的像素数据,在不同格式的图像文件中具有基本相同的存储结构。

3、RGB颜色空间

原理

人眼中的锥状细胞和棒状细胞对红、绿、蓝特别敏感。

在CRT显示系统中:彩色阴极射线管使用R、G、B数值,来驱动电子枪发射电子,分别激发荧光屏上的R、G、B三种颜色的荧光粉,以发出不同亮度的光线,并混合得到各种颜色。

坐标表示

RGB颜色模型对应笛卡尔坐标系中的一个立方体,R、G、B分别代表3个坐标轴。

Reading | 《数字图像处理原理与实践(MATLAB版)》(未完待续)

白色:(255,255,255)
黑色:(0,0,0)原点
灰度级:两点连成的对角线。

一般编程语言和编译环境都直接提供对RGB颜色表示的支持,并且3个分量取值范围都是0到255。

4、MATLAB中的图像文件

默认情况下,MATLAB将图像中的数据存储为double(64位浮点数);

但涉及运算时,必须转成double型,保证运算精度。

在图像文件中,uint8范围是[0,255],double范围是[0,1]。

图像类型

MATLAB中的图像类型包括:灰度图像,RGB图像,二值图像和索引图像4种。

  • 灰度图像:灰度级0~255。存储形式为矩阵,其元素可以是double,也可以是uint8。

  • RGB图像(真彩色图像):存储形式为mn3的矩阵,其元素也可以是double和uint8。

    例如,像素(20,10)的R、G、B值分别存在(20,10,1)、(20,10,2)和(20,10,3)。

  • 二值图像:也用矩阵存储,但只需要1个矩阵,并且元素也可以是uint8

  • 索引图像:包括一个数据矩阵X和一个颜色映射矩阵Map。Map含3列和若干行,每个元素均为[0,1]之间的double。

    当矩阵数值为1时,用色图矩阵中第2行表示的颜色绘制。
    当矩阵数值为0时,用色图矩阵中第1行表示的颜色绘制。

image()函数

可以直接显示8位图像,原始尺寸。
将double型数据取整(正数取整就是把小数部分舍掉),然后直接映射,按颜色表显示。

imshow()函数

功能最强,映射方式丰富。可以替代image()和imagesc()函数。

  • imshow(I)
    当图像为double型时,函数把显示范围设置成[0,1],小于0的变成黑色,大于1的变成白色。
    当图像为uint8型时,函数把显示范围设置成[0,255]。

    处理不当会出现全白。根本原因是数据类型和map范围不匹配。

  • imshow(I/(max(I(:))))
    解决超范围double数据出现的全白问题方法1。
    用max(I(:)) 对矩阵进行归一化,再显示。

    uint8型不要这么做!!!直接显示即可,否则会很黑。

  • imshow(uint8(I))
    解决超范围double数据出现的全白问题方法2。
    如果原本就是uint8类型,没影响。
    如果原本是超范围double类型,uint8()函数先把double数据转换成uint8,但方式很粗暴:负数归零,超过255置为255,小数被round。

    由于方式太粗暴,丢的信息比较多。

  • imshow(I,[ ])
    这种方式就是把imshow的显示范围设置成[min(I(:)) max(I(:))],也就是线性映射。
    相当于imagesc(I),colormap(gray(256))。

imread()函数

  • 如果是灰度图像,imread()把图像存入一个8位矩阵,色图矩阵转换为double矩阵。

  • 如果是RGB图像,imread()把图像存入一个8位RGB矩阵。

可以显式地给出图片路径。

图像转换

  • 灰度图像和索引图像
[X, MAP] = gray2ind(I, [n])

n是颜色值,默认为64

I = ind2gray(X, MAP)
  • RGB彩色图像和索引图像
[X, MAP] = rgb2ind(RGB)
RGB = ind2rgb(X, MAP)
  • RGB彩色图像和索引图像
[X, MAP] = rgb2ind(RGB)
RGB = ind2rgb(X, MAP)
  • RGB彩色图像 → 灰度图像
I = rgb2gray(RGB) % 由于灰度级的RGB三个分量是相同的,因此做算术平均即可

反过来不行。因为这是一个病态过程。

  • 其他图像 → 二值图像
BW = im2bw(I, MAP, level) % level是阈值,在0和1之间。默认为OSTU寻找阈值。
BW = im2bw(I, level)
BW = im2bw(RGB, level) % 先转换成灰度图像

有一个更强的函数:imbinarize(),可以设置method,比如局部level。

其他图片操作

whos I % 给出附加信息,如存储方式等。
imwrite(I, 'newImage.png') % filename可以包含完整路径

% 只适用于JPG图像:
imwrite(I, 'newImage.jpg', 'quality', q)
% q在0到100之间,控制压缩后的图像质量。q越小图像越差。

% 只适用于TIF图像:
imwrite(I, 'newImage.tif', 'compression', 'p', 'res', ...[colres rowres])
% p:none为无压缩,ccitt为CCITT压缩,packbits为比特压缩。
% clores是列分辨率,rowres是行分辨率,默认为[72 72]。即每单元的点数。

最后要注意的是,MATLAB中的图像坐标系,类似于笛卡尔坐标系的第四象限。

二、图像的点运算

点运算:操作对象是图像的单个像素值。

  • 输出像素值只与当前输入像素值有关。

  • 变换公式是最关键的,可唯一确定结果。

1、灰度直方图

高对比度:灰度分布范围广,灰度直方图整体比较平滑。对于彩色图像,图像会显得色彩丰富艳丽。
低对比度:灰度分布集中。

可用于:

  • 图像信息加密:理想秘图不仅摆脱原始图像的纹理特征信息,还应该具有均匀分布的直方图。

  • 无损信息隐藏:基于图像直方图移位。

2、灰度均衡

直方图均衡可以有效调节图像对比度。

后来延伸出自适应的直方图均衡化算法AHE,通过计算图像的局部直方图,重新分布亮度来改变图像对比度。

优势:改进图像局部对比度,获得更多的图像细节。
缺点:过度放大图像中相同区域的噪声。

为了解决这一问题,有学者提出了对比度有限的自适应直方图均衡化算法CLAHE。
CLAHE在图像去雾中广泛使用,因为去雾算法的本质,就是调节图像对比度和亮度。

当然,去雾还有其他算法,比如暗通道算法。这在后面会介绍。

3、直方图规定化

离散方式实现比较复杂,推导见P56。
就个人经验,大家普遍采用近似的方法:逐个累积,看合并多少个误差最小。这样更简单。
Matlab内置函数可以参考另外一个图像(的直方图),代码见P57。

三、图像的几何变换

图像几何变换:建立一种 源图像像素 与 变换后的图像像素 之间的映射关系。

1、图像几何变换的基本理论

分为前向映射(由输入图像坐标,推出输出图像坐标)和后向映射。

前向映射可能的问题:映射不完全或映射重叠。

此时需要相应规则,决定或生成输出坐标的像素值。

为了解决前向映射的问题,我们引入后向映射。我们寻找的映射作用在输出坐标上,反向寻找唯一的输入坐标。

在图像的旋转和缩放中,我们普遍采用后向映射。

2、插值算法

书上介绍了双线性插值,见P72。

四、图像增强

(未完待续)