OpenCV:如何实现“梯形校正”?

5
我想将从下方拍摄的矩形图像(创建梯形)转换为原始矩形。例如,假设您在地面上拍摄一幢摩天大楼的照片。我希望使用该数据找到摩天大楼侧面的外观。有什么方法可以实现?
基本上Keystone校正是指投影机的偏移,但这不完全是正在发生的情况。我的源图像已经以与偏移投影机相同的方式混乱了。我需要将它变为正面。
谢谢任何帮助。如果有关系,我正在使用OpenCV Java版本,但我对任何答案都很满意;我相信将其从任何其他语言转换为java很容易。
编辑:我想要的是在此页面上为巴黎圣母院所示的内容: https://en.wikipedia.org/wiki/Perspective_control
1个回答

6
这被称为单应性矩阵。您需要知道梯形的四个角,然后使用findHomography函数计算单应性矩阵,再使用warpPerspective函数生成校正后的图像。我为您编写了一个简单的Python程序,并提供了结果图像,以便您了解它的作用并查看是否符合您的要求。

enter image description here

代码

import cv2
import numpy as np
import cv

pSrc = [(  98,67),( 331 ,  75),( 415 , 469),(  27 , 466)]
pDst = [(  27,67),( 415 ,  75),( 415 , 469),(  27 , 466)]
def srcMouse(event, x, y, flags,params):
    global pSrc
    if event == cv.CV_EVENT_LBUTTONDOWN:

        if len(pSrc) >=4:
            pSrc=[]
        pSrc.append((x,y))
        print np.array(pSrc,dtype=np.float32)

def dstMouse(event, x, y, flags,params):
    global pDst
    if event == cv.CV_EVENT_LBUTTONDOWN:
        if len(pDst) >=4:
            pDst=[]
        pDst.append((x,y))

cv2.namedWindow('src')
cv.SetMouseCallback('src', srcMouse, 0)
cv2.namedWindow('dst')
cv.SetMouseCallback('dst', dstMouse, 0)

im = cv2.imread('c:/data/notre.jpg')
dst = np.zeros(im.shape,dtype=np.uint8)
while(1):
    imD = im.copy()
    dstD = dst.copy()
    for p in pSrc:
        cv2.circle(imD,p,2,(255,0,0),-1)
    for p in pDst:
        cv2.circle(dstD,p,2,(255,0,0),-1)

    if len(pSrc)==4 and len(pDst)==4:
        H = cv2.findHomography(np.array(pSrc,dtype=np.float32),np.array(pDst,dtype=np.float32),cv2.LMEDS)
        dstD=cv2.warpPerspective(imD,H[0],(dstD.shape[1],dstD.shape[0]))
    cv2.imshow('src',imD)
    cv2.imshow('dst',dstD)
    if cv2.waitKey(1) ==27:
        exit(0)    

抱歉,我对计算机视觉还不熟悉。什么是单应性变换? - dftba4ever
Homography是描述两个平面之间关系的矩阵。在这种情况下,一个平面被透视投影扭曲,另一个平面则被校正。findHomography基于4个点(最少要求)计算此矩阵(H),如果有多于4个点,则会计算最小化重投影误差的最小二乘拟合。warpPerspective执行将原始图像像素映射到由此矩阵描述的新平面的操作。请参考在线资源以获取更详细的解释(http://www.cs.toronto.edu/~jepson/csc2503/tutorials/homography.pdf)。 - Zaw Lin
@Zaw Lin,干得好!感谢您的发布。我正在使用Python 2.7.8 x64 + OpenCV 3.1.0(似乎已经融合了较旧的OpenCV API)。无论如何,代码在我这里无法运行,因此我为我的设置进行了修复,并将其清理了一下,同时让它倾倒出所得到的单应矩阵(我想将其与另一种计算方法进行比较)。这是链接:https://gist.github.com/psydbernz/8d980e0f9f4a1530f2e1ecef4d1b5210 - bernz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接