【目标测距】雷达投影测距
文章目录
- 前言
- 一、读取点云
- 二、点云投影图片
- 三、读取检测信息
- 四、点云投影测距
- 五、学习交流
前言
- 雷达点云投影相机。图片目标检测,通过检测框约束等等对目标赋予距离。
- 计算消耗较大,适合离线验证操作。在线操作可以只投影雷达检测框。
一、读取点云
- python 读取点云,我这里用的是 open3d 这个库。
import open3d as o3dpcd_path = "1.pcd"
pcd = o3d.io.read_point_cloud(pcd_path) # 点云
二、点云投影图片
- 明白标定原理,这部分就很简单,就是一个矩阵运算。投影像素误差多少与传感器标定强相关。
- 下面代码中 mtx:相机内参 r_camera_to_lidar_inv:相机到雷达的旋转矩阵的逆矩阵 t_camera_to_lidar:相机到雷达的平移向量
import open3d as o3d
import numpy as np
import cv2color_label = [(255, 0, 0), (121, 68, 222), (0, 0, 255), (0, 255, 0), (199, 199, 53)] # 红黄蓝绿青# 不同距显示不同颜色
def get_color(distance):for i in range(2, 50):if i < distance < i + 1:return color_label[i % len(color_label)]return color_label[0]pcd_path = "1.pcd"
pcd = o3d.io.read_point_cloud(pcd_path) # 点云
image = cv2.imread("1.jpg")cloud = np.asarray(pcd.points)
for point in cloud:camera_coordinate = np.dot(mtx, np.dot(r_camera_to_lidar_inv, point.reshape(3, 1) - t_camera_to_lidar))pixe_coordinate = camera_coordinate / camera_coordinate[2]x_pixe, y_pixe, _ = pixe_coordinatecv2.circle(image, (int(x_pixe), int(y_pixe)), 1, get_color(camera_coordinate[2]), 2)
三、读取检测信息
- 图像目标检测信息保存在txt文件。格式: frame , x_center , y_cente , width , height , score。
import numpy as npdef GetDetFrameRes(seq_dets, frame):detects = seq_dets[(seq_dets[:, 0] == frame) & (seq_dets[:, 5] <= 6), 1:6]detects[:, 0:2] -= detects[:, 2:4] / 2 # convert to [x中心,y中心,w,h] to [x左上,y左上,w,h]detects[:, 2:4] += detects[:, 0:2] # convert to [x左上,y左上,w,h] to [x左上,y左上,x右下,y右下]return detectsdet_dir = "result.txt"
det_data = np.loadtxt(det_dir, delimiter=',')
# 假如有100帧图片
for i in range(100):dets_frame = GetDetFrameRes(det_data, i) # 获取第i帧检测结果
四、点云投影测距
- 判断点云是否在图像目标检测框内。
- 对于图片目标检测框有重复的情况,需要对目标检测框进行排列,距离靠前的检测框优先计算。
- 选取点云中 x 最小的为目标的距离,y 距离取目标框内平均值
import os
import cv2
import yaml
import numpy as np
import open3d as o3d
from datetime import datetimedef read_yaml(path):with open(path, 'r', encoding='utf-8') as f:result = yaml.load(f.read(), Loader=yaml.FullLoader)camera_mtx = result["camera"]["front_center"]["K"]r_camera = result["camera"]["front_center"]["rotation"]t_camera = result["camera"]["front_center"]["translation"]lidar_to_car = result["lidar"]["top_front"]["coordinate_transfer"]c_m = np.array([camera_mtx]).reshape(3, 3)r_c = np.array([r_camera]).reshape(3, 3)t_c = np.array([t_camera]).reshape(3, 1)l_c = np.array([lidar_to_car]).reshape(4, 4)return c_m, r_c, t_c, l_cdef get_box_color(index):color_list = [(96, 48, 176), (105, 165, 218), (18, 153, 255)]return color_list[index % len(color_list)]# 不同距显示不同颜色
def get_color(distance):for i in range(2, 50):if i < distance < i + 1:return color_label[i % len(color_label)]return color_label[0]def GetDetFrameRes(seq_dets, frame):detects = seq_dets[(seq_dets[:, 0] == frame) & (seq_dets[:, 5] <= 6), 1:6]detects[:, 0:2] -= detects[:, 2:4] / 2 # convert to [x中心,y中心,w,h] to [x左上,y左上,w,h]detects[:, 2:4] += detects[:, 0:2] # convert to [x左上,y左上,w,h] to [x左上,y左上,x右下,y右下]return detects# 点云投影到图片
def point_to_image(image_path, pcd_point, det_data, show=False):cloud = np.asarray(pcd_point.points)image = cv2.imread(image_path)det_data = det_data[np.argsort(det_data[:, 3])[::-1]]n = len(det_data)point_dict = {i: [] for i in range(n)}for point in cloud:if 2 < point[0] < 100 and -30 < point[1] < 30:camera_coordinate = np.dot(mtx, np.dot(r_camera_to_lidar_inv, point.reshape(3, 1) - t_camera_to_lidar))pixe_coordinate = camera_coordinate / camera_coordinate[2]x_pixe, y_pixe, _ = pixe_coordinate# 判断一个点是否在检测框里面idx = np.argwhere((x_pixe >= det_data[:, 0]) & (x_pixe <= det_data[:, 2]) &(y_pixe >= det_data[:, 1]) & (y_pixe <= det_data[:, 3])).reshape(-1)if list(idx):index = int(idx[0])cv2.circle(image, (int(x_pixe), int(y_pixe)), 1, get_box_color(index), 2)point_dict[index].append([point[0], point[1]])for i in range(n):cv2.rectangle(image, (int(det_data[i][0]), int(det_data[i][1])), (int(det_data[i][2]), int(det_data[i][3])),get_box_color(int(det_data[i][4])), 2) # 不同类别画不同颜色框np_data = np.array(point_dict[i])if len(np_data) < 3:continuex = np.min(np_data[:, 0])min_index = np.argmin(np_data, axis=0)y = np.average(np_data[min_index, 1])cv2.putText(image, '{},{}'.format(round(x, 1), round(y, 1)), (int(det_data[i][0]), int(det_data[i][1]) - 10),cv2.FONT_HERSHEY_COMPLEX, 1, get_box_color(int(det_data[i][4])), 2)video.write(image)if show:cv2.namedWindow("show", 0)cv2.imshow("show", image)cv2.waitKey(0)def main():pcd_file_paths = os.listdir(pcd_dir)img_file_paths = os.listdir(img_dir)len_diff = max(0, len(pcd_file_paths) - len(img_file_paths))img_file_paths.sort(key=lambda x: float(x[:-4]))pcd_file_paths.sort(key=lambda x: float(x[:-4]))pcd_file_paths = [pcd_dir + x for x in pcd_file_paths]img_file_paths = [img_dir + x for x in img_file_paths]det_data = np.loadtxt(det_dir, delimiter=',')for i in range(min(len(img_file_paths), len(pcd_file_paths))):pcd = o3d.io.read_point_cloud(pcd_file_paths[i + len_diff]) # 点云now = datetime.now()dets_frame = GetDetFrameRes(det_data, i)point_to_image(img_file_paths[i], pcd, dets_frame, show=show)print(i, datetime.now() - now)video.release()if __name__ == '__main__':color_label = [(255, 0, 0), (121, 68, 222), (0, 0, 255), (0, 255, 0), (199, 199, 53)] # 红黄蓝绿青path = "F:\\data\\"pcd_dir = path + "lidar_points\\" # 点云文件夹绝对路径img_dir = path + "image_raw\\" # 图片文件夹绝对路径det_dir = path + "result.txt" # 目标检测信息video_dir = path + "point_img4.mp4"video = cv2.VideoWriter(video_dir, cv2.VideoWriter_fourcc('m', 'p', '4', 'v'), 10, (1920, 1080)) # 保存视频cali_dir = "sensor.yaml"mtx, r_camera, t_camera, lidar_to_car = read_yaml(cali_dir)r_lidar, t_lidar = lidar_to_car[:3, :3], lidar_to_car[:3, -1].reshape(3, 1)r_camera_to_lidar = np.linalg.inv(r_lidar) @ r_camerar_camera_to_lidar_inv = np.linalg.inv(r_camera_to_lidar)t_camera_to_lidar = np.linalg.inv(r_lidar) @ (t_camera - t_lidar) # 前相机,主雷达标定结果show = Truemain()
五、学习交流
有任何疑问可以私信我,欢迎交流学习。
相关文章:
【目标测距】雷达投影测距
文章目录 前言一、读取点云二、点云投影图片三、读取检测信息四、点云投影测距五、学习交流 前言 雷达点云投影相机。图片目标检测,通过检测框约束等等对目标赋予距离。计算消耗较大,适合离线验证操作。在线操作可以只投影雷达检测框。 一、读取点云 py…...
uniapp、小程序canvas相关
1、圆形or圆形头像 //示例 const ctx uni.createCanvasContext(myCanvas); //canvas const round uni.upx2px(72) / 2; // 半径 const x uni.upx2px(92); //目标x轴位置 const y uni.upx2px(236); //目标y轴位置//if 图片是不是静态资源 async > const imgSrc https:/…...
[工业自动化-23]:西门子S7-15xxx编程 - 软件编程 - 西门子PLC人机界面交互HMI功能概述、硬件环境准备、软件环境准备
目录 一、什么是人机界面 二、什么是PLC人机交互界面HMI 三、人机界面设计的功能列表 四、开发主机与PLC的连接方式 五、开发主机与HMI的连接方式 六、HMI组态 一、什么是人机界面 人机界面是指人与机器或系统之间的交互界面。它是人类与计算机或其他设备之间进行信息交换…...
在Ubuntu系统中安装VNC并结合内网穿透实现公网远程访问
🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…...
java基础练习缺少项目?看这篇文章就够了(上)!
公众号:全干开发 。 专注分享简洁但高质量的动图技术文章! 项目概述 本教程适合刚学习完java基础语法的同学,涉及if语句、循环语句、类的封装、集合等基础概念,使用大量gif图帮助读者演示代码操作、效果等,是一个非常…...
鸿蒙为什么使用typescript 作为开发语言 而不是 flutter 或者 kotlin
猜想如下 dev studio 是基于 idea 二次开发的 ,使用kotlin 应该是更合理 变成 jetbrain 全家桶, 但是 现在android 开发也是kotlin 是不是为了做分割 ,所以不使用kotlin flutter 是谷歌的 安卓也是谷歌的 所以不采用 typescript 是微软的…...
Flutter NestedScrollView 、SliverAppBar全解析,悬浮菜单的应用
在我们开发过程中经常会使用到悬浮菜单的使用,当我们滑动到指定位置后,菜单会自动悬浮。 实现效果如下(左为滑动前、右为滑动后): 上述便是通过NestedScrollView 、SliverAppBar实现的效果,通过两个控件我…...
Mongodb 副本集名称重命名
副本集重命名 要重命名副本集,您必须关闭副本集的所有成员,然后使用新的副本集名称配置每个成员的数据库。 此过程需要停机。 先决条件 确保您的副本集未分片。重命名过程仅适用于未分片的副本集。 在重命名副本集之前,请 对 MongoDB 部…...
C#WPF属性触发器实例
本文讲解C#WPF属性触发器的实例 在属性触发器中,当一个属性发生更改时,它将立即或动画更改另一个属性 实例 <Windowx:Class="TriggerDemo.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://sch…...
Kotlin 核心语法,为什么选择Kotlin ?
Kotlin 是一个基于 JVM 的新的编程语言,由 JetBrains 开发。与Java相比,Kotlin的语法更简洁、更具表达性,而且提供了更多的特性。 Kotlin是使用Java开发者的思维被创建的,Intellij作为它主要的开发IDE。对于 Android开发者&#…...
SpringCloud微服务:Nacos的集群、负载均衡、环境隔离
目录 集群 在user-service的yml文件配置集群 启动服务 负载均衡 order-service配置集群 设置负载均衡 当本地集群的服务挂掉时 访问权重 环境隔离 1、Nacos服务分级存储模型 一级是服务,例如userservice 二级是集群,例如杭州或上海 …...
Selenium+Python做web端自动化测试框架实战
最近受到万点暴击,由于公司业务出现问题,工作任务没那么繁重,有时间摸索seleniumpython自动化测试,结合网上查到的资料自己编写出适合web自动化测试的框架,由于本人也是刚刚开始学习python,这套自动化框架目…...
Linux:安装MySQL服务(非docker方式)
1、下载安装包 下载MySQL安装包,需要Oracle官网的账号 下面是网友提供的账号及密码,亲测有效。 账户:3028064308qq.com 我用的这个,可以登陆 密码:OraclePassword123!Oracle Account: 602205528qq.com Oracle Pass…...
C++实现有理数类 四则运算和输入输出
面试 C 程序员,什么样的问题是好问题? - 知乎 https://www.cnblogs.com/bwjblogs/p/12982908.html...
小鸟飞呀飞
欢迎来到程序小院 小鸟飞呀飞 玩法:鼠标控制小鸟飞翔的方向,点击鼠标左键上升,不要让小鸟掉落,从管道中经过,快去飞呀飞哦^^。开始游戏https://www.ormcc.com/play/gameStart/204 html <canvas width"288&quo…...
Unity 场景烘培 ——unity Post-Processing后处理1(四)
提示:文章有错误的地方,还望诸位大神不吝指教! 文章目录 前言一、Post-Processing是什么?二、安装使用Post-Processing1.安装Post-Processing2.使用Post-Processing(1).添加Post-process Volume(…...
Burpsuite抓HTTPS证书导入问题
Burpsuite证书导出有两种方法: 第一种方法 1、开启代理后直接在浏览器中输入burp下载CA证书 2、在中间证书颁发机构中导入刚导出的证书 3、导入完成后再把这个证书选择导出,另存为cer格式的文件 4、在受信任的根证书颁发机构中导入刚保存的cer格式证书…...
python保存文件到zip压缩包中
这里我们使用zipfile这个库进行操作,保存压缩文件相对简单,只需要指定文件名即可,不需要读取那个文件: with zipfile.ZipFile("zip文件路径", mode, zipfile.ZIP_DEFLATED) as z:z.write("压缩源文件路径", …...
java发送媒体类型为multipart/form-data的请求
文章目录 public static String sendMultipartFormDataPostRequest(String urlString, String data) throws IOException {String fullUrl urlString "?" data;log.info("完整请求路径为{}", fullUrl);URL url new URL(fullUrl);HttpURLConnection co…...
自定义类使用ArrayList中的remove
Java中ArrayList对基础类型和字符串类型的删除操作,直接用remove方法即可。但是对于自定义的类来说,用remove方法删除不了,因为没有办法确定是否是要删除的对象。 ArrayList中remove源码是: public boolean remove(Object o) {if…...
突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
日常一水C
多态 言简意赅:就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过,当子类和父类的函数名相同时,会隐藏父类的同名函数转而调用子类的同名函数,如果要调用父类的同名函数,那么就需要对父类进行引用&#…...
云原生周刊:k0s 成为 CNCF 沙箱项目
开源项目推荐 HAMi HAMi(原名 k8s‑vGPU‑scheduler)是一款 CNCF Sandbox 级别的开源 K8s 中间件,通过虚拟化 GPU/NPU 等异构设备并支持内存、计算核心时间片隔离及共享调度,为容器提供统一接口,实现细粒度资源配额…...
绕过 Xcode?使用 Appuploader和主流工具实现 iOS 上架自动化
iOS 应用的发布流程一直是开发链路中最“苹果味”的环节:强依赖 Xcode、必须使用 macOS、各种证书和描述文件配置……对很多跨平台开发者来说,这一套流程并不友好。 特别是当你的项目主要在 Windows 或 Linux 下开发(例如 Flutter、React Na…...
【HarmonyOS 5】鸿蒙中Stage模型与FA模型详解
一、前言 在HarmonyOS 5的应用开发模型中,featureAbility是旧版FA模型(Feature Ability)的用法,Stage模型已采用全新的应用架构,推荐使用组件化的上下文获取方式,而非依赖featureAbility。 FA大概是API7之…...
TJCTF 2025
还以为是天津的。这个比较容易,虽然绕了点弯,可还是把CP AK了,不过我会的别人也会,还是没啥名次。记录一下吧。 Crypto bacon-bits with open(flag.txt) as f: flag f.read().strip() with open(text.txt) as t: text t.read…...

