《opencv实用探索·二十》点追踪技术

前言:
在学习点追踪技术前需要先了解下光流发追踪目标,可以看上一章内容:光流法检测运动目标

如果以光流的方式追踪目标,基本上我们可以通过goodFeaturesToTrack函数计算一系列特征点,然后通过Lucas-Kanade算法进行一系列特征点的预测,并画出这些预测点的运动轨迹。点的追踪技术就是在这种方式基础上把goodFeaturesToTrack计算的一系列特征点换成一个我们选中的点进行追踪。

点追踪基本流程:
(1)采集一帧图像,用鼠标在图像上选择一个特征点,并使用cornerSubPix对特征点进行精细化调整
(2)循环采集下一帧图像,利用Lucas-Kanade光流法估计上一帧的特征点在下一帧中的位置
(3)保存估计的特征点在图像上进行追踪显示

需要用到的几个重要的函数:
cornerSubPix 是 OpenCV 中用于提高角点检测精度的函数之一。它用于在角点检测后对检测到的角点位置进行亚像素级别的精细化调整。

在角点检测过程中,通常使用诸如 goodFeaturesToTrack 等函数检测图像中的角点。这些函数可以找到可能是角点的位置,但它们的精度可能会受到像素级别的限制。cornerSubPix 的作用就是对这些检测到的角点位置进行进一步的精细化调整,使得角点的位置更加精确。

void cornerSubPix(InputArray image, InputOutputArray corners, Size winSize, Size zeroZone, TermCriteria criteria);

image:输入的灰度图像,用于角点精细化的操作。
corners:输入/输出参数,是一个 vector 或 Mat,包含需要精细化的角点的坐标。经过 cornerSubPix 处理后,这个数组中的角点坐标会被更新为更准确的位置。
winSize:搜索窗口的大小。这个参数定义了算法用于寻找角点的搜索范围。
zeroZone:定义了搜索区域的一些特殊的约束条件。
criteria:定义了终止条件,通常包括迭代的最大次数、精度等。
cornerSubPix 的工作原理是基于像素灰度值的梯度,它通过迭代优化来细化角点位置。这种亚像素级别的精细化可以提高角点检测的准确性,特别是在计算光流等计算中,有时候需要非常精确的角点位置信息。

对于cornerSubPix和calcOpticalFlowPyrLK,如果使用搜索窗口winSize怎么设置比较好?
winSize 参数的合适值取决于你正在处理的图像以及需要进行光流估计或特征跟踪的具体应用场景。这个值影响着光流算法或特征跟踪的准确性、计算效率和对运动变化的敏感度。
一般来说,winSize 的大小应该与你希望跟踪的特征尺度相匹配。以下是一些参考建议:
特征尺度大小:
对于小尺度的特征(如角点),选择一个相对较小的窗口大小可能更合适。这样可以更好地捕捉和跟踪这些特征的运动。
对于大尺度的特征(如纹理区域或物体),可能需要一个更大的窗口来更好地描述它们的运动。
运动速度和变化范围:
如果你处理的场景中物体的运动速度较快或者变化范围较大,可能需要一个更大的窗口来保证算法能够正确地捕捉到这些运动。
计算资源和实时性:
较大的窗口可能需要更多的计算资源,因此在资源受限或需要实时处理的情况下,可能需要权衡窗口大小和计算效率之间的关系。
一般情况下,使用较小的窗口大小可能对光流估计和特征跟踪有利,因为它们更灵敏,但也更容易受到图像噪声和局部变化的影响。同时,过小的窗口也可能限制了算法对大尺度运动的捕捉能力。
如果没有特定的规则来选择 winSize,可以通过实验和调整来找到最适合你的场景的值。通常,初始选择一个合理的默认值,然后通过观察跟踪结果和实际效果来进行调整。这个调整过程可能需要根据应用的具体情况进行多次迭代

calcOpticalFlowPyrLK函数已在上一章介绍过,这里不再赘述。

代码示例:


#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"

#include <iostream>
#include <ctype.h>

using namespace cv;
using namespace std;


Point2f point;
bool addRemovePt = false;

//--------------------------------【onMouse( )回调函数】------------------------------------
//		描述:鼠标操作回调
//-------------------------------------------------------------------------------------------------
static void onMouse(int event, int x, int y, int /*flags*/, void* /*param*/)
{
	if (event == EVENT_LBUTTONDOWN)
	{
		point = Point2f((float)x, (float)y);
		addRemovePt = true;
	}
}

//-----------------------------------【main( )函数】--------------------------------------------
//		描述:控制台应用程序的入口函数,我们的程序从这里开始
//-------------------------------------------------------------------------------------------------
int main(int argc, char** argv)
{

	VideoCapture cap;

	TermCriteria termcrit(TermCriteria::MAX_ITER | TermCriteria::EPS, 20, 0.03);
	Size winSize(31, 31);

	const int MAX_COUNT = 500;

	cap.open(0);

	if (!cap.isOpened())
	{
		cout << "Could not initialize capturing...\n";
		return 0;
	}

	namedWindow("LK Demo", 1);
	setMouseCallback("LK Demo", onMouse, 0);

	Mat image;
	Mat grayNow, grayPre;
	vector<Point2f> pointsPre;
	vector<Point2f> pointsNow;

	for (;;)
	{
		//采集下一帧图像
		Mat frame;
		cap >> frame;
		if (frame.empty())
			break;
		frame.copyTo(image);
		cvtColor(image, grayNow, COLOR_BGR2GRAY);

		if (!pointsPre.empty())
		{
			vector<uchar> status;
			vector<float> err;
			//Lucas-Kanade光流法运动估计(根据上一帧中选择的点进行估计,pointsNow存放的是估计下一帧grayNow图像中的特征点)
			//搜索窗口大小为 winSize(31, 31)
			//termcrit为迭代终止条件
			calcOpticalFlowPyrLK(grayPre, grayNow, pointsPre, pointsNow, status, err, winSize,
				3, termcrit, 0, 0.001);
			size_t i, k;
			for (i = k = 0; i < pointsNow.size(); i++)
			{
				//去除不好的预测点
				if (!status[i])
					continue;

				pointsNow[k++] = pointsNow[i];  //把好的特征点重新保存到pointsNow容器中
				circle(image, pointsNow[i], 3, Scalar(0, 255, 0), -1, 8);  //在图像上显示鼠标选的特征点
			}
			pointsNow.resize(k);  //修改容器长度为最新数据的长度
		}

		//每次鼠标在下一帧图像上选择一个点,先对选择点进行精细化调整在保存
		if (addRemovePt && pointsNow.size() < (size_t)MAX_COUNT)
		{
			//获取鼠标点击坐标
			vector<Point2f> tmp;
			tmp.push_back(point);
			//对下一帧图像中选择的点进行精细化调整
			cornerSubPix(grayNow, tmp, winSize, Size(-1, -1), termcrit);
			//保存精细化调整后的选择点
			pointsNow.push_back(tmp[0]);
			addRemovePt = false;
		}

		imshow("LK Demo", image);

		char c = (char)waitKey(10);

		//采集下一帧图像之前,把当前帧数据保存到上一帧容器中
		pointsPre = pointsNow;
		grayPre = grayNow.clone();
	}

	return 0;
}

效果显示:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/252278.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue3 setup语法糖写法基本教程

前言 官网地址&#xff1a;Vue.js - 渐进式 JavaScript 框架 | Vue.js (vuejs.org)下面只讲Vue3与Vue2有差异的地方&#xff0c;一些相同的地方我会忽略或者一笔带过与Vue3一同出来的还有Vite&#xff0c;但是现在不使用它&#xff0c;等以后会有单独的教程使用。目前仍旧使用v…

XXE漏洞 [NCTF2019]Fake XML cookbook1

打开题目 查看源代码 发现我们post传入的数据都被放到了doLogin.php下面 访问一下看看 提示加载外部xml实体 bp抓包一下看看 得到flag 或者这样 但是很明显这样是不行的&#xff0c;因为资源是在admin上&#xff0c;也就是用户名那里 PHP引用外部实体&#xff0c;常见的利用…

Explain工具-SQL性能优化

文章目录 SQL性能优化的目标Explain中type效率级别&#xff08;重要&#xff09;注意 Explain覆盖索引ExplainindexExplainfilesortExplainfilesort创建 idx_bd(b,d) SQL性能优化的目标 达到 range 级别 Explain中type效率级别&#xff08;重要&#xff09; 显示的是单位查询…

Ubuntu系统入门指南:基础操作和使用

Ubuntu系统的基础操作和使用 一、引言二、安装Ubuntu系统三、Ubuntu系统的基础操作3.1、界面介绍3.2、应用程序的安装和卸载3.3、文件管理3.4、系统设置 四、Ubuntu系统的日常使用4.1、使用软件中心4.2、浏览器的使用和网络连接设置4.3、邮件客户端的配置和使用4.4、文件备份和…

【上海大学数字逻辑实验报告】七、中规模元件及综合设计

一、实验目的 掌握中规模时序元件的测试。学会在Quartus II上设计序列发生器。 二、实验原理 74LS161是四位可预置数二进制加计数器&#xff0c;采用16引脚双列直插式封装的中规模集成电路&#xff0c;其外形如下图所示&#xff1a; 其各引脚功能为&#xff1a; 异步复位输…

我的世界指令大全

不知道我的世界指令大全&#xff1f;我的世界玩家我的世界指令大全&#xff0c;在下面的攻略中就为小伙伴们带来了我的世界指令大全。不知道我的世界指令大全的玩家们那就继续看下去这篇攻略吧。 1./summon&#xff1a;召唤实体。 2./give&#xff1a;给予玩家物品。 3./tp&a…

Epic 安装失败,错误代码SUPQR1612,必要的先决条件安装失败,弹窗CD-ROM

错误记录 并且弹出来这个窗口the feature you are trying to use is on a CD-ROM or other removable disk that is not available. 让我寻找这个msi文件 正在想办法解决 如果有人能解决 麻烦告知评论区&#xff01;

Nginx编译安装+Nginx模块详解+Nginx虚拟主机(新版)

Nginx编译安装Nginx模块详解Nginx虚拟主机 Nginx编译安装Nginx模块详解Nginx虚拟主机一、编译安装Nginx服务二、nginx版本升级1、nginx平滑升级的步骤2、示例 三、添加Nginx系统服务1、使用init.d脚本2、使用 systemd 服务配置 四、认识Nginx服务的主配置文件 nginx.conf1、全局…

为什么Apache Doris适合做大数据的复杂计算,MySQL不适合?

为什么Apache Doris适合做大数据的复杂计算&#xff0c;MySQL不适合&#xff1f; 一、背景说明二、DB架构差异三、数据结构差异四、存储结构差异五、总结 一、背景说明 经常有小伙伴发出这类直击灵魂的疑问&#xff1a; Q&#xff1a;“为什么Apache Doris适合做大数据的复杂计…

819. 最常见的单词

819. 最常见的单词 Java&#xff1a;split() 过滤 class Solution {public String mostCommonWord(String paragraph, String[] banned) {String s paragraph.replaceAll("\\p{Punct}", " "); // 去除所有标点符号String arr[] s.split(" "…

OpenCV开发:MacOS源码编译opencv,生成支持java、python、c++各版本依赖库

OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个开源的计算机视觉和机器学习软件库。它为开发者提供了丰富的工具和函数&#xff0c;用于处理图像和视频数据&#xff0c;以及执行各种计算机视觉任务。 以下是 OpenCV 的一些主要特点和功能&#xff…

Apache Flume(3):数据持久化

1 使用组件 File Channel 2 属性设置 属性名默认值说明type-filecheckpointDir~/.flume/file-channel/checkpoint检查点文件存放路径dataDirs~/.flume/file-channel/data日志存储路径&#xff0c;多个路径使用逗号分隔. 使用不同的磁盘上的多个路径能提高file channel的性能 …

74hc244驱动数码管显示电路及程序

把七或八只发光二极管组合在一个模件上组成了个8字和小数点&#xff0c;用以显示数字。为了减少管脚&#xff0c;把各个发光管的其中同一个极接在一起作为共用点&#xff0c;因此就产生了共阳极和共阴极数码之说。共阳管就是把各个发光管的正极接在一起&#xff0c;而共阴管就刚…

PMI相关证书的获取步骤及注意内容

近几年很多行业的从业人员都在考取PMI项目管理相关证书&#xff0c;可在中国大陆地区参加考试的认证主要有&#xff1a;PMP, PgMP, PMI-RMP, PMI-ACP, PMI-PBA, CAPM。PfMP, PMI-SP尚未在中国大陆地区开放考试。 现整理该类证书的相关获取步骤及注意内容 一、证书获取步骤 S…

SOLIDWORKS编码重命名批量完成原来这么简单

每个公司都有自己的编码规则及命名规则&#xff0c;因此新产品设计完成之后&#xff0c;都需要对新设计的零部件进行重新编码及命名&#xff0c;今天我们来介绍一款提高编码及命名效率的插件—SolidKits.BatchCoding。 SolidKits.BatchCoding批量编码器是对于PDM的SolidKits分…

活动 | Mint Blockchain 将于 2024 年 1 月 10 号启动 MintPass 限时铸造活动

MintPass 是由 Mint Blockchain 官方发行的 Mint 网络和社区的 NFT 通行证&#xff0c;将在 2024 年 1 月份启动限时铸造活动。今天这篇文章会着重向大家介绍即将举办的 MintPass 活动的基础信息。 MintPass 有 2 种类型&#xff1a; 类型 1&#xff1a;Mint Genesis NFT Mint…

栈(C语言版)

一.栈的概念及结构 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。 进行数据插入和删除操作的一端 称为栈顶&#xff0c;另一端称为栈底。 栈中的数据元素遵守 后进先出 LIFO &#xff08; Last In First Out &#xff09;的原则。…

人工智能导论复习资料

题型 1、简答题&#xff08;5题&#xff09; 2、设计题 3、综合题 4、论述题&#xff08;10分&#xff09; 考点 第一章 1、人工智能的定义、发展&#xff1b; 2、人工智能的学派、认知观及其间的关系&#xff1b; 3、人工智能要素及系统分类&#xff1b; 4、人工智能的研究、…

下午好~ 我的论文【CV边角料】(第三期)

文章目录 CV边角料Pixel ShuffleSENetCBAMGlobal Context Block (GC)Criss-Cross Attention modules (CC) CV边角料 Pixel Shuffle Real-Time Single Image and Video Super-Resolution Using an Efficient Sub-Pixel Convolutional Neural Network pixelshuffle算法的实现流…

八大排序——快速排序(霍尔 | 挖空 | 前后指针 | 非递归)

我们今天来讲讲八大排序中的快速排序&#xff0c;快速排序最明显的特点就是排序快&#xff0c;时间复杂度是O&#xff08;N* logN&#xff09;&#xff0c;但是坏处就是如果排序的是一个逆序的数组的时候&#xff0c;时间复杂度是O&#xff08;N^2&#xff09;,还不用我们的插入…