Remove Grid Lines from a Graph

23 visualizaciones (últimos 30 días)
Carl Youel
Carl Youel el 11 de Jun. de 2021
Comentada: Carl Youel el 6 de Jul. de 2021
Hello,
I'm trying to write a script that can remove grid lines from a graph. This question is very similar to this unanswered question.
I've attached an example below:
I'm pretty new to MATLAB, so this question may have an easy/obvious answer. But how do I use the image processing toolkit to identify and then manipulate lines (by manipulate, I mean delete, color, etc.)?
  1 comentario
DGM
DGM el 11 de Jun. de 2021
Are you just trying to get an approximation of the data represented by the graph, or are you just trying to edit the image?

Iniciar sesión para comentar.

Respuesta aceptada

DGM
DGM el 11 de Jun. de 2021
Editada: DGM el 11 de Jun. de 2021
It depends what you want and what you expect. If all you want is one or two pictures, it's by far easier to do this manually outside of Matlab.
That said, here's a passing attempt to get rid of the lines.
inpict = rgb2gray(imread('testgraph.jpg'));
% process with a really wide edge filter
w = 100;
fk = repmat([-1 1],[w 1])./w;
a = imfilter(inpict,fk);
b = imfilter(inpict,fk.');
t = 20; % pick some threshold
% only pick N largest objects
c = bwareafilt(a>t,13,4) | bwareafilt(b>t,11,4);
% reduce line widths
c = bwmorph(c,'skel',100);
% make sure line ends don't touch image boundary
c([1 end],:) = 0;
c(:,[1 end]) = 0;
% make a mask to cover line ends and outer box
d = imdilate(bwareafilt(~c,1),ones(7));
% exclude ends & box, dilate wide enough to cover lines
c = imdilate(c&~d,ones(4));
outpict = inpict;
outpict(c) = 255; % apply mask
If you want to convert the image to numeric data, that's something else. Considering how almost every single graph I've ever tried to process or transcribe has been a tiny JPG with thick ambiguous lines and a crust of artifacts, I can't imagine any automated approach that isn't an exercise in frustration.
Here's an example, continuing from above:
% isolate plot box, get location
c = bwmorph(inpict<128,'skel',100);
c = bwareafilt(c,1,4);
S = regionprops(c,'boundingbox');
xl = [S.BoundingBox(1) sum(S.BoundingBox([1 3]))];
yl = [S.BoundingBox(2) sum(S.BoundingBox([2 4]))];
% isolate the curve only, find points
lpict = (255-outpict).*uint8(~d);
lpict = bwmorph(lpict>128,'thin',100);
lpict(1:100,:) = 0; % get rid of that number on top
[y x] = find(lpict);
% data range from graph
xrange = [-50 250];
yrange = [0 1E4];
% rescale to fit data range
x = xrange(1) + diff(xrange)*(x-xl(1))./diff(xl);
y = yrange(2) - diff(yrange)*(y-yl(1))./diff(yl);
% get rid of nonunique points; smooth
[x,idx,~] = unique(x);
y = y(idx);
xn = smooth(x);
yn = smooth(y);
plot(xn,yn); grid on
xlim(xrange)
ylim(yrange)
  3 comentarios
DGM
DGM el 14 de Jun. de 2021
Editada: DGM el 14 de Jun. de 2021
There can be plenty of improvements to the above code to improve accuracy. For instance, instead of using BoundingBox properties to define the plot box, you could filter to find the grid lines from a and b. Then you could use their Centroid properties to sort them and find the outermost four. That would make the calculation of the plot box (and consequently the data scaling) less susceptible to influence from spur defects on the lines. Like I said though, I don't really trust anything to automatically process the original images without tedious levels of oversight anyway
Personally, I tend to just throw the image in Inkscape and redefine the plot box with fine lines (or a rectangle) and trace over the curve with a bezier. I can then export the image at whatever resolution I want and use a similar technique to process it in Matlab. I suppose it would make more sense to process the SVG to get the curve more directly, but using a high-res raster copy is plenty adequate given the expected accuracy limitations of the source material.
For example, this image is a lot easier to process:
The SVG from which that was exported is attached. I had to put it in a zip archive because the editor doesn't know what an SVG is. Note that Matlab no longer needs to programmatically find the plot box; it's simply defined by the image geometry.
Carl Youel
Carl Youel el 6 de Jul. de 2021
Thanks much, I'll certainly look into these methods. I was able to get some pretty good results, at least with the one graph I shared above, but I can definitely see how making this process automated would be pretty difficult

Iniciar sesión para comentar.

Más respuestas (0)

Categorías

Más información sobre Image Processing Toolbox en Help Center y File Exchange.

Productos


Versión

R2020a

Community Treasure Hunt

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

Start Hunting!

Translated by