MIT-BIH这一数据集在几乎所有的ECG信号相关的论文的实验部分都会提到,大部分对其的处理都是filter,segment,或者是求一下RR_interval这一类时域特征,然后换换model,跑一跑。而且大部分代码都是不开源的。
针对于此,在本篇文章中,1,笔者提供了一个信号分割代码的写作思路。2.提供了一个将一维信号转变为二维信号的代码写作思路。并可由此实现快速的dataset构建。
数据链接如下:
MIT-BIH Database (kaggle.com)
平台:kaggle云平台
开始
遍历数据文件。
fannotation = []
frecording = []
lst = os.listdir('/kaggle/input/mitbih-database')
lst.sort()
for file in lst:
if file.endswith(".csv"):
frecording.append(file)
else:
fannotation.append(file)
print(frecording)
print(fannotation)
在kaggle平台上,如果进行大规模的图像生成的话,会有比较可怕的效果(亲身实测)
因此,在这个平台上,我只进行一些小规模的二维图像生成。
下面以100.csv以及100annotations.txt为例
filename_csv = '/kaggle/input/mitbih-database' +'/'+ frecording[0]
test_csv = pd.read_csv(filename_csv)
print(test_csv)
#该csv的column打出来好麻烦,换掉。
test_csv.columns = list(range(len(test_csv.columns)))
print(test_csv)
处理一下txt文件,将其变成dataframe格式。
filename_txt =os.path.join('/kaggle/input/mitbih-database',fannotation[0])
f = open(filename_txt, 'r')
next(f) # skip first line!,因为第一行是表头。
annotations = []
for line in f:
tmp_list = line.split()
annotations.append(tmp_list)
f.close
#第一个元素是波峰在总时间段的时刻,第二个是波峰的在样本中的序号。第三个是label的代号。
print('the data_format example is:',annotations[1])
#把波峰的序号和label提取出来
def slice_label_and_dot(annotations):
labels = []
sample_dot = []
for i in range(len(annotations)):
labels.append(annotations[i][2])
sample_dot.append(int(annotations[i][1]))
return labels,sample_dot
labels,sample_dot = slice_label_and_dot(annotations)
#新建dataframe,表头为位置信息和标签信息。
data_frame = {'sample_dot':sample_dot,'labels':labels}
test_df = pd.DataFrame(data_frame)
print(test_df)
下面代码的大体思路是这样的,我通过test_df中的波峰位置,找出test_csv(也就是100.csv中的原始信号)中对应的点,用上一个波峰的位置+20,和下一个波峰的位置减20,构成一个序列,把这个序列画出来,用灰度的形式保存,同时将jpg名字,和对应test_df的label信号写进一个csv中,变成大家非常熟悉的filename和label的那种dataframe。 非常容易进行dataset的编写。
import cv2
import sys
import os
def draw_pictures(data_frame,raw_data):
directory = '/kaggle/working'
labels = []
file_name = []
#避免生成太多的图片,平台直接卡死
#for i in range(1,len(data_frame['labels']-1)):
for i in range(1,30):
#把坐标系,框架之类的全部隐藏
fig = plt.figure(frameon=True)
labels.append(data_frame['labels'][i])
plt.plot(raw_data[2][data_frame['sample_dot'][i-1]+20:data_frame['sample_dot'][i+1]-20])
plt.xticks([]), plt.yticks([])
for spine in plt.gca().spines.values():
spine.set_visible(False)
#filename构建,可以把峰值点和label信息藏在名字中,方便后续的查找以及验证
filename = directory + '/' + str(data_frame['sample_dot'][i])+data_frame['labels'][i]+'.jpg' #.png
file_name.append(filename)
#保存图片
fig.savefig(filename)
#颜色信息无用,用cv2裁剪,转化为灰度图,再次保存。
im_gray = cv2.imread(filename, cv2.IMREAD_GRAYSCALE)
im_gray = cv2.resize(im_gray, (128, 128), interpolation = cv2.INTER_LANCZOS4)
cv2.imwrite(filename, im_gray)
plt.close()
dataset_frame = {'file_name':file_name,'labels':labels}
test_dataset_frame = pd.DataFrame(dataset_frame)
return test_dataset_frame
test_data_frame= draw_pictures(test_df,test_csv)
print(test_data_frame)
转化成了我们喜闻乐见的形式。
简单看一下生成的图片对不对。
from PIL import Image
img1 = Image.open('/kaggle/working/6527N.jpg')
img2 = Image.open('/kaggle/working/2044A.jpg')
fig, axs = plt.subplots(1, 2, figsize=(10, 5))
axs[0].imshow(img1, cmap='gray')
axs[0].axis('off')
axs[0].set_title('Image 1')
axs[1].imshow(img2, cmap='gray')
axs[1].axis('off')
axs[1].set_title('Image 2')
plt.show()
完毕。
这个代码只是提供一个思路,还是有一些缺陷的,比如在filename的命名上,可以做的再标准一点,受限于平台的计算能力,也没有使用一整套代码,一键将所有数据全部转化为我们想要的格式。
等我把剩下的代码整理整理,第二篇就发。
notebook名称:
在dataset中的code一栏中很容易找到。欢迎来调试和玩耍。