【目标跟踪】跨相机如何匹配像素

news/2024/2/25 13:03:28/文章来源:https://blog.csdn.net/qq_49560248/article/details/135523179

文章目录

    • 前言
    • 一、计算思路
    • 二、代码
    • 三、结果

前言

  1. 本篇博客介绍一种非常简单粗暴的方法,做到跨相机像素匹配。
  2. 已知各相机内外参,计算共视区域像素投影(不需要计算图像特征)。废话不多说,直接来,见下图。

同一时刻相机A与相机B的图

相机A

在这里插入图片描述

相机B

在这里插入图片描述

问:相机 A 检测出目标1 box位置,如何计算得出目标1在相机 B 中像素的位置?

在这里插入图片描述


一、计算思路

  1. 取相机 A 目标1中一个像素点 (Ua, Va)
  2. 计算改点在相机A中的相机坐标系坐标 (Xa,Ya,Za)
  3. 相机 A 坐标转化到相机 B 下的相机坐标 (Xb,Yb,Zb)
  4. (Xb,Yb,Zb) 转化到像素坐标 (Ub,Vb)

第2点与第3点中像素坐标转化到相机坐标。

在这里插入图片描述

其中Zcamera 可以近似求出。看过之前博客的朋友应该可以明白,具体计算方式,代码会全部给出。

第3点就是一个三维坐标系旋转平移变化。

在这里插入图片描述

二、代码

import yaml
import numpy as np
import cv2def read_yaml(path):with open(path, 'r', encoding='utf-8') as f:result = yaml.load(f.read(), Loader=yaml.FullLoader)return resultdef get_r_t_mtx(path, f_r_b_l):sensor_list = ["front_center", "right_center", "back_center", "left_center"]yaml_result = read_yaml(path)  # 读取yaml配置文件hres_pitch = yaml_result[sensor_list[f_r_b_l]]["pitch"]res_h = yaml_result[sensor_list[f_r_b_l]]["height"]res_r = np.array(yaml_result[sensor_list[f_r_b_l]]["rotation"]).reshape(3, 3)res_t = np.array(yaml_result[sensor_list[f_r_b_l]]["translation"]).reshape(3, 1)res_mtx = np.array(yaml_result[sensor_list[f_r_b_l]]["K"]).reshape(3, 3)return res_pitch, res_h, res_mtx, res_r, res_t# 近似计算相机坐标系 Zcamera
def get_camera_z(children, pixe_y):pitch, h, K, *_ = childrensigma = np.arctan((pixe_y - K[1][2]) / K[1][1])z = h * np.cos(sigma) / np.sin(sigma + pitch)  # 深度return zdef get_sensor_pixe(children, parent, x, y, distance):r, t = get_two_camera_r_t(children, parent)children_pitch, children_h, children_mtx, *c = childrenparent_pitch, parent_h, parent_mtx, *p = parentdistance_init = distancex = (x - children_mtx[0][2]) / children_mtx[0][0]y = (y - children_mtx[1][2]) / children_mtx[1][1]coor = np.array([x, y, 1]).reshape(3, 1) * distance_initres_coor = r @ coor + t  # 车体坐标系res_x = (res_coor[0] / res_coor[2]) * parent_mtx[0][0] + parent_mtx[0][2]res_y = (res_coor[1] / res_coor[2]) * parent_mtx[1][1] + parent_mtx[1][2]return res_x, res_ydef show_img(img):cv2.namedWindow("show")cv2.imshow("show", img)cv2.waitKey(0)def get_two_camera_r_t(children, parent):*children, children_mtx, children_r, children_t = children*parent, parent_mtx, parent_r, parent_t = parentres_r = np.array(parent_r).T @ np.array(children_r)res_t = np.array(parent_r).T @ (np.array(children_t) - np.array(parent_t)).reshape(3, 1)return res_r, res_tdef get_uv(point, param):*p, mtx, r, t = paramcoor_camera = r.T @ (np.array(point).reshape(3, 1) - t)coor_pixe = mtx @ coor_camera * (1 / coor_camera[2])return coor_pixe[0][0], coor_pixe[1][0]if __name__ == '__main__':front_img = cv2.imread("front_img.jpg")left_img = cv2.imread("left_img.jpg")img = np.concatenate((left_img, front_img), axis=1)  # 横向拼接front_param = get_r_t_mtx("./sensor_param.yaml", 0)left_param = get_r_t_mtx("./sensor_param.yaml", 3)color = np.random.randint(0, 255, (3000, 3))  # 随机颜色car_coor = [5.41, 6.5, 1.3]camera1 = np.ravel(get_uv(car_coor, left_param))camera2 = np.ravel(get_uv(car_coor, front_param))print(camera1, camera2)cv2.circle(img, (int(camera1[0]), int(camera1[1])), 1, color[0].tolist(), 2)cv2.circle(img, (int(camera2[0]) + 1920, int(camera2[1])), 1, color[1].tolist(), 2)cv2.line(img, (int(camera1[0]), int(camera1[1])), (int(camera2[0] + 1920), int(camera2[1])), color[0].tolist(), 2)show_img(img)# print(get_two_camera_r_t(front_param, left_param))# print(front_to_left_r.reshape(-1), "\n", front_to_left_t)# distance = get_camera_z(left_param, 640)# x1, y1 = 1429, 488# x2, y2 = 1509, 637# for x in range(x1, x2, 20):#     for y in range(y1, y2, 20):#         res_x, res_y = get_sensor_pixe(left_param, front_param, x, y, distance)#         cv2.circle(img, (int(x), int(y)), 1, color[x].tolist(), 5)#         cv2.circle(img, (int(res_x) + 1920, int(res_y)), 1, color[x].tolist(), 5)# cv2.line(img, (int(x) , int(y)), (int(res_x)+ 1920, int(res_y)), color[x].tolist(), 2)# distance = get_camera_z(front_param, 649)# x1, y1 = 271, 469# x2, y2 = 353, 649# for x in range(x1, x2, 20):#     for y in range(y1, y2, 20):#         res_x, res_y = get_sensor_pixe(front_param, left_param, x, y, distance)#         cv2.circle(img, (int(x) + 1920, int(y)), 1, color[x].tolist(), 2)#         cv2.circle(img, (int(res_x), int(res_y)), 1, color[x].tolist(), 2)# cv2.line(img, (int(x) + 1920, int(y)), (int(res_x), int(res_y)), color[x].tolist(), 2)# show_img(img)

三、结果

在这里插入图片描述

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

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

相关文章

C#--核心

CSharp核心知识点学习 学习内容有: 绪论:面向对象的概念 Lesson1:类和对象 练习: Lesson2:封装--成员变量和访问修饰符 练习: Lesson3:封装--成员方法 Lesson4:封装--构造函数和析构函数 知识点四 垃圾回收…

git主分支合并到本地分支起冲突的解决办法

1.原因:一个项目几个人共同承担,难免有交叉的部分,这个时候交叉部分的提交就会导致冲突 2.方法:点开该类手动进行更改: 一般会有两种情况:一个是更改,一个是冲突(IDEA右上角会显示);…

meter报OOM错误,如何解决?

根据在之前的压测过程碰到的问题,今天稍微总结总结,以后方便自己查找。 一、单台Mac进行压测时候,压测客户端Jmeter启动超过2000个线程,Jmeter报OOM错误,如何解决? 解答:单台Mac配置内存为8G&…

详解java中ArrayList

目录 前言 一、ArrayList是什么 二、ArrayList使用 1、ArrayList的构造 2 、ArrayList常见操作 3、 ArrayList的遍历 4、 ArrayList的扩容机制 三、来个练习 前言 当你看到这篇文章我觉得很好笑,因为我开始也不懂ArrayList现在轮到你了,嘻嘻嘻&am…

GRE隧道(初级VPN)配置步骤

一、拓朴图: 要求:1、PC1 和 PC2 能访问充当互联网接口地址的ISP环回口地址8.8.8.8 2、PC1 和 PC2 走GRE隧道互通 二、配置步骤: 1、配置IP 2、R1、R2 配置nat,代理内网地址通过G0/0/0口上外网 acl 2000rule permit source a…

Nginx配置负载均衡实例

Nginx配置反向代理实例二 提醒一下:下面实例讲解是在Mac系统演示的; 负载均衡实例实现的效果 浏览器地址栏输入地址http://192.168.0.101/test/a.html,刷新页面进行多次请求,负载均衡效果,平均分配到8080端口服务和8…

iOS解决内存泄漏工具

在iOS应用中,有一些工具和技术可以帮助识别和解决内存泄漏问题。以下是一些常用的工具,希望对大家有所帮助。北京木奇移动技术有限公司,专业的软件外包开发公司,欢迎交流合作。 1.Instruments: Instruments 是Xcode中…

分布式搜索引擎--认识

elasticsearch的作用 elasticsearch是一款非常强大的开源搜索引擎,具备非常多强大功能,可以帮助我们从海量数据中快速找到需要的内容 。 elasticsearch结合kibana、Logstash、Beats,也就是elastic stack(ELK)。被广泛…

行为型设计模式——备忘录模式

备忘录模式 备忘录模式提供了一种状态恢复的实现机制,使得用户可以方便地回到一个特定的历史步骤,当新的状态无效或者存在问题时,可以使用暂时存储起来的备忘录将状态复原,很多软件都提供了撤销(Undo)操作…

使用mamba替换conda和anaconda配置环境安装软件

使用mamba替换miniconda和anaconda,原因是速度更快,无论是创建新环境还是激活环境 conda、mamba、anaconda都是蟒蛇的意思… 下载mambaforge wget https://github.com/conda-forge/miniforge/releases/latest/download/Mambaforge-Linux-x86_64.sh ba…

基于Matlab/Simulink开发自动驾驶的解决方案

文章目录 处理自动驾驶数据 仿真自动驾驶场景 设计感知算法 设计规划和控制算法 生成代码和部署算法 集成和测试 参考文献 使用 MATLAB/Simulink开发自动驾驶,能够深入建模真实世界的行为、减少车辆测试并验证嵌入式软件的功能,从而推进自动驾驶感…

Mybatis 常用条件语句,大于小于、if、for、模糊搜索、case when、choose

大于小于 方法1&#xff1a; > 大于 &#xff0c; < 小于 <if test"startTime ! null ">and a.create_time > #{startTime} </if> <if test"endTime ! null ">and a.create_time < #{endTime} </if> 方法2(建议写这…

java每日一题——ATM系统编写(答案及编程思路)

前言&#xff1a; 基础语句学完&#xff0c;也可以编写一些像样的程序了&#xff0c;现在要做的是多加练习&#xff0c;巩固下知识点&#xff0c;打好基础&#xff0c;daydayup! 题目&#xff1a;模仿银行ATM系统&#xff0c;可以创建用户&#xff0c;存钱&#xff0c;转账&…

一、MySQL 卸载

目录 1、软件的卸载准备 2、软件的卸载 方式一&#xff1a;通过控制面板卸载 方式二&#xff1a;通过mysql8的安装向导卸载 1、双击mysql8的安装向导 2、取消更新 3、选择要卸载的mysql服务器软件的具体版本 4、确认删除数据目录 5、执行删除 6、完成删除 3、清理残…

半小时实现GPT纯血鸿蒙版

仅需半小时&#xff0c;即可实现纯血鸿蒙版本的ChatGPT&#xff01; 废话少说&#xff0c;先看效果图&#xff1a; 如上图所示&#xff0c;这个小Demo实现了AI智能问答。靠右加粗的文本是用户点击底部提交按钮后出现的&#xff1b;后面靠左对齐的普通文本是来自AI的回答内容。当…

鸿蒙(HarmonyOS)应用开发指南

1. 概述 1.1 简介 鸿蒙&#xff08;即 HarmonyOS &#xff0c;开发代号 Ark&#xff0c;正式名称为华为终端鸿蒙智能设备操作系统软件&#xff09;是华为公司自 2012 年以来开发的一款可支持鸿蒙原生应用和兼容 AOSP 应用的分布式操作系统。该系统利用“分布式”技术将手机、电…

第十七周周报

文章目录 摘要目标检测锚框交并比NMS 非极大值抑制输出 文献阅读&#xff1a;SMPL: A Skinned Multi-Person Linear ModelIntroductionRelated WorkModel FormulationTraining评估动态SMPL讨论结论 总结 摘要 本周看了三维人体重建的领域&#xff0c;看了一篇SMPL的文章&#…

【sqlite3】sqlite3在linux下使用sqlitebrowser工具实现数据可视化

sqlite3在linux下使用sqlitebrowser工具实现数据可视化 1. ### install sqlitebrowser 1. ### install sqlitebrowser 安装指令 sudo apt-get install sqlitebrowser通过工具打开数据库 sqlitebrowser stereo.db打开效果

【蓝桥杯日记】第一篇——如何搭建系统环境

目录 前言 环境相关文件 学生机环境-Web应用开发环境&#xff08;第十五届大赛&#xff09; 学生机环境-Java编程环境&#xff08;第十五届大赛&#xff09; 学生机环境-C/C编程环境&#xff08;第十五届大赛&#xff09; 学生机环境-Python编程环境 &#xff08;第十五届…

Spring Boot - Application Events 同步 VS 异步 发布订阅事件实战

文章目录 PreCode基础工程启动类切入口事件 发布事件同步 Listener异步Listener增加EnableAsync增加 Async 测试 Pre Spring Boot - Application Events 的发布顺序_ApplicationStartingEvent Spring Boot - Application Events 的发布顺序_ApplicationEnvironmentPreparedEv…