I want to do some particle image velocimetry on dancing people but I was not able to record movies from the top (a bird's eye view). Instead, I managed to shot them from an upper position and my goal is to transform this series of images into a top/down bird's eye view using warpPerspective
from openCV in Python. The issues that I have are the following:
- I do not have reference points on the image;
- I do not know the distortion of the camera (the movie was shot with a Nikon D7000 and a 18-140 mm Nikon varifocal lens).
Here is the image I want to transform
P1, P2, P3 and P4 are reference points that I chose to transform the perspective. I chose them because I know, from the geometry of the white pillars in the image, they form a rectangle (approximately). Their position in pixel are (1248, 2160), (2730, 1764), (3336, 2994) and (4728, 2196) respectively.
Based on an earlier similar question, I tried to follow this answer but the results were poor. Here is my code
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
im = cv.imread("images/_DSC3318.JPG")
plt.imshow(im)
plt.show()
(height, width) = im.shape[:2]
assert (width, height) == (6000, 4000), "or whatever else"
K = np.eye(3)
K[0,0] = K[1,1] = 1000 # 500-5000 is common
K[0:2, 2] = (width-1)/2, (height-1)/2
dc = np.float32([-0.32, 0.24, 0. , 0. , 0. ]) # k1, k2, p1, p2, k3
im_undistorted = cv.undistort(im, K, dc)
modelpts = np.float32([
[0., 6.],
[8., 0.],
[8., 6.],
[0., 0.]])*20
pts1 = np.float32([(1248, 2160),
(2730, 1764),
(3336, 2994),
(4728, 2196)])
pts2 = cv.undistortImagePoints(pts1, K, dc)
impts_undist = pts2.reshape((-1, 1, 2))
H = cv.getPerspectiveTransform(impts_undist, modelpts)
topdown = cv.warpPerspective(im_undistorted, H, dsize=(90*15, 60*15))
K
and cd
are some parameters (that I don't really understand) used to obtained an undistorted image;pts1
are the coordinate in pixel of P1,...,P4 mentioned above; pts2
are supposed to be the coordinates of pts1
in the undistorted image, modelpts
are the coordinates of P1,...,P4 in the bird's eye image (my ultimate goal) which does not work.
To illustrate my point here are the resulting undistorted image im_undistort
And here is the final top/down view
My guesses to why it does not work are:
- I do not have a precise location of
modelpts
corresponding topts1
; - the order of the points in
modelpts
do not correspond to the order of points inpts1
, therefore generating a completely wrong top/down view; - parameters
K
anddc
used incv.undistort
are not precise enough to correct for image distortion (though I doubt it affect much since the undistorted image is not too "wrong").