OpenCV之GOTURN目标追踪

news2025/5/25 16:00:54
  • 💂 个人主页:风间琉璃
  • 🤟 版权: 本文由【风间琉璃】原创、在CSDN首发、需要转载请联系博主
  • 💬 如果文章对你有帮助、欢迎关注、点赞、收藏(一键三连)订阅专栏

目录

前言

一、goturn简介

二、预处理

三、模型加载

四、执行推理

五、解析输出


前言

GOTURN(Generic Object Tracking Using Regression Networks)是一种用于目标跟踪的计算机视觉算法,它使用回归神经网络来实现实时目标跟踪。GOTURN的目标是通过检测并跟踪特定物体,使其能够在视频序列中保持物体的连续性,即使物体发生尺寸变化、遮挡或平移。达到了Tracking中效果上的state-of-the-art,尤其在检测速度上达到了100FPS(第一个达到100FPS的深度学习方法)。

一、goturn简介

goturn整个算法的框架其实非常简单:输入当前帧和前一帧进入网络,输出当前帧bounding-box的位置。

以前一帧的目标区域为中心扩展,并crop出来。也就是说:在第t−1帧,Tracker预测的bounding-box位置为c=(cx,xy),宽和高分别为w,h,crop出来的框大小为k1*w,k1*h,k1决定接受多少背景信息。

对于当前帧,也就是第t帧,基于上一帧的位置,找到待搜寻目标的区域,即search region,网络的目的就是要回归目标在当前search region中的location。这里设置search region的中心坐标为c'=(cx',xy')=c,和前一帧框出来的区域是一样的,search region的大小为k2*w,k2*ℎ,w,ℎ是第t−1帧bounding-box的大小,设置k1=k2=2,对于快速移动的目标,k1,k2就需要增大了。

网络结构:

在当前帧和前一帧分别crop出region之后,送入网络进行feature extraction(CaffeNet的卷积层),将这些feature级联并输入fully-connected层,fc层的目的是为了比较object的特征和当前帧的特征,以找到object被移动到了哪里。fc层学习到的是一个复杂的特征比较函数,输出目标的相对运动。

随后fc层的输出被连接到一个4节点的层(分别代表bounding-box两个角的坐标),以输出object的位置。

二、预处理

图像预处理:对目标区域和搜索区域进行了预处理,包括调整大小和减去均值。这里因为是对视频流操作,因此需要对每一帧图像都进行预处理。

//图像预处理:调整尺寸和减去均值
resize(targetPatch, targetPatch, Size(width, height));
resize(searchPatch, searchPatch, Size(width, height));

targetPatch = targetPatch - meanval;
searchPatch = searchPatch - meanval;

//转换为浮点数
targetPatch.convertTo(targetPatch, CV_32F);
searchPatch.convertTo(searchPatch, CV_32F);

Mat targetBlob = blobFromImage(targetPatch);
Mat searchBlob = blobFromImage(searchPatch);

三、模型加载

数据预处理之后,就可以加载模型进行预测了。

//加载网络模型
net = readNetFromCaffe(goturn_config, goturn_model);

四、执行推理

这里使用了cuda进行加速处理,如果没有cuda,注释即可。

net.setInput(targetBlob, "data1");
net.setInput(searchBlob, "data2");

//使用cuda加速
net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);
net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA_FP16);

Mat res = net.forward("scale");
Mat resMat = res.reshape(1, 1);

五、解析输出

网络预测结果存储在res中,我们需要对其进行分析获取我们想要的数据,我们得到的是bounding-box两个对角的坐标。

curBB.x = targetPatchRect.x + (resMat.at<float>(0) * targetPatchRect.width / width) - targetPatchRect.width;
curBB.y = targetPatchRect.y + (resMat.at<float>(1) * targetPatchRect.height / height) - targetPatchRect.height;
curBB.width = (resMat.at<float>(2) - resMat.at<float>(0)) * targetPatchRect.width / width;
curBB.height = (resMat.at<float>(3) - resMat.at<float>(1)) * targetPatchRect.height / height;

if (curBB.width > 300)
	curBB.width = curBB.width / 4;
if (curBB.height > 300)
	curBB.height = curBB.height / 4;

//Predicted BB
Rect boundingBox = curBB;

最后的判断是由于不知道为什么在使用cuda进行加速时,到最后预测框会越来越大,帧率越来越低,只能强制限制范围,追踪效果改善了不少。如果觉得多余也可以注释。

运行结果:在视频开始前需要用鼠标在视频中确定追踪的目标,然后按下空格或者enter进行追踪。

1694681842016

源码:下载:OpenCVGoturn目标追踪资源-CSDN文库

// Goturn_Object_Track.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
#include <opencv2/highgui/highgui_c.h>


using namespace cv;
using namespace cv::dnn;
using namespace std;

String  goturn_model = "F:/data/CQU/VS/Goturn_Object_Track/goturn.caffemodel";
String goturn_config = "F:/data/CQU/VS/Goturn_Object_Track/goturn.prototxt";


Net net;
//当前帧和前一帧
Mat frame, prevFrame;
//前一帧的bounding-box的坐标
Rect prevBB;


//追踪物体矩形框
Rect trackObjects(Mat& frame, Mat& prevFrame)
{
	Rect rect;
	int width = 227;  //输入图像宽
	int height = 227; //输入图像高
	int meanval = 128;

	//思路:使用前一帧和前一帧的前一帧的bounding-box的坐标以及当前帧计算预测当前帧的bounding-box坐标
	Mat curFrame = frame.clone();
	//要预测输出的当前一帧的前一帧的bounding-box的坐标
	Rect2d curBB;

	float padTargetPatch = 2.0;
	Rect2f searchPatchRect, targetPatchRect;
	Point2f currCenter, prevCenter;
	Mat prevFramePadded, curFramePadded;
	Mat searchPatch, targetPatch;

	//前一帧bounding-box中心坐标
	prevCenter.x = (float)(prevBB.x + prevBB.width / 2);
	prevCenter.y = (float)(prevBB.y + prevBB.height / 2);

	targetPatchRect.width = (float)(prevBB.width * padTargetPatch);
	targetPatchRect.height = (float)(prevBB.height * padTargetPatch);
	targetPatchRect.x = (float)(prevCenter.x - prevBB.width * padTargetPatch / 2.0 + targetPatchRect.width);
	targetPatchRect.y = (float)(prevCenter.y - prevBB.height * padTargetPatch / 2.0 + targetPatchRect.height);

	copyMakeBorder(prevFrame, prevFramePadded, (int)targetPatchRect.height, (int)targetPatchRect.height, (int)targetPatchRect.width, (int)targetPatchRect.width, BORDER_REPLICATE);
	targetPatch = prevFramePadded(targetPatchRect).clone();

	copyMakeBorder(curFrame, curFramePadded, (int)targetPatchRect.height, (int)targetPatchRect.height, (int)targetPatchRect.width, (int)targetPatchRect.width, BORDER_REPLICATE);
	searchPatch = curFramePadded(targetPatchRect).clone();

	//图像预处理:调整尺寸和减去均值
	resize(targetPatch, targetPatch, Size(width, height));
	resize(searchPatch, searchPatch, Size(width, height));

	targetPatch = targetPatch - meanval;
	searchPatch = searchPatch - meanval;

	//转换为浮点数
	targetPatch.convertTo(targetPatch, CV_32F);
	searchPatch.convertTo(searchPatch, CV_32F);

	Mat targetBlob = blobFromImage(targetPatch);
	Mat searchBlob = blobFromImage(searchPatch);

	net.setInput(targetBlob, "data1");
	net.setInput(searchBlob, "data2");

	//使用cuda加速
	net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);
	net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA_FP16);

	Mat res = net.forward("scale");
	Mat resMat = res.reshape(1, 1);

	//printf("width : %d, height : %d\n", (resMat.at<float>(2) - resMat.at<float>(0)), (resMat.at<float>(3) - resMat.at<float>(1)));

	curBB.x = targetPatchRect.x + (resMat.at<float>(0) * targetPatchRect.width / width) - targetPatchRect.width;
	curBB.y = targetPatchRect.y + (resMat.at<float>(1) * targetPatchRect.height / height) - targetPatchRect.height;
	curBB.width = (resMat.at<float>(2) - resMat.at<float>(0)) * targetPatchRect.width / width;
	curBB.height = (resMat.at<float>(3) - resMat.at<float>(1)) * targetPatchRect.height / height;

	if (curBB.width > 300)
		curBB.width = curBB.width / 4;
	if (curBB.height > 300)
		curBB.height = curBB.height / 4;

	//Predicted BB
	Rect boundingBox = curBB;
	return boundingBox;
}


int main()
{
	//打开视频
	VideoCapture capture("cap.mp4");
	capture.read(frame);
	//加载网络模型
	net = readNetFromCaffe(goturn_config, goturn_model);
	

	frame.copyTo(prevFrame);
	//选取感兴趣区域
	prevBB = selectROI(frame, true, true);
	namedWindow("frame", CV_WINDOW_AUTOSIZE);
	//读取视频每一帧,并预测
	while(capture.read(frame)) 
	{
	
		//获得当前系统的计时间周期数,求FPS
		double t = (double)getTickCount();

		//预测
		Rect currentBB = trackObjects(frame, prevFrame);
		rectangle(frame, currentBB, Scalar(0, 255, 0), 2, 8, 0);

		// 准备下一帧
		frame.copyTo(prevFrame);
		prevBB.x = currentBB.x;
		prevBB.y = currentBB.y;
		prevBB.width = currentBB.width;
		prevBB.height = currentBB.height;

		//FPS计算
		t = ((double)getTickCount() - t) / getTickFrequency();//求输入帧后经过的周期数/每秒系统计的周期数=一帧用时多少秒
		int fps = 1.0 / t;//求倒数得到每秒经过多少帧,即帧率
		string text = "FPS:" + to_string(fps);
		cv::putText(frame, text, Point(10, 50), FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 0), 2, 8, 0);


		imshow("frame", frame);
		char c = waitKey(5);
		if(c == 27) 
		{
			break;
		}
	}	
	return 0;
}

结束语
感谢你观看我的文章呐~本次航班到这里就结束啦 🛬

希望本篇文章有对你带来帮助 🎉,有学习到一点知识~

躲起来的星星🍥也在努力发光,你也要努力加油(让我们一起努力叭)。

最后,博主要一下你们的三连呀(点赞、评论、收藏),不要钱的还是可以搞一搞的嘛~

不知道评论啥的,即使扣个666也是对博主的鼓舞吖 💞 感谢 💐

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

干洗店洗鞋店小程序家政保洁带商城一体化系统开发

干洗店洗鞋店小程序家政保洁带商城一体化系统开发&#xff1b; 一、核心功能介绍 1.(支持上门取送、送货到店、寄存网点、智能衣柜四种下单方式) 用户下单-上门取货拍照-送达门店工厂-入厂拍照-清洗完成拍照-上挂物品柜-物品送回 2.骑手端(接单上门、取货拍照&#xff0c;入库拍…

Can‘t load the model for ‘stabilityai/sd-vae-ft-mse‘

Can’t load the model for ‘stabilityai/sd-vae-ft-mse’. If you were trying to load it from ‘https://huggingface.co/models’, make sure you don’t have a local directory with the same name. Otherwise, make sure ‘stabilityai/sd-vae-ft-mse’ is the correct…

亚马逊两款毛绒玩具被紧急召回,毛绒玩具CPC认证办理(红色熊猫毛绒玩具和绿头鸭毛绒玩具)

近日&#xff0c;爱尔兰竞争和消费者保护委员会&#xff08;CCPC&#xff09;对在亚马逊上热卖的两款儿童毛绒玩具实施了召回&#xff0c;原因是存在窒息风险。 Wild Republic红色熊猫毛绒玩具 CCPC在公告中称&#xff1a;“在使用时&#xff0c;熊猫上的小部件&#xff08;眼…

第20章_瑞萨MCU零基础入门系列教程之DAC输出模拟信号

本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写&#xff0c;需要的同学可以在这里获取&#xff1a; https://item.taobao.com/item.htm?id728461040949 配套资料获取&#xff1a;https://renesas-docs.100ask.net 瑞萨MCU零基础入门系列教程汇总&#xff1a; ht…

算法分析与设计编程题 递归与分治策略

棋盘覆盖 题目描述 解题代码 // para: 棋盘&#xff0c;行偏移&#xff0c;列偏移&#xff0c;特殊行&#xff0c;特殊列 void dividedCovering(vector<vector<int>>& chessBoard, int dr, int dc, int sr, int sc, int size) {if (size 1) return;size / 2…

vueshowpdf 移动端pdf文件预览

1、安装 npm install vueshowpdf -S2、参数 属性说明类型默认值v-model是否显示pdf--pdfurlpdf的文件地址String- scale 默认放大倍数 Number1.2 minscale 最小放大倍数 Number0.8 maxscale 最大放大倍数 Number2 3、事件 名称说明回调参数closepdf pdf关闭事件-pdferr文…

图的基本知识

图 一、图的定义和基本术语二、图的存储结构&#xff08;1&#xff09;数组&#xff08;邻接矩阵表示法&#xff09;&#xff08;2&#xff09;数组&#xff08;邻接矩阵&#xff09;的实现&#xff08;3&#xff09;邻接表&#xff08;链式表示法&#xff09;&#xff08;4&am…

6、如何将 Flink 中的数据写入到外部系统(文件、MySQL、Kafka)

目录 1、如何查询官网 2、Flink数据写入到文件 3、Flink数据写入到Kafka 4、Flink数据写入到MySQL 1、如何查询官网 官网链接&#xff1a;官网 2、Flink数据写入到文件 传送门&#xff1a;Flink数据写入到文件 3、Flink数据写入到Kafka 传送门&#xff1a;Flink数据写入…

2023-9-14 最长公共子序列

题目链接&#xff1a;最长公共子序列 #include <iostream> #include <algorithm>using namespace std;const int N 1010;int n, m; char a[N], b[N]; int f[N][N];int main() {cin >> n >> m;cin >> a 1 >> b 1;for(int i 1; i < n…

30WSIP网络音柱

SV-7042VP 30WSIP网络音柱 一、描述 SV-7042VP是我司的一款SIP网络音柱&#xff0c;具有10/100M以太网接口&#xff0c;将网络音源通过自带的功放和喇叭输出播放&#xff0c;可达到功率30W。SV-7042VP作为SIP系统的播放终端&#xff0c;可用于需要广播播放的场所&#xff0c;…

用node开发微信群聊机器人第③章

▍PART 序 怎么https请求第三方api 有哪些免费的、付费的第三方api 记得先去看前几章&#xff0c;看明白了再来看本章&#xff0c;不然你会一脸懵。点合集》#程序员干货 记得先把小程序加个收藏不然等下你要调试的时候找不到》“程序员实用资源” ▍PART 正文 来&#xff…

NeuroFlash:AI文章写作与生成工具

【产品介绍 ​ 】 名称 NeuroFlash 上线时间 2015 具体描述 Neuroflash是一款基于人工智能的文本和图像生成器&#xff0c;可以帮助用户快速创建高质量的内容。Neuroflash拥有超过100种短文和长文的文本类型&#xff0c;涵盖了各种营销场景和需求。只需要输入简单的指示&#…

定时任务框架-xxljob

1.定时任务 spring传统的定时任务Scheduled&#xff0c;但是这样存在这一些问题 &#xff1a; 做集群任务的重复执行问题 cron表达式定义在代码之中&#xff0c;修改不方便 定时任务失败了&#xff0c;无法重试也没有统计 如果任务量过大&#xff0c;不能有效的分片执行 …

stackqueuepriority_queue

目录 一、容器适配器 二、deque 1、deque的相关函数 2、关于deque 3、deque的底层实现 4、deque的设计缺陷 5、结论 三、stack 1、stack的相关函数 2、stack相关函数使用 3、stack模拟实现 四、queue 1、queue的相关函数 2、queue相关函数使用 3、queue的模拟实…

2023-9-14 数字三角形

题目链接&#xff1a;数字三角形 #include <iostream> #include <algorithm>using namespace std;const int N 510, INF 1e9;int n; int a[N][N]; int f[N][N];int main() {cin >> n;for(int i 1; i < n; i )for(int j 1; j < i; j )cin >> …

书剑宠物疫苗接种管理软件操作教程

【软件简介】 书剑宠物疫苗接种管理软件是一款宠物疫苗接种管理的工具&#xff0c;适合宠物诊所使用。具有动物主人建档、宠物疫苗接种登记管理、每日提醒、打印疫苗接种通知卡、自定义短信提醒模板等完善的功能。 另外本软件的特色是同时具有手机网页版功能&#xff0c;手机…

全球十大优质炒黄金交易APP平台排名(信息汇总)

由于近些年全球通货膨胀高企&#xff0c;炒黄金交易平台越来越受到人们的关注。然而&#xff0c;如何在众多的平台中选择适合自己的平台&#xff0c;却是一个值得思考的问题。 随着移动互联网的快速发展&#xff0c;越来越多的投资者更倾向于通过手机APP来炒黄金。本文将为大…

Contents:帮助公司为营销目的创建内容

【产品介绍】 名称 Contents上线时间 2017年5月 具体描述 Contents是一家提供基于人工智能的内容生成平台的企业&#xff0c;可以帮助用户在各种网站和工具中使用最先进的机器学习模型&#xff0c;实现视频编辑、图像生成、3D建模等内容创作。【团队介绍…

“掌握技巧,轻松调整视频时长:打造完美短视频分享“

在今天的高速信息时代&#xff0c;视频已成为我们传递信息和娱乐的主要方式之一。但有时候&#xff0c;视频的时长可能会超出我们的预期&#xff0c;或者我们希望在特定的时间内呈现内容。那么&#xff0c;如何调整视频的时长呢&#xff1f;下面&#xff0c;我们将分享几种简单…

聚精品,通全球 2024中国(杭州)国际电商物流包装产业展览会四月隆重开幕

2024中国&#xff08;杭州&#xff09;国际电商物流包装产业展览会 2024年4月12-14日 | 杭州国际博览中心 同期举办&#xff1a;2024长三角快递物流供应链与技术装备展览会&#xff08;杭州&#xff09; 2024中国&#xff08;杭州&#xff09;国际数字物流技术与应用展览会 展会…