这里有两个一般性问题需要考虑:sphere 生成的 (x,y,z) 坐标的顺序以及图像映射到它们的方式:
积分排序
要查看sphere 是如何生成点的,我将warp 一个样本128×128 RGB 图像mapImage 放到球面上:
subplot(1, 2, 1);
imshow(mapImage);
subplot(1, 2, 2);
[x, y, z] = sphere(128);
warp(x, y, z, mapImage);
axis equal
请注意,图像的最左侧列被映射到球体左侧(从其底部到顶部)向上延伸的一条线。图像中的每个连续列都按照顺时针方向(向下看)围绕球体按顺序分段进行映射。这向我们展示了(x,y,z) 矩阵中的点是如何排序的。
如果您想要将图像映射到一个半球形“碗”上,您需要生成沿碗边缘的一半运行的点,围绕底部和边缘的另一半依次包裹。避免涉及几何解释,我将简单地告诉您,您可以通过在来自sphere 的返回调用中交换您的y 和z 矩阵,然后丢弃三个矩阵中的最后一半列来生成您的碗:
[x, z, y] = sphere(128);
x = x(:, 1:65);
y = y(:, 1:65);
z = z(:, 1:65);
warp(x, y, z, mapImage)
axis equal
映射您的图像
从上图可以看出,整个图像被映射到表面,而不仅仅是圆形中心区域。注意颜色鲜艳的角是如何在碗边缘的顶部和底部被夹起来的,球体的生成点在这里密集地聚集在一起。也许您只想将圆形中心区域映射到表面?
为此,您必须转换图像,使圆形区域沿每一行拉伸,以填充图像。你可以用imwarp 做这种事情,但我将展示一个用interpolation 做这件事的例子。
[Xq, Yq] = meshgrid(1:128);
Xq = 64.5+sqrt(abs(63.5^2-(Yq-64.5).^2)).*(Xq-64.5)./63.5;
centerImage(:, :, 1) = interp2(mapImage(:, :, 1), Xq, Yq);
centerImage(:, :, 2) = interp2(mapImage(:, :, 2), Xq, Yq);
centerImage(:, :, 3) = interp2(mapImage(:, :, 3), Xq, Yq);
subplot(1, 2, 1);
imshow(centerImage);
subplot(1, 2, 2);
warp(x, y, z, centerImage);
axis equal
计算Xq 的那行看起来有点难看。为了解释,Xq 的每一行中的索引从 -1 重新缩放到 1(而不是 1 到 128),乘以该行中圆形区域宽度的一半,然后向上移动以用作插值在 1 到 128 的范围内。这会在顶部和底部进一步拉伸圆形区域,使其填充整个方形图像并更好地映射到球面。