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

一 图像可行驶区域方案

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,一经查实,立即删除!

相关文章

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…

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

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

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…

中国东方资产管理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…

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;…

EHS是什么意思啊?EHS系统有什么作用?

当你走进一家现代化的工厂或企业&#xff0c;你可能会好奇&#xff1a;这些繁忙的生产线和高效运转的设备背后&#xff0c;是如何确保员工的安全、环境的保护和产品的质量的&#xff1f;答案可能就藏在“EHS系统”这个名词里。 那么&#xff0c;EHS是什么意思啊&#xff1f;它…

【C#】函数方法、属性分文件编写

1.思想 分文件编写是面向对象编程的重要思想&#xff0c;没有实际项目作为支撑很难理解该思想的精髓&#xff0c;换言之&#xff0c;一两个函数代码量因为太少无法体现分文件编写减少大量重复代码的优势。 2.项目结构介绍 整项目的名称叫AutoMetadata&#xff0c;是一个基于W…

JAVA:文件防重设计指南

1、简述 在现代应用程序中&#xff0c;处理文件上传是一个常见的需求。为了保证文件存储的高效性和一致性&#xff0c;避免重复存储相同的文件是一个重要的优化点。本文将介绍一种基于哈希值的文件防重设计&#xff0c;并详细列出实现步骤。 2、设计原理 文件防重的基本思路…

Dns被莫名篡改的逆向分析定位(笔记)

引言&#xff1a;最近发现用户的多台机器上出现了Dns被莫名修改的问题&#xff0c;从系统事件上看并未能正常确定到是那个具体软件所为&#xff0c;现在的需求就是确定和定位哪个软件具体所为。 解决思路&#xff1a; 首先到IPv4设置页面对Dns进行设置&#xff1a;通过ProcExp…

setjmp和longjmp函数使用

这里用最简单直接的描述&#xff1a;这两组函数是用于实现类似vscode全局的标签跳转功能&#xff0c;setjmp负责埋下标签&#xff0c;longjmp负责标签跳转。 #include <stdio.h> #include <stdlib.h> #include <setjmp.h>jmp_buf envbuf1; jmp_buf envbuf2;…

HttpServer内存马

HttpServer内存马 基础知识 一些基础的方法和类 HttpServer&#xff1a;HttpServer主要是通过带参的create方法来创建&#xff0c;第一个参数InetSocketAddress表示绑定的ip地址和端口号。第二个参数为int类型&#xff0c;表示允许排队的最大TCP连接数&#xff0c;如果该值小…

JAVA每日作业day7.4

ok了家人们今天学习了Date类和simpleDateformat类&#xff0c;话不多说我们一起看看吧 一.Date类 类 java.util.Date 表示特定的瞬间 ( 日期和时间 ) &#xff0c;精确到毫秒。 1.2 Date类的构造方法 public Date(): 用来创建当前系统时间对应的日期对象。 public Date(long …

【java开发环境】多版本jdk 自由切换window和linux

win10 一、准备 各种版本的jdk&#xff0c;按自己的需要下载。 我这里是需要jdk17和jdk8。 1、jdk17 下载&#xff1a;Java Downloads | Oracle&#xff0c;选择exe后缀文件 2、jdk8下 载&#xff1a;Java Downloads | Oracle&#xff0c;选择exe后缀文件 二、详细步骤 1、…