未标定相机的极线矫正

极线矫正的目的是其两张像对具有相同的y坐标,作用是:比如计算深度图/视差图,计算南极海冰漂移量等。如图:
这里写图片描述
Matlab 中语法为下

[T1,T2] = estimateUncalibratedRectification(F,inlierPoints1,inlierPoints2,imagesize)

T1,T2是投影变换矩阵,用来变换两张影像。
通过未标定相机来实现极线矫正的步骤如下:
1、 图像匹配(sift,surf,orb)
2、 估计基本矩阵
3、 从基本矩阵中恢复两张影像的各自变换矩阵
这里注意的是,如果极点在图像内部(I1/I2),那么T1,T2变换可能会使得图像产生不理想的扭曲效果,因此变换之前先做一个极点的判断。
具体算法如下:
以摄影测量的转角系统为例
这里写图片描述
这里写图片描述
python 代码如下:

# -*- coding: utf-8 -*-
'''cv2.stereoRectifyUncalibrated'''
import cv2
import numpy as np
from numba import autojit
@autojit
def mathching(im1,im2):
    surf=cv2.xfeatures2d.SURF_create()
    kp1,des1=surf.detectAndCompute(im1,None)
    kp2,des2=surf.detectAndCompute(im2,None)
    FLANN_INDEX_KDTREE=0
    index_p=dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
    searth_p=dict(checks=50)
    flann=cv2.FlannBasedMatcher(index_p,searth_p)
    matches=flann.knnMatch(des1,des2,k=2)
    good =[]
    pts1=[]
    pts2=[]
    for i,(m,n) in enumerate(matches):
        if m.distance<0.6*n.distance:
            good.append(m)
            pts1.append(kp1[m.queryIdx].pt)
            pts2.append(kp2[m.trainIdx].pt)
    pts1=np.float32(pts1)
    pts2=np.float32(pts2)
    F,mask=cv2.findFundamentalMat(pts1,pts2,cv2.RANSAC,0.01)
    points1=pts1[mask.ravel()==1]
    points2=pts2[mask.ravel()==1]
    return points1,points2,F
def returnH1_H2(points1,points2,F,size):
    p1=points1.reshape(len(points1)*2,1)#stackoverflow上需要将(m,2)的点变为(m*2,1),因为不变在c++中会产生内存溢出
    p2=points2.reshape(len(points2)*2,1)
    _,H1,H2=cv2.stereoRectifyUncalibrated(p1,p2,F,size) #size是宽,高
    return H1,H2
def getRectifystereo(H1,H2,im1,im2,size,e,F):
    #左极点
    e_l=compute_epipole(F.T)
    #右极点
    e_r=compute_epipole(F)
    w_l,h_l=im1.shape[1],im1.shape[0]
    w_r,h_r=im2.shape[1],im2.shape[0]
    if abs(e_l[0])>w_l and abs(e_l[1])>h_l and abs(e_r[0])>w_r and abs(e_r[1])>h_r:#判断极点在图像外部
        K=np.eye(3,3)
        left_R=np.linalg.inv(K)@H1@K
        right_R=np.linalg.inv(K)@H2@K
        d=np.zeros((5,1))
        map1,map2=cv2.initUndistortRectifyMap(K,d,left_R,K,size,cv2.CV_16SC2)
        map3,map4=cv2.initUndistortRectifyMap(K,d,right_R,K,size,cv2.CV_16SC2)
        rectifyim1=cv2.remap(im1,map1,map2,cv2.INTER_LINEAR)
        rectifyim2=cv2.remap(im2,map3,map4,cv2.INTER_LINEAR)
    else:
        print("极点在图像内部")
    return rectifyim1,rectifyim2
def compute_epipole(F):
    """
    利用F计算右极点,若要计算左极点,则分解F.T
    """
    U, S, V = np.linalg.svd(F)
    e = V[-1]
    return e / e[2]
if __name__=="__main__":
    im1=cv2.imread(r'C:\Users\Y\Desktop\12.jpg')
    im2=cv2.imread(r'C:\Users\Y\Desktop\23.jpg')
    size=im1.shape[1],im1.shape[0]
    points1,points2,F=mathching(im1,im2)
    H1,H2=returnH1_H2(points1,points2,F,size)
    rectifyim1,rectifyim2=getRectifystereo(H1,H2,im1,im2,size)

猜你喜欢

转载自blog.csdn.net/qq_15642411/article/details/80731517