计算机视觉——两视图几何求解投影矩阵

news2025/1/18 17:04:52

上文我提到了通过图像匹配得到基本矩阵,接下来我们要接着求解投影矩阵。

计算投影矩阵思路

假设两个投影矩阵为规范化相机,因此采用基本矩阵进行恢复。在规范化相机下, P = [ I ∣ 0 ] P=[I|0] P=[I∣0], P ′ = [ M ∣ m ] P'=[M|m] P=[Mm]
我们知道一对 ( P , P ′ ) (P,P') (P,P)可以唯一确定基本矩阵 F = [ m ] x M F=[m]_xM F=[m]xM,而基本矩阵则在相差一个射影变换的意义下才能唯一对应一组 ( P , P ′ ) (P,P') (P,P)
P = [ I ∣ 0 ] P=[I|0] P=[I∣0], P ′ = [ [ e ′ ] x F ∣ e ′ ] P'=[[e']_xF|e'] P=[[e]xFe],其中 e ′ e' e e ′ T F = 0 e'^TF=0 eTF=0的对极点。因此我们需要求解对极点。而对极点是极线聚焦的点:
l 1 × l 2 = e l_1 ×l_2=e l1×l2=e
同时我们可以通过两点确定一条直线:
p 1 × p 2 = l p_1 × p_2 = l p1×p2=l

这种点叉积为线,线叉积为点叫做对偶

def drawlines(img1,img2,lines,pts1,pts2):

    r,c,_ = img1.shape
    for r,pt1,pt2 in zip(lines,pts1,pts2):
        color = tuple(np.random.randint(0,255,3).tolist())
        x0,y0 = map(int, [0, -r[2]/r[1] ])
        x1,y1 = map(int, [c, -(r[2]+r[0]*c)/r[1] ])
        img1 = cv2.line(img1, (x0,y0), (x1,y1), color,1)
        img1 = cv2.circle(img1,tuple(pt1),5,color,-1)
        img2 = cv2.circle(img2,tuple(pt2),5,color,-1)
    return img1,img2

pts1 = np.int32(src_points)
pts2 = np.int32(dst_points)
lines1 = cv2.computeCorrespondEpilines(pts2.reshape(-1,1,2), 2,F)
lines1 = lines1.reshape(-1,3)
img_line1,_ = drawlines(left_img,right_img,lines1,pts1,pts2)

lines2 = cv2.computeCorrespondEpilines(pts1.reshape(-1,1,2), 1,F)
lines2 = lines2.reshape(-1,3)
img_line2,_ = drawlines(right_img,left_img,lines2,pts2,pts1)

在这里插入图片描述
然后我们统计一下对极点,还是采用SVD分解。因为两条直线相交能够唯一确定一个点,而我们这里有数十条直线,它们不一定能确保相交于一个点。因此我们需要找到一个点 e e e,使得 e e e到每一条直线的距离和最小,也就是:
a r g m i n e ∑ i N d i s t ( l i , e ) \underset{e}{argmin}\sum_{i}^{N} dist(l_i,e) eargminiNdist(li,e)
然后根据我上面写的公式 P = [ I ∣ 0 ] P=[I|0] P=[I∣0], P ′ = [ [ e ′ ] x F ∣ e ′ ] P'=[[e']_xF|e'] P=[[e]xFe]即可算出P矩阵

Ⅰ. [ a ] x [a]_x [a]x表示a×b中a的矩阵写法。当我们计算两个向量的叉积时,可以将向量写成一个反对称矩阵 [ a ] x [a]_x [a]x的形式。
Ⅱ. 设 a ⃗ = ( a 1 , a 2 , a 3 ) , [ a ] x = [ 0 − a 3 a 2 a 3 0 − a 1 − a 2 a 1 0 ] 设\vec{a}=(a_1,a_2,a_3),[a]_x=\begin{bmatrix} 0 & -a_3 &a_2 \\ a_3 & 0 & -a_1 \\ -a_2 & a_1 & 0 \end{bmatrix} a =(a1,a2,a3)[a]x= 0a3a2a30a1a2a10
Ⅲ. np.array格式的矩阵可以用@进行相乘,当然还有np.dot(),np.multiply(),np.matmul(),可以查一下区别。

def getEpiPoint(A):
    U,sigma,VT = np.linalg.svd(A)
    pts = VT.T[:,-1]
    pts  = pts / pts[2]
    return pts
Epts1 = getEpiPoint(lines1) 
Epts2 = getEpiPoint(lines2)
e2x = np.array([[0,-Epts2[2],Epts2[1]],[Epts2[2],0,-Epts2[0]],[-Epts2[1],Epts2[0],0]])
P1 = np.array([[1,0,0,0],
      [0,1,0,0],
      [0,0,1,0]])
P2 = np.column_stack((e2x @ F,np.array(Epts2).T))

对投影矩阵分解得到内参

我们知道 P = K [ R ∣ t ] = [ K R ∣ K t ] P=K[R|t]=[KR|Kt] P=K[Rt]=[KRKt],设 P P P前三列为 P ^ \hat P P^,那么我们对 P ^ \hat P P^进行QR分解可以得到两矩阵。在QR分解中,左Q矩阵为正交矩阵,右R矩阵为上三角矩阵,而 P ^ = K R \hat{P}=KR P^=KR中K为上三角矩阵,R为正交矩阵,与QR分解得到的矩阵并不能对应上。因此我们应该先对 P ^ \hat{P} P^进行求逆, P ^ − 1 = R − 1 K − 1 \hat{P}^{-1}=R^{-1}K^{-1} P^1=R1K1,而正交矩阵和上三角矩阵的逆仍保持自身的性质,因此我们对 P ^ \hat{P} P^进行QR分解,得到矩阵再求一遍逆即可。

def decompose_projection_matrix(projection_matrix):

    R_inv, K_inv = np.linalg.qr(np.linalg.inv(projection_matrix[:, :3])) 
    K_inv_tmp = K_inv
    K_inv /= K_inv[2, 2]  # 归一化

    K = np.linalg.inv(K_inv)
    R = np.linalg.inv(R_inv)
    # if np.linalg.det(K) < 0:
    #     K *= -1
    extrinsic_matrix = np.matmul(K_inv_tmp, projection_matrix)

    return K, R, extrinsic_matrix

线性三角测量

投影矩阵是将世界三维点投影到图像二维点,因此我们想通过图像二位点和投影矩阵恢复出三维点,从而恢复出图像中物体三维结构,这个过程叫做三维重建。想要恢复出较好的三维图,需要大量的多角度图片进行拍摄和计算。而两张图片只能用于简单的三维坐标计算。
λ [ x y 1 ] = P [ X Y Z 1 ] \lambda \begin{bmatrix} x\\ y\\ 1 \end{bmatrix}=P\begin{bmatrix} X \\ Y \\ Z \\ 1 \end{bmatrix} λ xy1 =P XYZ1
想要使用SVD分解就需要构造 A X = 0 AX=0 AX=0的形式。我们发现xPX是成比例的的,因此x × PX=0,从而得到:
x ( p 3 T X ) − ( p 1 T X ) = 0 y ( p 3 T X ) − ( p 2 T X ) = 0 x ( p 2 T X ) − y ( p 1 T X ) = 0 \begin{align*} x(p^{3T}X)-(p^{1T}X) & = 0 \\ y(p^{3T}X)-(p^{2T}X) & =0\\ x(p^{2T}X)-y(p^{1T}X) & = 0 \end{align*} x(p3TX)(p1TX)y(p3TX)(p2TX)x(p2TX)y(p1TX)=0=0=0
其中 p i T p^{iT} piT P P P的行的转置,这三个方程的系数的秩为2。
然后结合x × PX=0x’ × P’X=0得到:
A = [ x p 3 T − p 1 T y p 3 T − p 2 T x ′ p ′ 3 T − p ′ 1 T y ′ p ′ 3 T − p ′ 2 T ] , A X = 0 A = \begin{bmatrix} xp^{3T}-p^{1T} \\ yp^{3T}-p^{2T} \\ x'p'^{3T}-p'^{1T} \\ y'p'^{3T}-p'^{2T} \end{bmatrix},AX=0 A= xp3Tp1Typ3Tp2Txp3Tp1Typ3Tp2T ,AX=0
从而能够解出X的坐标。

def triangulate(P1, P2, x1, x2):
    A = np.vstack((x1[0] * P1[2] - P1[0],
                   x1[1] * P1[2] - P1[1],
                   x2[0] * P2[2] - P2[0],
                   x2[1] * P2[2] - P2[1]))
    _, _, VT = np.linalg.svd(A)
    X_homogeneous = VT.T[:,-1]
    
    X_homogeneous /= X_homogeneous[3] 
    X = X_homogeneous[:3] 
    
    return X

之后会给大家更新黄金标准标定算法和由基本矩阵诱导的单应性。今天看到课程成绩出来了,并没有达到我的预期,哎就这样吧。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【结构型模型】享元模式

一、享元模式概述 享元模式定义&#xff1a;又叫蝇量模式&#xff0c;运用共享技术有效地支持大量细粒度对象的复用。系统只使用少量的对象&#xff0c;而这些对象都很相似&#xff0c;状态变化很小&#xff0c;可以实现对象的多次复用。由于享元模式要求能够共享的对象必须是细…

创建SpringBoot和RabbitMQ的整合项目

文章目录 创建SpringBoot和RabbitMQ的整合项目首先快速创建一个maven项目引入SpringBoot整合rabbitMQ的依赖在src/main目录下创建resources目录并引入配置文件写消息发送者MessageSender写消息接收者MessageReceiver写RabbitMQConfig配置类写SpringBoot启动主类CommandLineRunn…

Bootloader应用启动分析详解

内存->磁盘 引导程序->核心->根文件系统rootfs->app 引导程序加载最重要 由于boot设计比较偏底层,所以根据CPU架构和OS类型可能有所不同 uboot是对CPU架构和OS类型支持得比较多得一种开源引导程序 Bootloader的种类 s5p6818启动流程 芯片最开始是从iROM启动,…

【漏洞复现】泛微e-Mobile 移动管理平台文件上传漏洞

0x01 阅读须知 “如棠安全的技术文章仅供参考&#xff0c;此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供…

大型企业不同安全域文件交换,常见方式的优势与问题对比

现在越来越多的企业通过对网络进行物理或逻辑隔离&#xff0c;将内部网络与外部网络隔离开来&#xff0c;从而限制非法访问和恶意渗透&#xff0c;防止敏感数据泄露和恶意代码的传播&#xff0c;提高网络安全性。对于大型企业而言&#xff0c;将网络分为内外网并不足以满足安全…

Redis底层数据结构之IntSet

目录 一、概述二、IntSet结构三、自动升级 redis底层数据结构已完结&#x1f44f;&#x1f44f;&#x1f44f;&#xff1a; ☑️redis底层数据结构之SDS☑️redis底层数据结构之ziplist☑️redis底层数据结构之quicklist☑️redis底层数据结构之Dict☑️redis底层数据结构之Int…

UNet网络在图像去模糊方向的应用

前一段时间&#xff0c;我们学习了关于UNet网络的结构和基于UNet网络的去模糊网络MIMO-UNet&#xff0c;DeepRFT等网络的结构&#xff0c;大致的对网络的结构组成和实现过程有了一定的了解&#xff0c;下面考虑在图像去模糊部分&#xff0c;基于UNet的已有的研究工作&#xff0…

【力扣】螺旋矩阵

59. 螺旋矩阵 II 刚开始遇到这道题目的时候相信没见过的同学多多少少都会有点懵圈&#xff0c;感觉题目有点无从下手&#xff0c;但其实只要抓住本质就行了&#xff0c;题目的最终目的就是返回一个二维数组的结果&#xff0c;这个二维数组的大小是的 int[n][n]&#xff0c;题目…

Linux-线程互斥和死锁

目录 一.线程互斥 1.1 进程线程间的互斥相关背景概念 1.2 互斥量mutex 二.互斥量的接口 2.1 初始化互斥量 2.2 销毁互斥量 2.3 互斥量加锁和解锁 2.4 改进后售票代码 三.死锁 3.1.什么是死锁&#xff1f; 3.2.死锁四个必要条件 3.3 避免死锁 一.线程互斥 1.1 进程…

纳米尺度下的单粒子追踪,厦门大学方宁团队用 AI 奏响「细胞里的摇滚」

在微观世界里&#xff0c;每一个细胞都是一个繁忙的城市&#xff0c;而分子们则是这个城市中的居民。想象一下&#xff0c;如果我们能够追踪这些居民的每一个动作&#xff0c;或许便能够揭开生命奥秘的一角。这就是科学家们在活细胞中进行 3D 单粒子跟踪 (single particle trac…

Android MVVM架构 + Retrofit完成网络请求

关于Retrofit&#xff0c;这个应该不是一个很新颖的东西了&#xff0c;简单过一下吧 1.由Square公司开发&#xff0c;基于Type-safe的REST客户端。 2.使用注解来定义API接口&#xff0c;使得HTTP请求变得简洁且易于维护。 3.支持同步和异步请求&#xff0c;可与RxJava、Corouti…

模块三:二分——162.寻找峰值

文章目录 题目描述算法原理解法一&#xff1a;暴力查找解法二&#xff1a;二分查找 代码实现解法一&#xff1a;暴力查找解法二&#xff1a;CJava 题目描述 题目链接&#xff1a;162.寻找峰值 根据题意&#xff0c;需要使用O(log N)的时间复杂度来解决&#xff0c;得出本道题…

HTTP协议的总结

参考 https://www.runoob.com/http/http-tutorial.html 1.简介 HTTP&#xff08;超文本传输协议&#xff0c;Hypertext Transfer Protocol&#xff09;是一种用于从网络传输超文本到本地浏览器的传输协议。它定义了客户端与服务器之间请求和响应的格式。HTTP 工作在 TCP/IP 模…

javaWeb项目-邮票鉴赏系统功能介绍

项目关键技术 开发工具&#xff1a;IDEA 、Eclipse 编程语言: Java 数据库: MySQL5.7 框架&#xff1a;ssm、Springboot 前端&#xff1a;Vue、ElementUI 关键技术&#xff1a;springboot、SSM、vue、MYSQL、MAVEN 数据库工具&#xff1a;Navicat、SQLyog 1、Java技术 Java 程…

《Linux运维实战:基于银河麒麟V10+鲲鹏920CPU部署DM8数据库主备集群》

总结&#xff1a;整理不易&#xff0c;如果对你有帮助&#xff0c;可否点赞关注一下&#xff1f; 更多详细内容请参考&#xff1a;Linux运维实战总结 一、安装前准备 1.1、硬件环境 数据守护集群安装部署前需要额外注意网络环境和磁盘 IO 配置情况&#xff0c;其他环境配置项建…

大春资料分析刷题班

大春资料分析刷题班&#xff0c;以其独特的教学方法和丰富的实战经验&#xff0c;深受广大学员喜爱。课程中&#xff0c;大春老师不仅深入剖析资料分析题的解题技巧&#xff0c;还结合大量真题进行实战演练&#xff0c;让学员们在刷题中不断提升解题速度和准确率。同时&#xf…

DHCP Relay配置与抓包

前言&#xff1a;DHCP请求报文是以广播包方式发送的&#xff0c;当DHCP服务器与DHCP客户端不在同一网段时&#xff0c;就需要在三层网关设备配置DHCP中继功能 。 为能更好理解DHCP Relay功能&#xff0c;建议先看看DHCP Server的内容 https://blog.csdn.net/weixin_58574637…

element -ui 横向时间轴,时间轴悬浮对应日期

效果&#xff1a; <el-tabs v-model"activeName" type"card" tab-click"handleClick"><el-tab-pane label"周期性巡视" name"zqxxs" key"zqxxs" class"scrollable-tab-pane"><div v-if…

WEP、WPA、WPA2 和 WPA3:区别和说明

无线网络安全是保持在线安全的一个重要因素。通过不安全的链路或网络连接到互联网是一种安全风险&#xff0c;可能会导致数据丢失、帐户凭据泄露&#xff0c;以及他人在您的网络上安装恶意软件。必须使用适当的 Wi-Fi 安全措施 - 但在这样做时&#xff0c;也必须了解不同的无线…

全新消费理念:探索消费增值的奥秘与价值

亲爱的朋友们&#xff0c;你们好&#xff01;今天我要和大家分享一种新颖的消费模式——消费增值&#xff0c;它能让我们的每一次消费都充满价值&#xff01; 在传统消费观念中&#xff0c;我们支付金钱&#xff0c;获得商品或服务&#xff0c;然后这些就逐渐淡出我们的生活。然…