直线追踪

news2024/12/24 3:27:35

由于项目的需要,最近在做一个直线追踪的东西,但是网上的代码关于车道线或者别的什么之类的直线追踪的代码只是提了一下,相关的代码并不是公开的,所以自己写了一些直线追踪的代码。

代码使用的是kalman滤波进行直线追踪,当然这个代码是实验代码,现在已经可以调试成功了,进行一下记录。

kalman_lanes.h:我这里只写了一个函数,直接将将这个函数进行一个引入便可以

#pragma once
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <vector>


using namespace cv;
using namespace std;


void kalman_line(VideoCapture video, Mat frame, vector<Vec2f> lines, float slope, float intercept);

kalman_lanes.cpp:函数的实现

#include "kalman_lines.h"
#include <vector>

using namespace std;

void kalman_line(VideoCapture video, Mat frame, vector<Vec2f> lines, float slope, float intercept)
{
	// 创建Kalman滤波器对象
	KalmanFilter kf(4, 2, 0);
	Mat state(4, 1, CV_32F);  // x, y, vx, vy
	Mat measurement = Mat::zeros(2, 1, CV_32F);  // mx, my

	// 设置Kalman滤波器初始状态
	kf.transitionMatrix = (Mat_<float>(4, 4) << 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1);
	setIdentity(kf.measurementMatrix);
	setIdentity(kf.processNoiseCov, Scalar::all(1e-4));
	setIdentity(kf.measurementNoiseCov, Scalar::all(1e-1));
	setIdentity(kf.errorCovPost, Scalar::all(1));

	
	// 选择特定斜率与截距的直线进行追踪
	



	for (size_t i = 0; i < lines.size(); i++)
	{
		float rho = lines[i][0];
		float theta = lines[i][1];

		if (abs(theta) < CV_PI / 4 || abs(theta - CV_PI / 2) < CV_PI / 4)
		{
			float a = cos(theta);
			float b = sin(theta);
			float x0 = a * rho;
			float y0 = b * rho;

			Point pt1(cvRound(x0 + 1000 * (-b)), cvRound(y0 + 1000 * (a)));
			Point pt2(cvRound(x0 - 1000 * (-b)), cvRound(y0 - 1000 * (a)));

			float current_slope = (pt2.y - pt1.y) / (float)(pt2.x - pt1.x);
			float current_intercept = pt1.y - current_slope * pt1.x;

			if (abs(current_slope - slope) < 0.2 && abs(current_intercept - intercept) < 100)
			{
				slope = current_slope;
				intercept = current_intercept;

				// 更新Kalman滤波器初始状态
				state.at<float>(0) = intercept;
				state.at<float>(1) = slope;
				kf.statePre.at<float>(0) = intercept;
				kf.statePre.at<float>(1) = slope;
			}
		}
	}
	Mat gray, edges;
	// 视频帧循环处理
	while (true)
	{
		// 读取下一帧图像
		video >> frame;

		// 检查是否到达视频末尾
		if (frame.empty())
			break;

		// 预测下一状态
		Mat prediction = kf.predict();

		// 提取当前帧直线
		cvtColor(frame, gray, COLOR_BGR2GRAY);
		Canny(gray, edges, 50, 150, 3);

		std::vector<Vec2f> lines;
		HoughLines(edges, lines, 1, CV_PI / 180, 100);


		// 选择最接近预测斜率与截距的直线进行追踪
		float min_distance = FLT_MAX;
		float closest_slope = 0.0;
		float closest_intercept = 0.0;


		for (size_t i = 0; i < lines.size(); i++)
		{
			float rho = lines[i][0];
			float theta = lines[i][1];

			if (abs(theta) < CV_PI / 4 || abs(theta - CV_PI / 2) < CV_PI / 4)
			{
				float a = cos(theta);
				float b = sin(theta);
				float x0 = a * rho;
				float y0 = b * rho;

				Point pt1(cvRound(x0 + 1000 * (-b)), cvRound(y0 + 1000 * (a)));
				Point pt2(cvRound(x0 - 1000 * (-b)), cvRound(y0 - 1000 * (a)));

				float current_slope = (pt2.y - pt1.y) / (float)(pt2.x - pt1.x);
				float current_intercept = pt1.y - current_slope * pt1.x;

				float distance = sqrt(pow(current_slope - prediction.at<float>(1), 2) + pow(current_intercept - prediction.at<float>(0), 2));

				if (distance < min_distance)
				{
					min_distance = distance;
					closest_slope = current_slope;
					closest_intercept = current_intercept;
				}
			}
		}

		// 更新Kalman滤波器状态
		Mat measurement(2, 1, CV_32F);
		measurement.at<float>(0) = closest_intercept;
		measurement.at<float>(1) = closest_slope;
		kf.correct(measurement);

		// 绘制预测线和测量线
		float slope_pred = kf.statePost.at<float>(1);
		float intercept_pred = kf.statePost.at<float>(0);
		float slope_meas = closest_slope;
		float intercept_meas = closest_intercept;

		Point pt1_pred(0, intercept_pred);
		Point pt2_pred(frame.cols, slope_pred * frame.cols + intercept_pred);
		Point pt1_meas(0, intercept_meas);
		Point pt2_meas(frame.cols, slope_meas * frame.cols + intercept_meas);

		line(frame, pt1_pred, pt2_pred, Scalar(0, 255, 0), 2);
		line(frame, pt1_meas, pt2_meas, Scalar(0, 0, 255), 2);

		imshow("Video", frame);

		// 检测键盘按下
		if (waitKey(30) == 27)
		{
			break;
		}
	}
}

main主函数:

#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#include "kalman_lines.h"

using namespace cv;

int main()
{
	// 打开视频文件
	VideoCapture video("2.mp4");

	// 检查视频是否成功打开
	if (!video.isOpened())
	{
		std::cout << "无法打开视频文件" << std::endl;
		return -1;
	}

	// 创建窗口,用于显示视频帧
	namedWindow("Video", WINDOW_NORMAL);

	// 获取第一帧图像
	Mat frame;
	video >> frame;

	// 提取第一帧的直线
	Mat gray, edges;
	cvtColor(frame, gray, COLOR_BGR2GRAY);
	Canny(gray, edges, 50, 150, 3);
	std::vector<Vec2f> lines;
	HoughLines(edges, lines, 1, CV_PI / 180, 100);

	
	kalman_line(video, frame,lines,1.0,0.0);
		

	return 0;
}

上述代码之中我根据直线的斜率和截距进行追踪。

我随便画了一条线,然后拍摄了一个视频大概是这样的情况(上传不了视频,将就着看一下):

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

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

相关文章

完美解决labelimg xml转可视化中文乱码问题,不用matplotlib

背景简述 我们有一批标注项目要转可视化&#xff0c;因为之前没有做过&#xff0c;然后网上随意找了一段代码测试完美&#xff08;并没有&#xff09;搞定&#xff0c;开始疯狂标注&#xff0c;当真正要转的时候傻眼了&#xff0c;因为测试的时候用的是英文标签&#xff0c;实…

Sci. Rep. | 一个对任意分子体系实现准确且高效几何深度学习的通用框架

这篇工作是来自纽约城市大学/康奈尔医学院谢磊团队的一篇论文。作者提出了一个通用框架&#xff0c;PAMNet&#xff0c;可以对任意分子体系实现准确且高效的几何深度学习。在小分子性质、RNA三维结构以及蛋白质-配体结合亲和力的预测任务上&#xff0c;PAMNet在准确性和效率方面…

网络编程-认识套接字socket

文章目录 套接字概念端口号网络字节序 套接字类型流套接字数据报套接字 socket常见APIsocket函数bind函数listen函数accept函数connect函数sockaddr结构 套接字概念 socket套接字是进程之间一种通信机制&#xff0c;通过套接字可以在不同进程之间进行数据交流。在TCP/UDP中&…

将html的radio单选框自定义样式为正方形和对号

将html的radio单选框自定义样式为正方形和对号 背景&#xff1a; 如何能把html的<input type"radio" name"option">改成自定义的样式呢&#xff1f;比如想要把他变成正方形&#xff0c;选中的时候是对号。默认的样式太丑了 默认样式&#xff1a; 自…

[数学]三角形的五心之内心

三角形内心的性质 三角形内切圆的圆心称为三角形的内心。内心也是三角形三个角的角平分线的交点 性质1 1.1 设 I I I为 △ A B C △ABC △ABC内一点&#xff0c;则 I I I为 △ A B C △ABC △ABC内心的充要条件是下列条件之一&#xff1a; 1.1.1 I I I到 △ A B C △ABC △…

【C语言】RDMACM、Verbs API与epoll一起使用的示例

一、epoll介绍 epoll是Linux内核为处理大批量文件描述符而作了改进的poll&#xff0c;是Linux下多路复用IO接口select/poll的增强版本&#xff0c;它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。 以下是epoll的主要使用方法和优点&#xff1a; epo…

代码随想录刷题题Day15

刷题的第十五天&#xff0c;希望自己能够不断坚持下去&#xff0c;迎来蜕变。&#x1f600;&#x1f600;&#x1f600; 刷题语言&#xff1a;C Day15 任务 ● 513.找树左下角的值 ● 112. 路径总和 113.路径总和ii ● 106.从中序与后序遍历序列构造二叉树 105.从前序与中序遍历…

整理了上百个开源中文大语言模型,涵盖模型、应用、数据集、微调、部署、评测

自ChatGPT为代表的大语言模型&#xff08;Large Language Model, LLM&#xff09;出现以后&#xff0c;由于其惊人的类通用人工智能&#xff08;AGI&#xff09;的能力&#xff0c;掀起了新一轮自然语言处理领域的研究和应用的浪潮。 尤其是以ChatGLM、LLaMA等平民玩家都能跑起…

广州华锐互动:汽车电子线束加工VR仿真培训与实际生产场景相结合,提高培训效果

随着科技的不断发展&#xff0c;虚拟现实&#xff08;VR&#xff09;技术已经逐渐渗透到各个领域&#xff0c;为企业和个人带来了前所未有的便利。在汽车制造行业中&#xff0c;线束加工作为一项关键的生产工艺&#xff0c;其质量直接影响到汽车的性能和安全。因此&#xff0c;…

LCR 181. 字符串中的单词反转

解题思路&#xff1a; class Solution {public String reverseMessage(String message) {message message.trim(); // 删除首尾空格int j message.length() - 1, i j;StringBuilder res new StringBuilder();while (i > 0) {while (i >…

局域网环境下的ntp对时

服务端&#xff1a; 此处为v4-sp4服务器 安装ntp&#xff0c;apt-get install ntp -y ,若为离线环境&#xff0c;则安装ntp和libopts25两个包。 配置&#xff1a; 在/etc/ntp.conf的配置文件里 加入 restrict default nomodify notrap noquery restrict 127.0.0.1 rest…

时序预测 | Python实现GRU-XGBoost组合模型电力需求预测

时序预测 | Python实现GRU-XGBoost组合模型电力需求预测 目录 时序预测 | Python实现GRU-XGBoost组合模型电力需求预测预测效果基本描述程序设计参考资料预测效果 基本描述 该数据集因其每小时的用电量数据以及 TSO 对消耗和定价的相应预测而值得注意,从而可以将预期预测与当前…

【IDEA】关于快捷键行注释时会从行首开始注释

前言 每次在使用IDEA写代码时&#xff0c;用快捷键进行行注释的时候&#xff0c;//会处于行首位置 但是我们想要的是这种注释效果 修改 IDEA中打开settings 找到Editor - Code Style- Java - 找到Code Genneration&#xff0c;取消勾选Line comment at first column&#x…

如何批量获取CSDN文章数据并进行持久化

自己去看文章数据的话&#xff0c;比较慢&#xff0c;所以一直想通过程序来批量获取CSDN的文章数据&#xff0c;最近研究了一下&#xff0c;发现还是挺简单的&#xff0c;能够直接通过解析json来获取文章数据&#xff0c;跟大家分享一下。 文章目录 一、步骤1、首先我们到自己的…

VUE学习三、前端项目部署

1.前端项目打包 执行命令 npm run build:prod正常命令结束 , 会在前端项目里面出现dist文件夹 2.nginx下载安装 nginx下载 : http://nginx.org/en/download.html Windows 下载版本 Mainline version&#xff1a;Mainline 是 Nginx 目前主力在做的版本&#xff0c;可以说…

【手撕算法系列】BN

BN的计算公式 BN中均值与方差的计算 所以对于输入x: b,c,h,w 则 mean: 1,c,1,1var: 1,c,1,1代码 class BatchNorm(nn.Module):def __init__(self, num_features, num_dims):# num_features&#xff1a;完全连接层的输出数量或卷积层的输出通道数。# num_dims&#xff1a;2表示…

【JavaEE】多线程(4) -- 单例模式

目录 什么是设计模式? 1.饿汉模式 2.懒汉模式 线程安全问题 什么是设计模式? 设计模式好⽐象棋中的 "棋谱". 红⽅当头炮, ⿊⽅⻢来跳. 针对红⽅的⼀些⾛法, ⿊⽅应招的时候有⼀ 些固定的套路. 按照套路来⾛局势就不会吃亏. 软件开发中也有很多常⻅的 "问题…

接口优先于反射机制

在Java中&#xff0c;使用接口通常比反射机制更为优雅和安全。接口提供了一种声明性的方式来定义类的契约&#xff0c;并且能够在编译时进行类型检查&#xff0c;而反射则是在运行时动态获取和操作类的信息。下面是一个简单的例子&#xff0c;说明为什么在某些情况下接口比反射…

基于Java SSM框架实现体育竞赛运动会成绩裁判管系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现体育竞赛运动会成绩裁判管系统演示 摘要 体育竞赛是各种体育体育项目比赛的总称。是在裁判员的主持下&#xff0c;按统一的规则要求&#xff0c;组织与实施的体育员个体或体育队之间的竞技较量&#xff0c;是竞技体育与社会发生关联&#xff0c;并作用于…

鼠标点击展开详情

网页部分&#xff1a; HTML部分&#xff1a; <body><br><div id"nav"><div id"dang"></div><ul id"aaa"><li class"a1"><img src"img/U011.jpg" width"195" heig…