• python—多视图几何


    多视图几何

    一、图像之间的基础矩阵

         1.1、代码实现

         1.2、结果截图

         1.3、小结

    二、极点和极线

          1.1、代码实现

          1.2、结果截图

          1.3 、小结

    三、图像集

    四、遇到的问题

    五、总结

    一、图像之间的基础矩阵

         1.1、代码实现

      1 # -*- coding: utf-8 -*-
      2 
      3 from PIL import Image
      4 from numpy import *
      5 from pylab import *
      6 import numpy as np
      7 
      8 from PCV.geometry import camera
      9 from PCV.geometry import homography
     10 from PCV.geometry import sfm
     11 from PCV.localdescriptors import sift
     12 
     13 
     14 camera = reload(camera)
     15 homography = reload(homography)
     16 sfm = reload(sfm)
     17 sift = reload(sift)
     18 
     19 # Read features
     20 im1 = array(Image.open('jia/1.jpg'))
     21 im2 = array(Image.open('jia/2.jpg'))
     22 
     23 
     24 sift.process_image('jia/1.jpg', 'im1.sift')
     25 l1, d1 =sift.read_features_from_file('im1.sift')
     26 
     27 sift.process_image('jia/2.jpg', 'im2.sift')
     28 l2, d2 =sift.read_features_from_file('im2.sift')
     29 
     30 matches = sift.match_twosided(d1, d2)
     31 
     32 ndx = matches.nonzero()[0]
     33 x1 = homography.make_homog(l1[ndx, :2].T)
     34 ndx2 = [int(matches[i]) for i in ndx]
     35 x2 = homography.make_homog(l2[ndx2, :2].T)
     36 
     37 d1n = d1[ndx]
     38 d2n = d2[ndx2]
     39 x1n = x1.copy()
     40 x2n = x2.copy()
     41 
     42 figure(figsize=(16,16))
     43 sift.plot_matches(im1, im2, l1, l2, matches, True)
     44 show()
     45 
     46 #def F_from_ransac(x1, x2, model, maxiter=5000, match_threshold=1e-6):
     47 def F_from_ransac(x1, x2, model, maxiter=5000, match_threshold=1e-6):
     48     """ Robust estimation of a fundamental matrix F from point
     49     correspondences using RANSAC (ransac.py from
     50     http://www.scipy.org/Cookbook/RANSAC).
     51 
     52     input: x1, x2 (3*n arrays) points in hom. coordinates. """
     53 
     54     from PCV.tools import ransac
     55     data = np.vstack((x1, x2))
     56     d = 10 # 20 is the original
     57     # compute F and return with inlier index
     58     F, ransac_data = ransac.ransac(data.T, model,
     59                                    8, maxiter, match_threshold, d, return_all=True)
     60     return F, ransac_data['inliers']
     61 
     62 # find F through RANSAC
     63 model = sfm.RansacModel()
     64 F, inliers = F_from_ransac(x1n, x2n, model, maxiter=5000, match_threshold=1e-1)
     65 print("F:", F)
     66 
     67 P1 = array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0]])
     68 P2 = sfm.compute_P_from_fundamental(F)
     69 
     70 print("P2:", P2)
     71 
     72 # triangulate inliers and remove points not in front of both cameras
     73 X = sfm.triangulate(x1n[:, inliers], x2n[:, inliers], P1, P2)
     74 
     75 # plot the projection of X
     76 cam1 = camera.Camera(P1)
     77 cam2 = camera.Camera(P2)
     78 x1p = cam1.project(X)
     79 x2p = cam2.project(X)
     80 
     81 figure(figsize=(16, 16))
     82 imj = sift.appendimages(im1, im2)
     83 imj = vstack((imj, imj))
     84 
     85 imshow(imj)
     86 
     87 cols1 = im1.shape[1]
     88 rows1 = im1.shape[0]
     89 for i in range(len(x1p[0])):
     90     if (0<= x1p[0][i]<cols1) and (0<= x2p[0][i]<cols1) and (0<=x1p[1][i]<rows1) and (0<=x2p[1][i]<rows1):
     91         plot([x1p[0][i], x2p[0][i]+cols1],[x1p[1][i], x2p[1][i]],'c')
     92 axis('off')
     93 show()
     94 
     95 d1p = d1n[inliers]
     96 d2p = d2n[inliers]
     97 
     98 # Read features
     99 im3 = array(Image.open('jia/3.jpg'))
    100 sift.process_image('jia/3.jpg', 'im3.sift')
    101 l3, d3 = sift.read_features_from_file('im3.sift')
    102 
    103 matches13 = sift.match_twosided(d1p, d3)
    104 
    105 ndx_13 = matches13.nonzero()[0]
    106 x1_13 = homography.make_homog(x1p[:, ndx_13])
    107 ndx2_13 = [int(matches13[i]) for i in ndx_13]
    108 x3_13 = homography.make_homog(l3[ndx2_13, :2].T)
    109 
    110 figure(figsize=(16, 16))
    111 imj = sift.appendimages(im1, im3)
    112 imj = vstack((imj, imj))
    113 
    114 imshow(imj)
    115 
    116 cols1 = im1.shape[1]
    117 rows1 = im1.shape[0]
    118 for i in range(len(x1_13[0])):
    119     if (0<= x1_13[0][i]<cols1) and (0<= x3_13[0][i]<cols1) and (0<=x1_13[1][i]<rows1) and (0<=x3_13[1][i]<rows1):
    120         plot([x1_13[0][i], x3_13[0][i]+cols1],[x1_13[1][i], x3_13[1][i]],'c')
    121 axis('off')
    122 show()
    123 
    124 P3 = sfm.compute_P(x3_13, X[:, ndx_13])
    125 
    126 print("P3:", P3)
    127 
    128 print("P1:", P1)
    129 print("P2:", P2)
    130 print("P3:", P3)

       调用的函数sfm.py:

      1 from pylab import *
      2 from numpy import *
      3 from scipy import linalg
      4 
      5 
      6 def compute_P(x,X):
      7     """    Compute camera matrix from pairs of
      8         2D-3D correspondences (in homog. coordinates). """
      9 
     10     n = x.shape[1]
     11     if X.shape[1] != n:
     12         raise ValueError("Number of points don't match.")
     13         
     14     # create matrix for DLT solution
     15     M = zeros((3*n,12+n))
     16     for i in range(n):
     17         M[3*i,0:4] = X[:,i]
     18         M[3*i+1,4:8] = X[:,i]
     19         M[3*i+2,8:12] = X[:,i]
     20         M[3*i:3*i+3,i+12] = -x[:,i]
     21         
     22     U,S,V = linalg.svd(M)
     23     
     24     return V[-1,:12].reshape((3,4))
     25 
     26 
     27 def triangulate_point(x1,x2,P1,P2):
     28     """ Point pair triangulation from 
     29         least squares solution. """
     30         
     31     M = zeros((6,6))
     32     M[:3,:4] = P1
     33     M[3:,:4] = P2
     34     M[:3,4] = -x1
     35     M[3:,5] = -x2
     36 
     37     U,S,V = linalg.svd(M)
     38     X = V[-1,:4]
     39 
     40     return X / X[3]
     41 
     42 
     43 def triangulate(x1,x2,P1,P2):
     44     """    Two-view triangulation of points in 
     45         x1,x2 (3*n homog. coordinates). """
     46         
     47     n = x1.shape[1]
     48     if x2.shape[1] != n:
     49         raise ValueError("Number of points don't match.")
     50 
     51     X = [ triangulate_point(x1[:,i],x2[:,i],P1,P2) for i in range(n)]
     52     return array(X).T
     53 
     54 
     55 def compute_fundamental(x1,x2):
     56     """    Computes the fundamental matrix from corresponding points 
     57         (x1,x2 3*n arrays) using the 8 point algorithm.
     58         Each row in the A matrix below is constructed as
     59         [x'*x, x'*y, x', y'*x, y'*y, y', x, y, 1] """
     60     
     61     n = x1.shape[1]
     62     if x2.shape[1] != n:
     63         raise ValueError("Number of points don't match.")
     64     
     65     # build matrix for equations
     66     A = zeros((n,9))
     67     for i in range(n):
     68         A[i] = [x1[0,i]*x2[0,i], x1[0,i]*x2[1,i], x1[0,i]*x2[2,i],
     69                 x1[1,i]*x2[0,i], x1[1,i]*x2[1,i], x1[1,i]*x2[2,i],
     70                 x1[2,i]*x2[0,i], x1[2,i]*x2[1,i], x1[2,i]*x2[2,i] ]
     71             
     72     # compute linear least square solution
     73     U,S,V = linalg.svd(A)
     74     F = V[-1].reshape(3,3)
     75         
     76     # constrain F
     77     # make rank 2 by zeroing out last singular value
     78     U,S,V = linalg.svd(F)
     79     S[2] = 0
     80     F = dot(U,dot(diag(S),V))
     81     
     82     return F/F[2,2]
     83 
     84 
     85 def compute_epipole(F):
     86     """ Computes the (right) epipole from a 
     87         fundamental matrix F. 
     88         (Use with F.T for left epipole.) """
     89     
     90     # return null space of F (Fx=0)
     91     U,S,V = linalg.svd(F)
     92     e = V[-1]
     93     return e/e[2]
     94     
     95     
     96 def plot_epipolar_line(im,F,x,epipole=None,show_epipole=True):
     97     """ Plot the epipole and epipolar line F*x=0
     98         in an image. F is the fundamental matrix 
     99         and x a point in the other image."""
    100     
    101     m,n = im.shape[:2]
    102     line = dot(F,x)
    103     
    104     # epipolar line parameter and values
    105     t = linspace(0,n,100)
    106     lt = array([(line[2]+line[0]*tt)/(-line[1]) for tt in t])
    107 
    108     # take only line points inside the image
    109     ndx = (lt>=0) & (lt<m) 
    110     plot(t[ndx],lt[ndx],linewidth=2)
    111     
    112     if show_epipole:
    113         if epipole is None:
    114             epipole = compute_epipole(F)
    115         plot(epipole[0]/epipole[2],epipole[1]/epipole[2],'r*')
    116     
    117 
    118 def skew(a):
    119     """ Skew matrix A such that a x v = Av for any v. """
    120 
    121     return array([[0,-a[2],a[1]],[a[2],0,-a[0]],[-a[1],a[0],0]])
    122 
    123 
    124 def compute_P_from_fundamental(F):
    125     """    Computes the second camera matrix (assuming P1 = [I 0]) 
    126         from a fundamental matrix. """
    127         
    128     e = compute_epipole(F.T) # left epipole
    129     Te = skew(e)
    130     return vstack((dot(Te,F.T).T,e)).T
    131 
    132 
    133 def compute_P_from_essential(E):
    134     """    Computes the second camera matrix (assuming P1 = [I 0]) 
    135         from an essential matrix. Output is a list of four 
    136         possible camera matrices. """
    137     
    138     # make sure E is rank 2
    139     U,S,V = svd(E)
    140     if det(dot(U,V))<0:
    141         V = -V
    142     E = dot(U,dot(diag([1,1,0]),V))    
    143     
    144     # create matrices (Hartley p 258)
    145     Z = skew([0,0,-1])
    146     W = array([[0,-1,0],[1,0,0],[0,0,1]])
    147     
    148     # return all four solutions
    149     P2 = [vstack((dot(U,dot(W,V)).T,U[:,2])).T,
    150              vstack((dot(U,dot(W,V)).T,-U[:,2])).T,
    151             vstack((dot(U,dot(W.T,V)).T,U[:,2])).T,
    152             vstack((dot(U,dot(W.T,V)).T,-U[:,2])).T]
    153 
    154     return P2
    155 
    156 
    157 def compute_fundamental_normalized(x1,x2):
    158     """    Computes the fundamental matrix from corresponding points 
    159         (x1,x2 3*n arrays) using the normalized 8 point algorithm. """
    160 
    161     n = x1.shape[1]
    162     if x2.shape[1] != n:
    163         raise ValueError("Number of points don't match.")
    164 
    165     # normalize image coordinates
    166     x1 = x1 / x1[2]
    167     mean_1 = mean(x1[:2],axis=1)
    168     S1 = sqrt(2) / std(x1[:2])
    169     T1 = array([[S1,0,-S1*mean_1[0]],[0,S1,-S1*mean_1[1]],[0,0,1]])
    170     x1 = dot(T1,x1)
    171     
    172     x2 = x2 / x2[2]
    173     mean_2 = mean(x2[:2],axis=1)
    174     S2 = sqrt(2) / std(x2[:2])
    175     T2 = array([[S2,0,-S2*mean_2[0]],[0,S2,-S2*mean_2[1]],[0,0,1]])
    176     x2 = dot(T2,x2)
    177 
    178     # compute F with the normalized coordinates
    179     F = compute_fundamental(x1,x2)
    180 
    181     # reverse normalization
    182     F = dot(T1.T,dot(F,T2))
    183 
    184     return F/F[2,2]
    185 
    186 
    187 class RansacModel(object):
    188     """ Class for fundmental matrix fit with ransac.py from
    189         http://www.scipy.org/Cookbook/RANSAC"""
    190     
    191     def __init__(self,debug=False):
    192         self.debug = debug
    193     
    194     def fit(self,data):
    195         """ Estimate fundamental matrix using eight 
    196             selected correspondences. """
    197         
    198         # transpose and split data into the two point sets
    199         data = data.T
    200         x1 = data[:3,:8]
    201         x2 = data[3:,:8]
    202         
    203         # estimate fundamental matrix and return
    204         F = compute_fundamental_normalized(x1,x2)
    205         return F
    206     
    207     def get_error(self,data,F):
    208         """ Compute x^T F x for all correspondences, 
    209             return error for each transformed point. """
    210         
    211         # transpose and split data into the two point
    212         data = data.T
    213         x1 = data[:3]
    214         x2 = data[3:]
    215         
    216         # Sampson distance as error measure
    217         Fx1 = dot(F,x1)
    218         Fx2 = dot(F,x2)
    219         denom = Fx1[0]**2 + Fx1[1]**2 + Fx2[0]**2 + Fx2[1]**2
    220         err = ( diag(dot(x1.T,dot(F,x2))) )**2 / denom 
    221         
    222         # return error per point
    223         return err
    224 
    225 
    226 def F_from_ransac(x1,x2,model,maxiter=5000,match_theshold=1e-6):
    227     """ Robust estimation of a fundamental matrix F from point 
    228         correspondences using RANSAC (ransac.py from
    229         http://www.scipy.org/Cookbook/RANSAC).
    230 
    231         input: x1,x2 (3*n arrays) points in hom. coordinates. """
    232 
    233     from PCV.tools import ransac
    234 
    235     data = vstack((x1,x2))
    236     
    237     # compute F and return with inlier index
    238     F,ransac_data = ransac.ransac(data.T,model,8,maxiter,match_theshold,20,return_all=True)
    239     return F, ransac_data['inliers']

     1.2、结果截图

    水平拍摄:

    sift特征匹配:

                                          图一

    基础矩阵和投影矩阵:

    Ransac算法剔除坏的匹配点:

     

                                          图二

    8点算法匹配:

     

                                          图三

     

     左右拍摄:

    sift特征匹配:

                                        图四

    基础矩阵和投影矩阵:

    Ransac算法剔除坏的匹配点:

                                             图五

    8点算法匹配:

     

                                              图六

    基础矩阵:

    前后拍摄:

    sift特征匹配:

     

                                               图七

    基础矩阵和投影矩阵:

    Ransac算法剔除坏的匹配点:

                                                图八

    8点算法匹配:

     

                                                图九

    两组图像的基础矩阵:

     1.3、小结:提取sift特征后匹配sift特征,之后用ransac算法剔除错配的特征,然后用8点算法来求出空间中两张蹄片对应的点的坐标。

    二、极点和极线

          1.1、代码实现

     1 # -*- coding: utf-8 -*-
     2 import numpy as np
     3 import cv2 as cv
     4 from matplotlib import pyplot as plt
     5 img1 = cv.imread('D:/new/beizi/1.jpg',0)  #索引图像 # left image
     6 img2 = cv.imread('D:/new/beizi/2.jpg',0) #训练图像 # right image
     7 sift = cv.xfeatures2d.SIFT_create()
     8 # 使用SIFT查找关键点和描述符
     9 kp1, des1 = sift.detectAndCompute(img1,None)
    10 kp2, des2 = sift.detectAndCompute(img2,None)
    11 # FLANN 参数
    12 FLANN_INDEX_KDTREE = 1
    13 index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
    14 search_params = dict(checks=50)
    15 flann = cv.FlannBasedMatcher(index_params,search_params)
    16 matches = flann.knnMatch(des1,des2,k=2)
    17 good = []
    18 pts1 = []
    19 pts2 = []
    20 
    21 for i,(m,n) in enumerate(matches):
    22     if m.distance < 0.8*n.distance:
    23         good.append(m)
    24         pts2.append(kp2[m.trainIdx].pt)
    25         pts1.append(kp1[m.queryIdx].pt)
    26 pts1 = np.int32(pts1)
    27 pts2 = np.int32(pts2)
    28 F, mask = cv.findFundamentalMat(pts1,pts2,cv.FM_LMEDS)
    29 # 我们只选择内点
    30 pts1 = pts1[mask.ravel()==1]
    31 pts2 = pts2[mask.ravel()==1]
    32 def drawlines(img1,img2,lines,pts1,pts2):
    33     ''' img1 - 我们在img2相应位置绘制极点生成的图像
    34         lines - 对应的极点 '''
    35     r,c = img1.shape
    36     img1 = cv.cvtColor(img1,cv.COLOR_GRAY2BGR)
    37     img2 = cv.cvtColor(img2,cv.COLOR_GRAY2BGR)
    38     for r,pt1,pt2 in zip(lines,pts1,pts2):
    39         color = tuple(np.random.randint(0,255,3).tolist())
    40         x0,y0 = map(int, [0, -r[2]/r[1] ])
    41         x1,y1 = map(int, [c, -(r[2]+r[0]*c)/r[1] ])
    42         img1 = cv.line(img1, (x0,y0), (x1,y1), color,1)
    43         img1 = cv.circle(img1,tuple(pt1),5,color,-1)
    44         img2 = cv.circle(img2,tuple(pt2),5,color,-1)
    45     return img1,img2
    46 # 在右图(第二张图)中找到与点相对应的极点,然后在左图绘制极线
    47 lines1 = cv.computeCorrespondEpilines(pts2.reshape(-1,1,2), 2,F)
    48 lines1 = lines1.reshape(-1,3)
    49 img5,img6 = drawlines(img1,img2,lines1,pts1,pts2)
    50 # 在左图(第一张图)中找到与点相对应的Epilines,然后在正确的图像上绘制极线
    51 lines2 = cv.computeCorrespondEpilines(pts1.reshape(-1,1,2), 1,F)
    52 lines2 = lines2.reshape(-1,3)
    53 img3,img4 = drawlines(img2,img1,lines2,pts2,pts1)
    54 plt.subplot(121),plt.imshow(img5)
    55 plt.subplot(122),plt.imshow(img3)
    56 plt.show()

          1.2、结果截图

          1.3 、小结:利用SIFT查找关键点和描述符,在图中找到极点,然后用plot绘画出外极线。

    三、图像集

    图像集didi:

    图像集jia:

    图像集beizi:

    四、遇到的问题

    4.1、图像的运行出现

    did not meet fit acceptance criteria

    持续报错,然后我就重新多拍了几组图片,换了好几组才成功的,可能是因为图像的拍摄不再一个水平和背景过于丰富。

    4.2、画外极线是报错

    'module' object has no attribute 'SIFT'

    我找了朋友给我看了一下,跟着他改的代码就运行成功了。

    五、总结

    首先,图片的拍摄还是有一定的要求,我们拍摄的图片要背景不要过于丰富,尽量在一个水平线上,保持图像的清晰度,因为不清晰可能会报错或者影响实验结果,然后从三组不同的拍摄角度的图片来运行,可以看出sift匹配的点很多,室内的景使用Ransac算法剔除的坏点较多,室外的景使用的Ransac算法剔除的坏点较少,说明Ransac算法对外景的处理比较有效。从运行结果看出,外景使用8点算法匹配比较有效。求出来的基础矩阵都是三行三列,行列式值等于0(秩为2的3阶方阵),是有七个参数,其中两个参数是对级,三个参数表示两个像平面的单应性矩阵。

  • 相关阅读:
    C#线程并发执行的实例[转]
    Win7怎么用IIS发布网站系统 部署项目
    C#:用SqlBulkCopy来实现批量插入数据
    jQuery 中post 、get的同步问题
    网页配色颜色表(推荐)
    如何修改eclipse的默认字符集和修改中文乱码
    eclipse学习
    SpringMVC开发流程
    SpringMVC的请求
    SpringMVC的数据响应
  • 原文地址:https://www.cnblogs.com/wyf-1999-1--6/p/12748284.html
Copyright © 2020-2023  润新知