简体   繁体   English

使用MATLAB将2D图像放入半球

[英]Place 2D image into Hemisphere using MATLAB

I am trying to place a 2D image into a 3D hemisphere. 我正在尝试将2D图像放入3D半球。 I have an image of size 128x128. 我有一个尺寸为128x128的图片。 I generate my hemisphere: 我产生了我的半球:

[x,y,z] = sphere(127);
x = x(64:end,:);
y = y(64:end,:);
z = z(64:end,:);

Attempt = warp(x,y,z,Img)

My image is a circle (as shown below). 我的图像是一个圆(如下所示)。 What I get is a strange warping around the hemisphere. 我得到的是半球周围的奇怪变形。 However, I essentially want how it would look if I dropped the image into the hemisphere (which is not what I get). 但是,我本质上想要将图像放到半球(这不是我得到的)中时的外观。

Thanks for any help you can provide! 感谢您的任何帮助,您可以提供!

图片示例 在此处输入图片说明

There are two general issues to consider here: The ordering of (x,y,z) coordinates generated by sphere and the way in which the image will be mapped to them: 这里有两个要考虑的一般问题: sphere生成的(x,y,z)坐标的顺序以及将图像映射到它们的方式:

Ordering of points 点的顺序

To see how sphere is generating points, I'm going to warp a sample 128-by-128 RGB image mapImage to the spherical surface: 要了解如何sphere被生成点,我将翘曲的样品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

在此处输入图片说明

Notice that the left-most column of the image gets mapped to a line running up the left side of the sphere (from its bottom point to its top point). 请注意,图像的最左列已映射到在球体左侧(从其最低点到最高点)的那条线上。 Each successive column from the image gets mapped in sequential segments following clock-wise (looking down) around the sphere. 图像中的每个连续列都按顺时针方向(向下)围绕球体按顺序分段映射。 This shows us how the points in our (x,y,z) matrices are ordered. 这向我们展示了(x,y,z)矩阵中的点如何排序。

If you want a hemispheric "bowl" to map an image onto, you would want to generate points running along one half of the bowls rim, wrapping in sequential segments around the bottom and to the other half of the rim. 如果希望将半球形的“碗”映射到图像上,则需要生成沿碗边缘一半的点,并依次围绕底部和边缘的另一部分缠绕点。 Avoiding involved geometric explanations, I'll simply tell you that you can generate your bowl by just swapping your y and z matrices in the return call from sphere , then discarding the last half of the columns from the three matrices: 避免涉及几何解释,我简单地告诉您,您可以通过在sphere的return调用中交换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

在此处输入图片说明

Mapping your image 映射图像

As you can see from the figure above, the entire image is mapped to the surface, not just the circular center region. 从上图可以看到,整个图像被映射到表面,而不仅仅是圆形的中心区域。 Notice how the bright-colored corners get pinched up at the top and bottom points of the bowl rim, where the generated points of the sphere are densely clustered. 注意,在碗边缘的顶部和底部,明亮的角如何被捏住,球的生成点密集地聚集在碗的顶部和底部。 Perhaps you only want to map the circular center region to the surface? 也许您只想将圆形中心区域映射到曲面?

To do this, you'll have to transform your image so that the circular region is stretched along each row so that it fills the image. 为此,您必须对图像进行变换,以使圆形区域沿每行延伸,从而填充图像。 You could probably do this sort of thing with imwarp , but I'm going to show an example of doing this with interpolation . 您可能可以通过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

在此处输入图片说明

The line where Xq is computed looks kinda ugly. Xq的计算行看起来很难看。 To explain, the indices in each row of Xq are rescaled from -1 to 1 (instead of 1 to 128), multiplied by half the width of the circular region in that row, then shifted back up to be used as an interpolant in the range of 1 to 128. This stretches the circular region moreso at the top and bottom so it fills the entire square image and maps better to the spherical surface. 为了解释,将Xq每一行中的索引从-1重新缩放(而不是从1到128),再乘以该行中圆形区域的宽度的一半,然后向上移回以用作Xq中的插值范围是1到128。这样会在顶部和底部进一步拉伸圆形区域,从而填充整个正方形图像,并更好地映射到球形表面。

You should pay attention the way that the wrap function is warping the image on the given surface, and make the surface prepared somehow that the center of the image stays on the minimum of the surface. 您应注意wrap功能使给定表面上的图像变形的方式,并以某种方式使表面准备好,使图像的中心保持在表面的最小值上。

In this case I use the following image by MATLAB (since I do not have your image, but the result would be the same): 在这种情况下,我使用MATLAB的以下图像(因为我没有您的图像,但是结果将是相同的):

Img = imread('ngc6543a.jpg');

在此处输入图片说明

Now I make a surface as follows: 现在,我将表面制作如下:

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);

在此处输入图片说明

Now do the warping: 现在进行变形:

warp(X,Y,Z,Img);
axis off

在此处输入图片说明

在此处输入图片说明

Note: remove the 5.0 from equation fy makes a semi-sphere instead of a praboloid. 注意:从等式fy删除5.0会生成半球体而不是生物球体。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM