-
-
Save royshil/0b21e8e7c6c1f46a16db66c384742b2b to your computer and use it in GitHub Desktop.
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) |
Any simple way that you recommend, to turn cylindrical warping to transverse-cylindrical warping?
@thennk can't see a simple way, but line 13 https://gist.github.com/royshil/0b21e8e7c6c1f46a16db66c384742b2b#file-cylindricalwarping-py-L13 is where you'd need to make a change
Yes, thank you.
For future reference, for transverse cylindrical propjection (wrapping around cylinder flipped by 90), line 13 should be:
A = np.stack([X[:,0],np.sin(X[:,1]), np.cos(X[:,1])],axis=-1).reshape(w_*h_,3)
Thanks for this. For future reference, to wrap an image with a transparent background:
img = cv2.imread("image.png", cv2.IMREAD_UNCHANGED)
I really want reverse method, cylinderical to flat image. Is there any way?
@hanish3464 you can invert the mapping B
and use that for cv2.remap. here's an answer on stackoverflow with an implementation for how to do that: https://stackoverflow.com/a/65566295
@thennk can't see a simple way, but line 13 https://gist.github.com/royshil/0b21e8e7c6c1f46a16db66c384742b2b#file-cylindricalwarping-py-L13 is where you'd need to make a change