光流金字塔calcOpticalFlowPyrLK进行特征点跟踪

光流描述的是图像上每个像素点的灰度的位置(速度)变化情况,光流的研究是利用图像序列中的像素强度数据的时域变化和相关性来确定各自像素位置的“运动”。研究光流场的目的就是为了从图片序列中近似得到不能直接得到的运动场。
光流法的前提假设:
- (1)相邻帧之间的亮度恒定;
- (2)相邻视频帧的取帧时间连续,或者,相邻帧之间物体的运动比较“微小”;
- (3)保持空间一致性;即,同一子图像的像素点具有相同的运动;

光流金字塔calcOpticalFlowPyrLK的C++定义如下:

CV_EXPORTS_W void calcOpticalFlowPyrLK( InputArray prevImg, InputArray nextImg,
                           InputArray prevPts, CV_OUT InputOutputArray nextPts,
                           OutputArray status, OutputArray err,
                           Size winSize=Size(21,21), int maxLevel=3,
                           TermCriteria criteria=TermCriteria(
                            TermCriteria::COUNT+TermCriteria::EPS,
                            30, 0.01),
                           double derivLambda=0.5,
                           int flags=0,
                           double minEigThreshold=1e-4);

各个参数代表的含义如下:
- prevImg
你的标定图像的灰度图
- nextImg
你想搜寻的图像的灰度图
- prevPts
输入的标定图像的特征点(可以是其他特征点检测方法找到的点)
- nextPts
输出场景的特征点
- status
输出状态向量(无符号char),如果在当前图像中能够光流得到标定的特征点位置改变,则设置status的对应位置为1,否则设置为0
- err
输出错误向量;向量的每个元素被设为相应特征的一个错误,误差测量的类型可以在flags参数中设置;如果流不被发现然后错误未被定义(使用status(状态)参数找到此情形)。
- winSize
在每个金字塔水平搜寻窗口的尺寸
- maxLevel
金字塔的高度,初始为3层

当使用calcOpticalFlowPyrLK作为光流金字塔的算法时候,我们只需要知道以下的几点:

  • calcOpticalFlowPyrLK必须和其他的角点识别算法进行搭配使用,比如我这里使用的goodFeaturesToTrack,将其他的角点识别算法中获得的角点作为光流算法的prevPts
  • status 的大小和当前需要识别的光流移动的特征点大小一样,所以我们可以判定当前的图像是否还能与标定图像进行光流的依据

运行环境为:

- opencv 2.3.1

- vs2017

以下是一个傻瓜示例代码:


#include<iostream>  

#include<opencv.hpp>


using namespace std;
using namespace cv;


int main()
{
    Mat image1, image2;
    vector<Point2f> point1, point2, pointCopy;
    vector<uchar> status;
    vector<float> err;


    VideoCapture video(0);
    video >> image1;
    Mat image1Gray, image2Gray;
    cvtColor(image1, image1Gray, CV_RGB2GRAY);
    goodFeaturesToTrack(image1Gray, point1, 100, 0.01, 10, Mat());
    pointCopy = point1;
    for (int i = 0; i < point1.size(); i++)    //绘制特征点位  
    {
        circle(image1, point1[i], 1, Scalar(0, 0, 255), 2);
    }
    namedWindow("光流特征图");
    while (true)
    {
        video >> image2;
        if (waitKey(33) == ' ')  //按下空格选择当前画面作为标定图像  
        {
            cvtColor(image2, image1Gray, CV_RGB2GRAY);
            goodFeaturesToTrack(image1Gray, point1, 100, 0.01, 10, Mat());
            pointCopy = point1;
        }
        cvtColor(image2, image2Gray, CV_RGB2GRAY);
        calcOpticalFlowPyrLK(image1Gray, image2Gray, point1, point2, status, err, Size(50, 50), 3); //LK金字塔       
        int tr_num = 0;
        vector<unsigned char>::iterator status_itr = status.begin();
        while (status_itr != status.end()) {
            if (*status_itr > 0)
                tr_num++;
            status_itr++;
        }
        if (tr_num < 6) {
            cout << "you need to change the feat-img because the background-img was all changed" << endl;
            if (waitKey(0) == ' ') {
                cvtColor(image2, image1Gray, CV_RGB2GRAY);
                goodFeaturesToTrack(image1Gray, point1, 100, 0.01, 10, Mat());
                pointCopy = point1;
            }
        }
        for (int i = 0; i < point2.size(); i++)
        {
            circle(image2, point2[i], 1, Scalar(0, 0, 255), 2);
            line(image2, pointCopy[i], point2[i], Scalar(255, 0, 0), 2);
        }

        imshow("光流特征图", image2);
        swap(point1, point2);
        image1Gray = image2Gray.clone();
    }
    return 0;
}

效果如图:

- 标定图像

这里写图片描述

- 镜头移动

这里写图片描述

ps: 红点为标定点,蓝线为跟踪点的光流移动

<think>嗯,用户想要用Python实现特征点跟踪的方法或者教程,特别是使用OpenCV。首先,我需要回想一下OpenCV中常用的特征点跟踪算法有哪些。根据引用[2]里的信息,OpenCV支持的特征跟踪算法有Lucas-Kanade法和稀疏法。对了,法应该是用来追踪视频序列中特征点的运动轨迹的。 用户可能需要一个具体的步骤说明和示例代码。记得引用中的示例提到了FAST关键点检测和ORB描述符计算,不过特征跟踪可能更多涉及法。Lucas-Kanade方法需要先检测特征点,然后在后续帧中追踪这些点。另外,可能需要使用cv2.calcOpticalFlowPyrLK函数,这个函数我记得是用来做稀疏跟踪的。 步骤方面,首先应该读取视频或者摄像头输入,然后检测初始帧的特征点。比如用Shi-Tomasi角点检测,或者FAST,但根据引用[4],FAST_create可能是个好的起点。不过Shi-Tomasi的参数可能在cv2.goodFeaturesToTrack里设置。接着,在后续帧中使用法计算这些点的新位置,并绘制轨迹。 代码部分需要注意读取视频帧,转换为灰度图像,然后处理每一帧。可能需要维护一个轨迹的列表,记录每个点的移动路径。还要处理那些追踪失败的点,比如用状态变量来过滤掉状态不佳的点。 用户可能还会关心如何优化或提高跟踪的准确性,这时候可以提到引用[2]中的RANSAC算法或者最小二乘法,但可能在跟踪中,参数调整比如窗口大小、金字塔层数更为直接。 另外,关于颜色空间的转换,引用[3]中的方法可能会用到,如果用户需要显示图像的话,但如果是处理灰度图像可能不需要。不过示例中可能需要将BGR转成RGB,用img[:, :, ::-1]的方法。 最后,生成相关问题的时候,可以围绕性能优化、其他跟踪方法、应用场景等方面提问,帮助用户深入理解。比如如何调整参数提升效果,或者法与特征匹配的区别,以及实时应用中的处理技巧。</think>### Python实现特征点跟踪的方法(OpenCV) #### 一、实现原理与特征点跟踪的核心是通过检测图像序列中关键点的位置变化来捕捉运动信息。OpenCV中常用的方法是**稀疏法**(如Lucas-Kanade算法)[^2]。其程为: 1. **特征点检测**:在初始帧中提取关键点(如角点)。 2. **追踪**:在后续帧中计算关键点的位置变化。 3. **轨迹可视化**:绘制关键点的运动路径。 #### 二、代码实现步骤 ##### 1. 基础代码框架 ```python import cv2 import numpy as np # 读取视频或摄像头 cap = cv2.VideoCapture(0) # 摄像头输入 # cap = cv2.VideoCapture("video.mp4") # 视频文件 # 定义Lucas-Kanade参数 lk_params = dict(winSize=(15, 15), maxLevel=2, criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03)) # 初始化特征点检测器 (Shi-Tomasi角点) feature_params = dict(maxCorners=100, qualityLevel=0.3, minDistance=7, blockSize=7) # 初始化第一帧 ret, old_frame = cap.read() old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY) p0 = cv2.goodFeaturesToTrack(old_gray, mask=None, **feature_params) # 轨迹存储 track_path = [] 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() track_path.append((a, b)) cv2.line(frame, (int(a), int(b)), (int(c), int(d)), (0, 255, 0), 2) cv2.circle(frame, (int(a), int(b)), 5, (0, 0, 255), -1) # 更新变量 old_gray = frame_gray.copy() p0 = good_new.reshape(-1, 1, 2) # 显示结果 cv2.imshow("Tracking", frame) if cv2.waitKey(30) & 0xFF == 27: break cap.release() cv2.destroyAllWindows() ``` ##### 2. 关键点说明 - **参数**:`winSize`定义搜索窗口大小,`maxLevel`为金字塔层数。 - **特征点检测**:使用Shi-Tomasi角点(`cv2.goodFeaturesToTrack`)或FAST算法(`cv2.FastFeatureDetector_create()`)[^4]。 - **轨迹优化**:通过`st`状态筛选有效跟踪点,避免噪声干扰。 #### 三、优化建议 1. **动态更新特征点**:当跟踪点数量减少时,重新检测新特征点。 2. **使用ORB/SIFT描述子**:结合特征描述子提升匹配鲁棒性(需调用`cv2.ORB_create()`等)。 3. **RANSAC筛选**:对匹配结果进行几何验证(通过`cv2.findHomography`)。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值