基于轨迹信息的图像近距离可行驶区域方案验证

一 图像可行驶区域方案

1.1 标定场景

标定场地

1.2 标定步骤

  1. 设计一定间距标定场,在标定场固定位置设置摄像头标定标识点。
  2. 主车开到标定场固定位置
  3. 录制主车在该位置各个摄像头数据,通过摄像头捕获图像获取图像上关键点坐标pts-2d
  4. 基于标定场设计,计算图像关键点对应车体坐标系中的3d坐标pts-3d
  5. 通过cv2.findHomography(obj_points, img_points, cv2.RANSAC, 5.0) 获取相机坐标系到地面的单应性变换矩阵H

1.3 实车使用

实时获取车辆行进过程中的固定纵向距离的轨迹点信息,使用单应性变换矩阵H反向计算轨迹信息在图像中的投影位置,从而获取到图像中检测目标的距离区间。

二 初步验证结果

'''
Author: XIEXINYAN “1532642675@qq.com”
Date: 2024-07-01 04:52:07
LastEditors: XIEXINYAN “1532642675@qq.com”
LastEditTime: 2024-07-03 05:40:06
FilePath: /202407/hom_matrix.py
Description: Copyright (c) 2024 by 1532642675@qq.com, All Rights Reserved. 
'''
import cv2  
import numpy as np  
import os
import argparseclass Counter:cnt = 0def __init__(self):Counter.cnt +=1@classmethoddef get_counter(cls):return cls.cnt 
class Calibrate:def __init__(self, pattern_size, real_square_size, offset_x, offset_y):self.pattern_size = pattern_sizeself.real_square_size = real_square_sizeself.offset_x = offset_xself.offset_y = offset_y# 1. 检测棋格板角点  def find_chessboard_corners(self, image, color=(0, 255, 0), vis=False,  save=False, calib=False): self.image = image.copy()image_painted = image.copy()gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)  ret, corners = cv2.findChessboardCorners(gray, pattern_size, None)  if ret:  criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)  #按照pattern_size[0]的个数排序,绘制的第一组数据个数=pattern_size[0]的个数self.corner = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)if self.corner is not None:'''0  3  6          2  5  8           6  3  0            8  5  21  4  7          1  4  7            7  4  1            7  4  1    2  5  8          0  3  6            8  5  2            6  3  0  '''if vis:#判断corners排序顺序index_list = []if (self.corner[0][0][1]<self.corner[1][0][1] and self.corner[0][0][0]<self.corner[np.prod(self.pattern_size)-1][0][0]):print("mode A")elif (self.corner[0][0][1]>self.corner[1][0][1] and self.corner[0][0][0]<self.corner[np.prod(self.pattern_size)-1][0][0]):print("mode B")for j in range(pattern_size[1]):for i in range(pattern_size[0]):index_list.append(pattern_size[0]-1-i+j*pattern_size[0])elif (self.corner[0][0][1]<self.corner[1][0][1] and self.corner[0][0][0]>self.corner[np.prod(self.pattern_size)-1][0][0]):print("mode C")index_list = []for j in range(pattern_size[1]):for i in range(pattern_size[0]):index_list.append(i+(pattern_size[1]-1-j)*pattern_size[0])print(index_list)elif (self.corner[0][0][1]>self.corner[1][0][1] and self.corner[0][0][0]>self.corner[np.prod(self.pattern_size)-1][0][0]):print("mode D")index_list = []for j in range(pattern_size[1]):for i in range(pattern_size[0]):index_list.append(i+(pattern_size[1]-1-j)*pattern_size[0])print(index_list)else:print("horizonal mode")self.corner = self.corner[index_list]cv2.circle(image_painted, (int(self.corner[0][0][0]), int(self.corner[0][0][1])), 25, (0, 255, 255), -1)  cv2.circle(image_painted, (int(self.corner[1][0][0]), int(self.corner[1][0][1])), 25, (0, 0, 255), -1) for corner in self.corner:cv2.circle(image_painted, (int(corner[0][0]), int(corner[0][1])), 5, (0, 0, 255), -1)  cv2.drawChessboardCorners(image_painted, pattern_size, self.corner, True)  cv2.imshow("chess",image_painted)if save:instance=Counter()cv2.imwrite(str(instance.get_counter())+".jpg", image)if calib:self.find_hom_matrix(vis=True, save=True)return Truereturn Falsedef world_chess_board_loc(self):# 初始化obj_points数组,注意使用齐次坐标(即每个点都是[x, y, 1])  obj_points = np.zeros((np.prod(self.pattern_size), 3), dtype=np.float32)  # x_start是每行开始的x坐标  # y_start是每行开始的y坐标 # # 填充obj_points数组  '''从左上角开始0  3  6  9  1  4  7  102  5  8  11'''# obj_points =np.array([#     [  0.,   0.,   1.],[  0.,  60.,   1.],[  0., 120.,   1.],#     [ 60.,   0.,   1.],[ 60.,  60.,   1.],[ 60., 120.,   1.],#     [120.,   0.,   1.],[120.,  60.,   1.],[120., 120.,   1.],#     [180.,  0.,   1.],[180.,  60.,   1.],[180., 120.,   1.]], dtype=np.float32)index = 0 for i in range(pattern_size[1]):  for j in range(pattern_size[0]):  # 计算x和y坐标  x = i * self.real_square_size y = j * self.real_square_size  # 将点添加到obj_points数组中,注意使用齐次坐标形式  obj_points[index, :] = [x, y, 1.0]  index += 1  return obj_points'''将世界坐标系下点转化为wraped图像上点'''def world_transation(self):obj_points = self.world_chess_board_loc()obj_points_t = obj_points.copy()obj_points_t[:,0] += self.offset_xobj_points_t[:,1] += self.offset_yobj_points_t[:,:2] *= 1000return obj_points_tdef world_to_image(self, img, vis=False, save=False):# obj_points 是世界坐标系下的点,需要是齐次坐标形式 obj_points_t = self.world_transation()# 使用np.dot进行矩阵乘法,并计算归一化的图像坐标  img_points_homogeneous = np.dot(self.H, obj_points_t.T).T  img_points = img_points_homogeneous[:, :2] / img_points_homogeneous[:, 2:].reshape(-1, 1) for pt_2d in img_points:cv2.circle(img, (int(pt_2d[0]), int(pt_2d[1])), 5, (0, 0, 255), -1) if vis:cv2.imshow("eval image", img)if save:counter = Counter()cv2.imwrite("eval_"+str(counter.get_counter())+".jpg",img)returndef find_hom_matrix(self, vis=False, save=False):# 世界坐标值 【横,纵,高】obj_points = self.world_chess_board_loc() # 偏移到某个坐标系obj_points[:,0] += self.offset_x obj_points[:,1] += self.offset_yobj_points[:,:2] *= 1000# print(obj_points)# 3. 计算单应性矩阵  img_points = self.corner.reshape(-1, 1, 2).astype(np.float32)  self.H, _ = cv2.findHomography(obj_points, img_points, cv2.RANSAC, 5.0)  warped_image = cv2.warpPerspective(self.image, self.H,  (self.image.shape[1], self.image.shape[0]))if vis:cv2.imshow("wrapped image",warped_image)cv2.waitKey()if save:cv2.imwrite("wrapped_"+str(Counter.cnt)+".jpg", warped_image)return def find_qrcode_corners(image, vis=False):gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)  # 二值化  _, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)  # # 查找轮廓  # contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 查找轮廓(OpenCV 4.x) contours, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)  #打印轮廓信息  print("总轮廓数:", len(contours))# 筛选和排序轮廓(这里我们假设二维码是最大的轮廓)  contours = sorted(contours, key=cv2.contourArea, reverse=True)  qrcode_contour = contours[0]  # 多边形近似  epsilon = 0.02 * cv2.arcLength(qrcode_contour, True)  approx = cv2.approxPolyDP(qrcode_contour, epsilon, True)  image_out = image.copy()# 提取角点坐标  corners = approx.reshape((-1, 2))  # 在原图上绘制角点  if len(corners) == 4:for corner in corners:  cv2.circle(image_out, (int(corner[0]), int(corner[1])), 25, (0, 0, 255), -1)  # 显示图像  cv2.imshow('QRCode Corners', image_out)  cv2.drawContours(image_out, qrcode_contour, -1, (0, 255, 0), 3)  cv2.imshow('Corners', image_out)  cv2.waitKey(1)   def argParser():parser = argparse.ArgumentParser()parser.add_argument('--rows', type=int, default=3,help='chess board raw num')parser.add_argument('--cols', type=int, default=4,help='chess board col num')parser.add_argument('--online',type=bool, default=False, help='online camera calib')opt = parser.parse_args()return optif __name__ == '__main__':opt = argParser()pattern_size = (opt.rows, opt.cols)calib = Calibrate(pattern_size, 0.06, 0.3, 0.7)cap = cv2.VideoCapture(0)if not cap.isOpened():exit()print(" now start calib %d\n",opt.online)if opt.online:while True:ret, frame = cap.read()flag = calib.find_chessboard_corners(frame, vis=True, save=True, calib=True) cv2.waitKey(1)  if flag:breakelse:path = "img"image_list = os.listdir(path)for img in image_list:img_path = os.path.join(path,img)if os.path.isfile(img_path):frame = cv2.imread(img_path)else:continueprint("image path is: ",img_path)flag = calib.find_chessboard_corners(frame, vis=True, save=False, calib=True)cv2.waitKey(1)if flag:breakprint(calib.H)print(" now start eval \n")if opt.online:while True:ret, frame = cap.read()# 如果正确读取帧,ret为Trueif not ret:print("无法接收帧,请退出")break       calib.world_to_image(frame,True, False)# 显示实时画面cv2.imshow('raw', frame)# 按 'q' 键退出循环if cv2.waitKey(1) & 0xFF == ord('q'):break# 释放摄像头资源并关闭所有窗口cap.release()else:path = "img"image_list = os.listdir(path)for img in image_list:img_path = os.path.join(path,img)if os.path.isfile(img_path):frame = cv2.imread(img_path)else:continuecalib.world_to_image(frame, True, True)# 显示实时画面cv2.imshow('raw', frame)# 按 'q' 键退出循环if cv2.waitKey(1) & 0xFF == ord('q'):breakcv2.destroyAllWindows()

三 存在问题

  1. 本方案在设计标定场过程中需要精确计算每个相机的FOV,与地面的交点,设计地面标志物,使得每个相机可以准确有效的提取地面标志物
  2. 会受到道路坡度和车辆pitch角影响,需要模拟分析pitch角对距离的影响度

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

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

相关文章

恢复出厂设置手机变成砖

上周&#xff0c;许多Google Pixel 6&#xff08;6、6a、6 Pro&#xff09;手机用户在恢复出厂设置后都面临着设备冻结的问题。 用户说他们在下载过程中遇到了丢失 tune2fs 文件的错误 。 这会导致屏幕显示以下消息&#xff1a;“Android 系统无法启动。您的数据可能会被损坏…

Python28-9 XGBoost算法

XGBoost&#xff08;eXtreme Gradient Boosting&#xff0c;其正确拼写应该是 "Extreme Gradient Boosting"&#xff0c;而XGBoost 的作者在命名时故意使用了不规范的拼写&#xff0c;将“eXtreme”中的“X”大写&#xff0c;以突出其极限性能和效率&#xff09;是一…

探索多模态预训练:MAnTiS、ActionCLIP、CPT与CoOp的Prompt技巧

上一篇博文整理了 预训练新范式&#xff08;Prompt-tuning&#xff0c;Prefix-tuning&#xff0c;P-tuning&#xff09; &#xff0c;主要是围绕NLP上的成果&#xff0c;具体的概念本文也不做过多赘述。本篇文章将主要整理几篇有代表性的Prompt方法在多模态领域中的应用。 Mult…

普中51单片机:数码管显示原理与实现详解(四)

文章目录 引言数码管的结构数码管的工作原理静态数码管电路图开发板IO连接图代码演示 动态数码管实现步骤数码管驱动方式电路图开发板IO连接图真值表代码演示1代码演示2代码演示3 引言 数码管&#xff08;Seven-Segment Display&#xff09;是一种常见的显示设备&#xff0c;广…

C-11 三角剖分的调研

C-11 三角剖分算法 三角剖分就是将输入的多边形&#xff0c;分割成一系列互不重叠的三角形&#xff0c;其重要性就在这不多赘述。这个是一个别人总结的链接&#xff1a;http://vterrain.org/Implementation/Libs/triangulate.html 图片链接&#xff1a;http://www-cgrl.cs.m…

【笔记】在window上连接虚拟机中的redis

愚昧啊 困扰了我近两天的问题居然是因为是java代码写错地方了 在虚拟机中进入redis.conf文件 vim redis.conf /bind --斜杠搜索关键词 将值设置为 bind 0.0.0.0 保存 退出:wq 回到java中 添加redis依赖 刷新maven 就是在这一步出问题……………………………………自己在蓝…

新型水冷电阻设计-双面水冷电阻器

一款革命性的电阻器&#xff0c;专为低压和中压应用而设计&#xff0c;尤其是汽车、牵引或船舶系统中的恶劣条件。 EAK采用先进材料制造&#xff0c;采用专利设计&#xff0c;将电阻元件与水基冷却液封装并完全分离&#xff0c;为水冷应用提供模块化、轻量级、小容量、高功率解…

PYTHON自学笔记(一)vscode配置

安装python 自行官网下载 安装vscode 自行官网下载 环境变量设置 把python和scripts的文件路径&#xff0c;添加到环境变量的path中&#xff0c;如图&#xff1a; 此项不弄&#xff0c;在命令行模式中系统不会认为你装了python和pip&#xff0c;你的输入相关命令shell不会…

【Elasticsearch】Elasticsearch倒排索引详解

文章目录 &#x1f4d1;引言一、倒排索引简介二、倒排索引的基本结构三、Elasticsearch中的倒排索引3.1 索引和文档3.2 创建倒排索引3.3 倒排索引的存储结构3.4 词典和倒排列表的优化 四、倒排索引的查询过程4.1 过程4.2 示例 五、倒排索引的优缺点5.1 优点5.2 缺点 六、倒排索…

ComfyUI+MuseV+MuseTalk图片数字人

电脑配置 GPU12G&#xff0c;如果自己电脑配置不够&#xff0c;选择云gpu&#xff0c;我就是用的这个&#xff0c;自己电脑太老配置跟不上 环境&#xff1a; Python 3.11.8 torch 2.2.1 cuda_12.1 资源提供&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1_idZbF…

subset使用

在R语言中&#xff0c;subset()函数用于从数据框中选择满足特定条件的观测。其语法如下&#xff1a; subset(x, subset, select, drop FALSE) 参数说明&#xff1a; x&#xff1a;数据框或矩阵。 subset&#xff1a;逻辑条件&#xff0c;用于筛选满足特定条件的行。 select…

MySQL—统计函数和数学函数以及GROUP BY配合HAVING

合计/统计函数 count -- 演示 mysql 的统计函数的使用 -- 统计一个班级共有多少学生&#xff1f; SELECT COUNT(*) FROM student -- 统计数学成绩大于 90 的学生有多少个&#xff1f; SELECT COUNT(*) FROM student WHERE math > 90 -- 统计总分大于 250 的人数有多少&…

axios和Mybatis

除了get和post方法还有其他的方法&#xff1a; 发送 PUT 请求 发送 PUT 请求通常用于更新服务器上的资源。 const updateData {title: foo updated,body: bar updated,userId: 1 };axios.put(https://jsonplaceholder.typicode.com/posts/1, updateData).then(function (res…

麦蕊智数,,另外一个提供免费的股票数据API,可以通过其提供的接口获取实时和历史的股票数据。

麦蕊智数&#xff0c;&#xff0c;提供免费的股票数据API&#xff0c;可以通过其提供的接口获取实时和历史的股票数据。 API接口&#xff1a;http://api.mairui.club/hslt/new/您的licence 备用接口&#xff1a;http://api1.mairui.club/hslt/new/您的licence 请求频率&#x…

Node.js_fs模块

文件删除 文件重命名和移动&#xff08;本质都是修改路径&#xff09; 文件夹操作 创建文件夹(mkdir) 读取文件夹(readdir) &#xff08;打印出来是该文件夹下名称的数组形式&#xff09; 读取当前的文件夹(readdir) 删除文件夹 &#xff08;rmdir&#xff09; 查看资源状态…

Golang | Leetcode Golang题解之第222题完全二叉树的节点个数

题目&#xff1a; 题解&#xff1a; func countNodes(root *TreeNode) int {if root nil {return 0}level : 0for node : root; node.Left ! nil; node node.Left {level}return sort.Search(1<<(level1), func(k int) bool {if k < 1<<level {return false}…

Apache Seata新特性支持 -- undo_log压缩

本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 Apache Seata新特性支持 – undo_log压缩 Seata新特性支持 – undo_log压缩 现状 & 痛点…

线程池理解及7个参数

定义理解 线程池其实是一种池化的技术实现&#xff0c;池化技术的核心思想就是实现资源的复用&#xff0c;避免资源的重复创建和销毁带来的性能开销。线程池可以管理一堆线程&#xff0c;让线程执行完任务之后不进行销毁&#xff0c;而是继续去处理其它线程已经提交的任务。 …

20、matlab信号波形生成:狄利克雷函数、高斯脉冲和高斯脉冲序列

1、名词说明 狄利克雷函数&#xff08;Dirac Delta Function&#xff09; 狄利克雷函数&#xff0c;也称为单位冲激函数或δ函数&#xff0c;是一个在数学和信号处理中常用的特殊函数。狄利克雷函数通常用符号δ(t)表示&#xff0c;其定义为&#xff1a; δ(t) { ∞, t 0{…

RabbitMq - Java客户端基础【简单案例 +Work模型】

目录 1、前置知识 1.1、AMQP怎么理解 1.2、Spring AMQP是什么 1.3、为什么要了解Spring-AMQP&#xff1f; 2、使用Spring-AMQP实现一个发消息案例 3、Work模型 问题&#xff1a; 优化&#xff1a; 小结&#xff1a;Work模型的使用&#xff1a; 1、前置知识 1.1、AMQP怎…