我有一个立方体贴图定义周围,但我需要将它传递给一个程序,只有经/纬度的地图作品。 我真的在这里失去了对如何做翻译。 任何帮助这里?
换句话说,我需要来自这里:
向该(我认为图像具有aditional的-90°在x轴旋转):
更新:我得到了突出的正式名称。 顺便说一句,我发现对面投射这里
我有一个立方体贴图定义周围,但我需要将它传递给一个程序,只有经/纬度的地图作品。 我真的在这里失去了对如何做翻译。 任何帮助这里?
换句话说,我需要来自这里:
向该(我认为图像具有aditional的-90°在x轴旋转):
更新:我得到了突出的正式名称。 顺便说一句,我发现对面投射这里
用于投影光栅图像等,这是一个一般程序:
for each pixel of the destination image:
calculate the corresponding unit vector in 3-dimensional space
calculate the x,y coordinate for that vector in the source image
sample the source image at that coordinate and assign the value to the destination pixel
最后一步是简单地插入。 我们将专注于其他两个步骤。
对于给定的纬度和经度的单位矢量是(+朝向北极Z,+ X朝本初子午线):
x = cos(lat)*cos(lon)
y = cos(lat)*sin(lon)
z = sin(lat)
假设该立方体是围绕原点(即2x2x2的整体尺寸)+/- 1个单位。 一旦我们有了单位向量,我们可以找到它通过寻找与绝对值最大的元素在立方体的脸。 例如,如果我们的单位矢量是<0.2099,-0.7289,0.6516>,然后在y元件具有最大绝对值。 它是负的,所以点将在立方体的-y面被发现。 通过由Y幅度将得到该面内的位置正常化其他两个坐标。 因此,该点将在x = 0.2879,Z = 0.8939的-y面。
我想与大家分享我的MATLAB实现这种转换。 我也从了OpenGL 4.1规格借来的,第3.8.10( 这里找到 ),以及保罗·伯克的网站( 在这里找到 )。 请确保你看看副标题: 转换并从6个立方环境贴图和球面地图 。
我还用上面的灵感Sambatyon的帖子。 它开始作为在Python到MATLAB的端口,但我所做的代码,以便它是完全矢量化(即没有for
循环)。 我也借此立方图像和高达分裂成6个独立的图像,作为应用程序,我的建筑具有这种格式的立方图像。 也没有错误的代码检查,而这假设所有的立方体图像的具有相同的尺寸(的nxn
)。 这还假定图像为RGB格式。 如果您想为单色图像做到这一点,只需注释掉需要访问多个频道的这些代码行。 开始了!
function [out] = cubic2equi(top, bottom, left, right, front, back)
% Height and width of equirectangular image
height = size(top, 1);
width = 2*height;
% Flags to denote what side of the cube we are facing
% Z-axis is coming out towards you
% X-axis is going out to the right
% Y-axis is going upwards
% Assuming that the front of the cube is towards the
% negative X-axis
FACE_Z_POS = 1; % Left
FACE_Z_NEG = 2; % Right
FACE_Y_POS = 3; % Top
FACE_Y_NEG = 4; % Bottom
FACE_X_NEG = 5; % Front
FACE_X_POS = 6; % Back
% Place in a cell array
stackedImages{FACE_Z_POS} = left;
stackedImages{FACE_Z_NEG} = right;
stackedImages{FACE_Y_POS} = top;
stackedImages{FACE_Y_NEG} = bottom;
stackedImages{FACE_X_NEG} = front;
stackedImages{FACE_X_POS} = back;
% Place in 3 3D matrices - Each matrix corresponds to a colour channel
imagesRed = uint8(zeros(height, height, 6));
imagesGreen = uint8(zeros(height, height, 6));
imagesBlue = uint8(zeros(height, height, 6));
% Place each channel into their corresponding matrices
for i = 1 : 6
im = stackedImages{i};
imagesRed(:,:,i) = im(:,:,1);
imagesGreen(:,:,i) = im(:,:,2);
imagesBlue(:,:,i) = im(:,:,3);
end
% For each co-ordinate in the normalized image...
[X, Y] = meshgrid(1:width, 1:height);
% Obtain the spherical co-ordinates
Y = 2*Y/height - 1;
X = 2*X/width - 1;
sphereTheta = X*pi;
spherePhi = (pi/2)*Y;
texX = cos(spherePhi).*cos(sphereTheta);
texY = sin(spherePhi);
texZ = cos(spherePhi).*sin(sphereTheta);
% Figure out which face we are facing for each co-ordinate
% First figure out the greatest absolute magnitude for each point
comp = cat(3, texX, texY, texZ);
[~,ind] = max(abs(comp), [], 3);
maxVal = zeros(size(ind));
% Copy those values - signs and all
maxVal(ind == 1) = texX(ind == 1);
maxVal(ind == 2) = texY(ind == 2);
maxVal(ind == 3) = texZ(ind == 3);
% Set each location in our equirectangular image, figure out which
% side we are facing
getFace = -1*ones(size(maxVal));
% Back
ind = abs(maxVal - texX) < 0.00001 & texX < 0;
getFace(ind) = FACE_X_POS;
% Front
ind = abs(maxVal - texX) < 0.00001 & texX >= 0;
getFace(ind) = FACE_X_NEG;
% Top
ind = abs(maxVal - texY) < 0.00001 & texY < 0;
getFace(ind) = FACE_Y_POS;
% Bottom
ind = abs(maxVal - texY) < 0.00001 & texY >= 0;
getFace(ind) = FACE_Y_NEG;
% Left
ind = abs(maxVal - texZ) < 0.00001 & texZ < 0;
getFace(ind) = FACE_Z_POS;
% Right
ind = abs(maxVal - texZ) < 0.00001 & texZ >= 0;
getFace(ind) = FACE_Z_NEG;
% Determine the co-ordinates along which image to sample
% based on which side we are facing
rawX = -1*ones(size(maxVal));
rawY = rawX;
rawZ = rawX;
% Back
ind = getFace == FACE_X_POS;
rawX(ind) = -texZ(ind);
rawY(ind) = texY(ind);
rawZ(ind) = texX(ind);
% Front
ind = getFace == FACE_X_NEG;
rawX(ind) = texZ(ind);
rawY(ind) = texY(ind);
rawZ(ind) = texX(ind);
% Top
ind = getFace == FACE_Y_POS;
rawX(ind) = texZ(ind);
rawY(ind) = texX(ind);
rawZ(ind) = texY(ind);
% Bottom
ind = getFace == FACE_Y_NEG;
rawX(ind) = texZ(ind);
rawY(ind) = -texX(ind);
rawZ(ind) = texY(ind);
% Left
ind = getFace == FACE_Z_POS;
rawX(ind) = texX(ind);
rawY(ind) = texY(ind);
rawZ(ind) = texZ(ind);
% Right
ind = getFace == FACE_Z_NEG;
rawX(ind) = -texX(ind);
rawY(ind) = texY(ind);
rawZ(ind) = texZ(ind);
% Concatenate all for later
rawCoords = cat(3, rawX, rawY, rawZ);
% Finally determine co-ordinates (normalized)
cubeCoordsX = ((rawCoords(:,:,1) ./ abs(rawCoords(:,:,3))) + 1) / 2;
cubeCoordsY = ((rawCoords(:,:,2) ./ abs(rawCoords(:,:,3))) + 1) / 2;
cubeCoords = cat(3, cubeCoordsX, cubeCoordsY);
% Now obtain where we need to sample the image
normalizedX = round(cubeCoords(:,:,1) * height);
normalizedY = round(cubeCoords(:,:,2) * height);
% Just in case.... cap between [1, height] to ensure
% no out of bounds behaviour
normalizedX(normalizedX < 1) = 1;
normalizedX(normalizedX > height) = height;
normalizedY(normalizedY < 1) = 1;
normalizedY(normalizedY > height) = height;
% Place into a stacked matrix
normalizedCoords = cat(3, normalizedX, normalizedY);
% Output image allocation
out = uint8(zeros([size(maxVal) 3]));
% Obtain column-major indices on where to sample from the
% input images
% getFace will contain which image we need to sample from
% based on the co-ordinates within the equirectangular image
ind = sub2ind([height height 6], normalizedCoords(:,:,2), ...
normalizedCoords(:,:,1), getFace);
% Do this for each channel
out(:,:,1) = imagesRed(ind);
out(:,:,2) = imagesGreen(ind);
out(:,:,3) = imagesBlue(ind);
我也做了公开的代码可以通过github上和你可以去这里吧 。 包括是主要的转换脚本,测试脚本,以显示其使用和6张立方图片来自保罗伯克的网站拉到一个样本集。 我希望这是有用的!
项目更名为libcube2cyl 。 同样的善良,无论是在C和C更好的工作实例++。
现在,在C.也可
我碰巧像你描述解决相同问题。
我写了这个小C ++的lib称为“ Cube2Cyl ”,你可以在这里找到算法的详细说明: Cube2Cyl
请找到github上的源代码: Cube2Cyl
它是根据MIT许可下发布,免费使用!
于是,我找到了一个解决方案混合本文从维基百科和3.8.10节从OpenGL的4.1规格球面坐标(加上一些黑客,使其工作)。 因此,假设立方图像具有高度h_o
和宽度w_o
中,等距离长方圆柱将具有高度h = w_o / 3
和宽度w = 2 * h
。 现在对每个像素(x, y) 0 <= x <= w, 0 <= y <= h
在方形投影,我们希望找到在立方投影对应的像素,我解决它使用在python下面的代码(我希望,而由C翻译它,我没有犯错)
import math
# from wikipedia
def spherical_coordinates(x, y):
return (math.pi*((y/h) - 0.5), 2*math.pi*x/(2*h), 1.0)
# from wikipedia
def texture_coordinates(theta, phi, rho):
return (rho * math.sin(theta) * math.cos(phi),
rho * math.sin(theta) * math.sin(phi),
rho * math.cos(theta))
FACE_X_POS = 0
FACE_X_NEG = 1
FACE_Y_POS = 2
FACE_Y_NEG = 3
FACE_Z_POS = 4
FACE_Z_NEG = 5
# from opengl specification
def get_face(x, y, z):
largest_magnitude = max(x, y, z)
if largest_magnitude - abs(x) < 0.00001:
return FACE_X_POS if x < 0 else FACE_X_NEG
elif largest_magnitude - abs(y) < 0.00001:
return FACE_Y_POS if y < 0 else FACE_Y_NEG
elif largest_magnitude - abs(z) < 0.00001:
return FACE_Z_POS if z < 0 else FACE_Z_NEG
# from opengl specification
def raw_face_coordinates(face, x, y, z):
if face == FACE_X_POS:
return (-z, -y, x)
elif face == FACE_X_NEG:
return (-z, y, -x)
elif face == FACE_Y_POS:
return (-x, -z, -y)
elif face == FACE_Y_NEG:
return (-x, z, -y)
elif face == FACE_Z_POS:
return (-x, y, -z)
elif face == FACE_Z_NEG:
return (-x, -y, z)
# computes the topmost leftmost coordinate of the face in the cube map
def face_origin_coordinates(face):
if face == FACE_X_POS:
return (2*h, h)
elif face == FACE_X_NEG:
return (0, 2*h)
elif face == FACE_Y_POS:
return (h, h)
elif face == FACE_Y_NEG:
return (h, 3*h)
elif face == FACE_Z_POS:
return (h, 0)
elif face == FACE_Z_NEG:
return (h, 2*h)
# from opengl specification
def raw_coordinates(xc, yc, ma):
return ((xc/abs(ma) + 1) / 2, (yc/abs(ma) + 1) / 2)
def normalized_coordinates(face, x, y):
face_coords = face_origin_coordinates(face)
normalized_x = int(math.floor(x * h + 0.5))
normalized_y = int(math.floor(y * h + 0.5))
# eliminates black pixels
if normalized_x == h:
--normalized_x
if normalized_y == h:
--normalized_y
return (face_coords[0] + normalized_x, face_coords[1] + normalized_y)
def find_corresponding_pixel(x, y):
spherical = spherical_coordinates(x, y)
texture_coords = texture_coordinates(spherical[0], spherical[1], spherical[2])
face = get_face(texture_coords[0], texture_coords[1], texture_coords[2])
raw_face_coords = raw_face_coordinates(face, texture_coords[0], texture_coords[1], texture_coords[2])
cube_coords = raw_coordinates(raw_face_coords[0], raw_face_coords[1], raw_face_coords[2])
# this fixes some faces being rotated 90°
if face in [FACE_X_NEG, FACE_X_POS]:
cube_coords = (cube_coords[1], cube_coords[0])
return normalized_coordinates(face, cube_coords[0], cube_coords[1])
最后我们只需要调用find_corresponding_pixel
每个像素的方形投影
我想从你的算法在Python中,你可能会在theta和披计算已经倒x和y。
def spherical_coordinates(x, y):
return (math.pi*((y/h) - 0.5), 2*math.pi*x/(2*h), 1.0)
从保罗·伯克的网站在这里
THETA披= Y = X PI PI / 2
并在代码中使用的是在计算theta和X在披计算年。
纠正我,如果我错了。