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

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

基本矩阵

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

特征点匹配+GMS过滤外点

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

  1. 读取图片,计算SIFT特征点
  2. 暴力匹配得到尽可能多的匹配对
  3. GMS算法对BFMatch结果进行过滤
python 复制代码
def SIFT(img):
    sift = cv2.xfeatures2d.SIFT_create(100)
    
    # 使用SIFT检测关键点  
    kps,decs = sift.detectAndCompute(img, None)  
    return kps,decs
    
left_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(),但这不利于提高我们的编码能力和对算法的理解程度,因此我们手动实现归一化八点算法,同时库函数和手动计算得到的结果进行对比。
库函数

首先给出库函数计算过程和结果:

python 复制代码
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。

python 复制代码
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 x′y′1 =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 x′xf11+x′yf12+x′f13+y′xf21+y′yf22+y′f23+xf31+yf32+f33=0\[x′x,x′y,x′,y′x,y′y,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。 ```python 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的相似程度,采用了余弦相似度计算两矩阵中每一个对应位置元素的相似程度。 ```python 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 similarity simi = [1. 0.99999809 0.99995647] [0.99999825 0.99999999 0.99997203] [0.99996774 0.99998164 0.99999912] ``` 以上就是归一化八点法的全部内容了。涉及到的理论部分并不多,主要想分享一下具体实现。之后大致还会安排一下几个内容,先挖个坑: 1. 相机标定中的黄金标准算法 2. 通过极线和极点构建投影矩阵 3. 张正友标定法

相关推荐
AI英德西牛仔2 分钟前
deepseek导出word排版
人工智能·ai·chatgpt·deepseek·ds随心转
(; ̄ェ ̄)。3 分钟前
深度学习入门(十)RNN、LSTM、GRU
人工智能·rnn·深度学习
谁在黄金彼岸14 分钟前
构建一个多Agent系统(Multi-Agent System, MAS)方法论
人工智能
pandafeeder19 分钟前
Agent工具调用范式:ReAct 和Function Calling
人工智能
jinanwuhuaguo19 分钟前
OpenClaw字节跳动的三只不同的claw龙虾飞书妙搭 OpenClaw、ArkClaw、扣子 OpenClaw 核心区别深度解析
人工智能·语言模型·自然语言处理·visual studio code·openclaw
咚咚王者27 分钟前
人工智能之语言领域 自然语言处理 第十八章 Python NLP生态
人工智能·python·自然语言处理
yeflx27 分钟前
三维空间坐标转换早期笔记
人工智能·算法·机器学习
zzh9407728 分钟前
Gemini 3.1 Pro 2026年国内使用指南:技术解析与镜像站实测
人工智能
初学大模型28 分钟前
基于三层架构的自动驾驶系统设计:环境建模、标准驾驶与风险调制
人工智能
●VON28 分钟前
半小时从零开发鸿蒙记事本应用:AI辅助开发实战
人工智能·华为·harmonyos