
Hey-o
Just sharing a code snippet to warp images to cylindrical coordinates, in case you’re stitching panoramas in Python OpenCV…
This is an improved version from what I had in class some time ago…
It runs VERY fast. No loops involved, all matrix operations. In C++ this code would look gnarly.. Thanks Numpy!
Enjoy!
Roy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import cv2 | |
import numpy as np | |
def cylindricalWarp(img, K): | |
"""This function returns the cylindrical warp for a given image and intrinsics matrix K""" | |
h_,w_ = img.shape[:2] | |
# pixel coordinates | |
y_i, x_i = np.indices((h_,w_)) | |
X = np.stack([x_i,y_i,np.ones_like(x_i)],axis=-1).reshape(h_*w_,3) # to homog | |
Kinv = np.linalg.inv(K) | |
X = Kinv.dot(X.T).T # normalized coords | |
# calculate cylindrical coords (sin\theta, h, cos\theta) | |
A = np.stack([np.sin(X[:,0]),X[:,1],np.cos(X[:,0])],axis=-1).reshape(w_*h_,3) | |
B = K.dot(A.T).T # project back to image-pixels plane | |
# back from homog coords | |
B = B[:,:-1] / B[:,[-1]] | |
# make sure warp coords only within image bounds | |
B[(B[:,0] < 0) | (B[:,0] >= w_) | (B[:,1] < 0) | (B[:,1] >= h_)] = -1 | |
B = B.reshape(h_,w_,-1) | |
img_rgba = cv2.cvtColor(img,cv2.COLOR_BGR2BGRA) # for transparent borders... | |
# warp the image according to cylindrical coords | |
return cv2.remap(img_rgba, B[:,:,0].astype(np.float32), B[:,:,1].astype(np.float32), cv2.INTER_AREA, borderMode=cv2.BORDER_TRANSPARENT) | |
if __name__ == '__main__': | |
img = cv2.imread("image.png") | |
h, w = img.shape[:2] | |
K = np.array([[800,0,w/2],[0,800,h/2],[0,0,1]]) # mock intrinsics | |
img_cyl = cylindricalWarp(img, K) | |
cv2.imwrite("image_cyl.png", img_cyl) |