python 几何_OpenCV-Python 对极几何|五十一

目标

在本节中

我们将学习多视图几何的基础知识我们将了解什么是极点,极线,极线约束等。基础概念

当我们使用针孔相机拍摄图像时,我们失去了重要信息,即图像深度。 或者图像中的每个点距相机多远,因为它是3D到2D转换。 因此,是否能够使用这些摄像机找到深度信息是一个重要的问题。 答案是使用不止一台摄像机。 在使用两台摄像机(两只眼睛)的情况下,我们的眼睛工作方式相似,这称为立体视觉。 因此,让我们看看OpenCV在此字段中提供了什么。

(通过Gary Bradsky学习OpenCV在该领域有很多信息。)

在深入图像之前,让我们首先了解多视图几何中的一些基本概念。在本节中,我们将讨论对极几何。请参见下图,该图显示了使用两台摄像机拍摄同一场景的图像的基本设置。

如果仅使用左摄像机,则无法找到与图像中的点相对应的3D点,因为线上的每个点都投影到图像平面上的同一点。但也要考虑正确的形象。现在,直线$OX$上的不同点投射到右侧平面上的不同点($x'$)。因此,使用这两个图像,我们可以对正确的3D点进行三角剖分。这就是整个想法。

不同点的投影在右平面$OX$上形成一条线(line$l'$)。我们称其为对应于该点的Epiline。这意味着,要在正确的图像上找到该点,请沿着该轮廓线搜索。它应该在这条线上的某处(以这种方式考虑,可以在其他图像中找到匹配点,而无需搜索整个图像,只需沿着Epiline搜索即可。因此,它可以提供更好的性能和准确性)。这称为对极约束。类似地,所有点在另一幅图像中将具有其对应的Epiline。该平面称为对极面。

$O$和$O'$是相机中心。从上面给出的设置中,您可以看到在点处的左侧图像上可以看到右侧摄像机$O'$的投影。它称为极点。极点是穿过相机中心和图像平面的线的交点。左摄像机的极点也同理。在某些情况下,您将无法在图像中找到极点,它们可能位于图像外部(这意味着一个摄像机看不到另一个摄像机)。

所有的极线都通过其极点。因此,要找到中心线的位置,我们可以找到许多中心线并找到它们的交点。

因此,在节中,我们将重点放在寻找对极线和极线。但是要找到它们,我们需要另外两种成分,即基础矩阵(F)和基本矩阵(E),基础矩阵包含有关平移和旋转的信息,这些信息在全局坐标中描述了第二个摄像头相对于第一个摄像头的位置。参见下图(图像由Gary Bradsky提供:Learning OpenCV):

但是我们会更喜欢在像素坐标中进行测量,对吧? 基本矩阵除包含有关两个摄像头的内在信息之外,还包含与基本矩阵相同的信息,因此我们可以将两个摄像头的像素坐标关联起来。(如果我们使用的是校正后的图像,并用焦距除以标准化该点,$F=E$)。简而言之,基本矩阵F将一个图像中的点映射到另一图像中的线(上)。这是从两个图像的匹配点计算得出的。 至少需要8个这样的点才能找到基本矩阵(使用8点算法时)。 选择更多点并使用RANSAC将获得更可靠的结果。

代码

因此,首先我们需要在两个图像之间找到尽可能多的匹配项,以找到基本矩阵。为此,我们将SIFT描述符与基于FLANN的匹配器和比率测试结合使用。

import numpy as npimport cv2 as cvfrom matplotlib import pyplot as pltimg1 = cv.imread('myleft.jpg',0) #索引图像 # left imageimg2 = cv.imread('myright.jpg',0) #训练图像 # right imagesift = cv.SIFT()# 使用SIFT查找关键点和描述符kp1, des1 = sift.detectAndCompute(img1,None)kp2, des2 = sift.detectAndCompute(img2,None)# FLANN 参数FLANN_INDEX_KDTREE = 1index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)search_params = dict(checks=50)flann = cv.FlannBasedMatcher(index_params,search_params)matches = flann.knnMatch(des1,des2,k=2)good = []pts1 = []pts2 = []# 根据Lowe的论文进行比率测试for i,(m,n) in enumerate(matches): if m.distance < 0.8*n.distance: good.append(m) pts2.append(kp2[m.trainIdx].pt) pts1.append(kp1[m.queryIdx].pt)现在,我们获得了两张图片的最佳匹配列表。 让我们找到基本面矩阵。

pts1 = np.int32(pts1)pts2 = np.int32(pts2)F, mask = cv.findFundamentalMat(pts1,pts2,cv.FM_LMEDS)# 我们只选择内点pts1 = pts1[mask.ravel()==1]pts2 = pts2[mask.ravel()==1]接下来,我们找到Epilines。在第二张图像上绘制与第一张图像中的点相对应的Epilines。因此,在这里提到正确的图像很重要。我们得到了一行线。因此,我们定义了一个新功能来在图像上绘制这些线条。

def drawlines(img1,img2,lines,pts1,pts2): ''' img1 - 我们在img2相应位置绘制极点生成的图像 lines - 对应的极点 ''' r,c = img1.shape img1 = cv.cvtColor(img1,cv.COLOR_GRAY2BGR) img2 = cv.cvtColor(img2,cv.COLOR_GRAY2BGR) 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 = cv.line(img1, (x0,y0), (x1,y1), color,1) img1 = cv.circle(img1,tuple(pt1),5,color,-1) img2 = cv.circle(img2,tuple(pt2),5,color,-1) return img1,img2现在,我们在两个图像中都找到了Epiline并将其绘制。

# 在右图(第二张图)中找到与点相对应的极点,然后在左图绘制极线lines1 = cv.computeCorrespondEpilines(pts2.reshape(-1,1,2), 2,F)lines1 = lines1.reshape(-1,3)img5,img6 = drawlines(img1,img2,lines1,pts1,pts2)# 在左图(第一张图)中找到与点相对应的Epilines,然后在正确的图像上绘制极线lines2 = cv.computeCorrespondEpilines(pts1.reshape(-1,1,2), 1,F)lines2 = lines2.reshape(-1,3)img3,img4 = drawlines(img2,img1,lines2,pts2,pts1)plt.subplot(121),plt.imshow(img5)plt.subplot(122),plt.imshow(img3)plt.show()以下是我们得到的结果:

您可以在左侧图像中看到所有极点都收敛在右侧图像的外部。那个汇合点就是极点。 为了获得更好的结果,应使用具有良好分辨率和许多非平面点的图像。

练习

一个重要的主题是相机的前移。然后,将在两个位置的相同位置看到极点,并且从固定点出现极点。 请参阅此讨论。基本矩阵估计对匹配,离群值等的质量敏感。如果所有选定的匹配都位于同一平面上,则情况会变得更糟。检查此讨论。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Opencv-python图像变换是通过使用不同的变换矩阵来实现的。其中,平移是一种最简单的空间变换。使用Opencv的函数cv2.warpAffine()可以实现平移操作。在代码中,我们需要定义一个变换矩阵M,这个矩阵是一个2行3列的矩阵,决定了平移的方式。其中,M矩阵中的tx和ty分别表示在x和y方向上平移的距离。更具体地说,如果我们向右平移tx个像素,向下平移ty个像素,那么变换矩阵M的定义如下: import numpy as np rows, cols = img.shape[:2] M = np.float32([[1, 0, tx], [0, 1, ty]]) dst = cv2.warpAffine(img, M, (cols, rows)) 在上述代码中,我们使用了NumPy库来创建一个2x3的浮点型变换矩阵M,并将其传递给cv2.warpAffine()函数,该函数会将图像img按照定义的方式进行平移,并生成一个新的图像dst。最后,我们可以通过cv2.imshow()函数显示平移后的图像。 除了平移之外,Opencv还提供了其他的图像变换操作,比如缩放。缩放可以按照指定的宽度和高度来调整图像的大小,也可以按照比例来进行缩放。通过cv2.resize()函数可以实现缩放操作。在代码中,我们可以使用下面的方式来进行缩放操作: import cv2 img = cv2.imread('drawing.jpg') # 按照指定的宽度、高度缩放图片 res = cv2.resize(img, (width, height)) # 按照比例缩放图片 res2 = cv2.resize(img, None, fx=scale_x, fy=scale_y, interpolation=cv2.INTER_LINEAR) 在上面的代码中,我们首先使用cv2.imread()函数读取图像,并将其存储在变量img中。然后,我们可以使用cv2.resize()函数来调整图像的大小。其中,如果我们指定了宽度和高度,那么图像将按照这些指定的大小进行缩放;如果我们指定了fx和fy的比例因子,那么图像将按照这些比例进行缩放。最后,我们可以使用cv2.imshow()函数来显示缩放后的图像。 总结起来,Opencv-python提供了多种图像变换操作,包括平移、缩放等。通过使用相应的函数和变换矩阵,我们可以实现对图像的各种变换操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [opencv-python 详解图像的几何变换缩放、平移、旋转、翻转](https://blog.csdn.net/RayChiu757374816/article/details/120036004)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值