OpenCV 光流Optical Flow示例

下面是对于“OpenCV 光流Optical Flow示例”的完整攻略以及两个示例说明。

简介

Optical Flow是指在视频中的相邻两帧之间,在像素级别上计算出像素点在两帧之间的位移的技术。OpenCV是一个广泛使用的计算机视觉库,也支持光流技术。本攻略将介绍如何使用OpenCV进行光流分析。

步骤

  1. 安装OpenCV。

如果你还没有安装OpenCV,请先前往官方网站下载安装。

  1. 加载视频。

将视频加载到OpenCV中。

import cv2

cap = cv2.VideoCapture('path/to/video')
  1. 设置参数。

设置角点检测器的最大角点数,角点检测器的质量水平等等。

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))
color = (0, 255, 0)
  1. 计算光流。

计算相邻两帧之间的光流,并将其绘制到新图像中。

# 读取一帧
ret, old_frame = cap.read()
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)

# 寻找角点
p0 = cv2.goodFeaturesToTrack(old_gray, mask=None, **feature_params)

# 创建一个mask用来绘制轨迹
mask = np.zeros_like(old_frame)

# 循环读取视频并计算光流
while True:
    ret, frame = cap.read()
    if not ret:
        break
    frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

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

    good_new = p1[st == 1]
    good_old = p0[st == 1]

    # 绘制轨迹
    for i, (new, old) in enumerate(zip(good_new, good_old)):
        a, b = new.ravel()
        c, d = old.ravel()
        mask = cv2.line(mask, (a, b), (c, d), color, 2)
        frame = cv2.circle(frame, (a, b), 5, color, -1)
    img = cv2.add(frame, mask)
    cv2.imshow('frame', img)

    # 更新帧和角点点
    old_gray = frame_gray.copy()
    p0 = good_new.reshape(-1, 1, 2)

    k = cv2.waitKey(30) & 0xff
    if k == 27:
        break

cv2.destroyAllWindows()
cap.release()

示例1

在这个示例中,我们模拟一个二维的均匀平移,它会随着时间的推移而减小。

import cv2
import numpy as np

# 创建画布
canvas = np.zeros((400, 400), dtype="uint8")

# 初始化变量
shift = 0
delta = 4

# 绘制旋转方格
for x in range(10, 390, 25):
    shift += delta
    pts = np.array([[10 + shift, x], [390, x], [390 - shift, x + 25], [10, x + 25]], dtype=np.int32)
    cv2.fillConvexPoly(canvas, pts, (255))

# 循环将画布变换
for i in range(120):
    M = np.float32([[1, 0, i * 3], [0, 1, 0]])
    rotated = cv2.warpAffine(canvas, M, (400, 400))

    # 计算光流
    flow = cv2.calcOpticalFlowFarneback(canvas, rotated, None, 0.5, 3, 25, 3, 5, 1.2, 0)
    magnitude, angle = cv2.cartToPolar(flow[..., 0], flow[..., 1])

    # 构造HSV图像
    hsv = np.zeros((400, 400, 3), dtype="uint8")
    hsv[..., 0] = angle * (180 / np.pi / 2)
    hsv[..., 1] = 255
    hsv[..., 2] = cv2.normalize(magnitude, None, 0, 255, cv2.NORM_MINMAX)

    # 转换为BGR图像并输出
    bgr = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
    cv2.imshow("Optical Flow", bgr)
    if cv2.waitKey(1) & 0xFF == ord("q"):
        break

cv2.destroyAllWindows()

该示例演示了如何在画布上进行均匀平移,然后使用OpenCV的calcOpticalFlowFarneback函数计算出运动的光流。最终使用cvtColor函数将光流图像转换为BGR空间,以便将其显示出来。

示例2

在这个示例中,我们将通过直接对NGC 2237进行光流处理来演示OpenCV的光流功能。NGC 2237是Rosette星云中的一个部分,是一个美丽的星云。

import cv2
import numpy as np
from urllib import request

# 加载图像
url = "https://www.winhelponline.com/blog/wp-content/uploads/2017/12/Windows-10-default-background-3.jpg"
resp = request.urlopen(url)
image = np.asarray(bytearray(resp.read()), dtype="uint8")
image = cv2.imdecode(image, cv2.IMREAD_GRAYSCALE)

# 初始化前一帧和光流
previous_frame = None
optical_flow = None

# 不断循环,直到用户终止程序
while True:
    # 如果前一帧为空,则将当前帧设置为前一帧
    if previous_frame is None:
        previous_frame = image.copy()
    else:
        previous_frame = current_frame.copy()

    # 如果当前帧为空,则退出循环
    current_frame = image.copy()
    if current_frame is None:
        break

    # 如果光流为空,则使用Farneback计算光流
    if optical_flow is None:
        optical_flow = cv2.calcOpticalFlowFarneback(previous_frame, current_frame, None, 0.5, 3, 15, 3, 5, 1.2, 0)

    # 在当前帧上绘制运动向量
    for y in range(0, current_frame.shape[0], 5):
        for x in range(0, current_frame.shape[1], 5):
            dx, dy = optical_flow[y, x].astype(np.int0)
            cv2.arrowedLine(current_frame, (x, y), (x + dx, y + dy), (255, 255, 255))

    # 显示帧
    cv2.imshow("Rosette Nebula (NGC 2237)", current_frame)

    # 侦听键盘事件,确定是否退出
    key = cv2.waitKey(1) & 0xFF
    if key == ord("q"):
        break

cv2.destroyAllWindows()

该示例加载一个图像,然后使用calcOpticalFlowFarneback函数计算出前一帧和当前帧之间的运动光流。最终,使用光流图像在当前帧上绘制运动向量,并显示结果。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:OpenCV 光流Optical Flow示例 - Python技术站

(0)
上一篇 2023年5月25日
下一篇 2023年5月25日

相关文章

  • vue.js项目nginx部署教程

    下面提供一份Vue.js项目Nginx部署的攻略,包含了具体的步骤和两条示例说明: 1. 环境准备 安装Vue CLI 根据Vue官方文档的指引,使用npm命令全局安装Vue CLI: npm install -g @vue/cli 构建Vue.js项目 使用Vue CLI构建一个Vue.js项目,在该项目中创建示例代码,确保能够在开发环境中成功运行。 安装…

    人工智能概览 2023年5月25日
    00
  • 利用Python的Django框架生成PDF文件的教程

    我来为您详细讲解“利用Python的Django框架生成PDF文件的教程”的完整攻略。 1. 确定需求 在开始制作PDF文件之前,我们需要确定需求,即需要制作哪些PDF文件以及需要包含哪些内容。这些PDF文件可能包括: 报告 订单 发票 协议 你需要确定文件的格式、内容以及必要的样式。在确定需求后,我们可以选择使用Python中的Django框架来生成PDF…

    人工智能概览 2023年5月25日
    00
  • nginx win32 版本静态文件测试 (Windows环境)

    针对题目所提出的问题,“nginx win32 版本静态文件测试 (Windows环境)”的完整攻略,我将从以下几方面介绍: nginx win32版本介绍 nginx win32版本的安装及配置 nginx win32版本静态文件测试的示例说明 1. nginx win32版本介绍 nginx是一款轻量级的Web服务器/反向代理服务器,其优点是占用资源少,…

    人工智能概览 2023年5月25日
    00
  • Nginx日志按日期切割详解(按天切割)

    这里是对“Nginx日志按日期切割详解(按天切割)”的完整攻略。 1. 为什么需要按日期切割日志 在网站运行中,生成的日志越来越多,过多的日志文件会占用大量的硬盘空间,同时对服务器的性能也会产生影响。因此需要对日志进行切割,以减小对磁盘空间的占用,同时提高日志的查询效率。而按日期切割日志,可以让我们更好地按时间段查找、归档和处理。 2. 日志切割的方式 我们…

    人工智能概览 2023年5月25日
    00
  • Python工程师必考的6个经典面试题

    下面我会详细讲解“Python工程师必考的6个经典面试题”的完整攻略。 1. 实现单例模式 单例模式指的是一个类只能创建一个实例。在Python中,实现单例模式有多种方法,包括使用装饰器、使用元类等。以下是使用装饰器的实现代码示例: def singleton(cls): instances = {} def wrapper(*args, **kwargs)…

    人工智能概览 2023年5月25日
    00
  • 详解nodejs中express搭建权限管理系统

    下面我为您详细讲解“详解nodejs中express搭建权限管理系统”的完整攻略。 一、前置准备 在开始搭建权限管理系统之前,我们需要先进行一些前置准备工作: 熟悉 Nodejs 和 Express 框架的基本语法和使用方法。 安装 MongoDB 数据库和 Mongoose 数据库模块。 了解 session 和 cookie 的基本概念。 二、安装依赖 …

    人工智能概览 2023年5月25日
    00
  • 如何利用AJAX获取Django后端数据详解

    如何利用AJAX获取Django后端数据详解 概述 AJAX(Asynchronous JavaScript and XML,异步的JavaScript和XML技术)主要通过XMLHttpRequest对象,以异步方式与后端进行数据交互。本文将介绍如何使用AJAX获取Django后端数据,包括利用jQuery和原生JavaScript两种方式。 操作步骤 1…

    人工智能概论 2023年5月25日
    00
  • Java Web实现自动登陆功能

    实现Java Web自动登录功能,一般需要以下步骤: 用户登录时,将用户名和密码传到后台,后台进行验证 在前端页面中,我们需要添加一个表单,输入用户名和密码等登录信息,然后点击登录按钮提交表单。 示例代码: <form action="login" method="post"> <label for=…

    人工智能概论 2023年5月25日
    00
合作推广
合作推广
分享本页
返回顶部