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

一 图像可行驶区域方案

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.mzph.cn/pingmian/40888.shtml

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

相关文章

保函到期提醒是银行或金融机构提供的一项服务,旨在确保客户及时了解保函即将到期的情况,从而避免因保函过期而导致的风险或违约责任。

保函到期提醒是银行或金融机构提供的一项服务&#xff0c;旨在确保客户及时了解保函即将到期的情况&#xff0c;从而避免因保函过期而导致的风险或违约责任。以下是保函到期提醒的一些关键方面&#xff1a; 1. **保函定义**&#xff1a; - 保函是一种由银行出具的书面承诺&…

vue实现左右拖动分屏

效果图如下&#xff1a; 封装组件 <template><div ref"container" class"container"><div class"left-content" :style"leftStyle">/**定义左侧插槽**/<slot name"left"></slot></div>…

Springboot+Vue3开发学习笔记《2》

SpringbootVue3开发学习笔记《2》 博主正在学习SpringbootVue3开发&#xff0c;希望记录自己学习过程同时与广大网友共同学习讨论。 总共涉及两部分&#xff0c;第一部分为基础部分学习&#xff0c;第二部分为实战部分。 一、学习路径 1.1 基础部分 配置文件整合MyBatisBea…

中英双语介绍美国的州:阿拉斯加州(Alaska)

中文版 阿拉斯加州&#xff08;Alaska&#xff09;位于美国西北角&#xff0c;是美国面积最大的州&#xff0c;以其壮丽的自然景观、丰富的矿产资源和独特的野生动物闻名。以下是对阿拉斯加州的详细介绍&#xff0c;包括其地理位置、人口、经济、教育、文化和主要城市。 地理…

QQ聊天记录删除了怎么恢复?这4个方法让你秒找回!

在现代社会&#xff0c;QQ已经成为我们日常交流和工作中不可或缺的沟通工具。然而&#xff0c;有时我们可能会不小心删除了重要的聊天记录&#xff0c;这会带来诸多不便甚至困扰。那么&#xff0c;当你发现自己误删了数据&#xff0c;qq聊天记录删除了怎么恢复呢&#xff1f;有…

第14届蓝桥杯Python青少组中/高级组选拔赛(STEMA)2022年8月21日真题

第14届蓝桥杯Python青少组中/高级组选拔赛&#xff08;STEMA&#xff09;2022年8月21日真题 题目总数&#xff1a;5 总分数&#xff1a;128 更多真题下载点我&#x1f446; 编程题 第 1 题 问答题 编程实现&#xff1a; 给定一个正整数&#xff0c;输出正整数个位上的…

tsconfig.json的include和exclude作用

tsconfig.json中的include和exclude属性用于指定需要被编译的TypeScript文件和需要被排除的文件。‌ include属性&#xff1a;‌用于指定哪些.ts、‌.tsx或.d.ts文件需要被编译。‌如果不指定include属性&#xff0c;‌则默认当前目录下除了exclude之外的所有.ts、‌.d.ts、‌…

昇思25天学习打卡营第11天|LSTM+CRF序列标注

序列标注指给定输入序列&#xff0c;给序列中每个Token进行标注标签的过程。序列标注问题通常用于从文本中进行信息抽取&#xff0c;包括分词(Word Segmentation)、词性标注(Position Tagging)、命名实体识别(Named Entity Recognition, NER)等。 和人理解语言一样&#xff0c…

2024-07-04 base SAS programming学习笔记8(HTML)

当使用ODS来进行结果或数据集输出的时候&#xff0c;可以同时设置多个ODS 命令&#xff0c;同时输出到多个不同的文件。使用_ALL_ 表示关闭所有的ODS输出窗口&#xff0c;比如&#xff1a; ods html file(body)"html-file-pathname"; ods html file"pdf-file-pa…

【C#】如何在窗体程序中调用多行CMD命令

【背景】 用VS写一个C#窗体程序&#xff0c;第一步需要用CMD启动一个外部服务并发送信息给该服务器&#xff0c;涉及两步命令&#xff0c;第一步是启动服务&#xff0c;第二步是发送信息。 【分析】 要点&#xff1a; 如何指定启动CMD的路径在服务exe所在路径下&#xff1b…

中国东方资产管理25届秋招北森测评笔试如何高分通过?真题考点分析看完这篇就够了

一、东方资管校招测评题型分析 中国东方资产管理股份有限公司&#xff08;中国东方资管&#xff09;的校园招聘测评题型主要包括以下几个部分&#xff1a; 1. **计分题&#xff0c;行测知识**&#xff1a;这部分题量大约在56-57题左右&#xff0c;分为不同的模块进行计时测试。…

Spzhi知识付费社区主题免费下载

主题介绍 用typecho打造一款知识付费社区主题&#xff0c;带会员功能&#xff0c;为内容创业者提供知识变现一站式解决方案&#xff0c;让用户沉淀到自己的平台&#xff0c;形成自己的私域流量池&#xff0c;打造流量闭环&#xff0c;零门槛搭建你的移动网络课堂 主题功能 支…

SpringBoot Task 定时任务

springboot中使用Task定时任务非常简单 springboot 中自带的都有注解不需要引入依赖 第一步&#xff1a;在启动类上添加启用定时任务注解 EnableScheduling //开启任务调度 第二步&#xff1a;创建一个springboot组件用于定时任务管理 package cn.lsy.api.Task;import cn.ls…

论文解读——如何生成高分辨率图像PGGAN

论文&#xff1a;Progressive Growing of GANs for Improved Quality, Stability, and Variation&#xff08;2017.10&#xff09; 作者&#xff1a;Tero Karras, Timo Aila, Samuli Laine, Jaakko Lehtinen 链接&#xff1a;https://arxiv.org/abs/1710.10196 代码&#xff1a…

前端必知的跨站脚本攻击(XSS)示例与解决方案

跨站脚本攻击&#xff08;Cross-Site Scripting&#xff0c;通常缩写为XSS&#xff09;是一种常见的网络安全漏洞&#xff0c;它允许攻击者将恶意脚本注入到其他用户会浏览的页面中。 XSS攻击的示例代码可以帮助我们了解攻击者可能使用的技术。但请注意&#xff0c;了解这些示例…

MyBatis中resultMap与resultType区别

在MyBatis中&#xff0c;resultType 和 resultMap 都是用来定义查询结果如何被映射到Java对象上的&#xff0c;但它们的使用场景和方式有所不同。 resultType 含义: resultType 是一个简化的结果映射方式&#xff0c;用于直接将查询结果映射到一个已知类型的Java Bean或基本…

idea删除分支并同步到gitLab以及gitLab上的分支删除

目录 idea删除分支并同步到gitLab 方法一&#xff08;推荐&#xff09; 方法二&#xff08;命令行&#xff09; gitLab上的分支删除 前言-与正文无关 ​ 生活远不止眼前的苦劳与奔波&#xff0c;它还充满了无数值得我们去体验和珍惜的美好事物。在这个快节奏的世界中&…

初入Node.js必备知识

Node.js因什么而生&#xff0c;作用是干什么&#xff1f; Node.js是一个用c和c打造的一个引擎&#xff0c;他能够读懂JavaScript&#xff0c;并且让JavaScript能够和操作系统打交道的能力 JavaScript 原本只能在浏览器中运行,但随着Web应用程序越来越复杂,仅靠客户端JavaScri…

绩效管理,不再只是一串数字!

在数字化转型的大潮中&#xff0c;绩效管理不再只是枯燥的数字统计。搭贝的绩效管理系统&#xff0c;为企业提供灵活多样的考核模式与工具&#xff0c;助力实现科学、高效的管理。无论是KPI&#xff08;关键绩效指标&#xff09;还是OKR&#xff08;目标与关键成果&#xff09;…