回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页
best-icon

基于行空板的opencv lk_homography目标追踪 简单

头像 auroraAA 2024.06.05 93 0

一、实践目标

 

本项目在行空板上外接USB摄像头,通过摄像头来检测目标,并进行跟踪。

 

二、知识目标

 

1、学习使用opencv库的lk homography方法来检测目标物并进行跟踪的方法。

 

三、实践准备

 

硬件清单:

截屏2024-06-05 下午2.07.06.png

软件使用:Mind+编程软件x1

 

四、实践过程

 

1、硬件搭建

 

1、将摄像头接入行空板的USB接口。

 

image.png

 

2、通过USB连接线将行空板连接到计算机。

 

image.png

 

2、软件编写

第一步:打开Mind+,远程连接行空板

 

image.png

 

第二步:在“行空板的文件”中新建一个名为AI的文件夹,在其中再新建一个名为“基于行空板的opencv lk_homography目标追踪”的文件夹,导入本节课的依赖文件。

 

image.png

 

第三步:编写程序

在上述文件的同级目录下新建一个项目文件,并命名为“main.py”。

 示例程序:

代码
#!/usr/bin/env python

'''
Lucas-Kanade homography tracker
===============================
...
'''

# Python 2/3 compatibility
from __future__ import print_function

import numpy as np
import cv2 as cv

import video
from common import draw_str
from video import presets

# 设置Lucas-Kanade光流法的参数
lk_params = dict( winSize  = (19, 19),
                  maxLevel = 2,
                  criteria = (cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 0.03))

# 设置寻找好特征点的参数
feature_params = dict( maxCorners = 1000,
                       qualityLevel = 0.01,
                       minDistance = 8,
                       blockSize = 19 )

# 定义跟踪函数,通过比较前后两帧的特征点位置,判断是否为有效的跟踪点
def checkedTrace(img0, img1, p0, back_threshold = 1.0):
    p1, _st, _err = cv.calcOpticalFlowPyrLK(img0, img1, p0, None, **lk_params)
    p0r, _st, _err = cv.calcOpticalFlowPyrLK(img1, img0, p1, None, **lk_params)
    d = abs(p0-p0r).reshape(-1, 2).max(-1)
    status = d < back_threshold
    return p1, status

green = (0, 255, 0)
red = (0, 0, 255)

class App:
    def __init__(self, video_src):
        # 创建视频捕捉对象
        self.cam = self.cam = video.create_capture(video_src, presets['book'])
        self.p0 = None
        self.use_ransac = True
        # 创建一个全屏窗口用于显示
        cv.namedWindow('lk_homography',cv.WND_PROP_FULLSCREEN)    #Set the windows to be full screen.
        cv.setWindowProperty('lk_homography', cv.WND_PROP_FULLSCREEN, cv.WINDOW_FULLSCREEN)    #Set the windows to be full screen.

    def run(self):
        while True:
            # 读取视频帧
            _ret, frame = self.cam.read()
            # 将视频帧转换为灰度图
            frame_gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
            vis = frame.copy()
            if self.p0 is not None:
                # 使用光流法跟踪特征点
                p2, trace_status = checkedTrace(self.gray1, frame_gray, self.p1)

                self.p1 = p2[trace_status].copy()
                self.p0 = self.p0[trace_status].copy()
                self.gray1 = frame_gray

                if len(self.p0) < 4:
                    self.p0 = None
                    continue
                # 找到两帧之间的单应性矩阵
                H, status = cv.findHomography(self.p0, self.p1, (0, cv.RANSAC)[self.use_ransac], 10.0)
                h, w = frame.shape[:2]
                overlay = cv.warpPerspective(self.frame0, H, (w, h))
                # 叠加两帧图像
                vis = cv.addWeighted(vis, 0.5, overlay, 0.5, 0.0)

                for (x0, y0), (x1, y1), good in zip(self.p0[:,0], self.p1[:,0], status[:,0]):
                    if good:
                        cv.line(vis, (int(x0), int(y0)), (int(x1), int(y1)), (0, 128, 0))
                    cv.circle(vis, (int(x1), int(y1)), 2, (red, green)[good], -1)
                draw_str(vis, (20, 20), 'track count: %d' % len(self.p1))
                if self.use_ransac:
                    draw_str(vis, (20, 40), 'RANSAC')
            else:
                p = cv.goodFeaturesToTrack(frame_gray, **feature_params)
                if p is not None:
                    for x, y in p[:,0]:
                        cv.circle(vis, (int(x), int(y)), 2, green, -1)
                    draw_str(vis, (20, 20), 'feature count: %d' % len(p))

            cv.imshow('lk_homography', vis)

            ch = cv.waitKey(1)
            if ch == 27:
                break
            if ch == ord('a'):
                self.frame0 = frame.copy()
                self.p0 = cv.goodFeaturesToTrack(frame_gray, **feature_params)
                if self.p0 is not None:
                    self.p1 = self.p0
                    self.gray0 = frame_gray
                    self.gray1 = frame_gray
            if ch == ord('b'):
                self.use_ransac = not self.use_ransac

def main():
    import sys
    try:
        video_src = sys.argv[1]
    except:
        video_src = 0

    # 运行应用程序
    App(video_src).run()
    print('Done')

if __name__ == '__main__':
    print(__doc__)
    main()
    cv.destroyAllWindows()

 

3、运行调试

第一步:运行主程序

运行“main.py”程序,将Mind+放入画面中,Mind+随即被检测出并以绿色光点标记,轻轻移动后,依旧在画面中,同时,可以在屏幕上方看到标记特征点的数量。

 

image.png

 

4、程序解析

在上述的“main.py”文件中,我们主要通过opencv库来调用摄像头,获取实时视频流,然后借助计算机视觉中的lk homography算法来实现实时跟踪视频中的特征点,并在视频帧上画出这些特征点的运动轨迹,整体流程如下,

①初始化:程序启动时,会创建一个App类的实例,打开视频源,创建一个全屏窗口用于显示。

②主循环:程序进入一个无限循环,每次循环都会读取一帧视频,然后进行以下处理:

如果已经找到了初始特征点(即self.p0不为None),那么程序会使用Lucas-Kanade光流法跟踪这些特征点在当前帧中的位置,然后根据前后两帧特征点的位置找到单应性矩阵,然后用这个矩阵将初始帧映射到当前帧,形成一个叠加图像。

如果还没有找到初始特征点,那么程序会在当前帧中寻找好的特征点,并标记出来。

③用户交互:程序会检查用户的键盘输入,如果按下'a'键,那么程序会在当前帧中寻找好的特征点,作为初始特征点;如果按下'b'键,那么程序会切换是否使用RANSAC算法来计算单应性矩阵;如果按下'ESC'键,那么程序会退出。

④结束:当主循环结束时,程序会关闭所有的窗口,然后退出。

这个程序的主要目标是跟踪视频中的特征点,并通过找到前后两帧之间的单应性,实现对场景的稳定。这是通过在每一帧中跟踪特征点,然后使用这些特征点来计算单应性矩阵,然后用这个矩阵将初始帧映射到当前帧,形成叠加图像来实现的。

 

五、知识园地

1. 了解lk homography

"Lucas-Kanade" (LK) 和 "Homography" 是两个分别代表不同概念的术语,但在计算机视觉和图像处理中,它们常常被联合使用以实现特定的功能。

 

Lucas-Kanade (LK):

Lucas-Kanade (LK) 是一种光流估计算法。光流是空间运动物体在观察成像平面上的像素变化,它可以描述图像序列中的运动对象的运动。Lucas-Kanade方法是基于对局部像素窗口进行最小二乘拟合的方法。LK算法假设窗口内的所有像素都有相同的运动。在实际应用中,LK算法常常被用来跟踪视频中的特征点。

 

Homography:

Homography 是一个变换,它描述了两个平面之间的映射关系。在计算机视觉中,Homography常常被用于图像配准和透视变换等任务。对于两幅图像,如果我们知道它们之间的特征点对应关系,就可以计算出这两幅图像之间的Homography,然后用这个Homography把一幅图像映射到另一幅图像上。

当我们谈论 "LK Homography" 时,通常是指结合使用LK算法和Homography来实现某种功能,比如特征点跟踪和图像配准。具体来说,可以先用LK算法在视频序列中跟踪特征点,然后用这些特征点计算出前后帧之间的Homography,最后用这个Homography实现图像的配准或叠加。

评论

user-avatar