【问题标题】:Place 2D image into Hemisphere using MATLAB使用 MATLAB 将 2D 图像放入半球
【发布时间】:2016-12-22 06:17:07
【问题描述】:

我正在尝试将 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)

我的图像是一个圆圈(如下图)。我得到的是一个奇怪的半球扭曲。但是,我基本上想要将图像放入半球时的外观(这不是我得到的)。

感谢您提供的任何帮助!

【问题讨论】:

  • 您的代码的第二行对我来说看起来不对?我没有图像工具箱(所以我没有扭曲),但你是否在追求这样的东西:ok = z>0;warp(x(ok), y(ok), z(ok), Img)
  • 虽然我的代码可能是错误的(我的错误),但基本上我的问题似乎是我需要移动 2D 图像对应于半球零的位置的中心。

标签: matlab image-processing


【解决方案1】:

这里有两个一般性问题需要考虑: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 的返回调用中交换您的yz 矩阵,然后丢弃三个矩阵中的最后一半列来生成您的碗:

[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 的范围内。这会在顶部和底部进一步拉伸圆形区域,使其填充整个方形图像并更好地映射到球面。

【讨论】:

  • 非常感谢。我从这个详细的答案中学到了很多东西。这正是我想要实现的目标。
【解决方案2】:

您应该注意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

注意:从方程 fy 中删除 5.0 会生成半球体而不是抛物面。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-18
    • 1970-01-01
    • 2015-07-29
    • 2016-03-27
    • 2018-08-10
    • 1970-01-01
    • 2022-08-05
    相关资源
    最近更新 更多