无人机光流定位系列——(二)实践

本文介绍在龙板410c上使用Python实现Lucas-Kanade光流算法进行目标跟踪的方法。文章详细展示了如何利用OpenCV库中的cv2.calcOpticalFlowPyrLK函数进行光流计算,并提供了关键代码片段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      在本系列blog中的http://blog.youkuaiyun.com/andymfc/article/details/53316404文章中,已经对光流定位的原理进行了详细的分析,详细介绍了著名的lucas-kanade光流算法,本期,将带大家一起在dragonboard 410c上来用Python编程实现光流算法,虽然Python语言编写出来的处理效率不高,但是便于我们理解整个光流算法应用方法,并且后续我们使用C或者其他高效率的语言来实现光流算法会变得更简单。

     在实现光流分析的过程中,我们使用cv2模块提供的算法接口来实现光流计算,在cv2中也就是opencv提供的Python接口,lucas-kanade算法被封装在cv2.calcOpticalFlowPyrLK()函数中,通过该接口可以方便的创建光流处理程序。但是在实现中我们首先要确定我们要跟踪的点,然后才能使用lucas-kanade算法来对这些点进行迭代跟踪,接下来参考cv2中提供的Python例程代码详细介绍利用cv2提供的光流计算处理函数接口如何完成基于光流的跟踪实现,其核心代码如下:

     首先为了方便调用cv2.calcOpticalFlowPyrLK算法,我们需要定义一个算法参数结构体,确定算法参数,用Python定义如下:

     lk_params = dict( winSize  = (15, 15), 
                  maxLevel = 2, 
                  criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03),
                  derivLambda = 0.0 )  

     同时在调用cv2.calcOpticalFlowPyrLK算法的时候我们还需要调用cv2.goodFeatureToTrack函数来确定需要跟踪的点,所以还需要给该接口传递一个参数,具体定义如下:

     feature_params = dict( maxCorners = 500, 
                       qualityLevel = 0.3,
                       minDistance = 7,
                       blockSize = 7 )

     完成参数定义后,就可以开始编写核心代码了,这里我们在读取视频帧的时候,根据前文的分析可以知道,光流算法需要依靠前后帧的数据来进行分析,所以在读取视频第一帧的时候,我们还需要在第0帧的时候进行初始化处理,这里使用便利frame_idx和detect_interval两个参数来进行控制,对第一帧进行处理,其中前者为帧数,后者为检测间隔,在这里初始化处理主要是需要找到适合跟踪的点,具体代码如下:

     if self.frame_idx % self.detect_interval == 0:
                mask = np.zeros_like(frame_gray)
                mask[:] = 255
                for x, y in [np.int32(tr[-1]) for tr in self.tracks]:
                    cv2.circle(mask, (x, y), 5, 0, -1)
                p = cv2.goodFeaturesToTrack(frame_gray, mask = mask, **feature_params)
                if p is not None:
                    for x, y in np.float32(p).reshape(-1, 2):
                        self.tracks.append([(x, y)])

    完成第一帧处理后,就需要进一步对后续帧进行处理,这里处理其实就是一个循环迭代的过程,不断的根据前后帧来执行光流算法,调用cv2calcOpticalFlowPyrLK函数来计算光流数据,这里通过tracks参数来进行控制,核心代码如下:

     if len(self.tracks) > 0:
                img0, img1 = self.prev_gray, frame_gray
                p0 = np.float32([tr[-1] for tr in self.tracks]).reshape(-1, 1, 2)
                p1, st, err = cv2.calcOpticalFlowPyrLK(img0, img1, p0, None, **lk_params)
                p0r, st, err = cv2.calcOpticalFlowPyrLK(img1, img0, p1, None, **lk_params)
                d = abs(p0-p0r).reshape(-1, 2).max(-1)
                good = d < 1
                new_tracks = []
                for tr, (x, y), good_flag in zip(self.tracks, p1.reshape(-1, 2), good):
                    if not good_flag:
                        continue
                    tr.append((x, y))
                    if len(tr) > self.track_len:
                        del tr[0]
                    new_tracks.append(tr)
                    cv2.circle(vis, (x, y), 2, (0, 255, 0), -1)
                self.tracks = new_tracks
                cv2.polylines(vis, [np.int32(tr) for tr in self.tracks], False, (0, 255, 0))
                draw_str(vis, (20, 20), 'track count: %d' % len(self.tracks)) 

     以上就是整个光流算法进行点跟踪的处理核心过程,完整代码可以参考

     在dragonboard 410c开发板上搭好鼠标键盘和显示器,我们就可以使用该脚本在上面运行测试了,具体效果如下:

     

     下期blog,将在该代码的基础上,进一步实现如何利用光流法来对运动的目标进行跟踪。

### 无人机流定位技术概述 #### 流定位的基本概念 流定位是一种基于计算机视觉的技术,用于估计物体在场景中的运动。它通过分析连续帧之间的像素位移来计算相机或目标的相对运动[^1]。这种技术广泛应用于无人机领域,尤其是在缺乏全球导航卫星系统(GNSS)信号的情况下,例如室内环境。 #### 室内定位的应用背景 流定位特别适合于室内的无人机应用。由于室内环境中通常无法接收到GPS信号,因此需要依赖其他传感器完成精确定位。流定位通过摄像头捕捉地面纹理的变化并进行图像处理,从而推算出无人机的位置和姿态信息[^2]。 #### 技术实现的核心环节 模块的工作程可以分为以下几个方面: - **图像采集**:利用安装在无人机底部的摄像头持续拍摄地面图像。 - **数据传输**:将捕获的图像发送至主控制器进行进一步处理。 - **算法运算**:采用特定的算法对图像序列进行分析,提取特征点及其位移向量。 - **结果输出**:经过处理的数据最终被传递给飞行控制系统,以便调整无人机的姿态和轨迹[^3]。 #### 常见误差校正机制 尽管流定位能够提供较高的精度,但在某些情况下仍可能出现偏差。例如当无人机仅发生轻微振动而非真实平移时,可能会错误地报告存在速度分量。针对这种情况,可以通过融合惯性测量单元(IMU)或其他辅助传感手段来进行补偿,消除虚假的速度读数[^4]。 ```python import cv2 import numpy as np def calculate_optical_flow(prev_frame, curr_frame): """ 计算两幅图像间的场 参数: prev_frame (numpy.ndarray): 上一帧灰度图 curr_frame (numpy.ndarray): 当前帧灰度图 返回: flow (numpy.ndarray): 向量场 """ # 使用OpenCV库中的Dense Optical Flow方法Lucas-Kanade flow = cv2.calcOpticalFlowFarneback( prev_frame, curr_frame, None, pyr_scale=0.5, levels=3, winsize=15, iterations=3, poly_n=5, poly_sigma=1.2, flags=cv2.OPTFLOW_FARNEBACK_GAUSSIAN ) return flow ``` 上述代码片段展示了如何使用Python结合OpenCV库实现基本的密集型计算功能。此函数接收前后两个时间戳对应的灰度图片作为输入参数,并返回描述两者之间像素对应关系的结果矩阵。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值