plot polar grey values in matrix without interpolating every for loop

此生再无相见时 提交于 2019-12-10 16:43:57

问题


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.

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:

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.

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.


回答1:


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.

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.

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.

Implementation

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

The images used and plotted:

Le awesomely-drawn 512×960 PNG image

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.

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

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.

Wrapping

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

  • 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.



来源:https://stackoverflow.com/questions/37182879/plot-polar-grey-values-in-matrix-without-interpolating-every-for-loop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!