这一篇在干嘛?

二维信号处理实战:图像格式与基本操作、HDL 边缘检测、中值滤波、VGA 系统、视频运动检测协处理器。 原书代码为 VHDL,本篇所有代码已改写为 Verilog。

  • 图像和视频处理
  • 10.1 图像和视频处理概述
  • 10.2 案例研究 1: HDL 中的边缘检测
  • 10.3 案例研究 2: 使用图像处理库进行中值滤波
  • 10.4 案例研究 3: 视频处理中的运动检测由自定义协处理器改进
  • 练习

自测一下

图像和视频处理

如果说一维 DSP 处理的是随时间变化的波形,那么图像处理就是把信号”升了一个维度”——多出一个空间坐标 ;视频处理则再升一维,加入时间。好消息是,前面学过的滤波、FFT 等算法大部分都能直接推广到二维、三维;但也有一些内容是纯一维世界里完全不出现的:

  • 去除脉冲噪声的非线性滤波器(中值、最大/最小滤波等);
  • 用于发现视觉不连续点的边缘检测,目的是压缩输入特征、保留最有用的信息;
  • 视频中的运动向量,用来描述一个数据块如何从上一帧移动到下一帧,是视频压缩的核心工具;
  • 形态学图像处理,这类操作在一维 DSP 中根本没有对应物。

为什么这本书要专门用 FPGA 讲图像处理?关键在硬件条件的变化:现代 FPGA 配备了大容量片内存储块(例如 Stratix II 有 512 Mbit 的片上存储),图像处理算法中大量的行缓存、帧缓存可以直接放在片内,实现效率大幅提升。放在过去没有快速片上存储的年代,工程师必须花费大量开发时间去搭建与外部存储芯片(DDRAM、QDR、RLDRAM、SDRAM 等)的接口,门槛高得多。

实现图像处理算法有几种典型路线:1) 直接用 HDL 设计;2) 使用 IP 库;3) 嵌入式微处理器加定制协处理器(μP)。本章的案例研究会覆盖这些方法。初学者建议先在 MATLAB 的图像处理和计算机视觉工具箱中练习,UNIX 系统上还有集成了许多算法的图形程序 XV 可以参考。

在进入二维、三维细节之前,先弄清楚一维处理、图像和视频在格式与基本处理上的差异。

10.1 图像和视频处理概述

一维处理与图像处理有一个根本性的态度差别:一维滤波强调因果性——输出只能依赖过去时刻的输入,否则硬件不可实现;而图像处理面对的是一整幅已经存好的数据,我们并不希望每次滤波都把图像”翻转”一遍。于是图像处理中的惯例是:

  • 使用”类因果”滤波:用滤波器输出替换中心像素;
  • 只用 、 方向都为奇数长度的滤波器,如 、、,这样才存在真正的”中心像素”;
  • 滤波器用**核(掩模)**定义而不是卷积运算。对尺寸 的核,输出为

注意这里没有做卷积要求的翻转——如果真按卷积定义来,矩阵运算前信号要先翻转 180°,图像处理中通常省略这一步。

边界效应

二维中比一维更突出的另一个问题是边界效应:一个 的掩模在 的图像上滑动时,掩模一旦出界就无法完整计算,损失的像素数为

计算示例:拉普拉斯-高斯(LoG)滤波器取 时核尺寸 ,作用在 的图像上,丢失像素数为 ,占整幅图的 ——将近四分之一的边界面积没了!这个损失相当可观。

就保持边界而言,IIR 滤波器理论上表现更好(不需要掩模完整覆盖),但由于非线性相位和稳定性问题,图像处理中很少使用。更常见的做法是把图像向外扩展半个核宽,扩展方式有四种:

  • 常数值填充,通常取 ;
  • 对称扩展:…3,2,1 | 1,2,3,…(镜像);
  • 复制边界值:…1,1,1 | 1,2,3,…;
  • 圆形(环绕)扩展:…,8,9,10 | 1,2,3…,8,9,10 |。

行方向和列方向都要做同样的扩展。

硬件中的折中:一行偏移

真正做硬件时,图像数据通常以一维流的方式进出,我们常采用类似”圆形扩展、只偏移一行”的近似:

… 1 23 4 510 11 12 …
3 4 510 11 1213 14 …

也就是第一行的末尾值(3、4、5)直接接到第二行的开头参与计算,第二行的开头值(10、11、12)与第一行的末尾一并处理。这种”跨行借用”只有在假设图像边界是背景、且整幅图背景相似时才合理——大多数自然图像满足这一点,所以工程上很实用。

10.1.1 图像格式

数字图像中最基本的单元叫像素,常用 8 位表示(医学成像可达 12 位)。编码约定是:0 代表黑,最大值(8 位格式即 255)代表白。

彩色怎么来?全彩色谱只用三种基色——红、绿、蓝(RGB)就能合成;从灰度图转 RGB 时三个通道赋相同的灰度值即可。但人眼有个特点:对亮度变化比对颜色变化敏感得多,所以实用的编码方案把灰度(亮度 Y)和差分色度分开传输——亮度用更高的精度/分辨率,色度可以适当压缩,图像质量几乎不降。RGB 中三通道位数相同,没有利用这一特性,于是在电视、JPEG、MPEG 中流行两种分离方案:YIQ 和 YUV(也叫 YCrCb)。

NTSC 电视系统采用的 YIQ 编码变换为:

ITU BT.601-5 建议的 YCrCb 方案则是:

考虑到 8 位量化下亮度范围限定在 16~220(留工作余量)、色度零电平在 128,ITU 给出整数化映射:

Altera 视频处理工具箱采用略有修改的近似(亮度范围 16 至 ,色度最大 ):

分辨率与显示顺序

传统图像显示在阴极射线管(CRT)显示器上:像素从左上角开始,从左到右扫完一行,再回到左边开始下一行。分辨率用”先水平 后垂直 “的像素数表示,常见有 、、、。坐标排列如下:

(0,0)(0,1)…(0,C-1)
(1,0)(1,1)…(1,C-1)
⋮⋮
(R-1,0)(R-1,1)…(R-1,C-1)

视频处理中,典型图像大小是 宏块的倍数,最流行的是 的通用中间格式(CIF)和 的四分之一 CIF(QCIF)。

彩色图像的每个像素由 R、G、B 三个子像素组成,但并非所有格式都按这个顺序存储——例如流行的原始 BMP 格式从左下角开始,到右上角结束。大多数格式对灰度数据用 8 位、每个 RGB 分量也用 8 位;典型的图像文件以包含行列数、颜色表、压缩方案等信息的文件头开始,随后才是图像数据。有些格式支持无损或有损压缩(如 GIF、JPEG)。只有少数静止图像格式(JPEG、JPEG-2000)由 ISO/IEC/ITU 等国际委员会定义,其余很多由公司定义,知识产权未必完全清晰。MATLAB 的 imread() 函数支持下述所有格式。

BMP:不压缩的原始图像格式,使用 RGB 颜色表、每分量 8 位,也允许用少于 24 位编码(例如只存常用颜色的 8 位颜色表放进文件头;8 位灰度则不需要颜色表)。DE2 演示工程(DE2_Default)用的就是它,在嵌入式 μP 设计中也很流行;DE2 板附带的 BMP2MIF 转换器教程见逻辑教材附录 F。

GIF:包含无损图像压缩,做 PPT 幻灯片是好选择,也常被用来做小动画(GIF 动画)。

PNG:另一种无损压缩方案,常用于网页。PNG 采用差分编码,但不使用 GIF 的 Lempel-Ziv-Welch(LZW)压缩算法,因此不需要 LZW 的许可证费用。

格式Int.STD无损压缩有损压缩MATLAB
BMP---√
GIF-√LZW√
PNG-√DPCM√
JPEG√√DCT√
JPEG-2K√√DWT√

JPEG:唯一官方静止图像标准之一

JPEG 标准(即 ITU-T 建议 T.81)可在 CCITT 网页免费下载。注意一个细节:标准只规定了解码器,没有限制编码器,给实现改进留了空间。图 10-1 是基本 DCT 有损压缩的主要编码与解码步骤。


图 10-1 JPEG 压缩方案

流程是这样的:8 位输入图像(假定灰度;彩色图像通常先用式 10.1 的 YIQ 或式 10.2 的 YCrCb 变换)被划分为互不重叠的 块,做二维 DCT。因为二维 DCT-II 在 、 方向可分离,实现时先对八行做一维变换,再对八列做变换。DC 分量(块内均值)位于 数据块左上角。之后用不同的表量化亮度和色度 DCT 系数——标准第 143 页建议的亮度量化表见图 10-2(a)。

1611101624405161
1212141926586055
1413162440576956
1417222951878062
182237566810910377
243555648110411392
49647887103121120101
72929598112100103199

(a) 量化表


(b) AC 系数的 Zig-zag 编码
图 10-2 JPEG 压缩方案细节

表中的值是解码端重构 DCT 值时要乘的系数;编码端则先除以这些值再四舍五入到整数——把昂贵的除法负担放在编码器一侧。从量化表可以看出:左上(低频)量化因子小,用更多比特表示;右下(高频)量化因子大,8 位输入的高频系数通常只剩 0 或 ±1。随后按”之字形”顺序排列系数,编码器对第一个非零系数对编码,用块结束(EOB)符号终止整个块,见图 10-2(b)。

由于相邻块的 DC 值(即 块内所有像素的平均值)通常相近,DC 先做差分编码(),再做霍夫曼编码:先用 4 位编码”大小”,再编码差值本身:

4位SSSSDIFF 值
00
1-1, 1
2-3, -2, 2, 3
3-7,…,-4, 4,…,7

其余 63 个 AC 系数用可变游程长度编码(VLC),格式为(零游程长度,下一个值),各用 4 位;游程长于 15 时插入特殊符号 (15,0),EOB 用 (0,0) 编码。

计算示例:DCT 编码系数

先依据前一个块的 DC 值译出 DC,AC 系数则译码为:

其中 (0,3) 表示”零游程 0、数值 3”,(2,-1) 表示”跳过 2 个零后是 -1”,依次类推,(0,0) 即 EOB。DCT 值还可以再用霍夫曼编码进一步压缩;标准附录 K 给出了需写入 JPEG 文件头的 DC/AC 亮度和色度示例表。编码表通常是中等偏高压缩率的——这也是很多文件的实际压缩比不如预期的原因之一。

图 10-3 给出了几个 JPEG 编码结果:低压缩比时 JPEG 与 BMP 几乎看不出差别;高压缩时则能看到 DCT 分块带来的块效应。


(a) 原始 BMP 图像(677KB)


(b) Q20 的 JPEG 低压缩图像(53KB)


(c) Q1 的 JPEG 高压缩图像(22KB)
图 10-3 JPEG 压缩结果

JPEG-2000:从小波出发的新工具箱

JPEG-2000 可以看作原始 JPEG 的更新版,但有几处实质性变化。最核心的是: DCT 块处理被 DWT(离散小波变换) 取代——有损压缩通常用浮点 Daubechies 9/7 小波滤波器,无损压缩用 5/3 整数滤波器。初始 DWT 之后进行量化与算术编码,见图 10-4。


图 10-4 JPEG-2000 压缩方案

JPEG-2000 是 ISO、IEC/ITU 多个小组的联合成果,遗憾的是标准规范文档并不免费(本书写作时售价 96 瑞士法郎),不过有许多出版物把基本思想讲得很清楚。新标准不是单一算法,而是一个”工具箱”,其中最有趣的特点有:

  • 低比特率下性能卓越——DWT 天然避免了经典 JPEG 的块效应;
  • 同时支持无损与有损压缩;
  • 感兴趣区域(ROI)编码:允许对图像中特别重要的部分(例如说话者的面部相对背景)用更高质量编码;
  • 通过同步标记、固定长度编码器和重复报头增强抗比特错误鲁棒性;
  • 通过水印、标签、冲压和加密实现图像安全。

代价是复杂度更高。JPEG-2000 通常以比 JPEG 更高的计算复杂度换取更好的 PSNR、MSE 或 SSIM。如果应用需要高质量或低比特率,或需要安全性等特性,就选 JPEG-2000。

10.1.2 基本图像处理操作

图像/视频工具箱里最常用的基本操作包括:

  • 改变图像尺寸,增减处理的像素数;
  • 裁剪出感兴趣区域(ROI);
  • 旋转图像;
  • 对一幅或多幅图像做加、减、乘、除和平均;
  • 彩色↔灰度转换;
  • 以 BMP、GIF、JPEG 等格式读取和存储图像。

点操作

基于像素自身值进行变换的叫点操作。典型用途包括调整整体过亮/过暗的图像,或依据局部/全局像素统计(直方图)进行调整。CRT 显示器必备的点操作是 γ 校正,对 8 位数据:

时是指数型曲线,图像变暗; 时是对数型曲线,图像变亮。例如 的曲线在低输入区抬升缓慢、在高输入区快速上升,暗部被进一步压暗; 则相反,暗部被大幅提亮。NTSC 电视系统采用 。


(a)


(b)


(c)
图 10-5 γ 校正示例

滤波操作

图像滤波可线性可非线性,作用对象不只是单个像素,还包括相邻像素,多数用于图像增强。大多数线性方法也可以在变换域(FFT、DCT)中求解。几个典型例子:

  • 低通滤波器消除随机噪声;
  • 差分滤波器检测边缘;
  • 最大值滤波器去除胡椒噪声(因为黑色编码为 0,取邻域最大值就把黑点抹掉了);
  • 最小值滤波器去除盐噪声(因为白色编码为 255,取最小值把白点抹掉);
  • 中值滤波器同时抑制盐和胡椒噪声;
  • 去抖滤波器,消除相机移动时反褶积滤波造成的模糊;
  • 自适应维纳滤波器去噪。

图像压缩(静止图像与视频)是活跃的研究领域,许多方法利用了人眼的物理特性——对低频变化比对高频变化更敏感。这类变换编码通常再结合可变长度编码、霍夫曼编码或算术编码等(无损)熵编码。图像/视频处理中最流行的二维变换是 FFT、DCT 和 DWT,Haar 变换、Hartley 变换等二维形式也有使用。

形态学操作

形态操作用于增强信息或减小模式识别系统的输入空间,基本动作是”在邻域中添加像素”(增厚,即膨胀/dilation)和”删除邻域中的像素”(稀疏,即侵蚀/erosion)。膨胀产生更多像素,使线条变粗、填拢小孔;侵蚀使线条变细,并去掉”单个像素”这类小噪声区域。两者通常组合使用:先侵蚀后膨胀称为开运算(opening),先膨胀后侵蚀称为闭运算(closing)。开、闭都能平滑物体轮廓,闭运算还能填充小孔和间隙。

这些操作可定义在灰度图像和黑白(BW)图像上,BW 更常见。灰度图的形态操作通常就是邻域内的最大/最小操作;BW 图则定义邻域掩模以何种规则替换像素。

图 10-6 展示了用 MATLAB 函数 bwmorph 和 bwperim 的若干形态操作:开运算能去掉手写文本下的背景横线(图 10-6(b));骨架化是一系列侵蚀与开运算的组合,为每个对象生成中心线,让所有对象的结构像 X 光片里的骨骼一样显现(图 10-6(c));边界提取可以先对图像用掩模 M 侵蚀,再用图像减法计算 ,其中 表示侵蚀,结果得到边界/周边图(图 10-6(d))。此外,“多数黑色”操作在邻域中多数像素为黑时把当前像素置黑,作用类似膨胀,对边缘检测也有帮助。