前言

本系列文章为学校课程《数字图像处理》布置的一些小project作业

除了给出每个问题的解答和代码,我也会附上相关知识点,以方便后续复习

前置概念

图像表示方法及相关概念

做题之前先回顾一些前置概念

一般来说一张图片可以从色彩丰富度上分析,也可以从亮度上分析

灰度是表明图像明暗的数值,即黑白图像中点的颜色深度,范围一般从0到255,白色为255 ,黑色为0,故黑白图片也称灰度图像。灰度值指的是单个像素点的亮度。灰度值越大表示越亮。

灰度图像与黑白图像不同,在计算机图像领域中黑白图像只有黑色与白色两种颜色;但是,灰度图像在黑色与白色之间还有许多级的颜色深度。

灰度级:灰度级表明图像中不同灰度的最大数量。灰度级越大,图像的亮度范围越大。

如果我们需要表示彩色图片,就需要引入RGBHSV两种表示方法了

RGB和HSV分别是两种常见的彩色图像表示方法

RGB颜色空间以R(Red:红)、G(Green:绿)、B(Blue:蓝)三种基本色为基础,进行不同程度的叠加,产生丰富而广泛的颜色,所以俗称三基色模式。

与灰度图不同之处在于,RBG图的每个像素点都有3个值表示颜色,也叫3通道。如RGB(10,47,200)

相比于类似调色板的RGB颜色空间,HSV更接近于颜色的直观特性

HSV颜色模型是指H、S、V三维颜色空间中的一个可见光子集,它包含某个颜色域的所有颜色。每一种颜色都是由色相(Hue,简H),饱和度(Saturation,简S)和色明度(Value,简V)所表示的。这个模型中颜色的参数分别是:色调(H),饱和度(S),亮度(V)。

色调色彩信息,即所处的光谱颜色的位置。该参数用一角度量来表示,取值范围为0°~360°。若从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,紫色为300°

饱和度是指色彩的鲜艳程度,也称色彩的纯度。饱和度取决于该色中含色成分和消色成分(灰色)的比例。含色成分越大,饱和度越大;消色成分越大,饱和度越小。取值范围为0.0~1.0

亮度(色明度)的概念与RGB中三原色的值类似,代表色彩的明亮程度。

HSV模型对应于圆柱坐标系中的一个圆锥形子集,圆锥的顶面对应于V=1。它包含RGB模型中的R=1,G=1,B=1 三个面,所代表的颜色较亮。色彩H由绕V轴的旋转角给定。饱和度]S取值从0到1,所以圆锥顶面的半径为1。

该圆锥形为倒立,顶点处V值为0,而底面上的V值为1

对比度:指一幅图中灰度反差的大小,$对比度 = 最大灰度值/最小灰度值$

深度:图像深度是指像素深度中实际用于存储图像的灰度或色彩所需要的比特位数。假定图像的像素深度为16bit,但用于表示图像的灰度或色彩的位数只有15位,则图像的图像深度为15。图像深度决定了图像的每个像素可能的颜色数,或可能的灰度级数。例如,彩色图像每个像素用R,G,B三个分量表示,每个分量用8位,像素深度为24位

图像基本运算

像素级运算

点运算

点运算针对图像中的每一个像素灰度,独立地进行灰度值的改变

输出图像中每个像素点的灰度值,仅取决于相应输入像素点的值

代数运算

逻辑运算

图像的空域变换

空域变换是指在图像空间,对图像的形状、像素值等进行变化、映射等处理

空域变换可以分为几何变换和非几何变换

几何变换

几何变换是指对原始图像,按照需要改变其大小、形状和位置的变化

实现几何变换,我们可以使用多项式变换透视变换

另一种形式的几何变换是灰度插值

即缩小图片分辨率时如何保留原有图像的信息

常用的灰度插值方法有最近邻插值法双线性插值三次卷积插值算法等等

非几何变换(灰度变换)

非几何变换属于像素值的变换,没有几何位置的改变,也可以称作灰度变换

灰度变换的目的是为了改善画质,使图像的显示效果更加清晰

空间域图像增强

基本灰度变换

这里介绍几种常用的灰度变换

图像反转:故名思义,使用灰度级的最大灰度值减去原来图像每个像素点的灰度值

  • 公式:$S=L-1-r\quad L=2^b$

  • 应用:例如查看医学图像中病变组织的位置

对数变换:使得新灰度值为原灰度值的对数,将输入中范围较窄的低灰度值映射为输出中范围较宽的灰度值。

  • 公式:

  • 应用:用来增强图像中较暗的部分

幂次变换

  • 公式:$s=c\cdot r^\gamma $

  • 应用:使图像变得更接近真实值

灰度直方图

灰度直方图展示了图像中每种灰度级的像素个数

横坐标为灰度级,纵坐标表示该灰度级出现的频率

绘制图像的灰度直方图可以按照如下算法:

假设有一个灰度级为L的灰度图像f(x,y),大小为M*N

  1. 初始化$hist[k]=0;k=0,…,L-1$
  2. 统计$hist[f(x,y)]$++$;x=0,…,M-1,y=0,…,N-1$
  3. 归一化$hist[f(x,y)]/(M*N)$

灰度直方图可以应用于图像快速检测分割前景背景目标面积计算

彩色图像可以分别计算其R、G、B通道上的直方图

直方图处理

直方图均衡化

直方图呈均匀分布时,对比度会有明显增强

通过灰度变换函数,将原图像直方图的分布均衡化,这一过程称为直方图均衡化

想要使直方图均衡化,那么此时$D_B$就是均匀分布

可以推导出均衡化公式如下

下面是直方图均衡化比较直观的效果

直方图匹配

有一些应用方向上用均匀直方图的基本增强并不是好方法,有时问希望指定处理的图像所具有的直方图形状

这种用于产生处理后有特殊直方图的图像的方法,叫做直方图匹配或直方图规定化处理

一般来说,从当前直方图形状变为均衡化直方图的变换函数更为好求

那么我们可以考虑利用均衡直方图作为中间桥梁

HW1 直方图均衡

作业要求 :

实现river.jpg 图像的直方图均衡,不能直接使用Matlab的histeq( )函数。将有关

均衡图像和调用histeq( )函数的结果作比较。

river.jpg如下

首先我们需要读入图像

matlab中使用imread()函数,括号中参数为图片路径,本题为river.JPG

我们想要对比图像在直方图均衡前后的灰度直方图变化,就需要展示变换前后的直方图

MATLAB的图像处理工具箱(Image Processing Toolbox)中的imhist 函数用于计算图像的直方图,其返回一个表示直方图的向量 counts,我们可以将其作为直方图纵轴;和一个灰度级别的向x 是灰度级别的向量,它表示了直方图的横坐标,通常是从0到255的整数。

查阅matlab的文档和老师发的PPT《A Quick Tutorial on MATLAB》,在同一个窗口展示多张图片,我们需要用到subplot()函数

所以展示原图以及原图的灰度直方图可以通过如下代码实现:

1
2
3
4
5
6
img1 = imread('river.JPG');
figure(1),
subplot(1,2,1),
imshow(img1);title('原图');
subplot(1,2,2),
imhist(img1);title('原图直方图');

那么接下来就需要编写直方图均衡的代码

首先直方图均衡的变换函数如下

其中积分的部分我们可以通过累加图像的灰度值频率向量来获得

1
2
3
[counts, x] = imhist(img1,256); 
total_pixels = numel(img1);
cdf = cumsum(counts) / total_pixels;

numel()统计了图像的像素点个数

cumsum()即为累加函数,对于输入数组 A = [1, 2, 3, 4]cumsum(A) 返回数组 [1, 3, 6, 10]

本题的灰度级为255,所以我们将cdf乘以255得到变换函数

1
2
f = uint8(cdf * 255);
img2 = f(img1 + 1);

最后我们还需要与Matlab的histeq()函数进行对比,该函数直接调用即可

1
img3 = histeq(img1)

本题完整代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
img1 = imread('river.JPG');
[counts, x] = imhist(img1,256);
total_pixels = numel(img1);
% 计算累计分布函数 CDF
cdf = cumsum(counts) / total_pixels;
% 得到直方图均衡的变换函数
f = uint8(cdf * 255);
% 映射原始图像的像素值
img2 = f(img1 + 1);
% 调用histeq直接直方图均衡
img3 = histeq(img1);
figure(),
subplot(3,2,1),
imshow(img1);title('原图');
subplot(3,2,2),
imhist(img1,256);title('原图直方图');
subplot(3,2,3),
imshow(img2);title('直方图均衡后的图像');
subplot(3,2,4),
imhist(img2,256);title('直方图均衡后的直方图');
subplot(3,2,5),
imshow(img3);title('histeq后的图像');
subplot(3,2,6),
imhist(img3,256);title('histeq后的直方图');

运行效果如下图

如果想保存中间结果图像,可以使用imwrite()函数,而最终的结果对比窗口可以使用saveas()

1
2
3
imwrite(img2,'river2.jpg');
imwrite(img3,'river3.jpg');
saveas(gcf,'result.png');

HW2 直方图匹配

作业要求 :

将图像 EightAM.png 的直方图匹配为图像LENA.png的直方图 , 显示EightAM.png在直方图匹配前后的图像,并绘制LENA.png的直方图、直方图匹配前后EightAM.png的直方图,检查直方图匹配的效果。

回顾PPT中的直方图匹配算法

首先计算原图的直方图均衡转换函数,接着计算目标图的直方图均衡函数

1
2
3
4
5
6
7
ori_img = imread('EightAM.png');
tar_img = imread('LENA.png');
ori_hist = imhist(ori_img);
tar_hist = imhist(tar_img);
% 计算原始图像和目标图像的CDF
ori_cdf = cumsum(ori_hist) / numel(ori_img);
tar_cdf = cumsum(tar_hist) / numel(tar_img);

得到$D_A$和$D_C$之间的映射表,然后我们将原图根据映射表转为目标直方图形状的图像,即完成直方图匹配

1
2
3
4
5
6
7
8
% 建立映射表
Match = uint8(zeros(1,256));
for index = 1 : 256
[tmp,ind] = min(abs(ori_cdf(index) - tar_cdf));
Match(index) = ind-1;
end

res_img = Match(ori_img+1);

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
ori_img = imread('EightAM.png');
tar_img = imread('LENA.png');
ori_hist = imhist(ori_img);
tar_hist = imhist(tar_img);
% 计算原始图像和目标图像的CDF
ori_cdf = cumsum(ori_hist) / numel(ori_img);
tar_cdf = cumsum(tar_hist) / numel(tar_img);
% 建立映射表
Match = uint8(zeros(1,256));
for index = 1 : 256
[tmp,ind] = min(abs(ori_cdf(index) - tar_cdf));
Match(index) = ind-1;
end

res_img = Match(ori_img+1);

figure(),
subplot(3,2,1),
imshow(ori_img);title('原图');
subplot(3,2,2),
imhist(ori_img,256);title('原图直方图');
subplot(3,2,3),
imshow(tar_img);title('目标图');
subplot(3,2,4),
imhist(tar_img,256);title('目标图直方图');
subplot(3,2,5),
imshow(res_img);title('直方图匹配后的图像');
subplot(3,2,6),
imhist(res_img,256);title('直方图匹配后的直方图');
imwrite(res_img,'res_img.png');
saveas(gcf,'result.jpg');

最终效果如下图,可以看到结果图片和LENA这张图的对比度很相似