计算机视觉——基本矩阵的计算

最近在上研究生的课程《计算机视觉》,完成了老师布置的大作业,结合我看《计算机视觉中的多视图几何》的一些感悟和收获完成此篇博客。在学习的过程中我发现很多算法并没有开源,或者版本太落后难以执行,因此想通过这篇博客将一些算法展现出来,让更多的人在学习的过程中少走弯路!笔者水平能力有限,如有错误,敬请指出。

基本矩阵

关于基本矩阵的介绍,网上很多博客都写的很好,这里就不再赘述了。基本矩阵主要是应用在两视图几何中的,用来约束两视图间的匹配点对,因此下面我们实现的代码都是基于两视图的。

特征点匹配+GMS过滤外点

首先我们需要提取出两个视图中的匹配点对。这里采用了效果比较好的SIFT算法和外点过滤效果好的GMS算法得到匹配点对。

  1. 读取图片,计算SIFT特征点
  2. 暴力匹配得到尽可能多的匹配对
  3. GMS算法对BFMatch结果进行过滤
def SIFT(img):sift = cv2.xfeatures2d.SIFT_create(100)# 使用SIFT检测关键点  kps,decs = sift.detectAndCompute(img, None)  return kps,decsleft_img = cv2.imread("./left2.jpg")
right_img = cv2.imread("./right2.jpg")
kps1,desc1 = SIFT(left_img)
kps2,desc2 = SIFT(right_img)
matcher  = cv2.BFMatcher_create()
matches_all = matcher.match(desc1, desc2)
matches_gms = matchGMS(left_img.shape[:2], right_img.shape[:2], kps1, kps2, matches_all, withScale=True,withRotation=True, thresholdFactor=6)
match_result = cv2.drawMatches(left_img, kps1, right_img, kps2, matches_gms,None,flags=2)

我们可以展示匹配结果看一下匹配效果:
在这里插入图片描述

这里SIFT点我只提取了100个,因为当我把匹配点设置过多的时候,内点率会逐渐下降。

计算基本矩阵

opencv已经给出了一个函数库cv2.findFundamentalMat(),但这不利于提高我们的编码能力和对算法的理解程度,因此我们手动实现归一化八点算法,同时库函数和手动计算得到的结果进行对比。
库函数
首先给出库函数计算过程和结果:

src_points = np.float32([kps1[m.queryIdx].pt for m in matches_gms]).reshape(-1, 2)
dst_points = np.float32([kps2[m.trainIdx].pt for m in matches_gms]).reshape(-1, 2)
F,mask = cv2.findFundamentalMat(src_points,dst_points,cv2.FM_RANSAC)
F = [-5.77184137e-07 -6.67998326e-06  6.56611343e-03][ 7.18639182e-06 -4.60223599e-07 -4.59609635e-03][-6.47510627e-03  3.81943240e-03  1.00000000e+00]

归一化八点算法
可能有些同学还不清楚步骤,这里我简述一下具体步骤:

  1. 先对点坐标系进行平移,使所有点位于几何中心。然后使所有点距离坐标中心的平均距离为 2 \sqrt{2} 2
  2. SVD求解方程组得到 F ^ \hat F F^
  3. F ^ \hat F F^一般是秩为3,而rank(F)=2,因此需要通过SVD调整 F ^ \hat F F^的秩
  4. 调整回原坐标系下的F,即进行步骤1的逆过程

第一步进行数据归一化,关键是平移矩阵和缩放矩阵的构建,在计算的过程中可以多关注一下矩阵的shape。

src_ax,src_ay = np.mean(src_points,axis=0)
dst_ax,dst_ay = np.mean(dst_points,axis=0)
n = len(src_points)
## 平移矩阵
T1 = np.array([[1,0,-src_ax],[0,1,-src_ay],[0,0,1]])
T2 = np.array([[1,0,-dst_ax],[0,1,-dst_ay],[0,0,1]])
p1 = (T1 @ np.array([[x,y,1] for x,y in src_points]).T).T
p2 = (T2 @ np.array([[x,y,1] for x,y in dst_points]).T).T
src_sum = 0
dst_sum = 0
for i in range(n):src_sum += math.sqrt(p1[i][0]**2+p1[i][1]**2)dst_sum += math.sqrt(p2[i][0]**2+p2[i][1]**2)
src_sum /= n
dst_sum /= n
alpha = math.sqrt(2) / src_sum
beta = math.sqrt(2) / dst_sum
## 缩放矩阵
S1 = np.array([[alpha,0,0],[0,alpha,0],[0,0,1]])
S2 = np.array([[beta,0,0],[0,beta,0],[0,0,1]])
u = (S1 @ p1.T).T
v = (S2 @ p2.T).T

第二步构建方程组,利用SVD求解超定方程组。
[ x y 1 ] [ f 11 f 12 f 13 f 21 f 22 f 23 f 31 f 32 f 33 ] [ x ′ y ′ 1 ] = 0 \begin{bmatrix} x & y &1 \end{bmatrix}\begin{bmatrix} f_{11} & f_{12} & f_{13}\\ f_{21} & f_{22} & f_{23}\\ f_{31} & f_{32} &f_{33} \end{bmatrix}\begin{bmatrix} x'\\ y'\\ 1 \end{bmatrix} = 0 [xy1] f11f21f31f12f22f32f13f23f33 xy1 =0
把上述表达展开,并以 [ f i j ] [f_{ij}] [fij]为未知向量构建 A X = 0 AX=0 AX=0的方程:
x ′ x f 11 + x ′ y f 12 + x ′ f 13 + y ′ x f 21 + y ′ y f 22 + y ′ f 23 + x f 31 + y f 32 + f 33 = 0 [ x ′ x , x ′ y , x ′ , y ′ x , y ′ y , y ′ , x , y , 1 ] [ f 11 f 12 f 13 f 21 f 22 f 23 f 31 f 32 f 33 ] = 0 x'xf_{11}+x'yf_{12}+x'f_{13}+y'xf_{21}+y'yf_{22}+y'f_{23}+xf_{31}+yf_{32}+f_{33}=0 \\ [x'x,x'y,x',y'x,y'y,y',x,y,1]\begin{bmatrix} f_{11} \\ f_{12} \\ f_{13}\\ f_{21}\\ f_{22}\\ f_{23}\\ f_{31} \\ f_{32} \\ f_{33} \end{bmatrix}=0 xxf11+xyf12+xf13+yxf21+yyf22+yf23+xf31+yf32+f33=0[xx,xy,x,yx,yy,y,x,y,1] f11f12f13f21f22f23f31f32f33 =0
因为我们已知 [ x , y , 1 ] T [x,y,1]^T [x,y,1]T [ x ′ , y ′ , 1 ] T [x',y',1]^T [x,y,1]T,每一组匹配点对便可以构建出一个方程。F的自由度为7,那么至少需要八对点来求解F。通常我们得到的匹配点对超过了8对,对于超定方程组我们需要利用多余的方程计算最小二乘解

最小二乘法就是通过拟合实际数据得到的函数使得通过函数得到的数据与实际数据之间误差的平方和为最小

我们对A矩阵进行SVD分解, U , Σ , V T = S V D ( A ) U,\Sigma,V^T=SVD(A) U,Σ,VT=SVD(A),我们所求的最小二乘解就是矩阵V的最后一列。

这是因为矩阵V最后一列对应 Σ \Sigma Σ中的特征值是最小的,所以误差也就最小

上述求得基本矩阵 F ^ \hat F F^的秩通常为3,而实际 r a n k ( F ) = 2 rank(F)=2 rank(F)=2,因此我们需要对 F ^ \hat F F^再进行SVD分解,并将 Σ \Sigma Σ中最后一列的元素设置为0,再将 U U U Σ \Sigma Σ V T V^T VT乘回去得到 F F F

l1 = np.multiply(v[:,0],u[:,0])
l2 = np.multiply(v[:,0],u[:,1])
l3 = v[:,0]
l4 = np.multiply(v[:,1],u[:,0])
l5 = np.multiply(v[:,1],v[:,1])
l6 = v[:,1]
l7 = u[:,0]
l8 = u[:,1]
l9 = np.ones_like(v[:,1])
A = np.vstack((l1,l2,l3,l4,l5,l6,l7,l8,l9)).T
U,Sigma,VT = np.linalg.svd(A)
V = VT.T[:,-1].reshape(-1,3)
U,D,VT = np.linalg.svd(V)
D[2] = 0
F_ = U @ np.diag(D) @ VT
# eight_F = (S1 @ T1).T @ F_ @ S2 @ T2
eight_F_tmp = (S2 @ T2).T @F_ @(S1 @ T1)
eight_F = eight_F_tmp / eight_F_tmp[2,2]
F = [-6.01698176e-07 -8.10162516e-06  7.81740018e-03][ 8.47767046e-06 -6.76200912e-07 -5.09137869e-03][-7.60729655e-03  4.50740583e-03  1.00000000e+00]

我们计算一下两种方法计算F的相似程度,采用了余弦相似度计算两矩阵中每一个对应位置元素的相似程度。

def cosine_similarity(matrix1, matrix2):dot_product = np.dot(matrix1, matrix2.T)norm_matrix1 = np.linalg.norm(matrix1, axis=1)norm_matrix2 = np.linalg.norm(matrix2, axis=1)similarity = abs(dot_product) / np.outer(norm_matrix1, norm_matrix2)return similaritysimi = [1.         0.99999809 0.99995647][0.99999825 0.99999999 0.99997203][0.99996774 0.99998164 0.99999912]

以上就是归一化八点法的全部内容了。涉及到的理论部分并不多,主要想分享一下具体实现。之后大致还会安排一下几个内容,先挖个坑:

  1. 相机标定中的黄金标准算法
  2. 通过极线和极点构建投影矩阵
  3. 张正友标定法

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

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

相关文章

ELK及ELFK排错

目录 一、ELK及ELFK排错思路 1.1filebeat侧排查 1.2logstash侧排查 1.3ES、kibana侧问题 一、ELK及ELFK排错思路 1.1filebeat侧排查 第一步:排查filebeat上的配置文件有没有写错,filebeat的配置文件是yml文件,一定要注意格式。 第二步…

WebKit内核游览器

WebKit内核游览器 基础概念游览器引擎Chromium 浏览器架构Webkit 资源加载这里就不得不提到http超文本传输协议这个概念了: 游览器多线程HTML 解析总结 基础概念 百度百科介绍 WebKit 是一个开源的浏览器引擎,与之相对应的引擎有Gecko(Mozil…

初识ansible核心模块

目录 1、ansible模块 1.1 ansible常用模块 1.2 ansible-doc -l 列出当前anisble服务所支持的所有模块信息,按q退出 1.3 ansible-doc 模块名称 随机查看一个模块信息 2、运行临时命令 2.1 ansible命令常用的语法格式 3、常用模块详解与配置实例 3.1命令与…

【攻防世界】bug

垂直越权IP绕过文件上传 垂直越权 IP绕过 bp抓包,添加请求头X-Forwarded-For:127.0.0.1 文件上传 文件上传绕过: 1. mime检测(Content-Type) 2. 大小写绕过 3. 等价替换(php5,php3) 4. 利用J…

python笔记 | 哥德巴赫猜想

哥德巴赫猜想:每个不小于6的偶数都可以表示成两个素数之和。 素数:只能被1和自身整除的正整数。就是大于1且除了1和它本身之外没有其他因数的数。例如,2、3、5、7、11等都是素数,而4、6、8、9等则不是素数。 下面这段Python代码…

SRIO系列-基本概念及IP核使用

参考:串行RapidIO: 高性能嵌入式互连技术 | 德州仪器 SRIO协议技术分析 - 知乎 PG007 目录 一、SRIO介绍 1.1 概要 1.2 SRIO与传统互联方式的比较 1.3 串行SRIO标准 1.4 SRIO层次结构: 1.4.1 逻辑层 1.4.2 传输层协议 1.4.3 物理层 二、Xilinx…

动手写sql 《牛客网80道sql》

第1章:SQL编写基础逻辑和常见问题 基础逻辑 SELECT语句: 选择数据表中的列。FROM语句: 指定查询将要从哪个表中检索数据。WHERE语句: 过滤条件,用于提取满足特定条件的记录。GROUP BY语句: 对结果进行分组。HAVING语句: 对分组后的结果进行条件过滤。O…

Springboot项目的测试类书写(速通)

目录 前言1. 单元测试的测试类2. 框架测试的测试类 前言 在实际开发中,如果只是做一个简单的单元测试(不涉及端到端、数据库交互、API调用、消息队列处理等),我为了方便一般都是找块儿地方写一个main方法来跑一下就行了&#xff…

支付系统核心逻辑 — — 状态机(JavaGolang版本)

支付系统核心逻辑 — — 状态机 代码地址:https://github.com/ziyifast/ziyifast-code_instruction/tree/main/state_machine_demo 1 概念:FSM(有限状态机),模式之间转换 状态机,也叫有限状态机&#xff08…

UE5 HLSL 详细学习笔记

这里的POSITION是变量Position的语义,告诉寄存器,此变量的保存位置,通常语义用于着色器的输入和输出,以冒号“:”的方式进一步说明此变量,COLOR也类似 还有什么语义呢? HLSL核心函数&#xff1a…

云服务器安装Mysql、MariaDB、Redis、tomcat、nginx

前置工作 进入根目录 cd / 都在/usr/local/src文件夹) 上传压缩包 rz 压缩包 Mysql 1.下载并安装MySQL官方的 Yum Repository wget http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm rpm -ivh mysql-community-release-el7-5.noarch.rpm yum…

每日算法4/17

1552. 两球之间的磁力 题目 在代号为 C-137 的地球上,Rick 发现如果他将两个球放在他新发明的篮子里,它们之间会形成特殊形式的磁力。Rick 有 n 个空的篮子,第 i 个篮子的位置在 position[i] ,Morty 想把 m 个球放到这些篮子里&…

工业数学模型——高炉煤气发生量预测(三)

1、工业场景 冶金过程中生产的各种煤气,例如高炉煤气、焦炉煤气、转炉煤气等。作为重要的副产品和二次能源,保证它们的梯级利用和减少放散是煤气能源平衡调控的一项紧迫任务,准确的预测煤气的发生量是实现煤气系统在线最优调控的前提。 2、…

A Geolocation Databases Study(2011年)第二部分:Geolocation Services

下载地址:A Geolocation Databases Study | IEEE Journals & Magazine | IEEE Xplore 被引次数:195 Shavitt Y, Zilberman N. A geolocation databases study[J]. IEEE Journal on Selected Areas in Communications, 2011, 29(10): 2044-2056. 2. Geolocation Services…

2024认证杯数学建模C题思路模型代码

目录 2024认证杯数学建模C题思路模型代码:4.11开赛后第一时间更新,获取见文末名片 以下为2023年认证杯C题: 2024年认证杯数学建模C题思路模型代码见此 2024认证杯数学建模C题思路模型代码:4.11开赛后第一时间更新,获…

一文掌握:图片转Base64编码的原理、实践(自定义图片本地缓存等)以及优化事项

图片转Base64是指将一幅图片(如PNG、JPEG、GIF等格式)的二进制数据编码为符合Base64规范的文本字符串的过程。图片Base64编码将图片数据转换为ASCII字符串,便于网络传输和存储。实现步骤包括读取图片文件、转换为字节数组,再通过编…

Windows 安装 A UDP/TCP Assistant 网络调试助手

Windows 安装 A UDP/TCP Assistant 网络调试助手 0. 引言1. 下载地址2. 安装和使用 0. 引言 需要调试一个实时在线聊天程序,安装一个UDP/TCP Assistant 网络调试助手,方便调试。 1. 下载地址 https://github.com/busyluo/NetAssistant/releases 2. 安…

Vue3项目 网易严选_学习笔记

Vue3项目 网易严选_第一天 主要内容 项目搭建vuex基础路由设计首页顶部和底部布局 学习目标 知识点要求项目搭建掌握vuex基础掌握路由设计掌握首页顶部和底部布局掌握 一、项目搭建 1.1 创建项目 vue create vue-wangyi选择vue3.0版本 1.2 目录调整 大致步骤&#xff…

美格智能出席紫光展锐第三届泛金融支付生态论坛,引领智慧金融变革向新

4月16日,以“融智创新,共塑支付产业新生态”为主题的紫光展锐第三届泛金融支付生态论坛在福州举办,来自金融服务机构、分析师机构、终端厂商、模组厂商等行业各领域生态伙伴汇聚一堂,探讨金融支付产业的机遇与挑战。作为紫光展锐重…

个人网站制作 Part 24 添加用户反馈功能[Userback] | Web开发项目添加页面缓存

文章目录 👩‍💻 基础Web开发练手项目系列:个人网站制作🚀 添加用户反馈功能🔨使用反馈工具🔧步骤 1: 选择反馈工具🔧步骤 2: 注册Userback账户🔧步骤 3: 获取反馈按钮代码 使用Vue.…