光流分析是计算机视觉中的重要技术,用于检测视频序列中物体的运动模式。本文将介绍如何使用OpenCV和Python实现一个实时的光流分析系统,该系统能够检测运动、生成热力图并提供详细的统计分析。
技术概述
本系统基于Farneback稠密光流算法,能够:
-
实时计算视频帧之间的运动向量
-
生成运动热力图可视化
-
提供多种统计分析(均值、中位数、众数等)
-
显示历史数据趋势图表
核心代码解析
初始化设置
class DenseOpticalFlow:
def __init__(self):
self.init_parameters()
self.prev_time = None
self.fps = 30
# 历史统计数据
self.max_history_length = 100
self.displacement_history = deque(maxlen=self.max_history_length)
self.mean_history = deque(maxlen=self.max_history_length)
self.median_history = deque(maxlen=self.max_history_length)
self.mode_history = deque(maxlen=self.max_history_length)
self.speed_history = deque(maxlen=self.max_history_length)
使用deque
数据结构来存储历史数据,自动维护固定长度的历史记录。
光流计算
def do(self, frame, device="cpu"):
current_time = cv2.getTickCount() / cv2.getTickFrequency()
gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 计算光流
flow = cv2.calcOpticalFlowFarneback(
self.prev_gray, gray_frame, None,
self.flow_params["pyr_scale"], self.flow_params["levels"],
self.flow_params["winsize"], self.flow_params["iterations"],
self.flow_params["poly_n"], self.flow_params["poly_sigma"],
self.flow_params["flags"]
)
使用OpenCV的calcOpticalFlowFarneback
函数计算稠密光流,该算法能够为每个像素点生成运动向量。
数据处理与可视化
# 计算运动幅值
magnitude, _ = cv2.cartToPolar(flow[...,0], flow[...,1])
# 排除0值,只分析实际运动区域
nonzero_magnitude = magnitude[magnitude > 0]
# 生成热力图
magnitude_norm = cv2.normalize(magnitude, None, 0, 255, cv2.NORM_MINMAX)
heatmap = cv2.applyColorMap(np.uint8(magnitude_norm), cv2.COLORMAP_INFERNO)
通过极坐标转换获取运动幅值,并使用INFERNO色彩映射生成热力图,红色表示高强度运动,蓝色表示低强度运动。
统计分析
# 计算统计量
if len(nonzero_magnitude) > 0:
mean_val = float(np.mean(nonzero_magnitude))
median_val = float(np.median(nonzero_magnitude))
mode_val = float(stats.mode(nonzero_magnitude, keepdims=True)[0][0])
else:
mean_val = median_val = mode_val = 0.0
# 更新历史数据
self.mean_history.append(mean_val)
self.median_history.append(median_val)
self.mode_history.append(mode_val)
系统计算三种主要统计量:
-
均值:运动幅值的平均值
-
中位数:运动幅值的中位数,对异常值不敏感
-
众数:最常见的运动幅值
可视化界面
def add_statistics_chart(self, side_by_side, magnitude):
# 创建matplotlib图表
fig = plt.figure(figsize=(width/100, chart_height/100), dpi=100)
gs = fig.add_gridspec(1,2, width_ratios=[1,1], wspace=0.3)
# 左图:当前帧位移分布直方图
ax1 = fig.add_subplot(gs[0])
if len(magnitude) > 0:
ax1.hist(magnitude.flatten(), bins=30, color="green", alpha=0.7)
# 右图:历史统计趋势线
ax2 = fig.add_subplot(gs[1])
x_vals = np.arange(len(self.mean_history))
if len(x_vals) > 0:
ax2.plot(x_vals, list(self.mean_history), label="Mean", color="blue")
ax2.plot(x_vals, list(self.median_history), label="Median", color="orange")
ax2.plot(x_vals, list(self.mode_history), label="Mode", color="green")
可视化界面分为两部分:
-
左侧直方图:显示当前帧的运动幅值分布
-
右侧折线图:显示最近100帧的统计趋势
应用场景
1. 运动检测与监控
-
检测监控视频中的异常运动
-
统计人流量和运动模式
-
识别运动方向和强度
2. 体育分析
-
分析运动员的运动轨迹
-
计算运动速度和加速度
-
评估运动表现
3. 交通监控
-
检测车辆运动
-
分析交通流量
-
识别交通违规行为
4. 科学研究
-
动物行为研究
-
流体动力学分析
-
微观粒子运动跟踪
结论
本文介绍的光流分析系统提供了一个完整的运动检测解决方案,结合了实时处理、统计分析和可视化功能。通过OpenCV和Python的强大组合,开发者可以轻松实现各种运动相关的计算机视觉应用。
该系统具有良好的可扩展性,可以根据具体需求添加更多功能,如物体跟踪、行为识别和高级统计分析。无论是学术研究还是工业应用,这都是一个强大的基础框架。
对 PiscTrace or PiscCode感兴趣?更多精彩内容请移步官网看看~🔗 PiscTrace