不同物体运动方向的检测-python

方法

优点

适用场景

缺点

光流法

实时性强、支持稠密方向分析

视频流中物体整体运动

对背景复杂场景鲁棒性差

特征点跟踪

精确捕捉局部运动

特征点明显的物体

特征点丢失影响结果

帧间差分

简单快速,适合实时检测

背景稳定、低复杂度场景

对噪声和阴影敏感

深度摄像头

三维方向检测,抗背景干扰能力强

需要深度信息的场景

需要特殊硬件,成本较高

惯性传感器

不依赖视觉,适用环境广泛

设备本体的运动分析

精度受传感器噪声影响

机器学习

能适应复杂非线性场景

复杂场景,非规则运动

数据需求高,训练成本高

背景建模

对静态背景场景鲁棒性好

固定背景的视频监控

背景变化会降低精度

1. 特征点跟踪(基于Lucas-Kanade光流法)

import cv2

import numpy as np

# Parameters for Lucas-Kanade optical flow

lk_params = dict(winSize=(15, 15), maxLevel=2,

                 criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))

# Initialize video capture

cap = cv2.VideoCapture("input_video.mp4")

# Capture the first frame and detect Shi-Tomasi corners

ret, old_frame = cap.read()

if not ret:

    print("Failed to read video.")

    cap.release()

    exit()

old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)

p0 = cv2.goodFeaturesToTrack(old_gray, mask=None, maxCorners=100, qualityLevel=0.3, minDistance=7, blockSize=7)

while cap.isOpened():

    ret, frame = cap.read()

    if not ret:

        break

    frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # Calculate optical flow

    p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)

    # Select good points

    good_new = p1[st == 1]

    good_old = p0[st == 1]

    # Draw tracks

    for (new, old) in zip(good_new, good_old):

        a, b = new.ravel()

        c, d = old.ravel()

        cv2.arrowedLine(frame, (c, d), (a, b), (0, 255, 0), 2)

    # Display the result

    cv2.imshow("Feature Point Tracking", frame)

    # Update the previous frame and points

    old_gray = frame_gray.copy()

    p0 = good_new.reshape(-1, 1, 2)

    if cv2.waitKey(1) & 0xFF == ord('q'):

        break

cap.release()

cv2.destroyAllWindows()

2. 帧间差分

import cv2

cap = cv2.VideoCapture("input_video.mp4")

ret, prev_frame = cap.read()

if not ret:

    print("Failed to read video.")

    cap.release()

    exit()

prev_gray = cv2.cvtColor(prev_frame, cv2.COLOR_BGR2GRAY)

while cap.isOpened():

    ret, frame = cap.read()

    if not ret:

        break

    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # Frame difference

    diff = cv2.absdiff(prev_gray, gray)

    # Threshold and find contours

    _, thresh = cv2.threshold(diff, 25, 255, cv2.THRESH_BINARY)

    contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    for contour in contours:

        if cv2.contourArea(contour) > 500:

            x, y, w, h = cv2.boundingRect(contour)

            cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)

    # Display the result

    cv2.imshow("Frame Difference", frame)

    prev_gray = gray.copy()

    if cv2.waitKey(1) & 0xFF == ord('q'):

        break

cap.release()

cv2.destroyAllWindows()

3. 深度摄像头(RGB-D)

import cv2

import pyrealsense2 as rs  # Requires Intel RealSense SDK

# Initialize RealSense pipeline

pipeline = rs.pipeline()

config = rs.config()

config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)

config.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30)

pipeline.start(config)

try:

    while True:

        # Get frames

        frames = pipeline.wait_for_frames()

        depth_frame = frames.get_depth_frame()

        color_frame = frames.get_color_frame()

        if not depth_frame or not color_frame:

            continue

        depth_image = np.asanyarray(depth_frame.get_data())

        color_image = np.asanyarray(color_frame.get_data())

        # Visualize depth and motion direction (simple demo)

        cv2.imshow("Color Image", color_image)

        cv2.imshow("Depth Image", depth_image)

        if cv2.waitKey(1) & 0xFF == ord('q'):

            break

finally:

    pipeline.stop()

    cv2.destroyAllWindows()

4. 惯性传感器(IMU)

from sense_hat import SenseHat  # For Raspberry Pi with Sense HAT

sense = SenseHat()

while True:

    accel = sense.get_accelerometer_raw()

    x = accel['x']

    y = accel['y']

    z = accel['z']

    print(f"Acceleration -> X: {x:.2f}, Y: {y:.2f}, Z: {z:.2f}")

    if abs(x) > 0.5:

        print("Device moving in X direction")

    if abs(y) > 0.5:

        print("Device moving in Y direction")

    # Add a short delay

    time.sleep(0.1)

5. 背景建模

import cv2

cap = cv2.VideoCapture("input_video.mp4")

# Initialize background subtractor

fgbg = cv2.createBackgroundSubtractorMOG2()

while cap.isOpened():

    ret, frame = cap.read()

    if not ret:

        break

    fgmask = fgbg.apply(frame)

    # Find contours

    contours, _ = cv2.findContours(fgmask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    for contour in contours:

        if cv2.contourArea(contour) > 500:

            x, y, w, h = cv2.boundingRect(contour)

            cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)

    # Display the result

    cv2.imshow("Background Subtraction", frame)

    if cv2.waitKey(1) & 0xFF == ord('q'):

        break

cap.release()

cv2.destroyAllWindows()

6. 机器学习

利用深度学习框架(如PyTorch或TensorFlow)训练模型判断运动方向。这部分需要采集数据集并进行模型训练,属于更复杂的场景。

需要更多帮助,可针对具体方法详细展开!

代码:光流法显示运动方向并用箭头表示

python

复制代码

import cv2import numpy as np

# Parameters for optical flow

lk_params = dict(winSize=(15, 15), maxLevel=2,

                 criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))

# Colors for drawing

color = (0, 255, 0)  # Green for arrows

# Capture video

cap = cv2.VideoCapture("input_video.mp4")  # Replace with 0 for webcam

# Read the first frame

ret, old_frame = cap.read()if not ret:

    print("Failed to read video.")

    cap.release()

    exit()

old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)

# Detect initial feature points

p0 = cv2.goodFeaturesToTrack(old_gray, mask=None, maxCorners=100, qualityLevel=0.3, minDistance=7, blockSize=7)

# Create a mask image for drawing purposes

mask = np.zeros_like(old_frame)

while cap.isOpened():

    ret, frame = cap.read()

    if not ret:

        break

    frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # Calculate optical flow

    p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)

    # Select good points

    if p1 is not None:

        good_new = p1[st == 1]

        good_old = p0[st == 1]

        # Draw the tracks with arrows

        for (new, old) in zip(good_new, good_old):

            a, b = new.ravel()

            c, d = old.ravel()

            # Draw arrow

            cv2.arrowedLine(mask, (int(c), int(d)), (int(a), int(b)), color, 2, tipLength=0.3)

    # Overlay the mask on the frame

    output = cv2.add(frame, mask)

    # Display the result

    cv2.imshow("Optical Flow with Arrows", output)

    # Update the previous frame and points

    old_gray = frame_gray.copy()

    p0 = good_new.reshape(-1, 1, 2)

    if cv2.waitKey(1) & 0xFF == ord('q'):

        break

cap.release()

cv2.destroyAllWindows()

代码说明:

  1. 输入视频或实时摄像头:使用 cap = cv2.VideoCapture("input_video.mp4") 输入视频文件。
    1. 替换为 cap = cv2.VideoCapture(0) 使用摄像头输入。

光流计算

  1. 利用 cv2.calcOpticalFlowPyrLK 计算特征点在连续帧中的运动。

方向显示

  1. 使用 cv2.arrowedLine 绘制箭头,从旧点指向新点,表示运动方向。

绘制掩膜

  1. 为了让箭头保持在画面中,使用掩膜 (mask) 来绘制轨迹。

按键退出

  1. 按下 q 键可以退出程序。

效果:

  • 箭头会显示运动的方向和大小,箭头起点为特征点的旧位置,箭头指向特征点的新位置。
  • 整体运动轨迹会持续绘制在画面上,方便分析运动。

你可以调整以下参数以适应不同场景:

  • maxCorners(最大特征点数)和 qualityLevel(特征点质量)。
  • winSize(光流窗口大小)以平衡速度和精度。
  • tipLength(箭头长度)控制箭头外观。

你可能感兴趣的:(python,开发语言)