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

PiscCode使用光流法计算漂浮物位移速度

在计算机视觉中,光流法(Optical Flow)是一种常用的技术,通过分析连续图像帧之间的像素运动,推测物体的运动情况。光流法可以用于目标跟踪、运动分析等任务,广泛应用于机器人导航、视频分析等领域。

本文将介绍如何使用光流法分析物体的运动速度。我们将这个过程分成两个阶段:计算位移像素根据像素计算速度。下面是详细的实现过程。

光流法原理

光流法的核心思想是通过比较连续帧中相同位置的像素点,计算它们的位移。这个过程通常依赖于一些特征点(如角点),在两帧之间跟踪这些点的位移。最终,我们可以推算出物体的速度。

步骤一:计算像素位移

首先,我们使用光流法来计算图像中每个特征点的位移。这里我们采用 Lucas-Kanade 光流算法,这是最常用的光流估计方法之一。

  1. 角点检测:在第一帧图像中检测角点,这些角点将在后续帧中被追踪。

  2. 光流计算:在后续帧中,通过光流算法追踪这些角点,计算每个点的位移。

代码实现如下:

import cv2
import numpy as npclass OpticalFlow:def __init__(self):# 设置 Lucas-Kanade 光流法的参数self.lk_params = dict(winSize=(15, 15),maxLevel=2,criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))# 创建随机数生成器self.rng = np.random.default_rng()def do(self, frame, device):# 转为灰度图gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 在第一帧中检测角点(角点是光流的起点)if not hasattr(self, 'prev_gray'):self.prev_gray = gray# 使用 goodFeaturesToTrack 来获取10个角点self.prev_points = cv2.goodFeaturesToTrack(gray,maxCorners=10,    # 最大角点数设置为10qualityLevel=0.05,  # 角点质量阈值minDistance=7,    # 最小角点间距blockSize=7)      # 用于计算角点的邻域大小# 为每个特征点分配一个唯一的颜色,确保饱和度最大self.colors = [tuple(int(c) for c in color) for color in self.rng.integers(200, 256, (len(self.prev_points), 3))]return frame# 计算光流(在当前帧中跟踪前一帧的角点)next_points, status, _ = cv2.calcOpticalFlowPyrLK(self.prev_gray, gray, self.prev_points, None, **self.lk_params)# 选出跟踪成功的点good_new = next_points[status == 1]good_old = self.prev_points[status == 1]# 计算位移并准备显示信息displacements = []# 绘制光流轨迹for i, (new, old) in enumerate(zip(good_new, good_old)):a, b = new.ravel()c, d = old.ravel()# 计算位移displacement = np.sqrt((a - c) ** 2 + (b - d) ** 2)displacements.append(f"Point {i+1}: {displacement:.2f} px")# 获取对应的颜色color = self.colors[i]# 绘制轨迹frame = cv2.line(frame, (int(a), int(b)), (int(c), int(d)), color, 2)frame = cv2.circle(frame, (int(a), int(b)), 5, color, -1)# 在右下角显示位移信息,确保每个信息的颜色与点的颜色一致y_offset = frame.shape[0] - 10for i, displacement in enumerate(displacements):color = self.colors[i]cv2.putText(frame, displacement, (10, y_offset), cv2.FONT_HERSHEY_SIMPLEX, 1, color, 2, cv2.LINE_AA)  # 字体增大,饱和度增加y_offset -= 40  # 每个信息之间间隔40个像素# 更新上一帧数据self.prev_gray = gray.copy()self.prev_points = good_new.reshape(-1, 1, 2)return frame
步骤二:根据像素和帧率计算速度

计算完每个特征点的位移后,我们接下来要根据实际情况(如帧率和像素与实际距离的换算)计算物体的运动速度。

  1. 位移换算:1厘米 = 10像素,这个换算关系用于将像素单位的位移转换为实际物理单位。

  2. 速度计算:通过已知的帧率(例如 25 帧/秒)和像素位移,可以计算物体的速度。

假设视频的帧率为 25 帧/秒,1厘米 = 10像素,我们可以使用以下公式来计算速度:

速度=位移10×帧率\text{速度} = \frac{\text{位移}}{10} \times \text{帧率}速度=10位移​×帧率

这里的 位移 为像素单位,帧率 为每秒的帧数,10 是像素与厘米之间的换算系数。

import cv2
import numpy as npclass OpticalFlow:def __init__(self):# 设置 Lucas-Kanade 光流法的参数self.lk_params = dict(winSize=(15, 15),maxLevel=2,criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))# 创建随机数生成器self.rng = np.random.default_rng()def do(self, frame, device):# 转为灰度图gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 在第一帧中检测角点(角点是光流的起点)if not hasattr(self, 'prev_gray'):self.prev_gray = gray# 使用 goodFeaturesToTrack 来获取10个角点self.prev_points = cv2.goodFeaturesToTrack(gray, maxCorners=10,  # 最大角点数设置为10qualityLevel=0.05,  # 角点质量阈值minDistance=7,  # 最小角点间距blockSize=7)  # 用于计算角点的邻域大小# 为每个特征点分配一个唯一的颜色,确保饱和度最大self.colors = [tuple(int(c) for c in color) for color in self.rng.integers(200, 256, (len(self.prev_points), 3))]return frame  # 在第一帧中返回原始图像# 计算光流(在当前帧中跟踪前一帧的角点)next_points, status, _ = cv2.calcOpticalFlowPyrLK(self.prev_gray, gray, self.prev_points, None, **self.lk_params)# 选出跟踪成功的点good_new = next_points[status == 1]good_old = self.prev_points[status == 1]# 计算位移并准备显示信息displacements = []speeds = []# 计算位移、速度并绘制光流轨迹for i, (new, old) in enumerate(zip(good_new, good_old)):a, b = new.ravel()c, d = old.ravel()# 计算位移displacement = np.sqrt((a - c) ** 2 + (b - d) ** 2)displacements.append(f"Point {i+1}: {displacement:.2f} px")# 计算速度(1秒25帧,1厘米 = 10像素)frame_rate = 25  # 帧率:25帧/秒displacement_cm = displacement / 10  # 1厘米 = 10像素speed = displacement_cm * frame_rate  # 速度单位为cm/sspeeds.append(f"Speed: {speed:.2f} cm/s")# 获取对应的颜色color = self.colors[i]# 绘制轨迹frame = cv2.line(frame, (int(a), int(b)), (int(c), int(d)), color, 2)frame = cv2.circle(frame, (int(a), int(b)), 5, color, -1)# 在右下角显示位移信息,确保每个信息的颜色与点的颜色一致y_offset = frame.shape[0] - 10  # 初始Y坐标在底部for i, (displacement, speed) in enumerate(zip(displacements, speeds)):color = self.colors[i]# 在表格中显示每个点的位移和速度cv2.putText(frame, f"{displacement} {speed}", (10, y_offset),cv2.FONT_HERSHEY_SIMPLEX, 1, color, 2, cv2.LINE_AA)y_offset -= 40  # 每行之间间隔40个像素# 更新上一帧数据self.prev_gray = gray.copy()self.prev_points = good_new.reshape(-1, 1, 2)return frame
完整流程
  1. 计算位移像素:通过光流算法,检测并追踪特征点,计算出每个特征点在两帧之间的位移,单位为像素。

  2. 根据像素计算速度:根据给定的帧率和像素与实际距离的换算关系,计算每个特征点的运动速度,单位为厘米/秒。

总结

光流法不仅可以帮助我们跟踪图像中的物体,还能够准确估算物体的运动速度。通过将位移计算与速度换算分开,我们可以更清晰地理解并应用光流法。在实际应用中,光流法广泛应用于运动检测、目标跟踪、水文气象检测等场景中。

 对 PiscTrace or PiscCode感兴趣?更多精彩内容请移步官网看看~🔗 PiscTrace

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

相关文章:

  • 把 AI 推理塞进「 8 位 MCU 」——0.5 KB RAM 跑通关键词唤醒的魔幻之旅
  • 监控插件SkyWalking(一)原理
  • 嵌入式学习的第四十九天-时钟+EPIT+GPT定时器
  • 无人机探测器技术解析
  • 阿里巴巴 Qwen-Image:免费开源,还要挑战 GPT-4.1 和 Midjourney?
  • 恢复GPT-4o,增加付费配额:OpenAI的“补救措施”如何重塑用户金字塔
  • OpenCV ------图像基础处理(一)
  • 【OpenCV】Mat详解
  • 论,物联网日志系统架构如何设计?
  • AI增强SEO关键词表现
  • Postman 平替 技术解析:架构优势与实战指南
  • 审批流程系统设计与实现:状态驱动、灵活扩展的企业级解决方案
  • Java研学-RabbitMQ(八)
  • Rabbitmq+STS+discovery_k8s +localpv部署排坑详解
  • 队列的使用以及泛型思考[二叉树的层序遍历]
  • 【P27 4-8】OpenCV Python——Mat类、深拷贝(clone、copyTo、copy)、浅拷贝,原理讲解与示例代码
  • Horse3D游戏引擎研发笔记(五):在QtOpenGL环境下,仿three.js的BufferGeometry管理VAO和EBO绘制四边形
  • 算法训练营day51 图论② 岛屿数量深搜、广搜、最大面积
  • 图论(5)最小生成树算法
  • Claude Code 国内直接使用,原生支持 Windows 免WSL安装教程
  • Day56--图论--108. 冗余的边(卡码网),109. 冗余的边II(卡码网)
  • Day58--图论--117. 软件构建(卡码网),47. 参加科学大会(卡码网)
  • MySQL窗口函数与PyMySQL以及SQL注入
  • MySQLl中OFFSET 的使用方法
  • 中国AI生态加速迭代,AI硬件引领人机互动新范式
  • LeetCode 分类刷题:2302. 统计得分小于 K 的子数组数目
  • Gradle(四)Maven 项目迁移 Gradle 项目实践
  • 文件服务器:samba
  • Java 并发新范式:用 Structured Concurrency 优雅收拾多线程烂摊子
  • 编排之神-Kubernetes微服务专题--ingress-nginx及金丝雀Canary的演练