在矩阵中绘制极坐标灰度值而不插入每个for循环

时间:2016-05-12 09:33:16

标签: matlab matrix polar-coordinates

我的矩阵的灰色值介于01之间。对于矩阵中的每个条目,存在指示灰度值的位置的某些极坐标。我已经有ThetaRho值(极值),两者都在单独的512×960矩阵中。每个CTheta组合的灰度值(在一个名为Rho的矩阵中)。我对XY也有同样的看法,因为我只使用pol2cart进行转换。问题是我不能直接绘制这些值,因为它们还不适合新矩阵的“箱”。

我想要的是:将灰度值放在1024×1024大小的方阵中。我不能直接这样做,因为极坐标落在这个矩阵的网格之间。因此,我们现在使用插值,但这非常耗时,并且必须为每个数据集单独完成,尽管从原始矩阵到最后一个矩阵的转换将始终相同。因此,我想解决这个矩阵一次(分析或数字)并使用矩阵乘法或类似的东西在代码的每个循环中有效地应用操作。

这些转换之一的一个例子如下:

enter image description here

第一个矩阵中的零是网格,值1(在网格之间)是落在四个网格点之间的灰度值,然后我想转换为第二个矩阵(不要介意点之间的视觉间距)。

对于每个数据集,我有数百个这样的矩阵,所以我想提高代码的效率。

背景:我现在正在使用TriScatteredInterp进行插值。我们也尝试了scatteredInterpolant,但速度较慢。我还发布了a related question,但决定拆分两个可能的解决方案,因为我在这里要求的解决方案也适用于非MATLAB代码,并且可能更快并且更平滑(没有连续弹出的数字) )执行代码。

1 个答案:

答案 0 :(得分:3)

使用图像处理工具箱

图片的工作方式与您拥有的数据略有不同。但是,将一个表示映射到另一个表示是相当简单的。

我看到的问题只有一个:包装。显然,θ=2π= 0,但MATLAB不知道。 AFAIK,没有简单的方法告诉M​​ATLAB。

为什么这很重要?嗯,简单地说,像素间插值使用来自最近的N个邻居的信息来找到中间颜色,N取决于插值内核。当在图像中间的某处执行此操作时没有问题,但在边缘处,MATLAB必须知道左边缘等于右边缘。这不是标准的图像处理,我不知道任何能够做到这一点的功能。

实施

现在,当忽略包装问题时,这是一种方法:

function resize_polar()

    %% ORIGINAL IMAGE
    % ==========================================================================

    % Some random greyscale data
    C = double(rgb2gray(imread('stars.png')))/255;

    % Your current size, and desired size    
    sz_x = size(C,2);    new_sz_x = 1024;
    sz_y = size(C,1);    new_sz_y = 1024;

    % Ranges for teat and rho;  
    % replace with your actual values
    rho_start = 0;     theta_start = 0;
    rho_end   = 10;    theta_end   = 2*pi;

    % Generate regularly spaced grid;
    theta = linspace(theta_start, theta_end, sz_x);
    rho   = linspace(rho_start,   rho_end,   sz_y);

    [theta, rho] = meshgrid(theta,rho);


    % Make plot of generated data
    plot_polar(theta, rho, C, 'Original image');

    % Resize data
    [theta,rho,C] = resize_polar_data(theta, rho, C, [new_sz_y new_sz_x]);

    % Make plot of generated data
    plot_polar(theta, rho, C, 'Rescaled image');

end


function [theta,rho,data] = resize_polar_data(theta,rho,data, new_dims)

    % Create fake RGB image cube 
    IMG = cat(3, theta,rho,data);

    % Rescale as if theta and rho are RG color data in the RGB
    % image cube
    IMG = imresize(IMG, new_dims, 'nearest');

    % Split up the data again
    theta = IMG(:,:,1);
    rho   = IMG(:,:,2);
    data  = IMG(:,:,3);

end

function plot_polar(theta, rho, data, label)

    [X,Y] = pol2cart(theta, rho);

    figure('renderer', 'opengl')
    clf, hold on

    surf(X,Y,zeros(size(X)), data, ...
         'edgecolor', 'none');     
    colormap gray

    title(label);

end

使用和绘制的图像:

令人敬畏的绘制512×960 PNG图像 stars made with MS Paint

The original

The rescaled image

现在,两者看起来一样(实际上并没有真正提出更合适的图像),所以你必须相信我已经将512×960重新调整为1024×1024,最近 - 邻居插值。

以下是一些简单内核的实际imresize()操作的一些时序:

nearest : 0.008511 seconds.
bilinear: 0.019651 seconds.
bicubic : 0.025390 seconds.  <-- default kernel

但这很大程度上取决于你的硬件;我相信imresize可以为GPU卸载很多工作,所以如果你有一个糟糕的工作,它会慢一些。

包装

如果包装问题对您非常重要,您可以修改上述功能以执行以下操作:

  • 首先,使用imresize()之前的图像重新缩放图像
  • 水平连接第二一半的灰度数据和第一一半。意思是,你交换了第一和第二半,使左右边缘(0和2π)在中间接触。
  • 使用imresize()
  • 重新缩放此中间图像
  • 提取重新缩放的中间图像的中央垂直条带
  • 将其分成两个相等宽度的条带
  • 并用刚刚创建的两个条带替换输出图像的边缘条

现在,这是一种蛮力方法:您正在重新缩放图像两次,并且第二轮图像的大部分像素将被丢弃。如果性能有问题,您当然可以将重新缩放仅应用于该中间图像的中心条带。但是,那将会有点复杂。