How can I convert data from a line figure to binary?

Hello again. I have the following line plot. Instead of that I want to create an image which will be consisted of pixel data. To be more specific I want the data to be binary and value '1' should match each pair (x,y) for each line (there are 25 lines plotted in the graph below)and value '0' everything else . I have extracted all data from the graph and they are in cell form (xdata cell 25x1 and ydata cell 25x1). Is it possible to be done? Thanks in advance.

 Accepted Answer

Just use a double for loop to set pixels. Assign the x to a column and the y to a row in the binary image.
binaryImage = false(4500, 200);
for k = 1 : length(x)
row = round(y);
col = round(x+100);
binaryImage(row, col) = true;
end

9 Comments

Greetings Image Analyst. Thanks for your response. I tried your suggestion. Part of my data (in cell form) was not positive integers so when I ran those commands above I got an error which stated "Subscript indices must either be real positive integers or logicals." So I used the command cellabs and then I had to change from round to ceil command so that the script could ran. The outcome though was not what I aimed to. It produced an almost total black image (picture on the left). I searched again and came across to calculation of pixels plotted. I also found an image which illustrates what I want to create (picture on the right). Below I include the script I ran.
clear all
% plot 1
open 'Ray_bty.fig'
h1=findall(gcf,'type','line')
x=get(h1,'xdata')
y=get(h1,'ydata')
% function X = cellabs( x )
[m n] = size( x );
X = cell( m, n );
for jj = 1:m*n
if iscell( x{jj} )
X{jj} = cellabs( x{jj} );
else
X{jj} = abs( x{jj} );
end
end
% function Y = cellabs( y )
[o p] = size( y );
Y = cell( o, p );
for jj = 1:o*p
if iscell( y{jj} )
Y{jj} = cellabs( y{jj} );
else
Y{jj} = abs( y{jj} );
end
end
close(gcf)
binaryImage = false(4500, 200);
for k = 1 : length(x)
row = ceil(Y{k,1}+100);
col = ceil(X{k,1});
binaryImage(row, col) = true;
end
imshow(binaryImage)
Well, what is the value of row and col when it bombs? And of x and y? Perhaps you need to adjust the offset, like from adding 100 to adding 101 or something.
By the phrase "when it bombs" you mean when I run the script? If so, the value of row and col is 0 or 1. The x and y data are double values. I tried to adjust the offset but it produces the same image. As I mentioned above the image on the right is close to what I aim to create. Can it be done with a different code or I should keep trying this one?
"When it bombs" means "when it crashes" or "when it throws an exception" or "when it throws an error". It does not mean "when you run the script".
I'm very surprised that when you tried to adjust the offset it was still zero. Exactly what did you do? It looks like your original x values are not outside the range of -100 to +100 so if you add 101 to the x value, it should not be zero. What does this say
fprintf('The max x value is %f.\n', max(x));
fprintf('The min x value is %f.\n', min(x));
Is there any chance you called xlim() and restricted the x axis to less than the actual x values? That's the only reason I can think of that adding 101 to x would still give 0 or negative values.
Also, show how you tried to adjust the offset - I'm wondering how you were not able to get it working since it's so easy.
Hello again. I am in the middle of exams so I couldn't answer any sooner. I checked what you suggested and had to make an adjustment because when I ran those two commands above the result was not what it should be. Also to be clear about something. Whenever I ran the script the values were not only zero but they were either 0 or 1 and I did not restrict the x-axis. Instead the problem (then the script bombed) was that my data was in cell form and I had to make adjustments because the program would not accept any other than positive integers or logicals. About the offset part of the adjustment was to add 104 and that solved the problem about the max and min. After running the commands above the results were 207.130383 (max) and 0.869617 (min). Below I include the script I ran as you requested. I commented the cellabs function for the X variable, otherwise the col variable ends up empty. I also include the outcome of the script.
clear all
% plot 1
open 'Ray_bty.fig'
h1=findall(gcf,'type','line')
x=get(h1,'xdata')
y=get(h1,'ydata')
close(gcf)
for i=1:length(x)
X{i,1}=(x{i,1})+104;
end
% function X = cellabs( x )
%
% [m n] = size( X );
%
% X = cell( m, n );
%
% for jj = 1:m*n
% if iscell( X{jj} )
% X{jj} = cellabs( X{jj} );
% else
% X{jj} = abs( X{jj} );
% end
% end
%
% function Y = cellabs( y )
[o p] = size( y );
Y = cell( o, p );
for jj = 1:o*p
if iscell( y{jj} )
Y{jj} = cellabs( y{jj} );
else
Y{jj} = abs( y{jj} );
end
end
close(gcf)
binaryImage = false(210,210);
for k = 1 : length(X)
row = ceil(Y{k,1});
col = ceil(X{k,1});
binaryImage(row,col) = true;
end
imshow(binaryImage)
Attach the original data, not the fig file but actual x,y data, and I'll see if I get time this weekend.
Those are the data files when I extracted them from the figure. They are in cell form 25*1 each and correspond to 25 rays. I will also keep on trying myself. Thanks in advance! I appreciate it!
Try this:
clc; % Clear the command window.
clear all;
close all;
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontsize = 24;
sx = load('x-data.mat')
sy = load('y-data.mat')
cellArrayX = sx.x
cellArrayY = sy.y
allX = [];
allY = [];
subplot(2, 1, 1);
for k = 1 : length(cellArrayX)
thisCellX = cellArrayX{k};
thisCellY = cellArrayY{k};
plot(thisCellX, thisCellY, 'b-');
grid on;
hold on;
% Append
allX = [allX, thisCellX];
allY = [allY, thisCellY];
end
% Set up figure properties:
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0 0 1 1]);
% Get rid of tool bar and pulldown menus that are along top of figure.
set(gcf, 'Toolbar', 'none', 'Menu', 'none');
% Give a name to the title bar.
set(gcf, 'Name', 'Demo by ImageAnalyst', 'NumberTitle', 'Off')
% Get min and max
minX = min(allX);
maxX = max(allX);
minY = min(allY);
maxY = max(allY);
fprintf('min x = %f\nmax x = %f\nmin y = %f\nmax y = %f\n',...
minX, maxX, minY, maxY);
% Shift to start at 1 on the x and y axes
allX = allX - minX + 1;
allY = allY - minX + 1;
% Get updated min and max
minX2 = min(allX);
maxX2 = max(allX);
minY2 = min(allY);
maxY2 = max(allY);
fprintf('min x = %f\nmax x = %f\nmin y = %f\nmax y = %f\n',...
minX2, maxX2, minY2, maxY2);
% Declare a binary image of about 600 rows by 800 columns.
rows = 600;
columns = 800;
binaryImage = false(rows, columns);
% Set pixels in the binary image.
for k = 1 : length(cellArrayX)
thisCellX = cellArrayX{k} - minX;
thisCellY = cellArrayY{k} - minY;
x = round(columns * thisCellX / maxX) + 1;
y = round(rows * thisCellY / maxY) + 1;
for k2 = 1 : length(x)
binaryImage(y(k2), x(k2)) = true;
end
end
subplot(2, 1, 2);
imshow(binaryImage);
title('Binary Image', 'FontSize', fontsize);
Or, if you want just what you see from plot(), then save the axes with export_fig.
Fantastic work Image Analyst! Exactly what I wanted. Seems I have to improve my Matlab skills. Thanks a lot for your time! It was really helpful!

Sign in to comment.

More Answers (0)

Categories

Find more on Creating, Deleting, and Querying Graphics Objects in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!