数字图像处理:差影法运动目标检测
项目简介
本项目是一个面向数字图像处理初学者的MATLAB教学级源码,旨在演示如何利用
差影法(Image Subtraction Method)在静态背景下检测和提取运动目标。
程序完整展示了从数据获取、图像预处理、差分运算、阈值分割、形态学优化到最终目标标记的全过程。代码通过模拟视频监控中的移动侦测原理,对比背景帧与当前帧的差异,结合自适应阈值和数学形态学滤波,精确地定位并标识出场景中的移动物体。
核心功能与特性
*
合成演示模式:内置演示数据生成器,无需外部文件即可运行。程序能自动生成带有渐变背景、随机噪声、静止干扰物以及模拟运动目标(矩形和圆形)的测试图像。
*
真实图片模式:支持读取本地背景图和包含目标的当前帧图片,并包含自动尺寸校正功能,防止因尺寸不一致导致的运算错误。
- 鲁棒的差分计算:利用双精度浮点数进行矩阵减法运算,避免了传统无符号整数运算中的溢出截断问题。
- 自适应阈值分割:不依赖固定阈值,而是根据差分图像的均值(Mean)和标准差(Std)动态计算二值化阈值,从而更好地适应不同光照强度和噪声水平。
- 多级形态学滤波:集成腐蚀、膨胀和孔洞填充操作,有效去除背景噪点,修复目标内部的断裂与空洞。
- 智能连通域分析:通过计算连通区域面积进行筛选,自动剔除小于特定阈值的非目标干扰,仅保留有效运动目标。
- 富交互可视化:提供四分屏结果展示,包含原始图像、伪彩色差分图、二值化掩膜以及叠加了半透明Mask、边界框(Bounding Box)和中心点的最终检测图。
算法实现与逻辑流程
本项目的主程序严格遵循以下数字图像处理流程:
1. 数据获取与校验
程序首先根据配置决定是生成合成图像还是读取本地文件。若读取本地文件,代码会自动检查背景图与当前帧的尺寸是否一致。如果尺寸不匹配,系统会将当前帧调整为背景图的大小,确保后续矩阵运算的对应性。
2. 图像预处理
为了降低计算复杂度,程序将彩色图像转换为灰度图像。随后,利用
im2double 将灰度数据转化为双精度浮点型(Double)。这一步至关重要,因为它防止了后续减法运算中负值被截断为0的情况,保证了差分信息的完整性。
3. 差影运算与平滑滤波
核心算法通过计算当前帧与背景帧的
绝对差值(|Current - Background|)来提取运动区域。
在获得差分图像后,程序立即应用
高斯低通滤波器(Gaussian Filter)。这一步在二值化之前进行,用于平滑图像中的高频噪声,减少后续步骤产生的伪影。
4. 自适应阈值二值化
程序采用统计学方法确定分割阈值。计算公式为:
阈值 = 差分图均值 + 3 × 差分图标准差
根据此阈值,将滤波后的灰度差分图转换为黑白二值掩膜(Mask),初步分离前景变化区域。
5. 数学形态学后处理
为了优化二值化结果,代码依次执行以下操作:
- 腐蚀(Erosion):使用半径为2的圆形结构元素,消除背景中细小的孤立噪点。
- 膨胀(Dilation):使用15x15的矩形结构元素,扩大目标区域,连接断裂的边缘,并填补由于颜色相近而在二值化时产生的内部空洞。
- 孔洞填充(Hole Filling):识别并填充闭合区域内部的黑色像素,确保目标区域是实心的。
6. 目标提取与标记
利用连通区域标记算法(Connected Component Labeling)统计画面中的独立对象。通过
regionprops 函数获取每个对象的
边界框(Bounding Box)、
面积和
质心。
程序设置了最小面积阈值(默认200像素),任何面积小于该值的区域将被视为残留噪声并被忽略,只有满足条件的区域才会被认定为有效目标。
7. 结果可视化
最终结果在一个窗口中以2x2子图形式呈现:
- 左上:显示原始的当前帧图像。
- 右上:显示灰度差分图,并应用Jet伪彩色映射,直观展示亮度变化幅度。
- 左下:显示经过阈值处理后的初步二值化掩膜。
- 右下:显示最终检测结果。在此图中,程序在原始图像上叠加了绿色的半透明Mask,并用红色矩形框圈出目标,同时标记出目标的中心点位置和计数标签。
系统要求与运行说明
系统环境
- MATLAB:建议版本 R2016a 及以上。
- 工具箱:必须安装 Image Processing Toolbox(图像处理工具箱),用于支持
rgb2gray, imfilter, imerode, bwlabel, regionprops 等核心函数。
使用方法
- 运行演示模式:
直接运行脚本。代码默认设置
useSyntheticData = true,会自动生成含有一辆“红色车”和一个“蓝色行人”的模拟场景进行演示。
- 检测真实图像:
* 准备两张图片:一张为无目标的纯背景图,另一张为含有移动目标的图片。
* 将图片放入代码所在目录。
* 在代码中将
useSyntheticData 变量修改为
false。
* 修改
imread 函数中的文件名,使其指向你的实际图片路径。
* 运行脚本即可看到检测结果。