DBL
DBL

Reputation: 159

Convert an image of a signal into a python list - by specifying no of points in 1D

I'm struggling to convert an image of a signal back to a python list (it was plotted a long time ago and I have lost the data I have only the images). I've searched on the internet but I find answers about how to convert a 2d image into a 1d and I want to get the signal back.

Long story short: I have this image of a signal:

enter image description here

and I want to convert this to a python list with a size of 65535 so my list should be looking like this: list = [0.14, 0.144, 0.12 ...... ]

Thanks!

Upvotes: 1

Views: 2360

Answers (2)

Thomas Kavanagh
Thomas Kavanagh

Reputation: 91

Essentially, you'll have to "scan" the images left to right and identify the correct signal value at each "time step." As the image you presented doesn't have scale / units, you'll probably want to normalize all signal values from 0 to 1, as you've implied in your answer. Later you can adjust the scale of the signal if that's not the right range.

It looks like your images have some anti-aliasing at each step of the signal, which means that you won't have columns of all zeros except for one "signal" value. You'll have a cluster of signal values at each time step, some of which are weaker, because the image compression has blurred the signal slightly. This shouldn't be a problem, since you'll just find the max at each time step.

Assuming these images are in grayscale (if not, convert to grayscale), you'd want to find the maximum (or minimum, if the signal is drawn in black) color value at each column of pixels in the images (representing timesteps of the signal).

Mark Setchell's suggestion of PIL/Pillow seems like a great first step.

numpy's amax takes a matrix and flattens it to the max across an entire axis.

Upvotes: 1

Mark Setchell
Mark Setchell

Reputation: 207540

As a first plan, you could load the image using PIL/Pillow, or OpenCV, greyscale it and resize it to 65536 pixels wide by 100 pixels tall.

Then you will have a Numpy array with dimensions (100,65536). You can then run np.argmin() to find the index (y-value) of the darkest pixel in each column.

Or, find the indices of all the low valued pixels and take their median instead of the second step above.

The code starts off like this:

#!/usr/bin/env python3

from PIL import Image
import numpy as np

# Load image and convert to greyscale
im = Image.open('signal.png').convert('L')

# Resize to match required output
big = im.resize((65536,100), resample=Image.NEAREST)

# Make Numpy array
na = np.array(big)

# This looks about right, I think
print(np.argmin(na,axis=0))

If you trim the image so that the signal touches the edges all the way around, then the first black pixel on the left comes out as list element 0, the last pixel on the right comes out as the last element of your list and the lowest black pixel comes out with y-value of 0 and the peak comes out with y-value of 100.

Trimming would look like this:

from PIL import Image, ImageOps
import numpy as np

# Load image and convert to greyscale
im = Image.open('signal.png').convert('L') 

# Get bounding box
bbox = ImageOps.invert(im).getbbox() 

# Trim original image so that signal touches edge on all sides
im = im.crop(bbox)

... continue as before ...

Upvotes: 4

Related Questions