【目标跟踪】跨相机如何匹配像素
文章目录
- 前言
- 一、计算思路
- 二、代码
- 三、结果
前言
- 本本篇博客介绍一种非常简单粗暴的方法,做到跨相机像素匹配。
- 已知各相机内外参,计算共视区域像素投影(不需要计算图像特征)。废话不多说,直接来,见下图。
同一时刻相机A与相机B的图
相机A

相机B

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

一、计算思路
- 取相机 A 目标1中一个像素点 (Ua, Va)
- 计算改点在相机A中的相机坐标系坐标 (Xa,Ya,Za)
- 相机 A 坐标转化到相机 B 下的相机坐标 (Xb,Yb,Zb)
- (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)
三、结果

相关文章:
【目标跟踪】跨相机如何匹配像素
文章目录 前言一、计算思路二、代码三、结果 前言 本本篇博客介绍一种非常简单粗暴的方法,做到跨相机像素匹配。已知各相机内外参,计算共视区域像素投影(不需要计算图像特征)。废话不多说,直接来,见下图。…...
Python 发微信:实现自动化沟通的利器
引言: 在当今信息爆炸的时代,微信已经成为人们日常生活中不可或缺的沟通工具。然而,手动发送微信消息往往耗时耗力,尤其是在需要频繁发送消息的场景下。为了提高工作效率和便利性,我们可以利用 Python 编程语言来实现自…...
计算机网络——HTTP协议
1. HTTP的概述 HTTP(超文本传输协议),定义在RFC2616中,是用于分布式和协作式多媒体系统之间交互的应用层通信协议。 1.1 无状态 HTTP是一个无状态协议,意味着它不保存先前交互的记录。每个请求都独立于其他请求处理。…...
QT上位机开发(利用tcp/ip访问plc)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 plc是工控领域很重要的一个器件。简单的plc一般就是对io进行控制,但是复杂的plc,还可以控制电机、变频器,在工业…...
MySQL-多表连接查询
🎉欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克🍹 ✨博客主页:小小恶斯法克的博客 🎈该系列文章专栏:重拾MySQL 🍹文章作者技术和水平很有限,如果文中出现错误&am…...
Qt第二周周二作业
代码: widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr);~Widget();void paintEvent(…...
docker 学习命令整理
文章目录 docker 学习命令整理(积累中...)0. 启动/停止1. 运行2. 查看运行中docker3. 删除指定container4. 查看本地镜像5. 拉取指定镜像6. 新起终端进入同一container7. 取消sudo8. 查看docker状态9. 查看docker存储10.删除镜像11.删除容器12. qemu12.1 安装12.2 卸载qemu 附&…...
windows安装RabbitMq,修改数据保存位置
1、先安装Erlang, Erlang和RabbitMQ有版本对应关系。 官网RabbitMQ与Erlang版本对应RabbitMQ Erlang Version Requirements — RabbitMQ 2、安装RabbitMQ。 3、修改数据保存地址。找到安装目录下的sbin文件夹,找到rabbitmq-env.bat,编辑文件…...
Redis面试题18
Redis 支持集群模式吗?如何实现 Redis 的集群? 答:是的,Redis 支持集群模式,并提供了 Redis Cluster 来实现分布式数据存储和高可用性。 Redis Cluster 是通过将数据分散到多个节点上来实现的,每个节点都拥…...
python实现文件批量分发
在Python中实现文件的批量分发通常涉及到文件的读取、网络通信以及目标系统上的文件写入。这里有几种方法来实现这一功能,但最常见的方法之一是使用FTP(文件传输协议)或SSH(安全外壳协议)。以下是使用Python通过SSH进行文件批量分发的一个基本示例。这里使用了paramiko库,…...
分销商城多端uniapp 可编译5端 - 等级提现额度
等级提现额度 等级提现额度是一种常见的财务管理策略,通常用于在线平台、金融服务或游戏中,用于控制不同等级用户的提现限额。这样的机制有助于平台管理资金流动性,防范欺诈,并鼓励用户提升他们的活跃度或忠诚度。以下是一个简单的…...
蓝桥杯基础知识5 unique()
蓝桥杯基础知识5 unique() #include <bits/stdc.h>int main(){std::vector<int> vec {1,1,2,2,3,3,3,4,4,5};auto it std::unique(vec.begin(), vec.end());vec.erase(it, vec.end());//vec.erase(unique(vec.begin(),vec.end()),vec.end(…...
设计一个抽奖系统
👏作者简介:大家好,我是爱吃芝士的土豆倪,24届校招生Java选手,很高兴认识大家📕系列专栏:Spring原理、JUC原理、Kafka原理、分布式技术原理、数据库技术🔥如果感觉博主的文章还不错的…...
IntelliJ IDEA使用学习
一、安装教程 网上自行下载,CSDN不然过审二、使用教程 2.1 快捷键操作与设置 设置 Setting——>按键映射——>选择顺手的系统快捷键 编写代码 CtrlShift Enter,语句完成。 “!”,否定完成,输入表达式时按 …...
sqlilabs第五十三五十四关
Less-53(GET - GET - Error based - ORDER BY CLAUSE-String- Stacked injection) 手工注入 单引号闭合,和上一关一样堆叠注入解决 自动注入 和上一关一样 Less-54(GET - challenge - Union- 10 queries allowed -Variation 1) 手工注入 这一关开始后面的可以看…...
❤ Uniapp使用三( 打包和发布上线)
❤ Uniapp使用三( 打包和发布上线) 一、介绍 什么是 uniapp? uniapp 是一种基于 Vue.js 的多平台开发框架,它可以同时用于开发安卓、iOS、H5 等多个平台。因此,只需要写一次代码就可以在多个平台上运行,提高了开发效率。 打包…...
【JavaEEj进阶】 Spring实现留言板
文章目录 🎍预期结果🍀前端代码🎄约定前后端交互接⼝🚩需求分析🚩接⼝定义 🌳实现服务器端代码🚩lombok 🌲服务器代码实现🌴运⾏测试 🎍预期结果 可以发布并…...
react、Vue打包直接运行index.html不空白方法
react vue 在根目录下创建 vue.config.js 文件,写入 module.exports {publicPath: ./, }...
SpringBoot-01
Spring Boot是一个开源的Java框架,用于快速构建独立的、可执行的、生产级的Spring应用程序。它基于Spring框架,简化了Spring应用程序的配置和部署过程,使开发者能够更快速地创建高效、可扩展的应用。 Spring Boot具有以下特点: 简…...
「解析」Jetson配置 git服务
这两天感冒了在家休养,想着把之前买的 Jetson 开发板用起来,买Jetson的初衷就是用来学习Linux系统,顺道可以部署算法,以及一些其他需求,相比树莓派而言,Jetson开发相对更贵,但是其配备了英伟达的…...
RTB点击率预估中的长尾失衡与价值重标定
1. 项目概述:当广告竞价遇上“长尾陷阱”——为什么实时竞价系统里99%的流量不说话,却决定着100%的效果你有没有遇到过这样的情况:训练了一个看起来AUC高达0.92的点击率预估模型,上线后CTR却比老模型还低0.3个百分点?或…...
RunPod H100集群实战:64卡AI训练的物理级优化与成本重构
1. 项目概述:当64张H100不再只是大厂的专利,而是一支创业团队的日常训练环境你有没有算过一笔账:在主流公有云上,用8卡H100节点跑一个70B参数模型的全量微调,单次实验成本动辄上万美元?我去年帮一家做金融垂…...
Layerdivider:AI智能分层工具完整指南 - 快速将单张图片转为分层PSD
Layerdivider:AI智能分层工具完整指南 - 快速将单张图片转为分层PSD 【免费下载链接】layerdivider A tool to divide a single illustration into a layered structure. 项目地址: https://gitcode.com/gh_mirrors/la/layerdivider Layerdivider是一个革命性…...
DownKyi深度解析:重新定义B站视频内容管理的新范式
DownKyi深度解析:重新定义B站视频内容管理的新范式 【免费下载链接】downkyi 哔哩下载姬downkyi,哔哩哔哩网站视频下载工具,支持批量下载,支持8K、HDR、杜比视界,提供工具箱(音视频提取、去水印等ÿ…...
2026 最新 OpenClaw(小龙虾)部署步骤 小白避坑手册
OpenClaw(小龙虾)Windows 一键部署保姆级教程 | 10 分钟养出你的数字员工(2026 最新版) ✨ 前言 2026 年爆火的开源 AI 智能体 OpenClaw(昵称小龙虾),GitHub 星标超 28 万,凭 “本…...
CyberChef:网络安全工程师的终极数据处理瑞士军刀
CyberChef:网络安全工程师的终极数据处理瑞士军刀 【免费下载链接】CyberChef The Cyber Swiss Army Knife - a web app for encryption, encoding, compression and data analysis 项目地址: https://gitcode.com/GitHub_Trending/cy/CyberChef 你是否曾遇到…...
微信好友关系检测:如何发现那些悄悄离开的“单向好友“
微信好友关系检测:如何发现那些悄悄离开的"单向好友" 【免费下载链接】WechatRealFriends 微信好友关系一键检测,基于微信ipad协议,看看有没有朋友偷偷删掉或者拉黑你 项目地址: https://gitcode.com/gh_mirrors/we/WechatRealFr…...
三步解锁RPG Maker MV/MZ加密资源:新手也能快速提取游戏文件
三步解锁RPG Maker MV/MZ加密资源:新手也能快速提取游戏文件 【免费下载链接】RPG-Maker-MV-Decrypter You can decrypt RPG-Maker-MV Resource Files with this project ~ If you dont wanna download it, you can use the Script on my HP: 项目地址: https://g…...
AI Agent落地元年:从对话交互到自主工作流的技术演进与落地实践
2026年被行业公认为AI Agent落地元年,生成式AI彻底告别单纯的参数内卷与对话式交互,进入自主决策、自动执行、闭环迭代的全新阶段。相较于传统大模型被动响应的工作模式,AI Agent凭借感知、规划、执行、复盘的完整闭环能力,成为企…...
达梦数据库-统计信息收集-记录
达梦数据库-统计信息收集-记录总结 1统计信息收集 统计信息主要是描述数据库中表和索引的大小及数据分布状况等信息。比如:表的行数、块数、平均每行的大小、索引的高度、叶子节点数以及索引字段的行数等。统计信息对于CBO(基于代价的优化器࿰…...
