这里有两个一般性问题需要考虑: 生成的 (x,y,z) 坐标的顺序sphere
以及图像映射到它们的方式:
点的排序
看看如何sphere正在生成积分,我要去warp128×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)
矩阵是有序的。
如果您想要将图像映射到半球形“碗”上,您可能需要生成沿着碗边缘的一半运行的点,以连续的段环绕底部并到达边缘的另一半。避免涉及几何解释,我只是简单地告诉你,你可以通过交换你的碗来生成你的碗y
and z
返回调用中的矩阵sphere
,然后丢弃三个矩阵中的后半列:
[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,但我将展示一个这样做的例子插值法.
[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 范围内的插值。这会拉伸圆形顶部和底部区域更是如此,因此它填充了整个方形图像并更好地映射到球面。