-
Notifications
You must be signed in to change notification settings - Fork 0
/
preprocessing.py
147 lines (108 loc) · 5.11 KB
/
preprocessing.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import glob
import os
import numpy as np
from librosa import power_to_db, load
from librosa.feature import melspectrogram
from pywt import dwt2
sr = 44100 # resample all to 44.1kHz
window_size = 1024 # ~23[mseg] at 44.1kHz
def extract_features(signal, normalize=False, wavelet=0):
# handle less than 3 [seg]
L = sr*3 # Total length for samples ~3[seg]
signal_length = signal.shape[0]
if signal_length < L:
#pad by repeating signal
signal = np.pad(signal, (0, L-signal_length), mode='wrap')
elif signal_length > L:
signal = signal[:L]
# Calculate melspectrogram
melspec = melspectrogram(signal, sr=sr, center=False, #fmax = sr/2
hop_length=window_size, win_length=window_size,
n_mels=128) # shape:[bands, frames]
# Transform to log scale and transpose
melspec = power_to_db(melspec, ref=np.amax(melspec)).T # shape:[frames, bands]
if normalize:
melspec = (melspec - np.mean(melspec))/np.std(melspec)
# 2D Discrete Wavelet Transform
if wavelet != 0:
LL, (LH, HL, HH) = dwt2(melspec, wavelet)
melspec = np.stack([LL,LH,HL,HH],axis=-1) # shape: [frames, bands, 4]
else:
melspec = melspec[..., np.newaxis]
# Reshape
features = melspec[np.newaxis, ...] # shape : [1, frames, bands, channels]
return features
def extract_fold(parent_dir, fold, frames=128, bands=128, channels=1, **kwargs):
# Extract features from one fold
features = np.empty(shape=[0, bands, frames, channels]) # shape : [samples, frames, bands]
labels = np.empty(shape=0 ,dtype=int)
for filename in glob.glob(parent_dir+"/"+fold+"/*.wav"):
# load signal
signal = load(filename, sr=sr, duration=3)[0]
#extract features
features_yield = extract_features(signal, **kwargs)
features = np.concatenate((features, features_yield))
#extract label
labels_yield = int(filename.split('-')[-3]) # filenames: [fsID]-[classID]-[occurrenceID]-[sliceID].wav
labels = np.append(labels, labels_yield)
return features, labels
def save_folds(data_dir, save_dir, **kwargs):
# Preprocess all folds and save
assure_path_exists(save_dir)
for k in range(1,10+1):
fold_name = 'fold' + str(k)
print ("\nSaving " + fold_name)
features, labels = extract_fold(data_dir, fold_name, **kwargs)
print ("Features of", fold_name , " = ", features.shape)
print ("Labels of", fold_name , " = ", labels.shape)
feature_file = os.path.join(save_dir, fold_name + '_x.npy')
labels_file = os.path.join(save_dir, fold_name + '_y.npy')
np.save(feature_file, features, allow_pickle = True)
print ("Saved " + feature_file)
np.save(labels_file, labels, allow_pickle = True)
print ("Saved " + labels_file)
return
def load_folds(load_dir, validation_fold, bands=128, frames=128, channels=1):
#load all folds except the validation fold, and a random testing fold
train_x = np.empty(shape=[0, bands, frames, channels]) # shape : [samples, frames, bands, channels]
train_y = np.empty(shape=0, dtype=int)
# take out validation from training set
train_set = set(np.arange(1,10+1))-set([validation_fold])
# take one random fold from the remaining for testing
test_fold = np.random.choice(list(train_set),1)[0]
train_set = train_set-set([test_fold])
print("\n*** Train on", train_set,
"Validate on", validation_fold, "Test on", test_fold, "***")
for k in range(1,10+1):
fold_name = 'fold' + str(k)
feature_file = os.path.join(load_dir, fold_name + '_x.npy')
labels_file = os.path.join(load_dir, fold_name + '_y.npy')
loaded_features = np.load(feature_file, allow_pickle=True)
loaded_labels = np.load(labels_file, allow_pickle=True)
if k == validation_fold:
val_x,val_y = load_fold(load_dir, fold_name)
elif k == test_fold:
test_x, test_y = load_fold(load_dir, fold_name)
else:
features, labels = load_fold(load_dir, fold_name)
train_x = np.concatenate((train_x, features))
train_y = np.append(train_y, labels)
print("val_x shape: ", val_x.shape)
print("test_x shape: ", test_x.shape)
print("train_x shape: ", train_x.shape)
print("val_y shape: ", val_y.shape)
print("test_y shape: ", test_y.shape)
print("train_y shape: ", train_y.shape)
return train_x, test_x, val_x, train_y, test_y, val_y
def load_fold(load_dir, fold_name):
features_file = os.path.join(load_dir, fold_name + "_x.npy")
labels_file = os.path.join(load_dir, fold_name + "_y.npy")
features = np.load(features_file, allow_pickle=True)
labels = np.load(labels_file, allow_pickle=True)
return features, labels
def assure_path_exists(path):
# checks if path exists, if it dosen't it is created
mydir = os.path.join(os.getcwd(), path)
if not os.path.exists(mydir):
os.makedirs(mydir)
return