2016-03-08 92 views
1

按照其他页面上的说明,例如MATLAB自定义数据提示图片

http://blogs.mathworks.com/videos/2011/10/19/tutorial-how-to-make-a-custom-data-tip-in-matlab/ http://it.mathworks.com/help/matlab/ref/datacursormode.html http://it.mathworks.com/matlabcentral/answers/68079-how-to-add-additional-info-to-the-data-cursor

我写了一个定制的回调函数的数据提示给我点上一XY图索引以及它们x和y坐标:

function output_txt = customCallback_DataTip(obj,event_obj) 
% Display the position of the data cursor 
% obj   Currently not used (empty) 
% event_obj Handle to event object 
% output_txt Data cursor text string (string or cell array of strings). 

pos = get(event_obj,'Position'); 
output_txt = {['X: ',num2str(pos(1),4)],... 
    ['Y: ',num2str(pos(2),4)]}; 

% If there is a Z-coordinate in the position, display it as well 
if length(pos) > 2 
    output_txt{end+1} = ['Z: ',num2str(pos(3),4)]; 
else % 2D plot: write index of current point 
    i = find(event_obj.Target.XData == pos(1), 1); 
    output_txt{end+1} = ['i: ',num2str(i)]; 
end 

这段代码从MATLAB建议的默认回调开始,并且在绘图是3D时添加z坐标信息。由于我经常需要知道图上某点的数组索引,所以在MATLAB启动时会自动启用自定义回调函数。

现在,每当我绘制的图像(例如,经由imagesc)我想有“正常”的图像数据提示:

image datatip

即具有在其上索引/ RGB信息。我如何修改回调函数以获得此行为?

编辑:我想修改我的定制的回调使其当我使用的是图像的数据提示会自动显示类似于默认MATLAB默认数据提示的东西。

回答

4

要做到这一点,您可以检查event_obj.Target的类型并作出相应的响应。

get(event_obj.Target, 'type') 

所有图像(无论是imagescimage,或imshow)将有imageType

isImage = strcmpi(get(event_obj.Target, 'type'), 'image') 

然后,您可以提取图像数据。如果您有索引图像,还可以通过颜色表来确定要进入数据提示的所有其他信息。

cdata = get(event_obj.Target, 'cdata'); 
cmap = colormap(ancestor(event_obj.Target, 'axes')); 

把这一切放在一起,我会修改你的自定义数据提示回调是这样的。

function output_txt = callback(obj, event_obj, clims) 
    % Get the cursor location 
    pos = get(event_obj, 'Position'); 

    output_txt = {sprintf('[X,Y]: [%i, %i]', pos(1), pos(2))}; 

    if strcmpi(get(event_obj.Target, 'type'), 'image') 
     % Get the image data 
     cdata = get(event_obj.Target, 'CData'); 

     % Check to ensure pos is in range 
     if pos(1) < 1 || pos(1) > size(cdata, 2) || ... 
      pos(2) < 1 || pos(2) > size(cdata, 1) 
      rgb = {NaN, NaN, NaN}; 
      newline = sprintf('[R,G,B]: [%0.4f %0.4f %0.4f]', rgb{:}); 
      output_txt = cat(1, output_txt, newline); 
      return 
     end 

     % If the image is RGB 
     if size(cdata, 3) == 3 
      rgb = num2cell(cdata(pos(2), pos(1), :)); 

     % If this is an indexed image 
     else 
      index = cdata(pos(2), pos(1)); 

      % Figure out the colormap 
      hax = ancestor(event_obj.Target, 'axes'); 
      cmap = colormap(hax); 

      % If the CData is scaled, we need to scale to the colormap 
      if strcmpi(get(event_obj.Target, 'CDataMapping'), 'scaled') 
       value = (index - clims(1)) * size(cmap, 1)/diff(clims); 
      else 
       value = index; 
      end 

      % Determine RGB value from colormap 
      rgb = num2cell(ind2rgb(round(value), cmap)); 

      if round(index) == index 
       newline = sprintf('Index: %d', index); 
      else 
       newline = sprintf('Index: %.4f', index); 
      end 

      % Generate datatip text 
      output_txt = cat(1, output_txt, newline); 
     end 

     output_txt = cat(1, output_txt, ... 
       sprintf('[R,G,B]: [%0.4f %0.4f %0.4f]', rgb{:})); 

    % Otherwise we use your custom datatip for plots 
    else 
     index = find(event_obj.Target.XData == pos(1), 1); 

     pos = get(event_obj, 'Position'); 
     output_txt = { sprintf('X: %0.4f', pos(1)); 
         sprintf('Y: %0.4f', pos(2))}; 

     % If there is a Z-coordinate in the position, display it as well 
     if length(pos) > 2 
      output_txt{end+1} = sprintf('Z: %0.4f', pos(3)); 
     else % 2D plot: write index of current point 
      output_txt{end+1} = sprintf('i: %d', index); 
     end 
    end 
end 

如果您注意到,我将一个附加变量(clims)传递给回调函数。这是因为有些版本实际上并不允许我从内的数据提示UpdateFcn中查询坐标轴属性。所以这意味着你将不得不改变你的匿名函数。

h = datacursormode(fig); 
set(h, 'Enable', 'on') 

% Here I have to pass the `clims` because I can't fetch them inside 
set(h, 'UpdateFcn', @(dt,e)callback(dt, e, caxis(ancestor(dt.Host, 'axes')))); 

使用这个,我能够显示适当的显示为图表和图像(索引和RGB)。

enter image description here

+0

太棒了。超过了我的预期。很痛! – lampo808

+0

为防万一别人想复制粘贴你的代码:在最后一个'else'后面,缺少以下行: 'i = find(event_obj.Target.XData == pos(1),1);' – lampo808

+0

@ lampo808谢谢你指出。我已经更新了包含您的代码的答案。 – Suever