How to display a group of subplots as a movie? - matlab

I have 30 heatmap subplots. How could I present these subplots as an animation or a movie (i.e. one heatmap each 0.5 seconds)?
The subplots are obtained with the following code:
var = {'GeneX','GeneY','GeneZ'};
syms x y z S
alpha_x = 3.9e-2;
beta_x = 6.1;
z_x = 1.3e-5;
n_zx = 2.32;
alpha_y= 4.3e-2;
beta_y = 5.7;
x_y = 7.9e-4;
n_xy = n_zx;
delta_y = 1.05;
x_z = 12e-2;
n_xz = n_zx;
y_z = 11e-3;
n_yz = n_zx;
delta_z = 0.2;
ACDC_X = (alpha_x+beta_x*S)/(1+S+(z/z_x)^n_zx)-x;
ACDC_Y = (alpha_y+beta_y*S)/(1+S+(x/x_y)^n_xy)-delta_y*y;
ACDC_Z = 1/(1+(x/x_z)^n_xz+(y/y_z)^n_yz)-delta_z*z;
ACDCsys_div = [ ACDC_X, ACDC_Y, ACDC_Z ];
J = jacobian(ACDCsys_div,[x;y;z]);
Jsolnew(x,y,z,S) = [J];
%%Construction of the coordinates as a matrix
A = load('matlab.mat','unnamed');% import data from directory
a2 = struct2array(A);% coordinates of the equilibrium point.
numofGraphs = 80;
bx = length(a2(1,1:numofGraphs));
%% Construction of the heatmaps
figure;
hmapax = ceil(sqrt(bx));
for kk = 1:bx %bnx %All bin windows = iteration
JacACDCnew(:,:,kk) = Jsolnew(a2(1,kk),a2(2,kk),a2(3,kk),a2(4,kk));
ACDC_HmapJnew = double(JacACDCnew(:,:,kk));
subplot(hmapax,hmapax,kk);%
heatmap(var,var,ACDC_HmapJnew,'ColorScaling','log');
S = a2(4,kk);
title(['Jac','s=',num2str(S)]);
end

Consider the following example:
function q56130816
% Load some data:
frames = imread('https://i.stack.imgur.com/03kN8.gif');
frames(frames > 1) = 2;
% Create subplots:
figure('WindowState','maximized'); subplot(2,4,1);
for ind1 = 1:8
subplot(2,4,ind1);
imagesc(frames(:,:,1,ind1)); axis image; axis off;
end
colormap([255 255 255; 188 188 188; 244 128 36]./255);
% Capture subplots as frames:
for ind1 = 8:-1:1
frameHolder(ind1) = getframe( subplot(2, 4 ,ind1) );
end
% Play as movie:
hF = figure(); movie(hF, frameHolder, 20, 2);
Which will turn:
Into:
As you can see, in the example above I used getframe, but frames can also be captured using print, as mentioned in the getframe docs. Frames can also be exported to a video file, as explained here.
Animation credit: frames were screen-captured from Johan Lindell's Codepen example.

Related

how to find the corners of rotated object in matlab?

I want to find the corners of objects.
I tried the following code:
Vstats = regionprops(BW2,'Centroid','MajorAxisLength','MinorAxisLength',...
'Orientation');
u = [Vstats.Centroid];
VcX = u(1:2:end);
VcY = u(2:2:end);
[VcY id] = sort(VcY); % sorting regions by vertical position
VcX = VcX(id);
Vstats = Vstats(id); % permute according sort
Bv = Bv(id);
Vori = [Vstats.Orientation];
VRmaj = [Vstats.MajorAxisLength]/2;
VRmin = [Vstats.MinorAxisLength]/2;
% find corners of vertebrae
figure,imshow(BW2)
hold on
% C = corner(VER);
% plot(C(:,1), C(:,2), 'or');
C = cell(size(Bv));
Anterior = zeros(2*length(C),2);
Posterior = zeros(2*length(C),2);
for i = 1:length(C) % for each region
cx = VcX(i); % centroid coordinates
cy = VcY(i);
bx = Bv{i}(:,2); % edge points coordinates
by = Bv{i}(:,1);
ux = bx-cx; % move to the origin
uy = by-cy;
[t, r] = cart2pol(ux,uy); % translate in polar coodinates
t = t - deg2rad(Vori(i)); % unrotate
for k = 1:4 % find corners (look each quadrant)
fi = t( (t>=(k-3)*pi/2) & (t<=(k-2)*pi/2) );
ri = r( (t>=(k-3)*pi/2) & (t<=(k-2)*pi/2) );
[rp, ip] = max(ri); % find farthest point
tc(k) = fi(ip); % save coordinates
rc(k) = rp;
end
[xc,yc] = pol2cart(tc+1*deg2rad(Vori(i)) ,rc); % de-rotate, translate in cartesian
C{i}(:,1) = xc + cx; % return to previous place
C{i}(:,2) = yc + cy;
plot(C{i}([1,4],1),C{i}([1,4],2),'or',C{i}([2,3],1),C{i}([2,3],2),'og')
% save coordinates :
Anterior([2*i-1,2*i],:) = [C{i}([1,4],1), C{i}([1,4],2)];
Posterior([2*i-1,2*i],:) = [C{i}([2,3],1), C{i}([2,3],2)];
end
My input image is :
I got the following output image
The bottommost object in the image is not detected properly. How can I correct the code? It fails to work for a rotated image.
You can get all the points from the image, and use kmeans clustering and partition the points into 8 groups. Once partition is done, you have the points in and and you can pick what ever the points you want.
rgbImage = imread('your image') ;
%% crop out the unwanted white background from the image
grayImage = min(rgbImage, [], 3);
binaryImage = grayImage < 200;
binaryImage = bwareafilt(binaryImage, 1);
[rows, columns] = find(binaryImage);
row1 = min(rows);
row2 = max(rows);
col1 = min(columns);
col2 = max(columns);
% Crop
croppedImage = rgbImage(row1:row2, col1:col2, :);
I = rgb2gray(croppedImage) ;
%% Get the white regions
[y,x,val] = find(I) ;
%5 use kmeans clustering
[idx,C] = kmeans([x,y],8) ;
%%
figure
imshow(I) ;
hold on
for i = 1:8
xi = x(idx==i) ; yi = y(idx==i) ;
id1=convhull(xi,yi) ;
coor = [xi(id1) yi(id1)] ;
[id,c] = kmeans(coor,4) ;
plot(coor(:,1),coor(:,2),'r','linewidth',3) ;
plot(c(:,1),c(:,2),'*b')
end
Now we are able to capture the regions..the boundary/convex hull points are in hand. You can do what ever math you want with the points.
Did you solve the problem? I Looked into it and it seems that the rotation given by 'regionprops' seems to be off. To fix that I've prepared a quick solution: I've dilated the image to close the gaps, found 4 most distant peaks of each spine, and then validated if a peak is on the left, or on the right of the centerline (that I have obtained by extrapolating form sorted centroids). This method seems to work for this particular problem.
BW2 = rgb2gray(Image);
BW2 = imbinarize(BW2);
%dilate and erode will help to remove extra features of the vertebra
se = strel('disk',4,4);
BW2_dilate = imdilate(BW2,se);
BW2_erode = imerode(BW2_dilate,se);
sb = bwboundaries(BW2_erode);
figure
imshow(BW2)
hold on
centerLine = [];
corners = [];
for bone = 1:length(sb)
x0 = sb{bone}(:,2) - mean(sb{bone}(:,2));
y0 = sb{bone}(:,1) - mean(sb{bone}(:,1));
%save the position of the centroid
centerLine = [centerLine; [mean(sb{bone}(:,1)) mean(sb{bone}(:,2))]];
[th0,rho0] = cart2pol(x0,y0);
%make sure that the indexing starts at the dip, not at the corner
lowest_val = find(rho0==min(rho0));
rho1 = [rho0(lowest_val:end); rho0(1:lowest_val-1)];
th00 = [th0(lowest_val:end); th0(1:lowest_val-1)];
y1 = [y0(lowest_val:end); y0(1:lowest_val-1)];
x1 = [x0(lowest_val:end); x0(1:lowest_val-1)];
%detect corners, using smooth data to remove noise
[pks,locs] = findpeaks(smooth(rho1));
[pksS,idS] = sort(pks,'descend');
%4 most pronounced peaks are where the corners are
edgesFndCx = x1(locs(idS(1:4)));
edgesFndCy = y1(locs(idS(1:4)));
edgesFndCx = edgesFndCx + mean(sb{bone}(:,2));
edgesFndCy = edgesFndCy + mean(sb{bone}(:,1));
corners{bone} = [edgesFndCy edgesFndCx];
end
[~,idCL] = sort(centerLine(:,1),'descend');
centerLine = centerLine(idCL,:);
%extrapolate the spine centerline
yDatExt= 1:size(BW2_erode,1);
extrpLine = interp1(centerLine(:,1),centerLine(:,2),yDatExt,'spline','extrap');
plot(centerLine(:,2),centerLine(:,1),'r')
plot(extrpLine,yDatExt,'r')
%find edges to the left, and to the right of the centerline
for bone = 1:length(corners)
x0 = corners{bone}(:,2);
y0 = corners{bone}(:,1);
for crn = 1:4
xCompare = extrpLine(y0(crn));
if x0(crn) < xCompare
plot(x0(crn),y0(crn),'go','LineWidth',2)
else
plot(x0(crn),y0(crn),'ro','LineWidth',2)
end
end
end
Solution

How project Velodyne point clouds on image? (KITTI Dataset)

Here is my code to project Velodyne points into the images:
cam = 2;
frame = 20;
% compute projection matrix velodyne->image plane
R_cam_to_rect = eye(4);
[P, Tr_velo_to_cam, R] = readCalibration('D:/Shared/training/calib/',frame,cam)
R_cam_to_rect(1:3,1:3) = R;
P_velo_to_img = P*R_cam_to_rect*Tr_velo_to_cam;
% load and display image
img = imread(sprintf('D:/Shared/training/image_2/%06d.png',frame));
fig = figure('Position',[20 100 size(img,2) size(img,1)]); axes('Position',[0 0 1 1]);
imshow(img); hold on;
% load velodyne points
fid = fopen(sprintf('D:/Shared/training/velodyne/%06d.bin',frame),'rb');
velo = fread(fid,[4 inf],'single')';
% remove every 5th point for display speed
velo = velo(1:5:end,:);
fclose(fid);
% remove all points behind image plane (approximation
idx = velo(:,1)<5;
velo(idx,:) = [];
% project to image plane (exclude luminance)
velo_img = project(velo(:,1:3),P_velo_to_img);
% plot points
cols = jet;
for i=1:size(velo_img,1)
col_idx = round(64*5/velo(i,1));
plot(velo_img(i,1),velo_img(i,2),'o','LineWidth',4,'MarkerSize',1,'Color',cols(col_idx,:));
where readCalibration function is defined as
function [P, Tr_velo_to_cam, R_cam_to_rect] = readCalibration(calib_dir,img_idx,cam)
% load 3x4 projection matrix
P = dlmread(sprintf('%s/%06d.txt',calib_dir,img_idx),' ',0,1);
Tr_velo_to_cam = P(6,:);
R_cam_to_rect = P(5,1:9);
P = P(cam+1,:);
P = reshape(P ,[4,3])';
Tr_velo_to_cam = reshape(Tr_velo_to_cam ,[3,4])';
R_cam_to_rect = reshape(R_cam_to_rect ,[3,3])';
end
But here is the result:
what is wrong with my code? I changed the "cam" variable from 0 to 3 and none of them worked. You can find a sample of Calibration file in this link:
How to understand KITTI camera calibration files
I fixed it by myself. here is the modification in readCalibration function:
Tr_velo_to_cam = P(6,:);
Tr_velo_to_cam = reshape(Tr_velo_to_cam ,[4,3])';
Tr_velo_to_cam = [Tr_velo_to_cam;0 0 0 1];

How to use the new functions of PDE toolbox in image processing (Matlab R2015a)

I want to use the line new command of PDE toolbox as Matlab R2015 to restore a noisy image with gaussian noise.
The PDE is:
∇.(( ∇u)/(√(1+|∇u|2))) +(f2)/(u2) = 1 in Ω (∂u)/(∂n)=0 in ∂Ω
Where f is the noisy image and u the restored image.
I tried the following code:
clear
close all
clc
img = 'AA.jpg';
mInputImage = double(imread(img));
mInputImage = rgb2gray(mInputImage);
[numRows, numCols] = size(mInputImage);
Var = 0.04;
Mean = 0;
mInputImageNoisy = imnoise((mInputImage(:,:,1)),'gaussian',Mean, Var);
% reshape the input and noisy images to vectors
mInputImageVector = reshape(mInputImage,numRows*numCols,1);
mInputImageNoisyVector = reshape(mInputImageNoisy,numRows*numCols,1);
Residu1 = norm(mInputImageVector-mInputImageNoisyVector)/norm(mInputImageVector)
RegularisationCoefficient = 0.7*ones((numRows-1)*(numCols-1),1);
mOutputImageVector = mInputImageNoisyVector;
%a = (mInputImageNoisyVector.^2) ./ mOutputImageVector.^3;
f = 1;
rtol = 1e-1;
c = '1./sqrt(1+ux.^2+uy.^2)';
% Create a PDE Model with a single dependent variable
numberOfPDE = 1;
pdem = createpde(numberOfPDE);
g = #squareg;
geometryFromEdges(pdem,g);
% Plot the geometry and display the edge labels for use in the boundary
% condition definition.
figure;
pdegplot(pdem, 'edgeLabels', 'on');
%axis([0 numRows 0 numCols]);
axis([-2 2 -2 2]);
title 'Geometry With Edge Labels Displayed'
b2 = applyBoundaryCondition(pdem,'Edge',[1 2 3 4], 'u', 0);
[p,e,t] = poimesh(g,numRows, numCols);
numCols
pdemesh(p,e,t);
axis equal
for iter = 1: numRows*numRows,
mOutputImageVector(iter) = pdenonlin(pdem,c,...
(mInputImageNoisyVector(iter).^2) ./ mOutputImageVector(iter).^3,...
f,'tol',rtol);
SaveImageVector(iter) = mOutputImageVector;
end
mOutputImage = reshape(SaveImageVector,numRows,numRows);
mOutputImage = uint8(mOutputImage);
figure()
imshow(mOutputImage)

Matlab surf only points, not lines

I have to draw a hipsometric map on a 3D plot. I have two vectors 1x401 (named xLabels and yLabels) which are the geo coordinates, and401x401(namedA`) matrix with the altitude data. To plot the data I use:
surf(xLabels, yLabels,A,'EdgeColor','None','Marker','.');
which leads to something like that:
But i would like to have something like that:
On the second image, only the surface is plotted, while my image looks like pillars.
I tried even make my vectors to 401x401 using meshgrid but it did not have any effect.
Do you have any idea what I should change?
#EDIT
I checked for X and Y data. I quess is too small interval (0.0083), but when i try plot good second of upper plots with same interval it draws correctly.
#EDIT2:
sizeX = 4800;
sizeY = 6000;
pixdegree = 0.0083; % 1 pixel is 0.0083 degree on map
intSize = 2;
lon = 37 + (35/60);
lat = 55+ (45/60);
fDEM = 'E020N90';
fHDR = 'E020N90.HDR';
[startXY, endXY] = calcFirstPixel(lon, lat); %calc borders for my area
f = fopen('E020N90.DEM');
offset = (startXY(1,2)*sizeX*intSize)+(startXY(1,1)*intSize);
fseek(f, offset,0); %seek from curr file pos
x = 0;
A = [];
BB = [];
jump = (intSize*sizeX)-(401*2);
while x<401
row = fread(f, 802);
fseek(f, jump, 0); %jump 2 next row
A = [A row];
x = x+1;
end
fclose(f);
A = A';
A = A(:,2:2:802);
m1 = min(A(:)); %wartość minimalna dla naszej podziałki
m2 = max(A(:)); %wartość maksymalna dla naszej podziałki
step = m2/8; % będzie 8 kolorów
highScale = m1:step:m2-step; %wartości graniczne dla każdego z nich
%handles.axes1 = A;
colormap(hObject, jet(8));
startXtick = 20 + pixdegree*startXY(1,1);
endXtick = 20 + pixdegree*endXY(1,1);
startYtick = 90 - pixdegree*endXY(1,2);
endYtick = 90 - pixdegree*startXY(1,2);
[XX,YY] = ndgrid(startXtick:pixdegree:endXtick,startYtick:pixdegree:endYtick);
xLabels = startXtick:pixdegree:endXtick;
yLabels = startYtick:pixdegree:endYtick;
surf(xLabels, yLabels,A,'EdgeColor','None','Marker','.');
set(gca,'YDir','normal');
grid on;
view([45 45])
And .DEM files
function [startXY, endXY] = calcFirstPixel(lon,lat)
global fHDR;
format = '%s %s';
f = fopen(fHDR);
cont = textscan(f, format);
LonStart = str2double(cont{1,2}{11,1});
LatStart = str2double(cont{1,2}{12,1});
diffPerPix = str2double(cont{1,2}{13,1});
fclose(f);
x = LonStart;
countX = 0
y = LatStart;
countY= 0;
while x<lon
x=x+diffPerPix
countX = countX +1;
end
while y>lat
y=y-diffPerPix
countY = countY+1;
end
startXY= [countX-200 countY-200];
endXY = [countX+200 countY+200];
end

plotting optical flow in matlab using vision tool box

I am trying to plot optical flow using quiver. I can plot the optical flow lines but not the arrows. This code is similar examples on Matlab tutorials.
Following is the code
function display_optical_flow (video_file_name)
vid_reader_obj = vision.VideoFileReader(video_file_name, 'VideoOutputDataType','single');
optical_flow_calculator = vision.OpticalFlow('Method','Lucas- Kanade','TemporalGradientFilter','Derivative of Gaussian', 'MotionVectorImageOutputPort', ...
true, 'OutputValue', 'Horizontal and vertical components in complex form', 'NoiseReductionThreshold',0.02);
screen_size = get(0, 'ScreenSize');
player_window_pos = [20 screen_size(4)-300 400 400];
video_display_originalVideo = vision.VideoPlayer('Name', 'Original Input Video', 'Position', player_window_pos);
player_window_pos(1) = player_window_pos(1) + 500;
video_display_opticalFlow = vision.VideoPlayer('Name','Optical Flow Vector', 'Position',player_window_pos);
player_window_pos(1) = player_window_pos(1) + 500;
video_display_of_image = vision.VideoPlayer('Name','Optical Flow image', 'Position',player_window_pos);
shape_inserter_line = vision.ShapeInserter('Shape','Lines', 'BorderColor','Custom','CustomBorderColor', [255 255 0]);
motion_vector_gain=20;
decimFactorRow = 5;
decimFactorCol = 5;
borderOffset = 5;
flag_first_time = true;
while ~isDone(vid_reader_obj)
cur_rgb_frame = step(vid_reader_obj);
cur_gray_frame = rgb2gray(cur_rgb_frame);
[optical_flow_vector IMV]= step(optical_flow_calculator, cur_gray_frame);
%magnitude of optical flow vectors by dot product
%of_magnitude= optical_flow_vector .* conj(optical_flow_vector);
if true == flag_first_time
flag_first_time = false;
[row col] = size(optical_flow_vector);
rowV = borderOffset:decimFactorRow:(row-borderOffset);
colV = borderOffset:decimFactorCol:(col-borderOffset);
[Y X] = meshgrid(rowV, colV);
end
lines =videooptflowlines(optical_flow_vector, 20);
if ~isempty(lines)
motion_vectors = step(shape_inserter_line, cur_rgb_frame, lines);
step(video_display_opticalFlow, motion_vectors);
end
%Display
step(video_display_originalVideo, cur_rgb_frame);
step(video_display_of_image, IMV);
%
[Xsize Ysize] = meshgrid(1:size(cur_gray_frame, 2), 1:size(cur_gray_frame, 1));
imshow(cur_gray_frame); hold on;
Real_part = real(optical_flow_vector(:));
Imag_part = imag(optical_flow_vector(:));
quiver(Xsize(:), Ysize(:), Real_part(:), Imag_part(:), 0);
pause;
end
release (video_display_opticalFlow);
release (video_display_originalVideo);
release (vid_reader_obj);
This do not show the arrow as I expect to see on each frame image by quiver.
What wrong I should do to correct the code?
nitin