直线追踪

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

代码使用的是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, vyMat 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.hqwc.cn/news/282371.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c语言-全局变量与局部变量

目录 1、&#xff08;作用&#xff09;域的概念 2、全局与局部的相对性 3、生命周期 3、静态变量static 结语&#xff1a; 前言&#xff1a; 在c语言中&#xff0c;全局变量的可见范围是整个工程&#xff0c;而局部变量的可见范围从该变量被定义到该作用域结束&#xff0c…

re:Invent2023大会隆重推出自研芯片Graviton4和Trainium2

目录 一、前言 二、体验Graviton系列产品 &#xff08;一&#xff09;创建普通的EC2实例 &#xff08;二&#xff09;创建Graviton处理器的EC2实例 &#xff08;三&#xff09;远程到服务器 方式1&#xff1a;创建成功时连接 方式2&#xff1a;SSH客户端 方式3&#xff1a;正确…

关于找不到XINPUT1_3.dll,无法继续执行代码问题的5种不同解决方法

一、xinput1_3.dll的作用 xinput1_3.dll是Windows操作系统中的一款动态链接库文件&#xff0c;主要用于支持游戏手柄和游戏输入设备。这款文件属于Microsoft Xbox 360兼容性库&#xff0c;它包含了与游戏手柄和其他输入设备相关的功能。在游戏中&#xff0c;xinput1_3.dll负责…

vue使用el-tag完成添加标签操作

需求&#xff1a;做一个添加标签的功能&#xff0c;点击添加后输入内容后回车可以添加&#xff0c;并且标签可以删除 1.效果 2.主要代码讲解 鼠标按下后触发handleLabel函数&#xff0c;根据回车的keycode判断用户是不是按下的回车键&#xff0c;回车键键值为13&#xff0c;用…

深入理解——快速排序

目录 &#x1f4a1;基本思想 &#x1f4a1;基本框架 &#x1f4a1;分割方法 ⭐Hoare版本 ⭐挖坑法 ⭐前后指针法 &#x1f4a1;优化方法 ⭐三数取中法 ⭐小区间内使用插入排序 &#x1f4a1;非递归实现快速排序 &#x1f4a1;性能分析 &#x1f4a1;基本思想 任取待排…

Qt 表格相关API

1.文本框 限制输入数据类型&#xff08;如仅英文&#xff09; QValidator* validator new QRegExpValidator(QRegExp("[a-zA-Z]"), lineText); // 创建正则表达式验证器lineText->setValidator(validator); // 将验证器设置给 QLineEdit QLineEdit&#xff1a;单…

【MyBatis-Plus】常用的插件介绍(乐观锁、逻辑删除、分页)

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于MyBatis-Plus的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.为什么要使用MyBatis-Plus中的插…

【气候模式降尺度】分位数增量映射(QDM)原理及MATLAB代码实现

分位数增量映射(quantile delta mapping, QDM) 1 QDM偏差订正原理2 MATLAB实现代码3 案例参考气候模式的模拟结果与观测数据往往存在着一定的系统偏差,若将气候模式结果直接应用于作物模型或者水文模型中,其偏差会对模拟产生很大的影响,因此需要对气候模拟结果进行误差订正…

JRT实现在线打印预览

在JRT打印元素绘制协议一篇已经介绍过打印把绘图和打印逻辑进行了分离&#xff0c;这是和老设计最大的不同。因为老的设计时候没想着做在线预览功能&#xff0c;是后面硬性扩出来的。这次从最初设计就考虑绘图逻辑各处共用&#xff0c;包括打印预览&#xff0c;在线打印预览等、…

搭建自托管密码管理器

文章目录 背景准备工作服务器域名SSL 证书 开始安装 Docker安装 Docker Compose阿里云安装 Docker安装 Docker Compose 验证 起飞安装官方 Bitwarden修改配置文件 (端口号、SSL 证书等)(可选) 修改环境配置文件&#xff1a;启动 Bitwarden 服务验证所有容器是否正常运行 安装第…

STM32 DAC+串口

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、DAC是什么&#xff1f;二、STM32 DAC1.什么型号有DAC2. 简介3. 主要特点4. DAC框图5. DAC 电压范围和引脚 三、程序步骤1. 开启DAC时钟2. 配置引脚 PA4 PA5…

Shell三剑客:sed(命令)一

一、删除命令&#xff1a;d [rootlocalhost ~]# sed -r /root/d passwd.txt bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync…