mitian@17: #!/usr/bin/env python mitian@17: # encoding: utf-8 mitian@17: """ mitian@17: HSeg.py mitian@17: mitian@17: Created by mi tian on 2015-08-14. mitian@17: Copyright (c) 2015 __MyCompanyName__. All rights reserved. mitian@17: """ mitian@17: mitian@17: import sys, os, optparse, csv mitian@17: from itertools import combinations mitian@17: from os.path import join, isdir, isfile, abspath, dirname, basename, split, splitext mitian@17: from copy import copy mitian@17: mitian@17: import matplotlib mitian@17: matplotlib.use('Agg') mitian@17: import matplotlib.pyplot as plt mitian@17: import matplotlib.gridspec as gridspec mitian@17: import numpy as np mitian@17: import scipy as sp mitian@17: from scipy.signal import correlate2d, convolve2d, filtfilt, resample mitian@17: from scipy.ndimage.filters import * mitian@17: from scipy.ndimage.interpolation import zoom mitian@17: from sklearn.decomposition import PCA mitian@17: from sklearn.mixture import GMM mitian@17: from sklearn.cluster import KMeans mitian@17: from sklearn.preprocessing import normalize mitian@17: from sklearn.metrics.pairwise import pairwise_distances mitian@17: mitian@17: # Load dependencies mitian@17: from utils.SegUtil import getMean, getStd, getDelta, getSSM, reduceSSM, upSample, normaliseFeature, normaliseArray mitian@17: from utils.PeakPickerUtil import PeakPicker mitian@17: from utils.gmmdist import * mitian@17: from utils.GmmMetrics import GmmDistance mitian@17: from utils.RankClustering import rClustering mitian@17: from utils.kmeans import Kmeans mitian@17: mitian@17: # Using the novelty based (Tian) boundary retrieval method mitian@17: import novelty as novelty_S mitian@17: import sf as sf_S mitian@17: import cnmf as cnmf_S mitian@17: mitian@17: # Algorithm params mitian@17: h = 8 # Size of median filter for features in C-NMF mitian@17: R = 15 # Size of the median filter for the activation matrix C-NMF mitian@17: rank = 4 # Rank of decomposition for the boundaries mitian@17: rank_labels = 6 # Rank of decomposition for the labels mitian@17: R_labels = 6 # Size of the median filter for the labels mitian@17: # Foote mitian@17: M = 2 # Median filter for the audio features (in beats) mitian@17: Mg = 32 # Gaussian kernel size mitian@17: L = 16 # Size of the median filter for the adaptive threshold mitian@17: # 2D-FMC mitian@17: N = 8 # Size of the fixed length segments (for 2D-FMC) mitian@17: mitian@17: # Define arg parser mitian@17: def parse_args(): mitian@17: op = optparse.OptionParser() mitian@17: # IO options mitian@17: op.add_option('-f', '--features1', action="store", dest="F1", default='/Users/mitian/Documents/experiments/mit/features/gammatonegram_fft/qupujicheng/2048_1024', type="str", help="Loading features from.." ) mitian@17: op.add_option('-e', '--features2', action="store", dest="F2", default='/Users/mitian/Documents/experiments/mit/features/gammatonegram_fft/qupujicheng/2048_1024', type="str", help="Loading features from.." ) mitian@17: op.add_option('-a', '--annotations', action="store", dest="GT", default='/Volumes/c4dm-03/people/mit/annotation/qupujicheng/lowercase', type="str", help="Loading annotation files from.. ") mitian@17: op.add_option('-d', '--dataset', action="store", dest="DATASET", default='qupujicheng', type="str", help="Specify datasets") mitian@17: op.add_option('-o', '--output', action="store", dest="OUTPUT", default=' /Users/mitian/Documents/experiments/mit/gmm/gammatone_fft/qupujicheng', type="str", help="Loading annotation files from.. ") mitian@17: op.add_option('-c', '--cache', action="store", dest="CACHE", default='/Users/mitian/Documents/experiments/mit/gmm/gammatone_fft/qupujicheng', type="str", help="Saving temporary cache files to.. ") mitian@17: op.add_option('-n', '--name', action="store", dest="NAME", default=None, type="str", help="Save output under the name..") mitian@17: mitian@17: # Plot/print/mode options mitian@17: op.add_option('-b', '--boundary-method', action="store_true", dest="BOUNDARY_ALL", default=False, help="Use all boundary method.") mitian@17: op.add_option('-p', '--plot', action="store_true", dest="PLOT", default=False, help="Save plots") mitian@17: op.add_option('-t', '--test-mode', action="store_true", dest="TEST", default=False, help="Test mode") mitian@17: op.add_option('-v', '--verbose-mode', action="store_true", dest="VERBOSE", default=False, help="Print results in verbose mode.") mitian@17: mitian@17: return op.parse_args() mitian@17: options, args = parse_args() mitian@17: mitian@17: class AudioObj(): mitian@17: __slots__ = ['name', 'feature_list', 'gt', 'label', 'features1', 'features2', 'ssm_timestamps'] mitian@17: mitian@17: class EvalObj(): mitian@17: __slots__ = ['TP', 'FP', 'FN', 'P', 'R', 'F', 'AD', 'DA', 'detection'] mitian@17: mitian@17: mitian@17: class Seg(object): mitian@17: '''The main segmentation object''' mitian@17: def __init__(self): mitian@17: self.SampleRate = 44100 mitian@17: self.NqHz = self.SampleRate/2 mitian@17: self.timestamp = [] mitian@17: self.previousSample = 0.0 mitian@17: self.featureWindow = 6.0 mitian@17: self.featureStep = 3.0 mitian@17: self.kernel_size = 100 # Adjust this param according to the feature resolution.pq mitian@17: self.blockSize = 2048 mitian@17: self.stepSize = 1024 mitian@17: mitian@17: '''NOTE: Match the following params with those used for feature extraction!''' mitian@17: mitian@17: '''NOTE: Unlike spectrogram ones, Gammatone features are extracted without taking an FFT. The windowing is done under the purpose of chunking mitian@17: the audio to facilitate the gammatone filtering with the specified blockSize and stepSize. The resulting gammatonegram is aggregated every mitian@17: gammatoneLen without overlap.''' mitian@17: self.gammatoneLen = 2048 mitian@17: self.gammatoneBandGroups = [0, 2, 6, 10, 13, 17, 20] mitian@17: self.nGammatoneBands = 20 mitian@17: self.lowFreq = 100 mitian@17: self.highFreq = self.SampleRate / 4 mitian@17: mitian@17: '''Settings for extracting tempogram features.''' mitian@17: self.tempoWindow = 6.0 mitian@17: self.bpmBands = [30, 45, 60, 80, 100, 120, 180, 240, 400, 600] mitian@17: mitian@17: '''Peak picking settings for novelty based method''' mitian@17: self.threshold = 30 mitian@17: self.confidence_threshold = 0.5 mitian@17: self.delta_threshold = 0.0 mitian@17: self.backtracking_threshold = 1.9 mitian@17: self.polyfitting_on = True mitian@17: self.medfilter_on = True mitian@17: self.LPfilter_on = True mitian@17: self.whitening_on = False mitian@17: self.aCoeffs = [1.0000, -0.5949, 0.2348] mitian@17: self.bCoeffs = [0.1600, 0.3200, 0.1600] mitian@17: self.cutoff = 0.34 mitian@17: self.medianWin = 7 mitian@17: mitian@17: mitian@17: def pairwiseF(self, annotation, detection, tolerance=3.0, combine=1.0, idx2time=None): mitian@17: '''Pairwise F measure evaluation of detection rates.''' mitian@17: mitian@17: res = EvalObj() mitian@17: res.TP, res.FP, res.FN = 0, 0, 0 mitian@17: res.P, res.R, res.F = 0.0, 0.0, 0.0 mitian@17: res.AD, res.DA = 0.0, 0.0 mitian@17: mitian@17: if len(detection) == 0: mitian@17: return res mitian@18: mitian@17: if idx2time != None: mitian@17: # Map detected idxs to real time mitian@17: detection.sort() mitian@17: if detection[-1] >= len(idx2time): mitian@18: detection = detection[:-len(np.array(detection)[np.array(detection)-len(idx2time)>=0])] mitian@17: detection = [idx2time[int(i)] for i in detection] mitian@17: detection = np.append(detection, annotation[-1]) mitian@17: res.detection = detection mitian@18: mitian@17: gt = len(annotation) # Total number of ground truth data points mitian@17: dt = len(detection) # Total number of experimental data points mitian@17: foundIdx = [] mitian@17: D_AD = np.zeros(gt) mitian@17: D_DA = np.zeros(dt) mitian@17: mitian@17: for dtIdx in xrange(dt): mitian@17: D_DA[dtIdx] = np.min(abs(detection[dtIdx] - annotation)) mitian@17: mitian@17: for gtIdx in xrange(gt): mitian@17: D_AD[gtIdx] = np.min(abs(annotation[gtIdx] - detection)) mitian@17: for dtIdx in xrange(dt): mitian@17: if (annotation[gtIdx] >= detection[dtIdx] - tolerance/2.0) and (annotation[gtIdx] <= detection[dtIdx] + tolerance/2.0): mitian@17: foundIdx.append(gtIdx) mitian@17: continue mitian@17: foundIdx = list(set(foundIdx)) mitian@17: res.TP = len(foundIdx) mitian@17: # res.FP = dt - res.TP mitian@17: res.FP = max(0, dt - res.TP) mitian@17: res.FN = gt - res.TP mitian@17: mitian@17: res.AD = np.mean(D_AD) mitian@17: res.DA = np.mean(D_DA) mitian@17: mitian@17: if res.TP == 0: mitian@17: return res mitian@17: mitian@17: res.P = res.TP / float(res.TP+res.FP) mitian@17: res.R = res.TP / float(res.TP+res.FN) mitian@17: res.F = 2 * res.P * res.R / (res.P + res.R) mitian@17: return res mitian@17: mitian@17: def writeVerifiedHeader(self, filename): mitian@17: '''Write header of output files for verified segmentation.''' mitian@17: mitian@17: with open(filename, 'a') as f: mitian@17: csvwriter = csv.writer(f, delimiter=',') mitian@17: csvwriter.writerow(['audio', 'novelty_05_TP', 'novelty_05_FP', 'novelty_05_FN', 'novelty_05_P', 'novelty_05_R', 'novelty_05_F', 'novelty_05_AD', 'novelty_05_DA', 'novelty_3_TP', 'novelty_3_FP', 'novelty_3_FN', 'novelty_3_P', 'novelty_3_R', 'novelty_3_F', 'novelty_3_AD', 'novelty_3_DA',\ mitian@17: 'verified_novelty_05_TP', 'verified_novelty_05_FP', 'verified_novelty_05_FN', 'verified_novelty_05_P', 'verified_novelty_05_R', 'verified_novelty_05_F', 'verified_novelty_05_AD', 'verified_novelty_05_DA', 'verified_novelty_3_TP', 'verified_novelty_3_FP',\ mitian@17: 'gt_verified_3_FN']) mitian@17: mitian@17: def writeVerifiedRes(self, filename, ao_name, novelty_05, novelty_3, verified_novelty_05, verified_novelty_3): mitian@17: '''Write result of single detection for verified segmentation.''' mitian@17: mitian@17: with open(filename, 'a') as f: mitian@17: csvwriter = csv.writer(f, delimiter=',') mitian@17: csvwriter.writerow([ao_name, novelty_05.TP, novelty_05.FP, novelty_05.FN, novelty_05.P, novelty_05.R, novelty_05.F, novelty_05.AD, novelty_05.DA, novelty_3.TP, novelty_3.FP, novelty_3.FN, novelty_3.P, novelty_3.R,\ mitian@17: novelty_3.F, novelty_3.AD, novelty_3.DA, verified_novelty_05.TP, verified_novelty_05.FP, verified_novelty_05.FN, verified_novelty_05.P, verified_novelty_05.R, verified_novelty_05.F, verified_novelty_05.AD, verified_novelty_05.DA, mitian@17: verified_novelty_3.TP, verified_novelty_3.FP, verified_novelty_3.FN, verified_novelty_3.P, verified_novelty_3.R, verified_novelty_3.F, verified_novelty_3.AD, verified_novelty_3.DA]) mitian@17: mitian@17: def localBoundaries(self, bound_idx, feature, confidence, peak_picker, thresh=0.3, tol=3, metric='novelty'): mitian@17: '''Detect local bounderies within fixed-len window around a boudary from the first round detection. mitian@17: args: bound_idx: index of boundary condidate for local inspection mitian@17: feature: an alternative feature for local pairwise distance measuring mitian@17: confidence: a list of confidence values assigned to all boundary candidates. mitian@17: thresh: threshold for boundary confidence mitian@17: tol: window length (L = 2*tol + 1) for extracting local features (unit=s) mitian@17: metric: 'novelty' (default), 'sf', 'cnmf' mitian@17: ''' mitian@17: mitian@17: local_boundaries = [] mitian@17: smoothed_local_novelty = None mitian@17: mitian@17: tol_win = float(tol) / self.stepSize * self.SampleRate mitian@17: mitian@17: if confidence[bound_idx] < thresh: mitian@17: return local_boundaries, smoothed_local_novelty mitian@17: # print 'bound_idx', bound_idx, len(confidence), feature.shape mitian@17: mitian@17: # If the boundary is of high relative confidence, keep it anyway mitian@17: if (1 < bound_idx < len(confidence)-1): mitian@17: if confidence[bound_idx-1] / thresh <= confidence[bound_idx] and confidence[bound_idx-1] / thresh <= confidence[bound_idx]: mitian@17: local_boundaries.append(bound_idx) mitian@17: pre_win = np.max([int(bound_idx-tol_win), 0]) mitian@17: post_win = np.min([int(bound_idx+tol_win), len(confidence)]) mitian@17: mitian@17: local_feature = feature[pre_win: post_win, :] mitian@17: local_ssm = pairwise_distances(local_feature, metric='cosine') mitian@17: mitian@17: if metric == 'novelty': local_novelty, smoothed_local_novelty, local_idxs = novelty_S.process(local_ssm, peak_picker, 48) mitian@17: elif metric == 'sf': nc, local_idxs = sf_S.segmentation(local_ssm) mitian@17: elif metric == 'cnmf': G, local_idxs = cnmf_S.segmentation(local_ssm) mitian@17: mitian@17: if local_idxs: local_idxs += map(lambda x: x+bound_idx, local_idxs) mitian@17: # print local_idxs mitian@17: mitian@17: return list(set(local_idxs)), smoothed_local_novelty mitian@17: mitian@17: def verifyPeaks(self, bound_idx, second_detection, thresh=0.6, tol = 3, second_detection_conf=None): mitian@17: '''Pruning second round detection. mitian@17: args: bound_idx: index of boundary condidate for local inspection mitian@17: second_detection: a list of peaks detected in the second round near a boudary candidates. mitian@17: thresh: confidence threshold for discarding detection mitian@17: second_detection_conf: a list of confidence values assigned to all local peaks. mitian@17: ''' mitian@17: mitian@17: tol_win = float(tol) / self.stepSize * self.SampleRate mitian@17: mitian@17: # Select peak with the highest local confidence mitian@17: if second_detection_conf: mitian@17: if np.max(second_detection_conf) > thresh: mitian@17: verified = bound_idx + np.argmax(second_detection_conf) - tol_win mitian@17: return verified mitian@17: else: mitian@17: return None mitian@17: mitian@17: # Select peak closest to the 1st round detection mitian@17: elif second_detection: mitian@17: # pos = np.argmin(abs(np.array(second_detection)-bound_idx)) mitian@17: pos = int(np.mean(np.where(abs(np.array(second_detection)-bound_idx) == abs(np.array(second_detection)-bound_idx).min())[0])) mitian@17: verified_peak = second_detection[pos] mitian@17: return verified_peak mitian@17: mitian@17: # No peak is secured around bound_idx in the second round verification mitian@17: else: mitian@17: return None mitian@17: mitian@18: def secondRoundDetection(self, peak_candidates, candidates_conf, feature, peak_verifier=None, tol=3, thresh1=0.4, thresh2=0.5): mitian@17: '''Second round detection.''' mitian@17: mitian@17: peaks = [] mitian@17: mitian@17: tol_win = float(tol) / self.stepSize * self.SampleRate mitian@17: for i, x in enumerate(peak_candidates): mitian@18: # Bypass peak candidates with low confidence mitian@18: if candidates_conf[x] < thresh1: continue mitian@17: mitian@18: # If with high confidence, keep it straight mitian@18: if candidates_conf[x] > 0.7: mitian@18: peaks.append(x) mitian@18: continue mitian@18: mitian@18: # 2nd round detection for questionable peaks mitian@17: pre_win = np.max([int(x-tol_win), 0]) mitian@17: post_win = np.min([int(x+tol_win), len(candidates_conf)]) mitian@17: if pre_win == post_win: continue mitian@17: mitian@17: local_feature = feature[pre_win: post_win, :] mitian@17: local_ssm = pairwise_distances(local_feature, metric='cosine') mitian@17: mitian@18: local_conf, local_peaks = novelty_S.process(local_ssm,peak_verifier,100)[-2:] mitian@17: if len(local_peaks)==0: mitian@17: continue mitian@17: mitian@17: local_conf = normaliseArray(local_conf) mitian@17: mitian@17: # Keep the one detected from the 2nd around with the highest confidence as final peak mitian@18: # if np.max(local_conf[local_peaks]) > thresh2: mitian@18: if local_conf[tol_win] >= thresh2: #v2 mitian@17: local_bound = x - tol_win + np.argmax(local_conf) mitian@17: peaks.append(np.rint(local_bound)) mitian@18: mitian@18: # remove very closely located peaks (duplicates from different rounds of detection) mitian@18: mitian@17: peaks.sort() mitian@17: return peaks mitian@17: mitian@17: def process(self): mitian@17: '''Load precomputed features for all audio samples and make segmentation calls.''' mitian@17: mitian@17: # peak_picker for the 1st round boudary detection mitian@17: peak_picker = PeakPicker() mitian@17: peak_picker.params.alpha = 9.0 # Alpha norm mitian@17: peak_picker.params.delta = self.delta_threshold # Adaptive thresholding delta mitian@17: peak_picker.params.QuadThresh_a = (100 - self.threshold) / 1000.0 mitian@17: peak_picker.params.QuadThresh_b = 0.0 mitian@17: peak_picker.params.QuadThresh_c = (100 - self.threshold) / 1500.0 mitian@17: peak_picker.params.rawSensitivity = 20 mitian@17: peak_picker.params.aCoeffs = self.aCoeffs mitian@17: peak_picker.params.bCoeffs = self.bCoeffs mitian@17: peak_picker.params.preWin = self.medianWin mitian@17: peak_picker.params.postWin = self.medianWin + 1 mitian@17: peak_picker.params.LP_on = self.LPfilter_on mitian@17: peak_picker.params.Medfilt_on = self.medfilter_on mitian@17: peak_picker.params.Polyfit_on = self.polyfitting_on mitian@17: peak_picker.params.isMedianPositive = False mitian@17: mitian@17: # peak_picker for the second round boudary verification (might need lower sensitivity) mitian@17: peak_verifier = PeakPicker() mitian@17: peak_verifier.params.alpha = 9.0 # Alpha norm mitian@17: peak_verifier.params.delta = self.delta_threshold # Adaptive thresholding delta mitian@18: peak_verifier.params.QuadThresh_a = (100 - 20) / 1000.0 mitian@17: peak_verifier.params.QuadThresh_b = 0.0 mitian@18: peak_verifier.params.QuadThresh_c = (100 - 20) / 1500.0 mitian@18: peak_verifier.params.rawSensitivity = 20 mitian@17: peak_verifier.params.aCoeffs = self.aCoeffs mitian@17: peak_verifier.params.bCoeffs = self.bCoeffs mitian@18: peak_verifier.params.preWin = 20 mitian@18: peak_verifier.params.postWin = 20 + 1 mitian@17: peak_verifier.params.LP_on = self.LPfilter_on mitian@17: peak_verifier.params.Medfilt_on = self.medfilter_on mitian@17: peak_verifier.params.Polyfit_on = self.polyfitting_on mitian@17: peak_verifier.params.isMedianPositive = False mitian@17: mitian@17: # Getting aggregated features. mitian@17: featureRate = float(self.SampleRate) / self.stepSize mitian@17: aggregation_window, aggregation_step = 20, 10 mitian@18: tempo_step = 0.204995725 * featureRate mitian@18: mitian@17: audio_files = [x for x in os.listdir(options.GT) if not x.startswith(".") ] mitian@17: audio_files.sort() mitian@17: if options.TEST: mitian@18: audio_files = audio_files[:2] mitian@17: audio_list = [] mitian@17: mitian@17: # Use mfccs feature 1st round segmentation (coarse) mitian@18: feature_list1 =['mfcc_harmonic'] mitian@18: # feature_list1 = ['ti_15_30_4_03_05', 'tir_15_30_4_03_05'] mitian@17: feature_list1 = [join(options.F1, f) for f in feature_list1] mitian@18: # feature_list2 = ['gt_stft_lpc'] mitian@18: feature_list2 = ['chromagram_harmonic'] mitian@17: feature_list2 = [join(options.F2, f) for f in feature_list2] mitian@17: mitian@17: # Prepare output files. mitian@18: outfile1 = join(options.OUTPUT, 'tbhm_verified_novelty_tol1th103th205_07_v2.csv') mitian@17: self.writeVerifiedHeader(outfile1) mitian@17: mitian@17: # For each audio file, load specific features mitian@17: for audio in audio_files: mitian@17: ao = AudioObj() mitian@17: ao.name = splitext(audio)[0] mitian@17: mitian@17: # Load annotations for specified audio collection. mitian@17: if options.DATASET == 'qupujicheng': mitian@17: annotation_file = join(options.GT, ao.name+'.csv') # qupujicheng mitian@17: ao.gt = np.genfromtxt(annotation_file, usecols=0, delimiter=',') mitian@17: ao.label = np.genfromtxt(annotation_file, usecols=1, delimiter=',', dtype=str) mitian@17: elif options.DATASET == 'salami': mitian@17: annotation_file = join(options.GT, ao.name+'.txt') # iso, salami mitian@17: ao.gt = np.genfromtxt(annotation_file, usecols=0) mitian@17: ao.label = np.genfromtxt(annotation_file, usecols=1, dtype=str) mitian@17: else: mitian@17: annotation_file = join(options.GT, ao.name+'.lab') # beatles mitian@17: ao.gt = np.genfromtxt(annotation_file, usecols=(0,1)) mitian@17: ao.gt = np.unique(np.ndarray.flatten(ao.gt)) mitian@17: ao.label = np.genfromtxt(annotation_file, usecols=2, dtype=str) mitian@17: mitian@17: featureset1, featureset2 = [], [] mitian@17: # Features for 1st round segmentation mitian@17: for feature in feature_list1: mitian@17: for f in os.listdir(feature): mitian@17: if f[:f.find('_vamp')]==ao.name: mitian@18: ao.ssm_timestamps = np.genfromtxt(join(feature, f), delimiter=',',filling_values=0.0)[1:,0] mitian@18: featureset1.append(np.genfromtxt(join(feature, f), delimiter=',',filling_values=0.0)[1:,1:14]) mitian@17: break mitian@17: if len(feature_list1) > 1: mitian@17: n_frame = np.min([x.shape[0] for x in featureset1]) mitian@17: featureset1 = [x[:n_frame,:] for x in featureset1] mitian@17: ao.features1 = np.hstack((featureset1)) mitian@17: else: mitian@17: ao.features1 = featureset1[0] mitian@17: mitian@18: # ao.ssm_timestamps = np.arange(0, ao.gt[-1], float(self.stepSize)/self.SampleRate) mitian@17: mitian@17: # Features for 2nd round verification mitian@17: for feature in feature_list2: mitian@17: for f in os.listdir(feature): mitian@17: if f[:f.find('_vamp')]==ao.name: mitian@18: featureset2.append(np.genfromtxt(join(feature, f), delimiter=',',filling_values=0.0)[:,1:14]) mitian@17: break mitian@17: if len(feature_list2) > 1: mitian@17: n_frame = np.min([x.shape[0] for x in featureset2]) mitian@17: featureset2 = [x[:n_frame,:] for x in featureset2] mitian@17: ao.features2 = np.hstack((featureset2)) mitian@17: else: mitian@17: ao.features2 = featureset2[0] mitian@17: mitian@17: mitian@17: pca = PCA(n_components=6) mitian@17: mitian@17: # Normalise features. mitian@17: # Note that tempogram features are extracted from a different stepsize as the others. mitian@17: step = ao.features1.shape[0] / aggregation_step mitian@17: ao.features1 = resample(ao.features1, step) mitian@17: ao.features1 = normaliseFeature(ao.features1) mitian@18: ao.features2 = normaliseFeature(ao.features2) mitian@17: mitian@17: pca.fit(ao.features1) mitian@17: ao.features1 = pca.transform(ao.features1) mitian@18: pca.fit(ao.features2) mitian@18: ao.features2 = pca.transform(ao.features2) mitian@18: mitian@18: mitian@17: ssm1 = getSSM(ao.features1) mitian@17: mitian@17: ssm1_timestamps = ao.ssm_timestamps[::aggregation_step] mitian@18: mitian@17: # Take care with this! It gains memory pressure when processing large dataset. mitian@17: # audio_list.append(ao) mitian@17: mitian@17: # Segment the music at a coarse scale mitian@17: # Within the neighborhood of each peak candidate, verify the boundary location at a finer scale. mitian@17: novelty, smoothed_novelty, novelty_idxs = novelty_S.process(ssm1, peak_picker, self.kernel_size) mitian@17: mitian@17: novelty_05 = self.pairwiseF(ao.gt, novelty_idxs, tolerance=0.5, combine=1.0, idx2time=ssm1_timestamps) mitian@17: novelty_3 = self.pairwiseF(ao.gt, novelty_idxs, tolerance=3, combine=1.0, idx2time=ssm1_timestamps) mitian@17: mitian@17: # Verification using different features at a finer scale. mitian@17: # Map to the orginal time scale mitian@17: peak_candidates = np.array(map(lambda x: int(np.rint(x*aggregation_step)), novelty_idxs)) mitian@18: # peak_candidates = np.array(map(lambda x: int((np.rint(x*tempo_step))), novelty_idxs)) mitian@18: mitian@17: peak_conf = normaliseArray(smoothed_novelty) mitian@17: if options.VERBOSE: mitian@17: np.savetxt(join(options.CACHE, ao.name+'-sn-raw.txt'), np.array(zip(ssm1_timestamps, peak_conf)), delimiter=',') mitian@17: peak_conf = zoom(peak_conf, aggregation_step) mitian@18: # peak_conf = zoom(peak_conf, tempo_step) mitian@17: peak_candidates = peak_candidates[:len(peak_conf)] mitian@17: mitian@18: verified_novelty_idxs = self.secondRoundDetection(peak_candidates, peak_conf, ao.features2, peak_verifier, tol=1, thresh1=0.3, thresh2=0.5) mitian@17: verified_novelty_idxs = list(set(verified_novelty_idxs)) mitian@17: mitian@17: verified_novelty_05 = self.pairwiseF(ao.gt, verified_novelty_idxs, tolerance=0.5, combine=1.0, idx2time=ao.ssm_timestamps) mitian@17: verified_novelty_3 = self.pairwiseF(ao.gt, verified_novelty_idxs, tolerance=3, combine=1.0, idx2time=ao.ssm_timestamps) mitian@17: mitian@17: # Write results. mitian@17: self.writeVerifiedRes(outfile1, ao.name, novelty_05, novelty_3, verified_novelty_05, verified_novelty_3) mitian@17: mitian@17: if options.VERBOSE: mitian@17: print ao.name, novelty_3.TP, novelty_3.FP, novelty_3.FN, novelty_3.P, novelty_3.R, novelty_3.F, verified_novelty_3.TP, verified_novelty_3.FP, verified_novelty_3.FN, verified_novelty_3.P, verified_novelty_3.R, verified_novelty_3.F mitian@17: np.savetxt(join(options.CACHE, ao.name+'-raw.txt'), novelty_3.detection, delimiter=',') mitian@17: np.savetxt(join(options.CACHE, ao.name+'-verified.txt'), verified_novelty_3.detection, delimiter=',') mitian@17: mitian@17: def main(): mitian@17: segmenter = Seg() mitian@17: segmenter.process() mitian@17: mitian@17: mitian@17: if __name__ == '__main__': mitian@17: main() mitian@17: