我正在尝试将2D图像放入3D半球。我的图像大小为128x128。我生成了我的半球:
[x,y,z] = sphere(127);
x = x(64:end,:);
y = y(64:end,:);
z = z(64:end,:);
Attempt = warp(x,y,z,Img)
我的图片是一个圆圈(如下所示)。我得到的是半球周围的奇怪翘曲。但是,我基本上想要将图像放入半球时看起来如何(这不是我得到的)。
感谢您提供的任何帮助!
答案 0 :(得分:2)
这里要考虑两个常见问题:sphere
生成的(x,y,z)坐标的排序以及图像映射到它们的方式:
要了解sphere
如何生成积分,我要warp将一个128 x 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)
矩阵中的点是如何排序的。
如果你想要一个半球形的碗#34;要将图像映射到图像上,您可能希望生成沿着碗边缘的一半运行的点,围绕底部和边缘的另一半包围连续的段。避免涉及几何解释,我只是告诉您,只需在y
的回复中交换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
执行此类操作,但我将展示使用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.这样可以在顶部和底部拉伸圆形区域,使其填满整个正方形图像,并更好地映射到球面。
答案 1 :(得分:1)
你应该注意wrap
函数在给定曲面上扭曲图像的方式,并以某种方式使表面准备好图像的中心保持在表面的最小值。
在这种情况下,我使用MATLAB的以下图像(因为我没有你的图像,但结果会是相同的):
Img = imread('ngc6543a.jpg');
现在我按如下方式制作表面:
fx = @(u,v) u.* cos(v);
fz = @(u,v) u.^2;
fy = @(u,v) 5.*u.*sin(v);
u = linspace(-10,10, 100);
v = linspace(-pi,pi, 100);
[uu,vv] = meshgrid(u, v);
X = fx(uu,vv);
Y = fy(uu,vv);
Z = fz(uu,vv);
surf(X, Y, Z);
现在做翘曲:
warp(X,Y,Z,Img);
axis off
注意:从等式5.0
中删除fy
会形成一个半球而不是一个抛物面。