# How do I recover the signal from an ECG image

In my project, I have to digitize an ECG image taken with a normal camera (jpeg). For example, I have the following camera captured image:

and I want to get something like this:-

and then the digitized data (x,y points), like in this video on digitization of ECG

I have no idea how to do it, so I searched and consulted several research papers. The general approach of the algorithms is like:-

1. change to gray level image
2. delete gridlines
4. convert 2D image to 1D image

I am stuck with the second point, i.e., deleting the gridlines. I looked up some more references to do this and found histogram analysis might be helpful.

Can you please guide me on how to do this (I'm using MATLAB 2010)? Any help would be appreciated.

• I asked basically the same thing here: stackoverflow.com/q/1657941/125507 Jan 3, 2012 at 21:07
• @ Deepak,seems like you have implemented the matlab part of the code mentioned in the post ,can you kindly share the matlab part where you are converting the scanned image to 1D signal for interpolation Dec 10, 2012 at 22:34
• You can extract the data using PlotDigitizer. It offers a free online app. Then export the extracted data in MATLAB and replot the graph. Jan 15, 2021 at 12:39

Sorry, I use Mathematica, but it should be really easy to implement the idea into Matlab. I give the code anyway, so when my description is not detailed enough, you can get the rest from the code.

Basic idea is: you look at your image column-wise. Process every column of pixels separately. Note, that in the plot, I inverted the gray-values. So black is 1 and white is 0.
If you plot the (inverted) brightness-pixel-values you have basically only two situations. The first one is, when your column is not on a vertical grid line. The the plot looks like

The second situation is, where you are directly on a vertical grid line. Then the grid line influences the brightness of the whole column

But what you see is, that your dark EEG seems to be always the maximum. Therefore, the very complex algorithm is: Go through every column and take the position of the most black pixel.

img = ColorConvert[
Import["https://i.sstatic.net/500Kg.jpg"], {{0, -20}, {0, 0}}],
"Grayscale"];

Image[
Transpose[Function[With[{m = Min[#]},
Map[Function[{v}, If[v == m, 1, 0]], #]]] /@
Transpose[ImageData[img, "Real"]]
]
]


Note, that I croped a bit of the right side of you image, since it was completely white there. The result is

Now you can join the points or interpolate them in every way you like and you get your EEG

• @Patrick: I like the idea! Jan 3, 2012 at 19:23
• Note that this will only work if the gridlines are straight and parallel to the image axes Jan 3, 2012 at 21:09
• @endolith, you have tried it, right?? Because here, it works when the image is not exact aligned. Btw, when the gridlines are not horizontal/vertical then the whole procedure of removing them is completely useless, since for a rotated image you would get wrong {x,y} values for the EEG. Jan 4, 2012 at 12:11
• @Patrick: I mean you would not get the correct x,y values if the data is not aligned with the coordinates of the pixels. Jan 4, 2012 at 17:41
• @Patrick your algo worked :) and i have successfully extracted the signal but still having some difficulty in interpolating the signal (as i am very new to image processing) , kindly help me in how to interpolate the signal? thanks again :) Jan 5, 2012 at 12:51

You have a colour image where the gridlines are red and the trace is black. so simply ignore any pixels which are red!

If you can't be sure the image is exactly aligned you could use the grid lines to calculate a skew (simply the slope of the image in pixels/pixel as you go right).

Then turning the black trace into a 1d value is simple. Start in the first column at the left edge and find the black pixel (or centroid of a small connected group of pixels) - the vertical position is your value.
Do that for each column in the image.
Where you have a missing value you will need to interpolate between the known values before and after.

For extra points you could set a limit on how much the trace can change from column-column to allow you to spot random dots or noise spikes.