Matlab image legend with color blocks - matlab

I'm trying to make a legend for a colormapped image that's been made from a label image and custom color map using label2rgb. Basically I want a legend that shows small rectangular samples of the colormap colors along with custom labels.
I would like to be able to set the color of the labels and the background. The image is displayed using imshow, and apparently legend has no effect on such figures.
I've tried a little hack around this using colorbar as shown below, but I'm pretty unsatisfied with it since if I resize the plot window everything gets thrown off.
Can anyone tell me how this type of legend should be made, preferably in a way so it floats and moves itself as necessary when the figure window is resized. If this is not possible, then can someone tell me how to either color the label text of a colorbar or give the colorbar's bounding box (encompassing its labels) a background color? As you can see, if I hadn't manually added a background white box, the labels would be invisible.
Thanks.
label_image = zeros(768, 1024);
label_image(100:400, 500:600)=1;
label_image(500:600, 100:600)=2;
label_image(25:300, 100:400)=3;
custom_colormap = [ 0 1 0; 1 0 0; 0 0 1;];
label_image = label2rgb(label_image, custom_colormap, [0 0 0]);
% Make a white backround for the colorbar.
% Don't want to have to do this line.
label_image(25:140, 775:1010,:)=255;
% Show the image
imshow(label_image, 'InitialMagnification', 50);
% Here, I would like to be able to set colorbar label text color and/ or
% colorbar bounding box background color, or better yet, use some variant
% on the legend function to do this automatically
colormap(custom_colormap);
labels={'Both', 'Always Moving', 'Moved'};
hcb=colorbar('peer',gca,...
[0.7 0.8 0.03 0.1],...
'YTickLabel',labels,...
'XAxisLocation','bottom',...
'TickLength',[0 0],...
'Color',[1 0 1]);

You want to set the color of the x and y axes of the colorbar, respectively.
set(hcb,'ycolor','w','xcolor','w')
Thus, you wont have to put the white rectangle. Check get(hcb) to see a list of all the properties you can modify.

Related

how to find and change all the default figure setting in Matlab?

This tutorial explains how to change certain default settings of Matlab figures, but what about the properties not listed there? For example, if I want to change the font size of the x-axis label and make the y-axis label in Latex style, whats the name for these properties? (what's the xxx in defaultxxx)
In other words, I'm looking for something similar to this matplotlib stylesheet (but for Matlab) where I can easily find the names of the properties I'm looking for so I can just change the values easily.
MATLAB has a built-in figure editor, so you can do pretty much anything there. When you plot something, in the figure, go to View > Property editor and you try different things.
If you want to do it manually, the problem is that there is not just one object in the plot figure. You can generally look at the options for figures, axes, plot and surface. However, it it possible that you will have to look further for some more specific types of figures. Useful things can be found here, that are not in the official MATLAB documentation, but you must usually search a lot.
I was looking at the link you provided for matplotlib and decided to do something similar as an example of working with MATLAB plots. The following code:
x = linspace(0, 2*pi, 100);
y = sin(x);
% Plot a sinus curve, make the data depicted with red line and red filled dots
plot(x, y, 'r-o','MarkerFaceColor','r')
set(gca, ... % Get current axes
'Color','k', ... % Set plot background color to black
'XColor',[1 1 1], ... % Set color of x axis to white
'YColor',[1 1 1], ... % Set color of y axis to white
'GridColor',[1 1 1], ... % Set color of grid to white
'GridLineStyle','--', ... % Set the grid to be dashed
'YTick',-1:0.25:1) % Set Y axis ticks from -1 to 1 with step 0.25
set(gcf,'Color','k') % Set background of the current figure to black
xlabel('Some x axis / Units') % Set X axis label
ylabel('Some y axis / Units') % Set Y axis label
grid on % Make the grid shown
And the result should look like this:
By the way, you can use some basic LaTeX notation in MATLAB without changing anything. Try writing something like
xlabel('\rho_{0} / kg m^{-3}')

Draw over legend in a Matlab figure

I would like to place an arrow over a legend in a matlab plot but when I add the arrow, the legend defaults to being "on top" (see the picture, the black line being covered by the legend).
Is there a way to push a subfigure, such as an arrow, to the "top" so that it appears over all other component of the figure, including the legend? I've tried to use uistack but that doesn't seem to work with legends. uistack as the doc says should "Reorder visual stacking of UI components".
edit:
Very simple example: the line that I'm drawing should appear on top of the legend.
figure;
b = bar(1:3,rand(3));
hold on;
p = plot([0,3],[0,.5],'Color','k','linewidth',1.5); % my arrow
l = legend(b,'value','Location','SouthWest','AutoUpdate','off');
uistack(l,'bottom');
You can make the legend background transparent - so you will see your arrow through the legend
figure;
b = bar(1:3,rand(3));
hold on;
p = plot([0,3],[0,.5],'Color','k','linewidth',1.5); % my arrow
l = legend(b,'value','Location','SouthWest','AutoUpdate','off');
l.BoxFace.ColorData = uint8([255 255 255 127]');
l.BoxFace.ColorType = 'truecoloralpha';
The ColorData Property is [R G B Transparency]
For Info: This was done using R2015b.
You can copyobj the current graphical axes gca and set its Color property to none. This method will draw the line over the legend's patches and associated texts.
Explanation : Copyobj will copy and display all the axes related to the bar and line but not the legend (legends have axes on their own). The display of the copied axes will overlay perfectly with the original one. And 'Color','none' makes the white background of the copied axes transparent, thus making the legend visible again but visible under the line.
Here is the code
f = figure;
b = bar(1:3,rand(3));
hold on;
p = plot([0,3],[0,.5],'Color','k','linewidth',1.5); % my arrow
l = legend(b, 'Location','SouthWest');
% add some magic
hax = copyobj(gca, f); % copy the current axes to the figure
set(hax, 'Color', 'none') % set the new axes's background transparent
What MATLAB version do you use? uistack seems to not work on legends anymore, since MATLAB 2015b (see this similar problem).
If, as you say, the line can be appear at any place, the best workaround may be choosing the best legend location
l = legend(b,'value','Location','Best','AutoUpdate','off');

How to place a colorbar in Matlab plot legend Icon

I visualize map overlays in Matlab with some surfaces with RGB texture. It looks like this:
I would like to have better Legend icons that make clear which layer is which. Something like this:
While I just did the second one in Gimp, I would like to have it in code.
Is it possible? It would be OK to use something from Matlab File Exchange or so.
One option will be to 'draw' this part of the legend manually after you create the figure. Here is how you can do this:
plot(nan(2)) % this is to make space in the legend box
hold on
plot(rand(15,1),'r') % here you plot all your data
hold off
hleg = legend({'Lidar Map','Radar Reprojection','Robot Path'});
% get the position of the legend, and calculate the place for the colormaps:
% this values may need to be adjusted
pos = hleg.Position.*[1.01 1+hleg.Position(4)/2.3 0.27 0.6];
% Create a 'picture' of what you want to appear in the legend:
level = 64; % level of color in the colormaps
cb = [1:level; zeros(1,level); (1:level)+level];
cmap = [1 1 1;0 0 0;flipud(gray(level-1)); jet(level)]; % custom colormap
legax = axes('Position',pos); % place the new picture above the legend
imagesc(legax,repelem(cb,[3 1 3],1)) % Create the picture
colormap(cmap) % appy custom colormap
axis off % remove all axes details
Here is the result:
The problem here is that the custom color map of the legend may interfere with the color map of the data itself, so you may need to take care of that also, but I can't tell you how without knowing how your data looks like and how do you currently apply the colormaps.

How to setup step colorbar in matlab?

I want to change the default color bar (jet color) generated by Matlab, especially the step of the color (just like the figure below). How to do that?
Here's my code
[hC hC] = contourf(interp2(sal,2,'spline'),[0:0.5:5]);
set(hC,'LineStyle','none','YTick',0:4);
colorbar;
If you are looking to reduce the number of colors in the contour plot and colorbar then you can set a new colormap with a reduce color set.
%Get 10 colors from jet
numColors = 10;
colormap(jet(numColors))
data = peaks;
contourf(data)
% Optionally you can set yTicks in conjunction with the number of items in your colormap to line up
colorbar('YTick',linspace(min(data(:)),max(data(:)),numColors+1))
EDIT:
If you want more control over where the contour lines are drawn then use the function in this form countourf(data,v) where v is an monotonically increasing vector of your desired contour levels. Example:
contourf(data,linspace(-7,8,numColors))
c = colorbar('YTick',linspace(-7,8,numColors+1));
The will draw 10 contour lines at -7, -5.33, -3.66 ... 8. Replace -7 and 8 with whatever you wish ex. min/max of data or whatever makes sense for your application
You can adjust the color bar properties by using:
c=colorbar;
c.Ticks=[vector of tick locations]
or alternately you could try
c.Limits=[min max]
See the MATLAB documentation for colorbar properties: http://www.mathworks.com/help/matlab/ref/colorbar-properties.html?refresh=true
this explains color bar customization in more detail

How can I create a rectangle with an outlined border?

I want to draw a rectangle to outline an area of an image that I've plotted in one axes of a figure. I have multiple axes in this figure, so I am using the rectangle() function. What I want is to draw a white rectangle a thin black border just inside and just outside the rectangle. The part of the image inside the rectangle should be visible, so all 'facecolor' should be 'none'. I have tried drawing 3 rectangles, two black ones with thin linewidths and one thicker white one, but the problem is that 'Position' is defined in axes units and 'LineWidth' is defined in point units, so that the scaling doesn't work too well, especially when the figure is resized.
FYI, the outline is so that the white rectangle is more visible against a light background. The images plotted vary widely, so a single color won't be universally visible for my data.
Any suggestions on how I can do this?
How about just using different line widths for black and white rectangle?
imshow('cameraman.tif')
rectangle('position',[80 30 100 100],'edgecolor','k','LineWidth',4)
rectangle('position',[80 30 100 100],'edgecolor','w','LineWidth',1)
Hmm, the corners look much better on MATLAB figure than as PNG file.
Better with getframe:
I like #Yuks solution. But there is another possibility that you can consider:
You could also calculate the mean value of the pixels inside the rectangle, and set the box color to the inverse. In this way, you will always have a good contrast.
Here is the code:
function PlotRect(im,x,y,w,h)
m = double(im( round(y): round(y+h) , round(x): round(x+w),:));
if (mean(m(:)) < 255/2)
col = [1 1 1];
else
col = [0 0 0];
end
rectangle('Position',[x y w h],'EdgeColor', col);
end
And the test:
function Inverse()
im = imresize( uint8(0:5:255), [250, 400]) ;
figure;imshow(im); hold on;
PlotRect(im,5,8,50,75);
PlotRect(im,100,30,25,42);
PlotRect(im,200,10,40,40);
PlotRect(im,300,10,40,40);
end
Yuk's solution works quite well for adding a rectangle to a normal MATLAB plot, too. The 'position' values are not interpretet as pixels but are adjusted to the plot values (see code example below):
figure;
plot(0:10,0:10); grid on;
hold on;
rectangle('position',[1 1 8.5 8.5],'LineWidth',2);
hold off;
This code results in the following plot: