目录
一、前言
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个坐标轴。
白色:(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。
四、图像增强
(未完待续)