Source code for flamingo.rectification.rectification

#!/usr/bin/env python

__author__ = "Bas Hoonhout"
__copyright__ = "Copyright 2014, The NEMO Project"
__credits__ = []
__license__ = "GPL"
__version__ = "1.0.1"
__maintainer__ = "Bas Hoonhout"
__email__ = "bas.hoonhout@deltares.nl"
__status__ = "production"

import numpy as np
import cv2


[docs]def find_homography(UV, XYZ, K, distortion=np.zeros((1,4)), z=0): '''Find homography based on ground control points Parameters ---------- UV : np.ndarray Nx2 array of image coordinates of gcp's XYZ : np.ndarray Nx3 array of real-world coordinates of gcp's K : np.ndarray 3x3 array containing camera matrix distortion : np.ndarray, optional 1xP array with distortion coefficients with P = 4, 5 or 8 z : float, optional Real-world elevation on which the image should be projected Returns ------- np.ndarray 3x3 homography matrix Notes ----- Function uses the OpenCV image rectification workflow as described in http://docs.opencv.org/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html starting with solvePnP. Examples -------- >>> camera_id = 4 >>> r = argus2.rest.get_rectification_data('kijkduin') >>> H = flamingo.rectification.find_homography(r[camera_id]['UV'], r[camera_id]['XYZ'], r[camera_id]['K']) ''' UV = np.asarray(UV).astype(np.float32) XYZ = np.asarray(XYZ).astype(np.float32) K = np.asarray(K).astype(np.float32) # compute camera pose # rvec, tvec = cv2.solvePnP(XYZ, UV, K, distortion)[1:] rvec, tvec = cv2.solvePnP(XYZ, UV, K, distortion) # convert rotation vector to rotation matrix R = cv2.Rodrigues(rvec)[0] # assume height of projection plane R[:,2] = R[:,2] * z # add translation vector R[:,2] = R[:,2] + tvec.flatten() # compute homography H = np.linalg.inv(np.dot(K, R)) # normalize homography H = H / H[-1,-1] return H
[docs]def get_pixel_coordinates(img): '''Get pixel coordinates given an image Parameters ---------- img : np.ndarray NxMx1 or NxMx3 image matrix Returns ------- np.ndarray NxM matrix containing u-coordinates np.ndarray NxM matrix containing v-coordinates ''' # get pixel coordinates U, V = np.meshgrid(range(img.shape[1]), range(img.shape[0])) return U, V
[docs]def rectify_image(img, H): '''Get projection of image pixels in real-world coordinates given an image and homography Parameters ---------- img : np.ndarray NxMx1 or NxMx3 image matrix H : np.ndarray 3x3 homography matrix Returns ------- np.ndarray NxM matrix containing real-world x-coordinates np.ndarray NxM matrix containing real-world y-coordinates ''' U, V = get_pixel_coordinates(img) X, Y = rectify_coordinates(U, V, H) return X, Y
[docs]def rectify_coordinates(U, V, H): '''Get projection of image pixels in real-world coordinates given image coordinate matrices and homography Parameters ---------- U : np.ndarray NxM matrix containing u-coordinates V : np.ndarray NxM matrix containing v-coordinates H : np.ndarray 3x3 homography matrix Returns ------- np.ndarray NxM matrix containing real-world x-coordinates np.ndarray NxM matrix containing real-world y-coordinates ''' UV = np.vstack((U.flatten(), V.flatten())).T # transform image using homography XY = cv2.perspectiveTransform(np.asarray([UV]).astype(np.float32), H)[0] # reshape pixel coordinates back to image size X = XY[:,0].reshape(U.shape[:2]) Y = XY[:,1].reshape(V.shape[:2]) return X, Y