在矩阵中绘制极性灰度值,而无需插入每个for循环 [英] plot polar grey values in matrix without interpolating every for loop

查看:67
本文介绍了在矩阵中绘制极性灰度值,而无需插入每个for循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个灰度值在01之间的矩阵.对于矩阵中的每个条目,都有某些极坐标指示灰度值的位置.我已经在单独的512×960矩阵中都有ThetaRho值(极性).每个ThetaRho组合的灰度值(在称为C的矩阵中).对于XY,我具有相同的功能,因为我只是将pol2cart用于转换.问题是我无法直接绘制这些值,因为它们还不适合新矩阵的"bin".

I have a matrix with grey values between 0 and 1. For every entry in the matrix, there are certain polar coordinates that indicate the position of the grey values. I already have either Theta and Rho values (polar) ,both in separate 512×960 matrices. And grayscale values (in a matrix called C) for every Theta and Rho combination. I have the same for X and Y, as I just use pol2cart for the transformation. The problem is that I cannot directly plot these values, as they do not yet fit in the 'bins' of the new matrix.

我想要的是:将灰度值放在大小为1024×1024的方阵中.我无法直接执行此操作,因为极坐标位于此矩阵的网格之间.因此,我们现在使用插值法,但这非常耗时,并且必须对每个数据集分别进行,尽管从原始矩阵到最终矩阵的转换将始终相同.因此,我想一次(解析地或数值地)求解此矩阵,并使用矩阵乘法或类似方法在代码的每个循环中有效地应用操纵.

What I want: to put the grey values in a square matrix of size 1024×1024. I cannot do this directly, because the polar coordinates fall in between the grid of this matrix. Therefore, we now use interpolation, but this is extremely time consuming and has to be done separately for every dataset, although the transformation from the original matrices to this final one will always be the same. Therefore, I'd like to solve this matrix once (either analytically or numerically) and use a matrix multiplication or something similar to apply the manipulation efficiently in every cycle of the code.

其中一个转换示例如下:

One example of what one of these transformations could look like this:

第一个矩阵中的零是网格,而值1(在网格之间)是介于四个网格点之间的灰度值,然后我想转换为第二个矩阵(don不必理会这些点之间的视觉间距).

The zeros in the first matrix are the grid, and the value 1 (in between the grid) is the grey value that falls in between four grid points, then I'd like to transform to the second matrix (don't mind the visual spacing between the points).

对于每个数据集,我都有数百个这样的矩阵,所以我想使代码更高效.

For every dataset, I have hundreds of these matrices, so I would like to make the code more efficient.

背景:我现在使用TriScatteredInterp进行插值.我们也尝试了scatteredInterpolant,但是速度较慢.我还发布了一个相关问题,但决定将两种可能的解决方案分开,因为我在这里要求的解决方案也适用于非MATLAB代码,并且可能会更快,并且可以使代码的执行更流畅(不会连续弹出图).

Background: I'm using TriScatteredInterp now for the interpolation. We tried scatteredInterpolant as well, but that is slower. I also posted a related question, but decided to split the two possible solutions, because the solution I ask for here is also applicable to non-MATLAB code and will probably be faster and makes for a smoother (no continuous popping up of figures) execution of the code.

推荐答案

使用图像处理工具箱

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

Using the image processing toolbox

Images work a bit differently than the data you have. However, it's fairly straightforward to map one representation into the other.

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

There is only one problem I see: wrapping. Obviously, θ = 2π = 0, but MATLAB does not know that. AFAIK, there is no easy way to tell MATLAB that.

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

Why does this matter? Well, simply put, inter-pixel interpolation uses information from the nearest N neighbors to find intermediate colors, with N depending on the interpolation kernel. When doing this somewhere in the middle of the image there is no problem, but at the edges MATLAB has to know that the left edge equals the right edge. This is not standard image processing, and I'm not aware of any function that is capable of this.

现在,当不考虑包装问题时,这是一种解决方法:

Now, when disregarding the wrapping problem, this is one way to do it:

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图片

现在,两者看起来相同(无法真正提供更适合的图像),因此您必须相信我,512×960的确已重新缩放为1024×1024,其中最接近的是邻居插值.

Now, the two look the same (couldn't really come up with a better-suited image), so you'll have to believe me that the 512×960 has indeed been rescaled to 1024×1024, with nearest-neighbor interpolation.

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

Here are some timings for the actual imresize() operation for some simple kernels:

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

但这在很大程度上取决于您的硬件;我相信imresize可将大量工作分担给GPU,因此,如果您手头很烂,它会变慢.

But this depends strongly on your hardware; I believe imresize offloads a lot of work to the GPU, so if you have a crappy one, it'll be slower.

如果包装问题对您确实很重要,则可以修改上面的函数以执行以下操作:

If the wrapping problem is really important to you, you can modify the function above to do the following:

  • 首先,像以前一样使用imresize()重新缩放图像
  • 水平合并灰度数据的第二部分和第一部分.意思是,您交换前半部分和后半部分,以使左边缘和右边缘(0和2π)在中间接触.
  • 使用imresize()
  • 缩放此中间图像
  • 提取重新缩放的中间图像的中央垂直条纹
  • 将其分成两个等宽的条带
  • 并将输出图像的边缘条替换为您刚创建的两条条纹
  • first, rescale the image with imresize() like before
  • horizontally concatenate the second half of the grayscale data and the first half. Meaning, you swap the first and second halves to make the left and right edges (0 and 2π) touch in the middle.
  • rescale this intermediate image with imresize()
  • Extract the central vertical strip of the rescaled intermediate image
  • split that up in two equal-width strips
  • and replace the edge strips of the output image with the two strips you just created

现在,这是一种蛮力方法:您将图像缩放两次 ,第二轮图像的大多数像素将被丢弃.如果性能存在问题,您当然可以将缩放比例仅应用于该中间图像的中央条纹.但是,那会更加复杂.

Now, this is kind of a brute force approach: you are re-scaling an image twice, and most of the pixels of the second image round will be discarded. If performance is a problem, you can of course apply the rescale to only the central strip of that intermediate image. But, well, that will be a bit more complicated.

这篇关于在矩阵中绘制极性灰度值,而无需插入每个for循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆