In [1]:
import numpy as np
import skimage.io
import skimage.filters
import skimage.color
import skimage.segmentation
import skimage.util
import skimage.restoration
import skimage.feature
import pandas as pd
import scipy.interpolate
import matplotlib.pyplot as plt
%matplotlib inline
plt.rcParams['figure.figsize'] = (20.0, 20.0)
In [2]:
#load raw data
fname='../ekg-m.png'
img = skimage.io.imread(fname)
img = skimage.color.rgb2gray(img)
plt.imshow(img)
Out[2]:
In [3]:
#denoise (ele edge detection is no good)
imgf = skimage.util.img_as_float(img)
denoised = skimage.restoration.denoise_tv_bregman(imgf, 15.2) # Go Bruins!
#denoised = skimage.restoration.nl_means_denoising(imgf,patch_size=5, patch_distance=12)
plt.imshow(denoised)
Out[3]:
In [4]:
#find edges, overlay on original image
edges = skimage.feature.canny(denoised,sigma=2)
plt.imshow(edges + img, cmap=plt.cm.gray)
Out[4]:
In [5]:
#use the edges to get a 1D signal out of the 2D one
xs = []
ys = []
for x in range(img.shape[1]):
y = np.median(np.where(edges[100:400,x])[0])
y = int(y) if not np.isnan(y) else None
if y:
ys.append(y)
xs.append(x)
f = scipy.interpolate.interp1d(xs,ys)
line = [f(x)+100 for x in range(min(xs), max(xs))]
line = scipy.signal.wiener(line,3)
hline = np.ones_like(line)*(np.median(line))
plt.plot(hline,c='b')
plt.plot(line,c='r')
plt.imshow(img+edges,cmap=plt.cm.gray)
plt.savefig('ekg-plotted.png')
Out[5]:
In [6]:
#trial/error to figure pixels per box... TODO statistics etc..
#I'm going to guess 55px per box (heart rate is ~300bpm?!)
#Looking at photos on crashingpatient.com suggests https://en.wikipedia.org/wiki/Supraventricular_tachycardia
box = img[20:71,0:280]
box = box[:,20:]
plt.imshow(box)
PIX_PER_BOX=55.0
In [7]:
#resample to time domain and save
#40px is 0.2 seconds => .005 seconds per pixel in x-direction
#40px is 0.5 mV => .0125 mV per pixel in y-direction
#use median as baseline (Does this make sense?)
df = pd.DataFrame(data=line,columns=['ekg'])
df['sec'] = [(0.2/PIX_PER_BOX)*x for x in range(len(df))]
df['ekg'] = (df['ekg'] - np.median(df['ekg']))*(0.5/PIX_PER_BOX)
df.to_csv('../ekg.tsv', index=False, sep='\t')
In [8]:
df
Out[8]:
In [ ]: