当前位置: 首页 > news >正文

OpenCV计算机视觉实战(20)——光流法运动分析

OpenCV计算机视觉实战(20)——光流法运动分析

    • 0. 前言
    • 1. Lucas–Kanade 稀疏光流
      • 1.1 应用场景
      • 1.2 实现过程
    • 2. Farneback 稠密光流
      • 2.1 应用场景
      • 2.2 实现过程
    • 3. 运动轨迹可视化
      • 3.1 应用场景
      • 3.2 实现过程
    • 小结
    • 系列链接

0. 前言

在视频分析与动态视觉系统中,运动信息的提取与理解是许多关键任务的基础,例如目标跟踪、动作识别、交通监控以及增强现实等。而其中最具代表性的技术之一,就是基于图像序列的光流 (Optical Flow) 分析。光流技术试图通过连续帧之间像素强度的变化来估计图像中每个像素的运动方向与速度,从而重建出视觉世界中的动态场景。

1. Lucas–Kanade 稀疏光流

使用 Lucas–Kanade 算法在图像中选择少量高角点,通过金字塔跟踪估计它们在下一帧中的位置,适合实时目标跟踪。

1.1 应用场景

  • 手势识别:跟踪手部关键点进行动作分类
  • 工业检测:监控流水线工件轻微抖动
  • 运动分析:球类或飞行物的轨迹捕捉

为了在特征点丢失或遮挡时保持鲁棒性,常在跟踪点减少到一定阈值后重新检测新角点。

1.2 实现过程

  • 读取视频或摄像头,获取首帧并灰度化
  • 基于 Shi–Tomasi 在首帧选取若干角点 (cv2.goodFeaturesToTrack)
  • 迭代读取下一帧,灰度化后用 cv2.calcOpticalFlowPyrLK 计算这些角点的新位置
  • 筛选成功跟踪的点 (status==1),在画布上绘制连线表示位移并更新上一帧
  • 实时显示跟踪结果
import cv2
import numpy as np# 功能:Lucas–Kanade 稀疏光流跟踪 Shi–Tomasi 角点
cap = cv2.VideoCapture('test.mp4')  # 或者 cap = cv2.VideoCapture(0)# 1. 读取首帧,灰度化并检测特征点
ret, prev = cap.read()
prev_gray = cv2.cvtColor(prev, cv2.COLOR_BGR2GRAY)
p0 = cv2.goodFeaturesToTrack(prev_gray,maxCorners=200,qualityLevel=0.3,minDistance=7,blockSize=7
)# 2. 准备画布与 LK 参数
mask = np.zeros_like(prev)
lk_params = dict(winSize=(15,15), maxLevel=2,criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))while True:ret, frame = cap.read()if not ret:breakframe_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 3. 计算稀疏光流p1, st, err = cv2.calcOpticalFlowPyrLK(prev_gray, frame_gray, p0, None, **lk_params)if p1 is None:break# 4. 筛选跟踪成功的点good_new = p1[st==1]good_old = p0[st==1]# 5. 绘制轨迹for new, old in zip(good_new, good_old):x1, y1 = new.ravel()x0, y0 = old.ravel()cv2.line(mask, (int(x1), int(y1)), (int(x0), int(y0)), (0,255,0), 2)cv2.circle(frame, (int(x1), int(y1)), 3, (0,0,255), -1)img = cv2.add(frame, mask)cv2.imshow('Sparse LK Flow', img)if cv2.waitKey(30) & 0xFF == 27:break# 更新上一帧和点集prev_gray = frame_gray.copy()p0 = good_new.reshape(-1,1,2)cap.release()
cv2.destroyAllWindows()

光流追踪

关键函数解析:

  • cv2.goodFeaturesToTrack(gray, maxCorners, qualityLevel, minDistance)Shi–Tomasi 角点检测,选择最显著的若干特征点
  • cv2.calcOpticalFlowPyrLK(prev, next, p0, None, **params):金字塔 Lucas–Kanade 算法,返回新点位置、状态与误差矩阵
  • cv2.add(frame, mask):叠加轨迹画布和当前帧,实现持续轨迹可视化

2. Farneback 稠密光流

Farneback 算法估计每个像素的运动矢量,生成稠密光流场,适合整体运动场分析与背景补偿。

2.1 应用场景

  • 交通监控:计算道路信号灯前后车流速度场
  • 流体仿真:视觉化水流或烟雾运动
  • 动作识别:用全图运动模式区分不同人体动作

可以对光流幅度进行阈值过滤,仅保留高速运动区域。

2.2 实现过程

  • 读取视频,对每帧灰度化
  • 使用 cv2.calcOpticalFlowFarneback 计算上一帧到当前帧的稠密光流场
  • 将流场转换为 HSV 映射:角度映射色相,幅度映射亮度,生成伪彩可视化
  • 实时显示稠密光流图
import cv2
import numpy as np# 功能:Farneback 稠密光流并伪彩可视化
cap = cv2.VideoCapture('r2.mp4')
ret, prev = cap.read()
prev_gray = cv2.cvtColor(prev, cv2.COLOR_BGR2GRAY)# 用于 HSV 映射
hsv = np.zeros_like(prev)
hsv[...,1] = 255while True:ret, frame = cap.read()if not ret:breakgray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 1. 计算稠密光流flow = cv2.calcOpticalFlowFarneback(prev_gray, gray,None,pyr_scale=0.5, levels=3, winsize=15,iterations=3, poly_n=5, poly_sigma=1.2, flags=0)# 2. 转换极坐标mag, ang = cv2.cartToPolar(flow[...,0], flow[...,1])hsv[...,0] = ang * 180/np.pi/2hsv[...,2] = cv2.normalize(mag, None, 0, 255, cv2.NORM_MINMAX)bgr = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)cv2.imshow('Dense Farneback Flow', bgr)if cv2.waitKey(30) & 0xFF == 27:breakprev_gray = graycap.release()
cv2.destroyAllWindows()

光流追踪

关键函数解析:

  • cv2.calcOpticalFlowFarneback(prev, next, None, pyr_scale, levels, winsize, iterations, poly_n, poly_sigma, flags)Farneback 稠密光流参数众多,可调节金字塔比例、窗口大小、拟合多项式阶数等
  • cv2.cartToPolar(dx, dy):笛卡尔坐标转极坐标,得到幅度与方向
  • HSV 映射:H 表示方向、V 表示幅度,使运动方向与强度一目了然

3. 运动轨迹可视化

结合稀疏光流跟踪结果,记录每个特征点的历史位置并绘制完整轨迹,直观呈现目标在视频中的运动路径。

3.1 应用场景

  • 多人运动:为不同对象分配不同颜色轨迹
  • 迁徙研究:可视化动物或车辆群的运动路径
  • 交互式分析:在轨迹上叠加时间戳或速度信息

deque 控制每条轨迹长度,并为每个轨迹随机分配颜色。

3.2 实现过程

  • 使用 Lucas–Kanade 初始化一组特征点
  • 建立一个列表 存储多帧跟踪结果,每帧将新位置追加到各自轨迹
  • 在每帧渲染 所有轨迹线段,并为最新点打标
  • 支持清除过旧轨迹或限制轨迹长度
import cv2
import numpy as np# 视频读取
cap = cv2.VideoCapture('r2.mp4')  # 替换为你的输入视频路径# Shi-Tomasi 角点检测参数
feature_params = dict(maxCorners=100, qualityLevel=0.3, minDistance=7, blockSize=7)# Lucas-Kanade 光流参数
lk_params = dict(winSize=(15, 15), maxLevel=2,criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))# 随机颜色用于不同轨迹
color = np.random.randint(0, 255, (100, 3))# 读取第一帧并检测角点
ret, old_frame = cap.read()
if not ret:print("无法读取视频")cap.release()exit()old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)
p0 = cv2.goodFeaturesToTrack(old_gray, mask=None, **feature_params)# 创建一个掩膜图像用于绘制轨迹
mask = np.zeros_like(old_frame)# 初始化轨迹列表
trajectories = [[] for _ in range(len(p0))]while True:ret, frame = cap.read()if not ret:breakframe_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 计算光流p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)if p1 is None or st is None:break# 选择跟踪成功的点good_new = p1[st == 1]good_old = p0[st == 1]# 更新轨迹new_trajectories = []for i, (new, old) in enumerate(zip(good_new, good_old)):a, b = new.ravel()c, d = old.ravel()trajectories[i].append((a, b))# 绘制轨迹线段for j in range(1, len(trajectories[i])):cv2.line(mask, tuple(np.int32(trajectories[i][j - 1]).ravel()), tuple(np.int32(trajectories[i][j]).ravel()), color[i].tolist(), 2)# 绘制当前点cv2.circle(frame, (int(a), int(b)), 5, color[i].tolist(), -1)img = cv2.add(frame, mask)cv2.imshow('Optical Flow Tracking', img)k = cv2.waitKey(30) & 0xffif k == 27:break# 更新前一帧和前一帧的点old_gray = frame_gray.copy()p0 = good_new.reshape(-1, 1, 2)cap.release()
cv2.destroyAllWindows()

光流追踪

小结

在视频分析与动态视觉系统中,光流 (Optical Flow) 技术是一种关键的运动估计方法。它通过分析连续帧之间像素强度的变化,估计图像中每个像素的运动方向与速度,从而重建出视觉世界中的动态场景。光流技术主要分为稀疏光流和稠密光流两种类型。稀疏光流(如 Lucas–Kanade 方法)关注图像中的少量特征点,适合实时目标跟踪;而稠密光流(如 Farneback 方法)则估计每个像素的运动矢量,适合整体运动场分析与背景补偿。

系列链接

OpenCV计算机视觉实战(1)——计算机视觉简介
OpenCV计算机视觉实战(2)——环境搭建与OpenCV简介
OpenCV计算机视觉实战(3)——计算机图像处理基础
OpenCV计算机视觉实战(4)——计算机视觉核心技术全解析
OpenCV计算机视觉实战(5)——图像基础操作全解析
OpenCV计算机视觉实战(6)——经典计算机视觉算法
OpenCV计算机视觉实战(7)——色彩空间详解
OpenCV计算机视觉实战(8)——图像滤波详解
OpenCV计算机视觉实战(9)——阈值化技术详解
OpenCV计算机视觉实战(10)——形态学操作详解
OpenCV计算机视觉实战(11)——边缘检测详解
OpenCV计算机视觉实战(12)——图像金字塔与特征缩放
OpenCV计算机视觉实战(13)——轮廓检测详解
OpenCV计算机视觉实战(14)——直方图均衡化
OpenCV计算机视觉实战(15)——霍夫变换详解
OpenCV计算机视觉实战(16)——图像分割技术
OpenCV计算机视觉实战(17)——特征点检测详解
OpenCV计算机视觉实战(18)——视频处理详解
OpenCV计算机视觉实战(19)——特征描述符详解

http://www.dtcms.com/a/338500.html

相关文章:

  • 云手机矩阵:重构企业云办公架构的技术路径与实践落地
  • 亚矩阵云手机智能定位:助力Snapchat矩阵账号的本地化内容运营穿透技术
  • MySQL实战45讲 24-25
  • Commons-io
  • Web11-Java Web服务:使用SOAP与RESTful API
  • 网络编程day3
  • Orbbec---setBoolProperty 快捷配置设备行为
  • docker回炉重造
  • PortainerCE 跨云管理:cpolar 内网穿透服务实现多环境统一控制
  • Lua学习记录 - 自定义模块管理器
  • Linux------《操作系统全景速览:Windows·macOS·Linux·Unix 对比及 Linux 发行版实战指南》
  • HiveQL | 个人学习笔记
  • JetBrains系列产品-IDEA/PyCharm/GoLand自动生成方法返回值的快捷键,查看方法参数的快捷键。
  • AI驱动的SEO关键词优化秘籍
  • MFC中使用EXCEL的方法之一
  • 数据迁移:如何从MySQL数据库高效迁移到Neo4j图形数据库
  • 迁移学习(Transfer Learning)
  • 当机器猫遇上具身智能:一款能读懂宠物心思的AI守护者
  • 分布式搜索(Elasticsearch)基本用法
  • kubeadm部署k8s集群环境搭建
  • Qt密码生成器项目开发教程 - 安全可靠的随机密码生成工具
  • QT聊天项目DAY19
  • 深入理解Prompt构建与工程技巧:API高效实践指南
  • 如何将Date类型的数据转换为LocalDateTime类型
  • 链表-2.两数相加-力扣(LeetCode)
  • 【C语言强化训练16天】--从基础到进阶的蜕变之旅:Day7
  • Java开发面试实战:Spring Boot微服务与数据库优化案例分析
  • 微服务如何集成swagger3
  • Leetcode70爬楼梯
  • CF思维训练回顾