像素振动(Pixel Vibration)使用说明书
基于视觉的振动分析工具:用普通相机拍摄的视频,框选区域后用光流 / 互相关测量亚像素级振动位移,并用运动放大直观地"看见"振型。
百度网盘下载地址: https://pan.baidu.com/s/17UTbpJ0Pq9P_ubYNmdQXsg?pwd=ugt3
目录
一、软件简介
像素振动是一款面向"微小振动测量"的桌面软件,它的前身是“视觉振动工具箱”,我们通过python和opencv重构了整个界面和交互逻辑,使其真正的从玩具蜕变成工具,这将是唯一一个不需要用户登录且有完整基础功能的版本。它只需要一台普通相机拍一段视频,就能做两件肉眼做不到的事:
- 测量振动:在画面上框一个感兴趣区域(ROI),自动算出这个区域每一帧位移了多少像素,并给出位移波形和振动频率(频谱)——精度可以达到 0.01 像素级(亚像素)。
- 看见振动:用"运动放大"把看不见的微小振动放大几十到几百倍,让你直接用眼睛看到物体是怎么振的(振型、节点、方向)。
典型应用场景:机械结构的共振/模态测试、管道/桥梁/塔架的健康监测、精密设备的微振动诊断、教学演示等。
运行方式
- 绿色免安装版:解压后双击
Pixel Vibration.exe即可运行(整个文件夹要一起复制)。 - 源码运行:安装 Python 依赖后执行
python main.py。
依赖(源码运行才需要):PySide6、numpy、scipy、opencv-python、pyqtgraph。
二、快速上手(5 分钟跑通)
第一次使用,按下面 6 步走一遍就能出结果:
- 启动:双击
Pixel Vibration.exe。 - 读视频:点左侧面板顶部「读取视频」按钮 → 选一个视频文件(或先点「生成演示视频」造一段测试视频)。
- 定范围:在「读取视频帧」窗口里,可框选区域、拖动起止滑块定帧范围,然后点「读入工作区」。
- 框 ROI:在播放器画面上拖动鼠标,框住你想测量的振动部位(出现一个彩色矩形框)。
- 测振:在左侧「振动测量」分区选中该 ROI,点「计算」。等一两秒,波形/频谱窗口会自动弹出。
- (可选)运动放大:在「运动放大」分区设好频带和放大倍数,点「计算放大」,再拖动「放大系数」滑块,就能在播放器里实时看到被放大的振动。
建议先点「生成演示视频」:软件会造一段"两个频率振动"的无损测试视频,用它能最快熟悉全部功能,不依赖你自己的素材。
三、界面总览
主界面是无边框窗口,左侧是固定工作区面板(上中下三张卡片),右侧是播放器(MDI 子窗口,可开多个素材)。

左侧工作区:三张卡片
| 卡片 | 作用 |
|---|---|
| 素材(原始图像帧数据) | 读取视频、加载/保存/删除素材,列表显示每个素材的名称、尺寸、帧率、占用内存 |
| 运动放大 | 选择放大算法、设置频带/倍率/金字塔层数,计算、释放缓存 |
| 振动测量(ROI) | 管理 ROI(框选区域)、选择测振算法、计算位移波形与频谱 |
右侧播放器
显示当前素材的画面,你在这里框选 ROI、播放/拖动视频、切换"原始 / 放大"显示,叠加 ROI 框和振动箭头。
四、功能详解
4.1 读取视频
点「读取视频」打开下面的对话框:

操作要点:
- 选择文件:点「浏览…」选视频;或点「生成演示视频」造一段测试视频。
- 预览:下方进度条可以拖动,随时看某一帧的画面。
- 框选区域(可选):点「框选区域」后在画面上拖一个矩形,只读这块区域(能大幅省内存、提速度);点「用全图」恢复全图。
- 定帧范围:用起止数字框或进度条上的范围滑块,只读某一段帧。
- 彩色 / 灰度:勾选「彩色」读彩色;不勾则读灰度(灰度更省内存,测振和放大其实只用亮度)。
- 内存估算:底部会实时显示"将读入 N 帧 × 宽×高 → 约 XXX"。如果超过 2 GB 会红字警告(见第六章)。
点「读入工作区」后,素材会出现在左侧素材列表里。
4.2 素材管理

- 列表四列:名称 / 尺寸 / 帧率 / 内存(把鼠标悬停在"内存"上,能看到帧数据、振动数据、放大缓存各自占多少)。
- 顶部按钮:读取视频(新素材)、加载素材(打开
.vvm文件)、删除素材(删除选中,释放内存)。 - 底部显示"共 N 个素材,合计 XXX"——多个素材的内存是叠加的,不用了就删掉。
4.3 振动测量(ROI)

- 添加 ROI:在播放器里拖动框选,或在 ROI 列表里添加。
- 计算方法:LK 光流 / 互相关(NCC) / 基于相位,三种算法怎么选见第五章 5.3。
- 计算:对选中的 ROI 计算位移,完成后自动弹出波形/频谱窗口。
- 箭头倍率:控制画面上"振动箭头"的长度(箭头长 = 位移 × 倍率,只是显示用,不影响测量结果)。
4.4 运动放大

- 算法:线性(欧拉) / 里斯金字塔(实时预览只支持这两种;复可控金字塔只在导出时用)。
- 带通下限 / 上限:只放大这个频率段的振动(Hz)。必须小于采样率的一半(奈奎斯特频率),否则会报错。
- 放大系数(gain):拖动即可实时预览放大效果,不用重新计算(这是本软件的设计亮点)。
- 金字塔层数 / 相位平滑 σ:高级参数,一般留"自动/默认"即可。
- 计算放大 / 取消放大 / 释放缓存:算完后点「释放缓存」能立刻释放大量内存(见第六章)。
4.5 播放器

- 底部控件:播放/暂停、进度条拖动、起止范围滑块。
- 显示切换:原始画面
放大画面。 - ROI 框与振动箭头会叠加在画面上,箭头方向和长度表示当前帧的位移。
4.6 导出

- 原始画面 / 放大画面:导出哪一种。
- 叠加标注:勾选后把 ROI 框、振动箭头画进导出的视频里。
- 高阶:基于相位的运动放大(复可控金字塔):质量最高,但计算量极大,可能耗时 30 分钟以上,请谨慎使用。
- 也支持导出振动数据 CSV(所有 ROI 的位移时程,可用 Excel 打开)和保存素材
.vvm。
4.7 设置

可设置 ROI 框的样式、界面主题、默认是否读彩色、运动放大的默认参数等。一般保持默认即可。
五、技术细节(重点)
这一章面向完全没有图像处理基础的读者,从零讲起,一步一步解释本软件"背后在算什么"。已经懂的人可以跳到 5.3 直接看算法对比。
5.1 零基础铺垫:先搞懂几个概念
① 像素与灰度
视频的每一帧就是一张图,由一个个小方格(像素)组成。灰度图里每个像素用一个数字表示亮度:0 是黑,255 是白。一个"移动了 1 个像素"的物体,就是它对应的那些像素值整体往旁边挪了一格。
② 帧率与采样率
视频一秒钟有很多帧,这个数量叫帧率(fps)。例如 120 fps 就是每秒 120 张图。帧率就是测量的"采样率":它决定了我们能测到多高的振动频率(最高能测到采样率的一半,即奈奎斯特频率)。
③ 频率与频谱
"振动"就是某个东西在一段时间里来回动。频率 = 一秒钟来回几次,单位赫兹(Hz)。把一段位移波形做数学变换(傅里叶变换 FFT),就能拆出"里面有哪些频率、各有多强",这就是频谱——它告诉我们物体到底在哪个频率上振。
④ 带通滤波
带通滤波 = 只保留"下限~上限"之间的频率,其余全滤掉。作用:只放大/只测量你关心的振动,把噪声、晃动、呼吸、摄像机抖动等都排除掉。

⑤ 图像金字塔
把一张图逐层缩小(每层宽高各缩一半),就像一座金字塔。缩小前是"细节 + 大块",缩小后只剩"大块趋势"。"细节层"恰恰对微小运动最敏感,所以测振和放大都要先做金字塔分解。

⑥ 相位
可以把"振动"理解成一列波。波上每个点处于"波峰、波谷、还是中间"的状态叫相位。物体移动一点,波峰位置就挪一点——相位的变化就对应位移。相位法测振和相位放大,本质都是"测量 / 放大相位的变化"。
5.2 软件架构与数据流
软件分为三层,依赖自上而下、单向调用:

- ui(界面层):只负责显示和交互。
- core(核心层):
Workspace是"唯一数据源",所有数据写操作都发生在这里;后台任务用TaskRunner跑在线程里,界面不卡。 - algo / data_io(算法与读写层):纯函数、不依赖界面,可以脱离界面单独测试——这是算法可靠、易维护的关键。
数据流动方向如下:

5.3 测振算法
测振的目标只有一个:算出 ROI 区域每一帧相对第一帧移动了多少像素(dx、dy)。软件内置三种算法,各有各的思路。
5.3.1 LK 光流法(默认,最常用)
一句话:先在 ROI 里找一批"好跟踪的角点",然后逐帧跟踪这些点往哪儿跑了,取所有点位移的中位数。
比喻:在物体表面贴几个荧光点,用摄像头持续盯着它们怎么移动。

分步解释:
- 找角点(
goodFeaturesToTrack):角点就是图像里"纹理丰富、拐角明显"的点,容易跟踪。软件在 ROI 里最多找 60 个这样的点。 - 逐帧跟踪(
calcOpticalFlowPyrLK):用"金字塔光流"——先在缩小图上粗跟踪,再逐层放大细化,又快又稳。每一帧都算出每个点移动了多少。 - 取中位数:60 个点会给出 60 个位移,取它们的中位数作为整块 ROI 的位移。取中位数(而不是平均数)的好处是:个别点跟踪错了也不会把结果带偏。
- 输出波形:把所有帧的位移连起来,就是 dx/dy 随时间变化的波形,再做频谱得到振动频率。
- 优点:精度高、抗噪好,适合大多数情况。
- 缺点:ROI 里纹理太少(比如纯色墙面)会找不到足够角点而报错。
5.3.2 NCC 互相关法
一句话:从第一帧 ROI 里扣一块小模板,到每一帧里"滑动搜索"这块模板最像的位置,位置挪了多少就是位移。
比喻:拼图找位置——拿一块模板到每帧画面里比对,看它"挪到了哪儿"。

分步解释:
- 扣模板:从第一帧的 ROI 中心内缩,取一小块当"参照物"。
- 逐帧滑动搜索(
matchTemplate,归一化互相关系数TM_CCOEFF_NORMED):在每一帧的 ROI 范围内逐像素滑动模板,算出每个位置的"相似度",相似度最高的位置就是模板当前所在位置。 - 抛物线亚像素插值:搜索只能精确到整像素,但真正的位移往往在两个像素之间。软件在"峰值位置"附近用一条抛物线拟合,求出更精细的亚像素偏移(可到 0.01 像素)。
- 输出波形:同样得到 dx/dy 波形(并做中值去毛刺)。
- 优点:对弱纹理、长时间稳定的场景更稳。
- 缺点:适合小位移;ROI 太小会报错(至少要 24×24 像素左右)。
5.3.3 相位法测振
一句话:把位移"读作相位差"——用里斯变换算出每帧的局部相位,相对第一帧的相位差就是运动量。
比喻:看水波——不追某一个水分子,而是看"波峰/波谷的相位"移动了多少。

分步解释:
- 金字塔分解:对 ROI 做拉普拉斯金字塔,取细节最丰富的第 0 层(对微小运动最敏感)。
- 里斯变换:把这一层变成"幅值 + 相位"(相位带有方向和大小)。
- 求相位差:每一帧的相位减去第一帧的相位,得到"相位差"——它正比于运动量。
- 幅值加权 + 标定:幅值大的地方信号更可信,做加权平均;最后用 NCC 的位移结果自动标定比例,把"相位差"换算成"像素"。
- 优点:擅长测亚像素微振动,主频直接精确。
- 缺点:实现最复杂,计算稍重。
5.3.4 三种测振算法怎么选?
| 场景 | 推荐算法 |
|---|---|
| 一般情况、不确定 | LK 光流(默认) |
| 纹理弱、但画面稳定 | 互相关(NCC) |
| 振幅极小、想测高精度微振动 | 基于相位 |
提示:ROI 尽量框在有纹理、对比度明显的地方(如边缘、花纹),避免纯色区域,三种算法的精度都会明显更好。
5.4 运动放大算法
运动放大回答另一个问题:怎么让看不见的微小振动"看得见"。软件内置三种算法,都来自 MIT 的经典论文。
5.4.1 线性(欧拉)放大 —— 放大"亮度的波动"
一句话:把"像素亮度随时间的小波动"放大 N 倍,再叠回原画面。
比喻:物体振动时,它边缘的像素会一明一暗地周期性变化(因为边缘一会儿盖住背景、一会儿移开)。把这种明暗变化放大,就"看见"振动了。

分步解释:
- 金字塔分解:把画面按尺度拆开(粗趋势 + 各层细节)。
- 时域带通:对每一层沿时间轴做带通,只留下你指定频率段(比如 1~5 Hz 的振动)。
- 乘放大倍数:把这些过滤出来的微小变化乘以放大倍数 N。
- 加回原图重建:放大后的波动叠加回原始画面。
核心公式:输出帧 = 原始帧 + 放大倍数 × 带通残差。
- 优点:快、能实时预览,实现简单。
- 缺点:放大倍数大时噪声也会被放大,可能出现"过曝/亮斑"伪影。
5.4.2 里斯金字塔放大 —— 放大"相位"(推荐)
一句话:不放大亮度,而是放大"局部相位"(相位 = 位置的编码)。
比喻:把运动编码成"相位",放大相位就等于放大位移;因为只动相位、不动亮度,所以更干净、噪声更少。

分步解释:
- 拉普拉斯金字塔分解:按尺度拆开,逐层处理。
- 里斯变换:把每一层变成"幅值 + 方向相位"。这里用了正则化里斯变换(
-i·ω/√(‖ω‖²+ε²)),避免直流分量处的奇异性。 - 相位差 + 带通:每帧相对第一帧求相位差(四元数共轭积,带方向两分量),再只留振动频率段。
- 幅值加权去噪:幅值大的地方权重高,压制噪声。
- 放大相位 + 重建:相位差 × 放大倍数,再逆变换、金字塔重建回整帧。
- 优点:比线性法支持更大倍率、噪声更少,是实时预览的默认推荐。
- 缺点:比线性法计算稍重,缓存更占内存(见第六章)。
软件亮点:放大中间量(各层相位)是与倍率无关的,所以算完后拖动"放大系数"滑块可以实时预览,不用重新计算。
5.4.3 复可控金字塔(相位法)—— 最高质量,仅导出用
一句话:用更精细的"多尺度 × 多方向"复可控金字塔分解,质量最高,但计算量极大。
比喻:把画面从"多个尺度"和"4 个方向"同时拆解,每个方向单独处理相位,因此对任意方向、任意尺度的运动都处理得最好。

分步解释:
- 每帧 FFT 到频域:整段视频批量傅里叶变换。
- 多尺度 × 多方向滤波:复可控金字塔滤波器把画面拆成多个尺度、4 个方向的子带。
- 相位差 + 带通 + 去噪:每个子带相对首帧求相位差,带通 + 幅值加权去噪。
- 相位放大(防混叠):相位差 × 倍率,并裁剪到不超过 π/2 防止混叠伪影。
- 逆变换重建:各子带拼回画面,去除 padding 得到结果。
- 优点:质量最高、伪影最少、能支持最大倍率。
- 缺点:固定倍率、一次性算完所有放大帧,计算量极大(可能 30 分钟以上),所以只在"导出放大视频"时可选。
5.4.4 三种放大算法对比
| 算法 | 速度 | 质量 | 实时预览 | 何时用 |
|---|---|---|---|---|
| 线性(欧拉) | 快 | 一般 | ![]() |
快速看看、倍率不大 |
| 里斯金字塔 | 中 | 好 | ![]() |
日常默认 |
| 复可控金字塔 | 极慢 | 最好 | (仅导出) |
出高质量成品视频 |
5.5 信号处理细节(进阶)
- 去趋势(detrend):测振结果(光流/相位累积)会有缓慢漂移,软件用最小二乘拟合一条直线并减掉,避免频谱低频端出现假峰、RMS 被抬高。
- 频谱(spectrum):单边幅值谱,默认加 Hanning 窗并做幅值修正,窗函数可选 Hanning / Hamming / 矩形。
- 去毛刺(despike):用 MAD 中值法,把波形里孤立的尖峰替换成中值,抗个别跟踪错误。
六、内存与性能(重点)
试用时最常见的报错,十有八九是"内存超了"。这一章把它彻底讲清楚。
6.1 内存都去哪了?
软件把数据放在内存(RAM)里计算,主要三块:
| 数据 | 类型 | 占多少 |
|---|---|---|
原始帧 frames |
uint8(1 字节/像素) | 灰度 = 帧数 × 高 × 宽 × 1 字节 |
| 振动数据 | float32 | 每个 ROI 一点点,可忽略 |
| 放大缓存 | float32(4 字节/像素)× 多层金字塔 | 最大头 |
下图是一个真实例子(1280×720 灰度视频,10 秒 @120fps):

结论一目了然:放大缓存才是内存大头,里斯金字塔放大缓存 ≈ 原始帧的 27 倍。
为什么这么夸张?因为运动放大要做金字塔分解,把画面拆成多层;每一层还要存多个 float32 缓冲(里斯法存 5 个:亮度、里斯两分量、相位差两分量),而 float32 是 uint8 的 4 倍。几层金字塔加起来,内存就翻了几十倍。
6.2 为什么"读的时候没事,一算放大就报错"?
这是关键,也是很多人误解的地方:
- 软件在读视频时有一个 2 GB 警告:读入的帧数据如果超过 2 GB,会红字提醒你"建议缩小区域或减少帧数"。
- 但这个警告只针对"原始帧",不针对"放大缓存"。
- 于是典型流程是:读入 1 GB 的帧(没超 2 GB,没有警告)→ 点「计算放大」→ 放大缓存突然要 27 GB → 内存爆了,报 MemoryError / 程序卡死或崩溃。
所以"试用时报错",绝大多数不是 bug,而是素材尺寸/帧数 × 里斯放大,超出了电脑的内存上限。
6.3 如何避免内存超限(照做即可)
- 优先读灰度:彩色是灰度的 3 倍内存,而测振和放大只用亮度,多数情况用灰度即可。
- 缩小 ROI / 裁剪区域:只读你关心的那块区域,帧数据直线下降。
- 减少帧数:只读需要的那一段(比如振动持续的那几秒),不要整段全读。
- 放大用完后点「释放缓存」:放大缓存很占内存,不看了就点「释放缓存」,立刻释放。
- 删除不用的素材:多个素材的内存是叠加的,处理完一个删一个。
- 内存小的机器优先用「线性」放大:线性缓存 ≈ 8 倍帧数据,比里斯(27 倍)省得多。
6.4 性能小提示
- 测振很快:三种测振都是逐帧轻量运算,通常几秒内完成。
- 实时放大不卡:放大中间量与倍率无关,算完后拖倍率滑块是实时预览。
- 复可控金字塔极慢:只在导出高质量视频时用,可能 30 分钟以上,期间请耐心等待、不要关程序。
- 取消有秒级延迟:单次 FFT/滤波是原子运算,无法中途打断,点"取消"后要等当前这一步算完才停,这是正常的。
七、常见问题与排错
Q1:报错"内存不足 / MemoryError / 程序直接闪退"
这是内存超限(见第六章)。按 6.3 的步骤:读灰度 → 缩小区域 → 减少帧数 → 用线性放大 → 用完释放缓存 → 删旧素材。
Q2:测振报错"ROI 内纹理不足,找不到足够特征点"
LK 光流需要纹理丰富的区域。换到有边缘/花纹的地方框 ROI,或改用「互相关(NCC)」算法(对纹理要求更低)。
Q3:报错"ROI 太小,至少要 24×24 像素"
把 ROI 框大一点即可。
Q4:报错"带通参数不合法:X ~ Y Hz"
带通必须满足 0 < 下限 < 上限 < 采样率的一半(奈奎斯特频率)。例如 120 fps 的视频,采样率 120 Hz,上限必须 < 60 Hz。
Q5:打不开视频文件
确认视频格式受支持(OpenCV 支持 mp4/avi/mjpeg 等常见格式)。换个文件或转码后再试。
Q6:波形乱、漂移、低频有假峰
- 尽量固定相机(三脚架),减少整体晃动。
- ROI 选纹理清晰处。
- 软件已内置"去趋势"和"去毛刺",如仍乱,可缩小 ROI 或换算法。
Q7:点"取消"后界面像卡住
后台任务是单线程原子运算,取消要等当前这一步算完(秒级延迟),属正常现象,稍等即可。
附录:算法论文出处
| 功能 | 算法 | 出处 |
|---|---|---|
| 运动放大 | 线性(欧拉) | Wu et al., Eulerian Video Magnification for Revealing Subtle Changes in the World, SIGGRAPH 2012 |
| 运动放大 | 里斯金字塔 | Wadhwa et al., Riesz Pyramids for Fast Phase-Based Video Magnification, ICCP 2014 |
| 运动放大 | 复可控金字塔 | Wadhwa et al., Phase-Based Video Motion Processing, SIGGRAPH 2013 |
| 测振 | LK 光流 | Lucas & Kanade, 1981(金字塔光流:Bouguet, 2000) |
| 测振 | NCC 互相关 | 归一化互相关模板匹配(OpenCV matchTemplate) |
| 测振 | 相位法 | Riesz 变换局部相位(与里斯金字塔同源) |
延伸阅读:上述论文均可在作者主页或学术搜索引擎免费获取,适合想深入了解原理的读者。
本文档由「像素振动」项目自动生成图文版与 Markdown 版,内容与软件实现一致。

(仅导出)