如何利用Optic Flow与Python将实时视频划分为指定区域并独立分析各区域运动情况
解答:用光流分析仓鼠笼各区域运动频率(附代码思路)
嘿,这个以仓鼠为研究对象的光流项目真的超酷!完全不用把视频分割成三个独立文件——直接通过坐标划定感兴趣区域(ROI),就能在每个区域单独运行光流分析,下面一步步给你讲清楚:
一、如何划定区域并独立分析
你的视频是上下三等分的,所以只需要根据每帧的高度计算三个区域的坐标范围就行,核心思路是:
- 获取视频帧的尺寸(宽度
frame_w、高度frame_h) - 计算三个区域的y轴范围:顶部是
0到frame_h//3,中间是frame_h//3到2*frame_h//3,底部是2*frame_h//3到frame_h - 对每帧图像,分别裁剪出这三个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
相关产品推荐
相关产品推荐

