Plotting rectangle on the frames of a video - matlab

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

Related

Creating a video from a set of 3D plots

I used a function called ind2patch to make a 3D block which contains a number of smaller blocks in 3 dimensions. Each small block has a value that is represented by a color. A typical plot is like this one:
Now I would like to show the evolution of values (i.e. the color) with time of these small blocks using a video. I have data at different moments but I only know how to plot the graphs at different time by reading different files. Is there a way to combine the plots to a video or directly plot the graphs in the form of video?
Here is my code:
clear; close all; clc;
fig = figure(1);
set (fig, 'Units', 'normalized', 'Position', [0,0,1,1]);
fig_color='w'; fig_colordef='white';
cMap=jet(256);
faceAlpha1=1;
faceAlpha2=0.65;
edgeColor1='none';
edgeColor2='none';
NumBoxX=100;%box number in x direction
NumBoxY=100;%box number in y direction
NumBoxZ=5;%box number in z direction
fid = fopen('rho 20950.dat','r');
datacell = textscan(fid, '%f%f%f%f%f%f%f%f');
fclose(fid);
all_data = cell2mat(datacell);
M=zeros(NumBoxX,NumBoxY,NumBoxZ);
for i=1:NumBoxX
for j=1:NumBoxY
for k=1:NumBoxZ
num=k+NumBoxZ*(j-1)+NumBoxZ*NumBoxY*(i-1);
M(i,j,k)=all_data(num,4);
end
end
end
indPatch=1:numel(M);
[F,V,C]=ind2patch(indPatch,M,'v');
title('\sigma_{xy} in different cells','fontsize',20);
xlabel('y','fontsize',20);ylabel('x','fontsize',20); zlabel('z','fontsize',20); hold on;
set(get(gca,'xlabel'),'Position',[5 -50 30]);
set(get(gca,'ylabel'),'Position',[5 50 -15]);
set(get(gca,'zlabel'),'Position',[64 190 -60]);
patch('Faces',F,'Vertices',V,'FaceColor','flat','CData',C,'EdgeColor','k','FaceAlpha',0.5);
axis equal; view(3); axis tight; axis vis3d; grid off;
colormap(cMap); caxis([min(M(:)) max(M(:))]);
cb = colorbar;
set(get(cb,'title'),'string','Stress (MPa)','fontsize',20);
lbpos = get(cb,'title'); % get the handle of the colorbar title
%set(lbpos,'Units','data');% change Units to data
%pos = get (lbpos,'position'); % get position of the colorbar title
set(lbpos,'units','normalized','position',[0,1.04]);
MyAxes=gca;
set(MyAxes,'Units','Normalized','position',[0.05,0.1,0.8,0.8]);
zoom(1.85);
You could do something like this:
Loop through each patch and grab an image of it.
Insert the images into a matrix
Convert the image matrix into a movie using immovie
% // Create a matrix to hold your images
A = zeros(row,col,numOfColours, numOfFrames);
where row is the number of rows and col is the number of columns in one image.
Loop through your patches and create a video of the individual images.
for n=1:numOfPatches
imshow(patches(:,:,n)) % // display the image
frame = getframe(gcf) % // get the current figure window
im = frame2im(frame); % // convert it to an image
A(:,:,1:3,n) = im; % // Insert the image into the matrix
end
The you can use immovie to convert it to a movie
mov = immovie(RGB);
movie(mov); % // play the movie

How to animate points on an image in MATLAB?

I have the pixel locations of P points on a -constant- image, for T iterations of an algorithm, so locations = [T x 2*P] double.
Now I want to create an animation where it plots the image, then plots the points, pauses for N seconds and updates their location to the next step. I don't know if there is a standard way to follow. I think I need something like:
figure;
imshow(img);
hold on;
for t=1:T
anim = updatePlot(locations(t,:), anim); % ?
end
How can I implement this updatePlot function?
Thanks for any help!
You can do this a couple of different ways. The first way would be to give the plotted points a handle so that you can delete them before the next iteration:
figure
imshow(img);
hold on;
for t = 1:T
% delete the previous points plotted (skip t = 1 since they won't exist)
if t > 1
delete(hPoints);
end
hPoints = plot(xLocations(t,:),yLocations(t,:),'.');
getframe;
pause(N);
end
(I am not exactly sure how you parse your locations along each row to separate the x and y components, so I've just used xLocations and yLocations to represent those values.)
The second way would be to re-draw the entire image at each iteration:
figure
for t = 1:T
clf;
imshow(img);
hold on;
plot(xLocations(t,:),yLocations(t,:),'.');
getframe;
pause(N);
end
Note that imshow might have its own getframe effect so that you'll see the image flicker before plotting the points -- if that happens just switch from imshow to image.

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.

Scatter overlay on image with 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

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)));