You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何利用Optic Flow与Python将实时视频划分为指定区域并独立分析各区域运动情况

解答:用光流分析仓鼠笼各区域运动频率(附代码思路)

嘿,这个以仓鼠为研究对象的光流项目真的超酷!完全不用把视频分割成三个独立文件——直接通过坐标划定感兴趣区域(ROI),就能在每个区域单独运行光流分析,下面一步步给你讲清楚:

一、如何划定区域并独立分析

你的视频是上下三等分的,所以只需要根据每帧的高度计算三个区域的坐标范围就行,核心思路是:

  1. 获取视频帧的尺寸(宽度frame_w、高度frame_h)
  2. 计算三个区域的y轴范围:顶部是0到frame_h//3,中间是frame_h//3到2*frame_h//3,底部是2*frame_h//3到frame_h
  3. 对每帧图像,分别裁剪出这三个ROI,在每个ROI上独立运行光流算法

结合Lucas-Kanade代码的修改示例

你可以在原代码基础上,给每个区域单独处理特征点跟踪:

import cv2
import numpy as np

# 光流相关参数(沿用你提供的配置)
feature_params = dict( maxCorners = 100, qualityLevel = 0.3, minDistance = 7, blockSize = 7 )
lk_params = dict( winSize = (15,15), maxLevel = 2, criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))

# 初始化视频捕获(替换成你的视频路径或摄像头索引)
cap = cv2.VideoCapture("hamster_cage.mp4")

# 获取第一帧并初始化三个区域的特征点
ret, old_frame = cap.read()
frame_h, frame_w = old_frame.shape[:2]

# 定义三个区域的坐标(x1, y1, x2, y2)
regions = {
    "top": (0, 0, frame_w, frame_h//3),
    "middle": (0, frame_h//3, frame_w, 2*frame_h//3),
    "bottom": (0, 2*frame_h//3, frame_w, frame_h)
}

# 为每个区域初始化旧特征点
old_pts = {}
for name, (x1, y1, x2, y2) in regions.items():
    old_roi = old_frame[y1:y2, x1:x2]
    old_gray = cv2.cvtColor(old_roi, cv2.COLOR_BGR2GRAY)
    pts = cv2.goodFeaturesToTrack(old_gray, mask=None, **feature_params)
    old_pts[name] = pts

# 统计每个区域的运动指标(比如总位移)
motion_stats = {name: 0.0 for name in regions}

while True:
    ret, frame = cap.read()
    if not ret:
        break
    frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    for name, (x1, y1, x2, y2) in regions.items():
        roi_gray = frame_gray[y1:y2, x1:x2]
        # 计算光流
        new_pts, status, err = cv2.calcOpticalFlowPyrLK(
            cv2.cvtColor(old_frame[y1:y2, x1:x2], cv2.COLOR_BGR2GRAY),
            roi_gray,
            old_pts[name],
            None,
            **lk_params
        )
        # 筛选跟踪成功的特征点
        good_new = new_pts[status==1]
        good_old = old_pts[name][status==1]
        
        # 计算该区域的总位移(作为运动频繁度的指标)
        if len(good_new) > 0:
            displacement = np.sum(np.sqrt((good_new[:,0]-good_old[:,0])**2 + (good_new[:,1]-good_old[:,1])**2))
            motion_stats[name] += displacement
        
        # 更新该区域的特征点(如果跟踪到的点太少,重新检测)
        if len(good_new) < 10:
            new_pts = cv2.goodFeaturesToTrack(roi_gray, mask=None, **feature_params)
            old_pts[name] = new_pts
        else:
            old_pts[name] = good_new.reshape(-1,1,2)
        
        # 可选:在帧上画出区域和跟踪点
        cv2.rectangle(frame, (x1,y1), (x2,y2), (0,255,0), 2)
        for (x,y) in good_new:
            cv2.circle(frame, (int(x)+x1, int(y)+y1), 2, (0,0,255), -1)
    
    # 打印实时统计(或保存到文件)
    print(f"运动总位移:顶部={motion_stats['top']:.2f} | 中间={motion_stats['middle']:.2f} | 底部={motion_stats['bottom']:.2f}")
    
    cv2.imshow('Hamster Motion Tracking', frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
    
    old_frame = frame.copy()

cap.release()
cv2.destroyAllWindows()

关于你疑惑的参数说明

  • winSize:这是Lucas-Kanade算法中每个特征点的计算窗口大小,和你划定的区域完全无关——它是用来计算特征点周围像素的运动信息的,值越大跟踪越稳定但计算越慢,15x15对于仓鼠笼场景很合适。
  • maxCorners:这是每个区域中最多检测的特征点数量,你可以给三个区域单独设置不同的值(比如跑轮区运动多,可以设大一点),或者保持全局统一,算法会自动在ROI里检测对应数量的角点。

二、光流的其他应用&夏季有趣项目

光流的应用场景超广,夏季可以试试这些好玩的方向:

  • 户外昆虫行为分析:拍花园里的蜜蜂、蝴蝶,用光流跟踪它们的飞行路径,统计它们在不同花朵区域的停留时间,分析觅食偏好。
  • 泳池/水流运动分析:拍泳池里的水波,或者小溪的水流,用光流可视化水流方向,甚至可以分析不同位置的水流速度。
  • 宠物/动物户外跟踪:带仓鼠(或猫狗)去户外,用光流跟踪它们的运动轨迹,统计它们在草地、树荫等区域的活动时长。
  • 运动姿态辅助分析:拍自己滑板、骑行的视频,用光流分析身体各部位的运动幅度,辅助调整动作姿势。
  • 视频稳定:用手机拍户外风景时容易手抖,用光流算法可以实现实时视频稳定,让画面更流畅。

内容的提问来源于stack exchange,提问作者usa_josh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 15:12:36