My plotted lines aren't appearing on my output figures - matlab

so I'm processing a bunch of images at the one time, trying to display them all as figures with a series of plotted lines on each individual image as a result of the process. With some help I fixed the figure title issue, However the plotted lines are not appearing on my final figures, below is the code:
inputFolder = fullfile(pwd, 'BMPData');
filePattern = fullfile(inputFolder, '*.bmp');
%Get list of all Bmp Files in Folder
BmpFiles = dir(filePattern)
for i=1:length(BmpFiles)
fname = BmpFiles(i).name;
fullFileNameInput = fullfile(inputFolder,fname);
A = imread(fullFileNameInput);
%// Change
AR=A(:,:,1);
[rows, columns] = size(AR);
y1 = 200;
y2 = 315;
row1 = AR(y1, :); % Extract this line of gray levels from the image.
row2 = AR(y2, :);
figure('name',fname),imshow(A), hold on;
plot([0, columns], [y1, y1], '.b');
plot([0, columns], [y2, y2], '.m');
end
The reason I am doing this is because I want to mark 2 rows (200 and 315) on all my images and then do some statistical analysis on all the pixels in them rows for further processing techniques.

The reason why you're getting columns undefined is due to variable scope. When you define columns in SegmentationNew, columns is only available within the lifetime of SegmentationNew and only visible within SegmentationNew. Once SegmentationNew completes, column is no longer defined.
I honestly can't make heads or tails of what SegmentationNew is doing, but from the looks of it, there is no good reason why you should call it. All you need from it is y1 and y2, which are defined as constants. columns you can determine from the columns of the image. I'm also going to borrow from the duplicate post that Martin J.H. has linked to make naming the figure window more elegant.
To add to this post, your original code was plotting just the points. If you want to plot the lines as well, you need to remove the . characters from your plotting string for each call to plot. Specifically, change .b and .m to b and m respectively.
As such, do this:
for i=1:length(BmpFiles)
fname = BmpFiles(i).name;
fullFileNameInput = fullfile(inputFolder,fname);
A = imread(fullFileNameInput);
%// Change
columns = size(A,2);
y1 = 200;
y2 = 315;
figure('name',fname); %// Change
imshow(A); hold on;
plot([0, columns], [y1, y1], 'b'); hold on; %// Change
plot([0, columns], [y2, y2], 'm');
end

Related

Generating 6plots in 3rows and 2columns with same legend symbol and colors for same data value in Matlab

I have x, y and t variables for the above function. t contains a 16 different names distributed among the 6 sections. I want to plot the six plots in a nexttile or subplot format such that the same names in different plots will have the same color. I have this code but it is plotting the points and assigning the same color but the names are not matching with their respective points.
Can anyone please help me to get this plot right? I have attached the variables and the figure with the error along with this.
https://www.dropbox.com/sh/zwyf4ts3olmmgx7/AABk5NAblWq1AuFYQyfB7L3Sa?dl=0
load('t.mat'); load('x.mat'); load('y.mat');
%whos
x, y, t
% concatenate t to get all types available
tall =[];
for i=1:length(t)
if ~isempty(t{i})
tall = [tall; string(t{i})];
end
end
ut=unique(tall); % unique types
ntypes = length(ut)
c = jet(ntypes); % different colors for different types
tiledlayout(2, 3);
for i=1:6
nexttile
hold on
% i, size(x{i}), size(y{i}), size(t{i})
for j=1:length(x{i})
if j>=length(t{i}) % this is not necessary if t{i} has enough entries
mc = ntypes; % use last color
else
mc = find(t{i}(j)==ut);
end
%mc = find(t{i}(j)==ut);
plot(x{i}(j), y{i}(j), "Marker", 'o', "MarkerEdgeColor", c(mc,:), "MarkerFaceColor", c(mc,:))
end
hold off
end
l=nexttile('south');
for i=1:ntypes
plot(nan(2,1), 'o', 'MarkerEdgeColor', c(i,:), 'MarkerFaceColor', c(i,:)); hold on
end
l.Visible = 'off';
lgd = legend(l, ut);
lgd.Location = 'east';
lgd.NumColumns = 4;
enter image description here

MATLAB: Blanked Plots when Looping on a Multidimensional Array

My goal output is to have four plots displaying (time, dist_a), (time, speed_a), (time, dist_b), and (time, speed_b) when looping through a multidimensional array. However, I am displaying only 2 blanked plots.
Here is my code:
time = rand(10, 1)
dist_a = rand(10,1)
dist_b = rand(10,1)
speed_a = rand(10,1)
speed_b = rand(10,1)
dist = cat(2, dist_a, dist_b);
speed = cat(2, speed_a, speed_b);
for k = 1:2
figure;
plot(time, dist(k));
plot(time, speed(k));
end
Your problems were two-fold. Firstly, you were only plotting a single point as opposed to a vector, changing dist(k) to dist(:,k) for example fixes this. Secondly, if you want four figures with a loop that executes twice, you need to include another figure command before the second plot. The following should do what you asked for, I also added in some formatting to make the plots looks nicer
for k = 1:2
figure
plot(time, dist(:,k),'o','LineWidth',2);
xlabel('time')
ylabel('distance')
box on
grid on
figure
plot(time, speed(:,k),'o','LineWidth',2);
xlabel('time')
ylabel('speed')
box on
grid on
end
which gives:

Handling and eliminating multiples entries in MatLab legend

I currently want to have the legend of graph, however i'm plotting several lines that should be group in only 3 types.
My currently option is to use a dummy plot out of the boundaries, plotting the relevant data and calling the legend just at the end. It works but it is prone to errors. I wanted to update the legend and select just a few of the plots.
I tried to use the leg_handle.String, but then it comes two problems:
It still plot 5 handles instead of 3.
It does not have the proper line style & color.
Any ideas?
Bellow follow the code (with dummy plot commented) and the pictures of the current version giving the error and what i want to look.
clear
figure()
hold on
%using
%dummy plot
% leg_text={'a','b','c'};
% plot(100,100,'-r')
% plot(100,100,'-b')
% plot(100,100,'-k')
for ii=1:20,
plot(1:11,linspace(0,ii,11),'-r')
end
for ii=30:50,
plot(1:11,linspace(0,ii,11),'-b')
end
for ii=70:80,
plot(1:11,linspace(ii,25,11),'-k')
end
Yaxl=[-1 80];
Xaxl=[1 11];
set(gca, 'Visible','on', ...
'Box','on', ...
'Layer','top',...
'Xlim',Xaxl, ...
'Ylim',Yaxl);
%using
% legend(leg_text)
%want to use
leg_hand=legend(gca,'show');
leg_hand.String=leg_hand.String([1 21 42]);
%extra comand will give the things that i wanted above
% leg_hand.String=leg_hand.String([1 2 3]);
What it gives:
What I expect to have:
I have tried this method using [a,b,c,d]=legend, but this give only the a handle that i already using.
This little workaround should do the job:
clear();
figure();
hold on;
h = gobjects(3,1);
for ii = 1:20
h(1) = plot(1:11,linspace(0,ii,11),'-r');
end
for ii = 30:50
h(2) = plot(1:11,linspace(0,ii,11),'-b');
end
for ii = 70:80
h(3) = plot(1:11,linspace(ii,25,11),'-k');
end
set(gca,'Box','on','Layer','top','Visible','on','Xlim',[1 11],'Ylim',[-1 80]);
legend(h,'A','B','C');
hold off;
Actually, what I did is very simple. I created an array of graphical objects of size 3 (one for each iteration) using the gobjects function. Then, inside each iteration, I assigned the last plotted line to its respective array placeholder. Finally, I created the legend using the three graphical objects I previously stored.
Alternatively:
clear();
figure();
hold on;
h1 = gobjects(20,1);
for ii = 1:20
h1(ii) = plot(1:11,linspace(0,ii,11),'-r');
end
h2 = gobjects(21,1);
for ii = 30:50
h2(ii-29) = plot(1:11,linspace(0,ii,11),'-b');
end
h3 = gobjects(11,1);
for ii = 70:80
h3(ii-69) = plot(1:11,linspace(ii,25,11),'-k');
end
set(gca,'Box','on','Layer','top','Visible','on','Xlim',[1 11],'Ylim',[-1 80]);
legend([h1(1) h2(1) h3(1)],'A','B','C');
hold off;
You create an array of graphical objects for storing the plot handlers produced by every iteration. Then you create the legend using the first (basically, any) item of each array of graphical objects.

Legend on scatter3 in Matlab

I was expecting that to work, but I am missing what is a "vector of handles", from MATLAB helpfile.
LEGEND(M), where M is a string matrix or cell array of strings, and
LEGEND(H,M) where H is a vector of handles to lines and patches also
works.
myone = ones(20,1);
mytwo = ones(20,1)+1;
rows = vertcat(myone,mytwo);
mylabels = {'Alpha', 'Beta'};
figure
grouplabels = mylabels(rows);
h = scatter3(rand(40,1),rand(40,1),rand(40,1),20,rows,'filled'), ...
view(-33,22)
legend(handle(h),grouplabels)
xlabel('X')
ylabel('Y')
zlabel('Z')
The problem with your code is that h, the output of scatter3, is a single handle. It's not an array of handles with the same size as your data (which is what you imply when trying to set 40x1 array of labels on it, ignoring irrelevant handle wrapper). And it's not even an array of two handles as one may have thought (one per color). So you cannot set legend like this. One way around would be to plot all the points of one color at a time:
hFig = figure();
axh = axes('Parent', hFig);
hold(axh, 'all');
h1 = scatter3(rand(20,1),rand(20,1),rand(20,1),20,'b','filled');
h2 = scatter3(rand(20,1),rand(20,1),rand(20,1),20,'r','filled');
view(axh, -33, 22);
grid(axh, 'on');
legend(axh, [h1,h2], {'Alpha', 'Beta'});

draw a line of best fit through data with shaded region for error

I have the following data:
dat = [9.3,0.6,0.4,0.7;...
3.2,1.2,0.7,1.9;...
3.9,1.8,0.7,1.9;...
1.0,7.4,5.6,10.7;...
4.7,1.0,0.5,1.3;...
2.2,2.6,1.2,2.7;...
7.2,1.0,0.5,1.1;...
1.0,4.8,7.5,10.3;...
2.7,1.8,1.7,4.0;...
8.2,0.8,0.4,0.9;...
1.0,4.9,5.7,8.2;...
12.9,1.3,0.6,1.6;...
7.7,0.8,0.5,1.3;...
5.8,0.9,0.6,1.9;...
1.1,4.5,6.2,12.1;...
1.1,4.5,2.8,4.8;...
16.4,0.3,0.3,0.5;...
10.4,0.6,0.3,0.7;...
2.2,3.1,2.2,4.6];
where the first column shows the observed values the second column shows the modeled values and the third and fourth columns show the min and max respectively.
I can plot the relationship between observed and modeled by
scatter(d(:,1),d(:,2))
Next, I would like to draw a smooth line through these points to show the relationship. How can this be done? Obviously a simple straight line would not be much use here.
Secondly, I would like to use the min and max (3rd and 4th columns respectively) to draw a shaded region around the modeled values in order to show the associated error.
I would eventually like to have something that looks like
http://www.giss.nasa.gov/research/briefs/rosenzweig_03/figure2.gif
Something like this?
%// Rename and sort your data
[x,I] = sort(dat(:,1));
y = dat(I,2);
mins = dat(I,3);
maxs = dat(I,4);
%// Assume a model of the form y = A + B/x. Solve for A and B
%// using least squares
P = [ones(size(x)) 1./x] \ y;
%// Initialize figure
figure(1), clf, hold on
set(1, 'Renderer', 'OpenGl');
%// Plot "shaded" areas
fill([x; flipud(x)], [mins; flipud(maxs)], 'y',...
'FaceAlpha', 0.2,...
'EdgeColor', 'r');
%// Plot data and fit
legendEntry(1) = plot(x, P(1) + P(2)./x, 'b',...
'LineWidth', 2);
legendEntry(2) = plot(dat(:,1), dat(:,2), 'r.',...
'Markersize', 15);