Scatter overlay on image with MATLAB - matlab

I have an RGB image, img, and I want to produce a new image, img2, with an overlay scatter plot on it.
If X Y Z are respectively the nx1 vectors of x-coord, y-coord and "magnitude" value of my scatter what I'm doing is:
imshow(img);
hold on;
scatter(X,Y,3,Z,'fill');
hold off;
In this way I actually get an image with the scatter plotted, but the problem is that every point of the scatter has the same color (blu) instead of what normally happens when I use
figure;
scatter(X,Y,3,Z,'fill');
Any suggestions? Thanks.

Try to add figure; before imshow(), which will enables you to draw on the image with the color that what normally it should be.
figure; % add this line before imshow()
imshow(img);
hold on;
scatter(X,Y,3,Z,'fill');
hold off;
Here is an example I just tested:
figure; % add this line before imshow()
imshow(img);
hold on;
load seamount
s = sqrt(-z/2);
c = z;
scatter(x,y,s,c,'fill')
hold off;
You can see that its color shown on the image is (roughly) consistent with the color when drawing it alone.
Edit: you can always change the color to whatever you like by setting scatter's color properties, i.e. MarkerEdgeColor and MarkerFaceColor.

Ok, remapping the values of Z to 0-255 it works fine. Here is my function to do that:
function [ Aremaped ] = remap( A,lnew,hnew )
Aremaped = zeros(size(A));
lold=min(A);
hold=max(A);
for i=1:length(A)
newVal = lnew + (A(i)-lold)*(hnew-lnew)/(hold-lold);
Aremaped(i) = newVal
end
end
Hope this can help

Related

Plotting rectangle on the frames of a video

I am trying to plot a rectangle over the frames of my video. I want the rectangle to appear on all the frames of the video. Due to the "hold on" that I have applied, I could see my bounding box on only a few of the frames.
v = VideoReader('test.mp4');
numFrames = get(v,'NumberOfFrames');
for k=1:numFrames
image = read(v,k);
rectangle('Position',[0 0 100 100],'EdgeColor','r','LineWidth', 3);
hold on;
imshow(image);
end
When I try to remove the hold on function the rectangle is not getting plotted on the frame. Any help would be appreciated.
Swap the imshow and rectangle calls so that imshow creates a figure that will fit the image first. Use rectangle after imshow to finally draw the rectangle. Finally, use drawnow after imshow so that you flush the graphics buffer and refresh the figure. You also need hold on; and hold off; between the rectangle call.
v = VideoReader('test.mp4');
numFrames = get(v,'NumberOfFrames');
for k=1:numFrames
image = read(v,k);
imshow(image);
hold on;
rectangle('Position',[0 0 100 100],'EdgeColor','r','LineWidth', 3);
hold off;
drawnow;
end

How to have an image in background of plot in matlab

I have a plot from a network of lines in 3D space and I have one image from the object as well. Now I want to put the image file in the background of my plot as a fixed background and then the network should be plotted on that background. By the way, since the Network is in 3D space I can rotate it easily and it is important for me rotate the network on the my combined plot as well.
this is my code that I have written but it shows my plot separately! if I put imshow inside the figure then image will be ploted on the top of my network and I can see only one point of my network. Here is the link of Network and the background image from background
Here is my code: the first line plot the image and the rest of the code plot my network of lines:
Img1 = imshow('STP1.png');
figure('name','Distance');
hold on;
labels = cellstr( num2str([1:SIFT_Length]') );
text(SIFT_3D(:,1), SIFT_3D(:,2),SIFT_3D(:,3),labels,'FontWeight','bold','FontSize', 12,...
'VerticalAlignment','bottom','HorizontalAlignment','right')
title('Distances Network with colorized lines based on Uncertainty','FontWeight','bold');
hold on
for k = 1:Num_Line_SIFTS
plot3([SIFT_3D(Line_among_2_Sifts(k,1),1),SIFT_3D(Line_among_2_Sifts(k,2),1)],...
[SIFT_3D(Line_among_2_Sifts(k,1),2),SIFT_3D(Line_among_2_Sifts(k,2),2)],...
[SIFT_3D(Line_among_2_Sifts(k,1),3),SIFT_3D(Line_among_2_Sifts(k,2),3)],...
'o-','Color',[RGB_0_1(k,1) RGB_0_1(k,2) RGB_0_1(k,3)],'MarkerFaceColor',[RGB_0_1(k,1) RGB_0_1(k,2) RGB_0_1(k,3)],'MarkerEdgeColor',...
'k', 'LineWidth',2)
end
hold off;
Please help me how can I solve this issue.
What about this:
clear
clc
close all
%// Read image
Im=flipud(imread('STP1_low.png'));
%// Dummy surface to plot.
Z = peaks(25);
%// Prepare image position
shift = 20;
xIm=zeros(size(Z))-shift;
hold on
surface(xIm,Im,'FaceColor','texturemap','EdgeColor','none','CDataMapping','direct')
surface(Z,'FaceAlpha',0.8,'LineStyle','none','FaceColor','interp');
axis on
view(-35,45)
box on
rotate3d on
Output:
You can rotate it and the image stays as the background.
I'm not sure I understood your need, nevertheless ...
figure('name','Distance','unit','normalized');
a=axes('position',[0 0 1 1])
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% UPDATED CODE STARTS HERE
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Disable zoom
h=zoom;
setAllowAxesZoom(h,a,false);
% Disable rotation
h = rotate3d;
setAllowAxesRotate(h,a,false)
%
%%%%%%%%%%%%%%%%%%%%%%%%%%
% UPDATED CODE ENDS HERE
%%%%%%%%%%%%%%%%%%%%%%%%%%
%
hold on
imshow('Jupiter_New_Horizons.jpg','parent',a)
t=0:.01:2*pi;
z=sin(t).*cos(t)
a1=axes('position',[0.3 0.3 .5 .5])
plot3(cos(t),sin(t),z,'r','linewidth',3)
grid on
set(gca,'color','none')
This script generates the following graph:
Hope this helps.

Matlab Colorbar: in scientific notation, the multiplier 10^-3 overlaps the first value.How to move it?

I have a Matlab plot, in which the multiplier (in my case 10^-3) overlaps the first value. How can I move it?
Here is a hack which works but could become a bit cumbersome. The trick is to fetch the YTickLabel of the colorbar, remove them from the plot, then plot them again but this time add a custom text that represents the exponent you want to display (here x 10^-3). The plus side is that you have complete control over the placement of this text.
Here is the code:
clear
clc
clear all; close all; clc;
A = rand(100,100)./(1e2);
figure;
imagesc(A);
colormap jet;
hBar= colorbar;
title('Before change','FontSize',18)
%// Get the positions of the axes and colorbar as well as the YTickLabel.
BarPos = get(hBar,'Position');
XL = get(gca,'XLim');
YTL = get(hBar,'YTickLabel');
figure;
imagesc(A);
colormap jet;
hBar= colorbar;
%// Remove current YTickLabel
set(hBar,'YTickLabel','');
%// Text to add. Note the syntax to print a superscript.
NewText = 'x 10 ^{-3}';
%// Restore YTickLabel. This time the x 10^-3 does not appear.
set(hBar,'YTickLabel',YTL);
%// Add the text
text(XL(2)+15,-5,NewText)
title('After change','FontSize',18)
Output:
Hope that helps!

Displaying a quiver plot of a gradient image in MATLAB

I have an image. I want to display a quiver plot of the gradient image that I get using gradient function in MATLAB, preferably superimposed on the gradient image.
I = imread('image.png');
[gx,gy] = gradient(double(rgb2gray(I)));
g = abs(gx) + abs(gy);
figure;
imshow(g, []);
hold on;
quiver(abs(gx),abs(gy));
This is what I tried, and all I get is a completely blue display.
I think all you see is the arrows, but they're too close together.
If you plot the two graphs (imshow(g) and quiver) separately, they show up normal. The imshow only shows the pixels without any scaling, if you fix that (make it scale) the quiver arrows also will have more space between them and become visible.
You can do just that by adding the 'InitialMagnification','fit' option to imshow:
imshow(g,'InitialMagnification','fit')
Or you can show less quiver arrows:
figure;
imshow(g, []); % [] to display image properly
hold on;
[Nx, Ny] = size(g);
xidx = 1:10:Nx;
yidx = 1:10:Ny;
[X,Y] = meshgrid(xidx,yidx);
quiver(Y',X',abs(gx(xidx,yidx)),abs(gy(xidx,yidx)));

How to control the margin size around subplots?

I'm plotting 5 x 3 plots using subplot command, but there are massive margins around each subplot.
How do I control the margin size around them?
figure;
for c=1:15
subplot(5,3,c);
imagesc(reshape(image(:,c), 360,480));
colormap gray;
axis image;
end
The problem is that Matlab assigns the position property of each axis such that there is space around each plot. You can either adjust the position property, or you can get subaxis from the File Exchange and set up the subplots the way you like.
Take a look at the axes's LooseInset and OuterPosition properties:
http://undocumentedmatlab.com/blog/axes-looseinset-property/
Since MATLAB R2019b you can use tiledlayout function to control the spacing of the subplots.
Here's an example which shows how to obtain subplots without tile spacing:
figure
example_image = imread('cameraman.tif');
t = tiledlayout(5,3);
nexttile
for c= 1:15
imagesc(example_image(:,c))
if c < 15
nexttile
end
end
t.TileSpacing = 'None';
In addition to the other answers, you could try Chad Greene's smplot from the FileExchange. This will produce a 'small multiple' plot and automatically deal with some of the hassle of Matlab's position property.
Example below showing default subplot behaviour, smplot with axis off and smplot with axis on, respectively:
image = randn(360*480,15);
% default subplot
figure;
for c=1:15
subplot(5,3,c);
imagesc(reshape(image(:,c), 360,480));
colormap gray;
axis image;
end
% smplot axis off
figure;
for c=1:15
smplot(5,3,c);
imagesc(reshape(image(:,c), 360,480));
colormap gray;
axis off;
end
% smplot axis on
figure;
for c=1:15
smplot(5,3,c,'axis','on');
imagesc(reshape(image(:,c), 360,480));
colormap gray;
axis tight;
end
To minimize the white space surrounding each subplot, run: [1]
for c=1:15
h_ax = subplot(5,3,c);
% [...]
outerpos = get(h_ax,'OuterPosition');
ti = get(h_ax,'TightInset');
left = outerpos(1) + ti(1);
bottom = outerpos(2) + ti(2);
ax_width = outerpos(3) - ti(1) - ti(3);
ax_height = outerpos(4) - ti(2) - ti(4);
set(h_ax,'Position',[left bottom ax_width ax_height]);
end
This implementation automates the principle outlined in Jonas's answer.
[1] https://www.mathworks.com/help/releases/R2015b/matlab/creating_plots/save-figure-with-minimal-white-space.html