【问题标题】:Plot image on dome在圆顶上绘制图像
【发布时间】:2021-03-08 21:25:56
【问题描述】:

我正在努力在 Matlab 的圆顶表面绘制圆形图像。这就是我所拥有的。这是png图片:

这是穹顶:

现在,我需要将此图像投影到圆顶上。我已经编写了一个代码来将图像放置在表面上:

r = 10;
r2 = 9;
cdata = imread('circle_image.png');
props.EdgeColor = 'none';
figure();
n = 50;
[X,Y,Z] = sphere(n) ;
X1 = X * r;
Y1 = Y * r;
Z1 = Z * r;

for i = 1:n+1
    for j = 1:n+1
            if Z1(i,j) < r2
                X1(i,j) = NaN;
                Y1(i,j) = NaN;
                Z1(i,j) = NaN;
            
            end
    end
end
my_dome = surf(X1,Y1,Z1,props) ;
alpha = 1;
set(kopula, 'FaceColor', 'texturemap', 'CData', cdata, 'FaceAlpha', alpha, 'EdgeColor', 'none');
axis equal

我得到的是这样的:

图像的中心似乎在错误的位置,甚至在错误的轴上。我该如何解决?

【问题讨论】:

    标签: image matlab geometry matlab-figure surface


    【解决方案1】:

    是的,图片居中位置错误。

    纹理映射应用于整个表面,而不仅仅是“活动”点(您没有 NaN 的那个点)。基本上,您得到的是将图像传播到整个球体上,然后当您裁剪球体的顶部以获得圆顶时,图像也会被裁剪:


    您需要做的实际上是删除所有转换为NaN 的点,因此它们根本不是表面的一部分,纹理映射仅应用于顶部圆顶表面。

    所以用下面的代码替换你的嵌套for循环:

    idx_Raws2crop = Z1(:,1) < r2 ;
    X1(idx_Raws2crop,:) = [] ;
    Y1(idx_Raws2crop,:) = [] ;
    Z1(idx_Raws2crop,:) = [] ;
    

    然后继续你的代码,你会得到:

    其实我也加了指令:

    cdata = flipud(cdata) ;
    

    为了使THE CIRCLEwriting 具有正确的方向(否则它会出现颠倒)。


    编辑:

    要根据您的评论以您喜欢的方式在圆顶上渲染图片,我可以看到2个选项:

    选项 1:建立在我们已有的基础上

    这将包括:

    • 正方形网格上扩展[X,Y]域(这样当纹理映射到表面时图片不会失真)。
    • 扩展图片本身(添加一些透明边距),这样边距将覆盖我们引入的域扩展,并且图片的实际可见部分将很好地居中在圆顶上。

    使用与上面代码相​​同的X1Y1Z1

    % Create a square grid large enough to cover the dome and a bit more:
    [X2,Y2] = meshgrid(linspace(-5,5,100),linspace(-5,5,100)) ;
    % reinterpolate Z1 over this new grid
    Z2 = griddata(X1,Y1,Z1,X2,Y2) ;
    

    现在您的表面如下所示:

    正如我警告过的那样,图像现在已正确应用,但圆顶的边缘看起来相当难看。为了便于您将 NaN 替换为圆顶的基本值,这将在 domeflat 域之间转换得更好:

    Z2(isnan(Z2)) = 9 ;
    

    现在将产生:

    如您所见,下一个问题是(如您的第一个问题),图像被拉伸到整个表面。因此,部分文字现在位于表面的平坦部分。为了简单地缓解这种情况,您可以修改图片(在每一侧添加一点透明边距),直到图像的可见部分与圆顶尺寸匹配。


    选项 2:以不同方式构建表面

    这实际上更简单、更直接。我们将首先用方形表面建造一个圆顶(没有修剪和NaNing)。

    此代码不需要您之前代码的任何部分,它是自包含的:

    r = 10 ;
    % Build a square grid
    [X2,Y2] = meshgrid(linspace(-5,5,100),linspace(-5,5,100)) ;
    % build Z2 according to the sphere equation.
    Z2 = sqrt( r^2 - X2.^2 - Y2.^2) ;
    
    figure();
    my_dome = surf(X2,Y2,Z2,'EdgeColor', 'none', 'FaceColor', 'texturemap', 'CData', cdata, 'FaceAlpha', 1) ;
    axis equal
    

    这会产生一个很好地居中的纹理贴图:

    注意:纹理映射效果很好,因为您的实际表面仍然是正方形,只是稍微弯曲以符合球体。纹理映射不显示图片透明的表面部分,因此它是不可见的,但是如果您在没有纹理映射的情况下查看表面,您将了解背景中发生了什么:

    hs=surf(X2,Y2,Z2) ; shading interp ; axis equal
    

    【讨论】:

    • 但它仍然没有以正确的方式覆盖圆顶。是否可以将穹顶盖成圆形?这样当您从上方看圆顶时,您会看到正常的圆形图像。
    • 不在您要求的配置中。失真效果是因为您将方形图像拉伸到圆形表面上。尝试将纹理贴图应用到一个简单的圆形(您将获得与圆顶大致相同的结果)和一个简单的方形表面。您会直接注意到正在发生的事情。
    • 要在圆顶表面上正确渲染图像,您必须 (1) 扩展表面的 [X,Y] 域,使其代表一个正方形(和 NaN 点在不属于圆顶的Z 中),然后(2)扩展实际图像(添加一些边距),因此该边距将覆盖正方形的NaN 部分,并且实际图像将很好地居中在您的圆顶上.即使这样,如果您的网格尺寸太粗,界面(圆顶的底部)可能看起来有点像素化。
    • @KamilSerafin,我添加了一些改进渲染的方法 ;-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-03
    • 1970-01-01
    • 1970-01-01
    • 2015-10-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多