OpenCV: How to implement "Keystone Correction"?

I want to take an image that is looking at the rectangle from the bottom (creating a trapezoid) and change it to the original rectangle. For example, imagine you were on the ground photographing a skyscraper. I want to use this data to find out what the side of a skyscraper looks like. How can i do this?

Keystone correction usually refers to an offset projector, but that's not really what's going on. My original image is already messed up just like an offset projector would. I need to get it straight.

Thanks for any help. If it's important, I'm using the Java version of OpenCV, but I'm happy with any answers; I'm sure it's easy to do this in java from any other language.

Edit: I want to do what is shown for Notre Dame on this page: https://en.wikipedia.org/wiki/Perspective_control

+3


source to share


1 answer


This is called homography. You need to know the angles of the trapezoid and then calculate the homography matrix using the findHomography function and then use the warpPerspective function to generate the corrected image. I wrote a simple python program for you to play around and provide an image of the result so you know what it does and see what you say.

enter image description here



code

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)    

      

+2


source







All Articles