1

I want to project an image from spherical to cubemap. From what I understood studying maths, I need to create a theta, phi distribution for each pixel and then convert it into cartesian system to get a normalized pixel map.

I used the following code to do so

theta = 0
phi = np.pi/2
squareLength = 2048

# theta phi distribution for X-positive face
t = np.linspace(theta + np.pi/4, theta - np.pi/4, squareLength)
p = np.linspace(phi + np.pi/4, phi - np.pi/4, squareLength)
x, y = np.meshgrid(t, p)

# converting into cartesion sytem for X-positive face (where r is the distance from sphere center to cube plane and X is constantly 0.5 in cartesian system)
X = np.zeros_like(y)
X[:,:] = 0.5
r = X / (np.cos(x) * np.sin(y))
Y = r * np.sin(x) * np.sin(y)
Z = r * np.cos(y)
XYZ = np.stack((X, Y, Z), axis=2)

# shifting pixels from the negative side
XYZ = XYZ + [0, 0.5, 0.5]

# since i want to project on X-positive face my map should be
x_map = -XYZ[:, :, 1] * squareLength
y_map = XYZ[:,:, 2] * squareLength

The above map created should give me my desired result with cv2.remap() but it's not. Then I tried looping through pixels and implement my own remap without interpolation or extrapolation. With some hit and trial, I deduced the following formula which gives me the correct result

for i in range(2048):
    for j in range(2048):
        try:
            image[int(y_map[i,j]), int(x_map[i,j])] = im[i, j]
        except:
            pass

which is reverse of actual cv2 remapping which says dst(x,y)=src(mapx(x,y),mapy(x,y))

I do not understand if did the math all wrong or is there a way to covert x_map and y_map to correct forms so that cv2.remap() gives the desired result.

INPUT IMAGE enter image description here

DESIRED RESULT (this one is without interpolation using loops) enter image description here

CURRENT RESULT (using cv2.remap()) enter image description here

Cybersupernova
  • 1,833
  • 1
  • 20
  • 37

2 Answers2

2

I'm quite new in opencv and I didn't work with so difficult math algorithms before but I tried to do this. I rewrote your code a bit and here it is:

import numpy as np
import cv2


src = cv2.imread("data/pink_sq.png")


def make_map():
    theta = 0
    phi = np.pi / 2
    squareLength = 4000

    # theta phi distribution for X-positive face
    t = np.linspace((theta - np.pi / 4), (theta + np.pi / 4), squareLength)
    p = np.linspace((phi + np.pi / 4), (phi - np.pi / 4), squareLength)
    x, y = np.meshgrid(t, p)

    x_res = np.zeros_like(y)
    x_res[:, :] = 0.5
    r = x_res * (np.cos(x))
    r /= np.amax(r)
    y_res = r * x
    z_res = r * np.cos(y)
    xyz = np.stack((x_res, y_res, z_res), axis=2)

    # shifting pixels from the negative side
    xyz = xyz + [0, 0.5, 0.5]

    # since i want to project on X-positive face my map should be
    x_map = xyz[:, :, 1] * squareLength
    y_map = xyz[:, :, 2] * squareLength

    map_x = y_map.astype("float32")
    map_y = x_map.astype("float32")
    return map_x, map_y


map_x, map_y = make_map()
dst = cv2.remap(src, map_y, map_x, cv2.INTER_LINEAR)

cv2.imwrite("res.png", dst)

I don't understand the math in this code at all but I rewrote it a bit and I should say that it works quite good. Here is the result image: enter image description here And yes, there is a bit difference between my result picture and yours but I hope it is ok :) If I'm not right somewhere of course downvote this answer because I'm not sure that it is correct one.

crackanddie
  • 688
  • 1
  • 6
  • 20
  • hey it is quite right result. Not accepted the answer yet since I need to verify the math on different theta phi angles – Cybersupernova Mar 05 '21 at 08:14
  • As you have already told, you don't know the maths. So this is wrong maths, It is only working for X-positive face (that too not perfectly). I have changed the maths and angle accordingly for other faces but it ain't working. You have just fitted the pattern which we required, and that pattern stops working when angles are like 120(theta) and 0(phi) – Cybersupernova Mar 05 '21 at 11:07
  • then I'm sorry and I hope that it was helpful a little – crackanddie Mar 05 '21 at 11:26
  • cv2.error: OpenCV(4.5.4) D:\a\opencv-python\opencv-python\opencv\modules\imgproc\src\imgwarp.cpp:668: error: (-215:Assertion failed) !ssize.empty() in function 'cv::remapBilinear' – yw173 Dec 20 '21 at 04:49
0

I'm almost certain the issue has to do with the orientation of the reference frame in space. Maybe if you clarify the Math a bit we can help.

error404
  • 11
  • 4
  • 1
    As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Mar 19 '22 at 20:07