2016-03-17 57 views
9

我有一个圆形网格,并在网格网站上绘制了归一化的箭头,这些箭头保持相同的大小并根据模拟方向改变方向,其细节无关紧要。用图像替换颤动箭头

我的情节是这样的

enter image description here

是否有可能通过一个JPG/BMP/GIF/PNG图像来替换在颤动情节的箭头?或通过任何其他命令?

理想的情况下,它会是这个样子(虽然不一定箭头)

enter image description here

+0

[这](http://stackoverflow.com/questions/18214874/how-to-draw-good-looking-arrows-in-matlab)可能的帮助。为了获得最佳效果,我建议您弄清楚如何自己绘制它们。 – horchler

回答

27

解释,你可以做到这一点

的一种方法,是使用一个surface objecttexture-map as the FaceColor

在MATLAB中,您可以创建一个简单的矩形表面。您可以将FaceColor设置为texturemap,这将使分配给CData的值映射到表面上。

然后得到透明性,还可以设置FaceAlpha值为texturemap并设置AlphaData和那些透明度值将在表面上的程度被映射为好。

为了将其应用于您的案例,您希望将CData设置为您要用来替换箭头的图像。并且您希望AlphaData的大小与图像数据的大小相同,值为1时您希望它不透明,而0则希望透明。这将使它看起来不像您张贴的图像,您可以清楚地看到边界框。然后,您将需要绘制其中一个表面,其中每个箭头都将适当地缩放/放置。

实施

更新:此代码(ImageQuiver)的更精致的版本是现在Github可还有MATLAB File Exchange

为了说明我在说什么,我创建了以下基本上只是做这件事的功能。它接受与quiver相同的输入(首先提供图像数据并在最后提供一个可选的AlphaData参数),并在所有请求的坐标上创建一个表面,指向请求的方向,并按指定的比例缩放。

function h = quiverpic(im, X, Y, dX, dY, scale, alpha) 
    % im - RGB or indexed image 
    % X - X positions 
    % Y - Y positions 
    % dX - X direction vector 
    % dY - Y direction vector 
    % scale - Any scaling (Default = 1) 
    % alpha - Transparency (same size as im), if not specified = ~isnan(im) 

    h = hggroup(); 

    if ~exist('scale', 'var') 
     % By default there is no scaling 
     scale = 1; 
    end 

    if ~exist('alpha', 'var') 
     % By default, any NaN will be transparent 
     alpha = ~isnan(im); 
    end 

    % Determine aspect ratio of the source image 
    width_to_height = size(im, 2)/size(im, 1); 

    for k = 1:numel(X) 
     % Determine angle from displacement vectors 
     theta = atan2(dY(k), dX(k)); 

     % Subtract pi/2 to +y is considered "up" 
     theta = theta + pi/2; 

     % Setup surface plot boundary 
     [xx,yy] = meshgrid([-0.5, 0.5] * width_to_height, [0 1]); 

     % Scale depending on magnitude of dX and dY 
     this_scale = scale * sqrt(dX(k).^2 + dY(k).^2); 

     % Scale X and Y components prior to rotating 
     xx = xx .* this_scale; 
     yy = yy .* this_scale; 

     % Rotate to align with the desired direction 
     xdata = xx .* cos(theta) - yy .* sin(theta); 
     ydata = xx .* sin(theta) + yy .* cos(theta); 

     % Determine what is considered the "anchor" of the graphic. 
     % For now this is assumed to be the "bottom-middle" 
     xoffset = X(k) - mean(xdata(2,:)); 
     yoffset = Y(k) - mean(ydata(2,:)); 

     % Actually plot the surface. 
     surf(xdata + xoffset, ... 
      ydata + yoffset, zeros(2), ... 
      'Parent', h, ... 
      'FaceColor', 'texture', ... 
      'EdgeColor', 'none', ... 
      'CData', im, ... 
      'FaceAlpha', 'texture', ... 
      'AlphaData', double(alpha)); 
    end 
end 

我写了一个小的测试脚本,以显示这可怎么使用,并显示结果。

t = linspace(0, 2*pi, 13); 
dX = cos(t(1:end-1)); 
dY = sin(t(1:end-1)); 
X = (3 * dX) + 5; 
Y = (3 * dY) + 5; 
scale = 1; 

% Load the MATLAB logo as an example image 
png = fullfile(matlabroot,'/toolbox/matlab/icons/matlabicon.gif'); 
[im, map] = imread(png); 
im = ind2rgb(im, map); 

% Determine alpha channel based on upper left hand corner pixel 
flatim = reshape(im, [], 3); 
alpha = ~ismember(flatim, squeeze(im(1,1,:)).', 'rows'); 
alpha = reshape(alpha, size(im(:,:,1))); 

% Plot some things prior to creating the quiverpic object 
fig = figure(); 
hax = axes('Parent', fig); 
axis(hax, 'equal'); 

% Plot a full circle 
t = linspace(0, 2*pi, 100); 
plot((cos(t) * 3) + 5, (sin(t) * 3) + 5, '-') 

hold(hax, 'on') 

% Plot markers at all the quiver centers 
plot(X, Y, 'o', 'MarkerFaceColor', 'w') 

% Plot a random image behind everything to demonstrate transparency 
him = imagesc(rand(9)); 
uistack(him, 'bottom') 

axis(hax, 'equal') 
colormap(fig, 'gray') 
set(hax, 'clim', [-4 4]); 

% Now plot the quiverpic 
h = quiverpic(im, X, Y, dX, dY, 1, alpha); 

axis(hax, 'tight') 

结果

enter image description here

荒诞

具有变化的矢量和缩放

enter image description here

任何宽高比的任何图像相同的图像会工作得很好

enter image description here