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

文章目录

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

前言

  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 cv2


def read_yaml(path):
    with open(path, 'r', encoding='utf-8') as f:
        result = yaml.load(f.read(), Loader=yaml.FullLoader)
    return result


def 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配置文件h
    res_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, *_ = children
    sigma = np.arctan((pixe_y - K[1][2]) / K[1][1])
    z = h * np.cos(sigma) / np.sin(sigma + pitch)  # 深度
    return z


def get_sensor_pixe(children, parent, x, y, distance):
    r, t = get_two_camera_r_t(children, parent)
    children_pitch, children_h, children_mtx, *c = children
    parent_pitch, parent_h, parent_mtx, *p = parent
    distance_init = distance
    x = (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_init
    res_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_y


def 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 = parent
    res_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_t


def get_uv(point, param):
    *p, mtx, r, t = param
    coor_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)

三、结果

在这里插入图片描述

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

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

相关文章

快速入门Java NIO(Not I/O)的网络通信框架--Netty

Netty 入门 了解netty前需要对nio有一定认识,该笔记基础来自bilinbili黑马,在此基础上自己学习的笔记,添加了一些自己的理解 了解java 非阻塞io编程 1. 概述 1.1 Netty 是什么? Netty is an asynchronous event-driven network application framework for rapid …

掌握这些测试开发技能,从容应对工作难题!

各位小伙伴, 大家好, 本期为大家分享一些测试开发工程师在企业中通过哪些测试开发技能解决难题。 一.如何定位缺陷 在企业中, 小伙伴们在发现bug后, 需要定位到具体产生bug的原因, 在这种情况下, 我们可以通过以下几种方案: 1.通过代理抓包来分析 常用的抓包工具有: Charles…

R语言【paleobioDB】——pbdb_subtaxa():统计指定类群下的子类群数量

Package paleobioDB version 0.7.0 paleobioDB 包在2020年已经停止更新,该包依赖PBDB v1 API。 可以选择在Index of /src/contrib/Archive/paleobioDB (r-project.org)下载安装包后,执行本地安装。 Usage pbdb_subtaxa (data, do.plot, col) Arguments…

Monorepo-uniapp 构建分享

Monorepo uniapp 构建灵感:刚好要做一个项目,于是想到升级一下之前自己写的一个vue3tspiniauno的模版框架,其实那个框架也不错;只是感觉还差点东西,我已经用那个小框架写了两三个项目;轻巧实用。为什么选…

CNN:Convolutional Neural Network(上)

目录 1 为什么使用 CNN 处理图像 2 CNN 的整体结构 2.1 Convolution 2.2 Colorful image 3 Convolution v.s. Fully Connected 4 Max Pooling 5 Flatten 6 CNN in Keras 原视频:李宏毅 2020:Convolutional Neural Network 1 为什么使用…

C#灵活控制多线程的状态(开始暂停继续取消)

ManualResetEvent类 ManualResetEvent是一个同步基元,用于在多线程环境中协调线程的执行。它提供了两种状态:终止状态和非终止状态。 在终止状态下,ManualResetEvent允许线程继续执行。而在非终止状态下,ManualResetEvent会阻塞线…

深度学习-标注文件处理(txt批量转换为json文件)

接上篇,根据脚本可将coco128的128张图片,按照比例划分成训练集、测试集、验证集,同时生成相应的标注的labels文件夹,最近再看实例分离比较火的mask rcnn模型,准备进行调试但由于实验室算力不足,网上自己租的…

stm32 - GPIO

stm32 - GPIO 基本结构输入输出 基本结构 所有GPIO都挂在APB2总线上 寄存器:内核通过APB2总线对寄存器进行读写,实现电平的读写 GPIO引脚的每一位对应寄存器中的某一位 GPIO中的驱动器是增加信号驱动能力的,用于增大驱动能力 输入 读取端口的…

初识C语言·内存函数

目录 1 memcpy的使用和模拟实现 2 memmove的使用和模拟实现 3 memset的使用和模拟实现 4 memcmp的使用和模拟实现 1 memcpy的使用和模拟实现 紧接字符串函数,出场的是第一个内存函数memcpy。前面讲的字符串函数是专门干关于字符串的事的,而这个函数…

如何使用程序控制微信发送消息

简介 使用杨中科老师的nuget包NetAutoGUI,控制微信给指定用户发送消息,如果想下面视频一样使用此功能用来轰炸朋友,可以直接跳到最后一节,或者直接下载我的打包好的程序集 【免费】控制微信发送消息的程序资源-CSDN文库 微信轰炸…

蓝桥杯备赛 | 洛谷做题打卡day5

蓝桥杯备赛 | 洛谷做题打卡day5 图论起航,一起来看看深(广)度优先吧 ~ 文章目录 蓝桥杯备赛 | 洛谷做题打卡day5图论起航,一起来看看深(广)度优先吧 ~【深基18.例3】查找文献题目描述 输入格式输出格式样例…

《如何制作类mnist的金融数据集》——1.数据集制作思路

1.数据集制作思路(生成用于拟合金融趋势图像的分段线性函数) 那么如何去制作这样的一个类minist的金融趋势曲线数据集呢? 还是如上图所示,为了使类别平均分布,因此可以选取三种“buy”的曲线、三种“sell”…

Web前端 ---- 【Vue3】computed计算属性和watch侦听属性(侦听被ref和reactive包裹的数据)

目录 前言 computed watch watch侦听ref数据 ref简单数据类型 ref复杂数据类型 watch侦听reactive数据 前言 本文介绍在vue3中的computed计算属性和watch侦听属性。介绍watch如何侦听被ref和reactive包裹的数据 computed 在vue3中,计算属性computed也是组合式…

C语言天花板——指针(经典题目)

指针我们已经学习的差不多了,今天我来给大家分享几个经典的题目,来让我们相互学习🏎️🏎️🏎️ int main() {int a[4] { 1, 2, 3, 4 };int* ptr1 (int*)(&a 1);int* ptr2 (int*)((int)a 1);printf("%x,%…

Java重修第六天—面向对象3

通过学习本篇文章可以掌握如下知识 1、多态; 2、抽象类; 3、接口。 之前已经学过了继承,static等基础知识,这篇文章我们就开始深入了解面向对象多态、抽象类和接口的学习。 多态 多态是在继承/实现情况下的一种现象&#xf…

随笔03 笔记整理

图源:文心一言 关于我的考研与信息安全类博文整理~🥝🥝 第1版:整理考研类博文~🧩🧩 第2版:提前列出博文链接,以便小伙伴查阅~🧩🧩 第3版:整理We…

学习记录-自动驾驶与机器人中的SLAM技术

以下所有内容均为高翔大神所注的《自动驾驶与机器人中的SLAM技术》中的内容 融合导航 1. EKF和优化的关系 2. 组合导航eskf中的预测部分&#xff0c;主要是F矩阵的构建 template <typename S> bool ESKF<S>::Predict(const IMU& imu) {assert(imu.timestamp…

基于杂交PSO算法的风光储微网日前优化调度(MATLAB实现)

微网中包含&#xff1a;风电、光伏、储能、微型燃气轮机&#xff0c;以最小化电网购电成本、光伏风机的维护成本、蓄电池充放电维护成本、燃气轮机运行成本及污染气体治理成本为目标&#xff0c;综合考虑&#xff1a;功率平衡约束、燃气轮机爬坡约束、电网交换功率约束、储能装…

Elasticsearch_8.11.4_kibana_8.11.4_metricbeat_8.11.4安装及本地部署_ELK日志部署

文章目录 Elasticsearch_8.11.4_kibana_8.11.4_metricbeat_8.11.4安装及本地部署_ELK日志部署分布式引擎Elasticsearch_8.11.4安装及本地部署系统环境要求1 Windows 安装 Elasticsearch下载完成后进行解压,进入 bin 目录,找到elasticsearch.bat脚本文件执行一键启动.启动都选允…

【Python学习】Python学习15-模块

目录 【Python学习】Python学习15-模块 前言创建语法引入模块from…import 语句from…import* 语句搜索路径PYTHONPATH 变量-*- coding: UTF-8 -*-导入模块现在可以调用模块里包含的函数了PYTHONPATH 变量命名空间和作用域dir()函数globals() 和 locals() 函数reload() 函数Py…