Converting multiple lines into separate equations from jpeg?

2 views (last 30 days)
Is there a way to import a jpeg to matlab and and have it follow the curves to produce fitting equations? My end goal is to have multiple phase diagrams for different chemicals e.i. water, CO2, CO, methane, etc. and be able to come up with curves so i can write some evaluating functions to tell me what state the chemical will be in based on input data for temperature and pressure. If it would be simpler, would it be possible to input vertical and horizontal lines over the graph and simply choose which chunk they intersect in without using any real math? I know phase diagrams can be messy, so would it be possible to get a few peicewise functions to fit the boundaries created from an image? I'm hoping the fact that each phase is color coded may make it easier for matlab to identify. An extra complication is that all of these graphs are on a logrythmic scale. I've added a sample graph from wolfram alpha as these will make up the mjority of my phase diagrams. Any input would be greatly appreciated.

Answers (2)

Bjorn Gustavsson
Bjorn Gustavsson on 2 Nov 2022
In similar situations I typically separate the problem into two steps, first extracting the curves, then fit parameters for equations to those curves. For the first part I use grabit to extract the curves. That is a very handy tool. To use it for log-scales you just have to do the extraction on the log-scale and then exponentiating the extracted curves. For the equation-fitting I typically use fminsearch or lsqnonlin to minimize the difference between curve and my parameterized equations, others prefer the more modern fit.

Sign in to comment.

DGM on 9 Nov 2022
Edited: DGM on 9 Nov 2022
I've played with Grabit and a few other transcription tools, but the view controls are universally cumbersome and buggy. You constantly have to disable your cursor tool so that you can move or zoom without dumping errors and warnings to console. Doing rotation/perspective correction is a nice feature though.
I prefer to just transcribe the curve with a spline in a vector image editor with actual view controls made for human use. The spline can be fit visually by you to whatever degree you feel best fits your particular JPG pixel salad. Bear in mind the limited value in a perfect fit to an imperfect representation of the underlying information.
That said, you are working with a clean GIF, so it's not as bad as it could be. It's just small.
Here is one spline example, with links to similar examples.
If I had an image that had perspective distortion, how would I handle it? One of the examples linked in that thread includes perspective correction. Here are a couple more examples.
Here's an example adapting the linked code to this case where the plot is semilog-y with multiple curves. Attached is the transcribed SVG. The spline discretization can give you as many points as you want to work with.
% using the following FEX tools:
% filename of manually-fit svg file
fname = 'brownphasediagram.svg';
% data range from original image axis labels
% this is where the rectangle is drawn in the SVG
xrange = [-260 200];
yrange = [-4 4]; % because this is semilog-scale
% spline discretization parameter [0 1]
coarseness = 0.001;
% get plot box geometry
str = fileread(fname);
str = regexp(str,'((?<=<rect)(.*?)(?=\/>))','match');
pbx = regexp(str,'((?<=x=")(.*?)(?="))','match');
pby = regexp(str,'((?<=y=")(.*?)(?="))','match');
pbw = regexp(str,'((?<=width=")(.*?)(?="))','match');
pbh = regexp(str,'((?<=height=")(.*?)(?="))','match');
pbrect = [str2double(pbx{1}{1}) str2double(pby{1}{1}) ...
str2double(pbw{1}{1}) str2double(pbh{1}{1})];
% get coordinates representing the curve
S = loadsvg(fname,coarseness,false);
% if there are multiple paths you want to extract
% you'll need to do do the rescaling, etc for each element of S
for k = 1:numel(S) % there are multiple curves
x = S{k}(:,1);
y = S{k}(:,2);
% rescale to fit data range
x = xrange(1) + diff(xrange)*(x-pbrect(1))/pbrect(3);
y = yrange(1) + diff(yrange)*(pbrect(4) - (y-pbrect(2)))/pbrect(4);
y = 10.^y; % because this is logscale
% get rid of nonunique points
% this may or may not be needed depending on the shape
% of the curves and how they're to be processed
%[x,idx,~] = unique(x);
%y = y(idx);
% shove the prepared data back into S for later
S{k} = [x y];
% plot each curve
for k = 1:numel(S)
x = S{k}(:,1);
y = S{k}(:,2);
semilogy(x,y); hold on
grid on;
ylim(10.^yrange) % log scale
  1 Comment
Bjorn Gustavsson
Bjorn Gustavsson on 9 Nov 2022
Edited: Bjorn Gustavsson on 9 Nov 2022
That is a good answer! Especially for a general curve-extraction task.
(For this problem, I have a vague tingling in the back of my memory that there should be some rather scary-looking closed-form few-free-parameter equation from thermodynamics/statistical physics for thess curves that one should fit to the extraced points. Therefore I suspect that the extracted curve is just an intermediate step. However, I'm not inclined to look up these phase-transision curves - because I worry about seeing some nightmare-inducing stuff. Water is going to make this "theoretical curve-fitting" task "a good full days worth of work": Phase_diagram_of_water.svg)

Sign in to comment.




Community Treasure Hunt

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

Start Hunting!

Translated by