def _preprocess(self, reference, hypothesis): if not isinstance(reference, Annotation): raise TypeError('reference must be an instance of `Annotation`') if isinstance(hypothesis, Annotation): hypothesis = hypothesis.get_timeline() # reference where short intra-label gaps are removed filled = Timeline() for label in reference.labels(): label_timeline = reference.label_timeline(label) for gap in label_timeline.gaps(): if gap.duration < self.tolerance: label_timeline.add(gap) for segment in label_timeline.coverage(): filled.add(segment) # reference coverage after filling gaps coverage = filled.coverage() reference_partition = self._partition(filled, coverage) hypothesis_partition = self._partition(hypothesis, coverage) return reference_partition, hypothesis_partition
def _get_collar(self, reference, duration): # initialize empty timeline collar = Timeline(uri=reference.uri) if duration == 0.: return collar # iterate over all segments in reference for segment in reference.itersegments(): # add collar centered on start time t = segment.start collar.add(Segment(t - .5 * duration, t + .5 * duration)) # add collar centered on end time t = segment.end collar.add(Segment(t - .5 * duration, t + .5 * duration)) # merge overlapping collars and return return collar.coverage()
def run(self): # wav file duration wav = self.in_wav().path with contextlib.closing(wave.open(wav, 'r')) as f: frames = f.getnframes() rate = f.getframerate() duration = frames / rate extent = Segment(0., duration) with self.in_speaker().open('r') as fp: speaker = pyannote.core.json.load(fp) timeline = Timeline() for segment, _ in speaker.itertracks(): timeline.add(segment) # fill gaps for gap in timeline.gaps(extent): if gap.duration < self.fill_gaps: timeline.add(gap) timeline = timeline.coverage() # dump as annotation... if self.to_annotation: annotation = Annotation() for s, segment in enumerate(timeline): annotation[segment] = s annotation = annotation.anonymize_labels(generator='string') with self.out_put().open('w') as fp: pyannote.core.json.dump(annotation, fp) # ... or as timeline else: with self.out_put().open('w') as fp: pyannote.core.json.dump(timeline, fp)
def apply(self, predictions, dimension=0): """ Parameters ---------- predictions : SlidingWindowFeature Must be mono-dimensional dimension : int, optional Which dimension to process """ if len(predictions.data.shape) == 1: data = predictions.data elif predictions.data.shape[1] == 1: data = predictions.data[:, 0] else: data = predictions.data[:, dimension] n_samples = predictions.getNumber() window = predictions.sliding_window timestamps = [window[i].middle for i in range(n_samples)] # initial state start = timestamps[0] label = data[0] > self.onset # timeline meant to store 'active' segments active = Timeline() for t, y in zip(timestamps[1:], data[1:]): # currently active if label: # switching from active to inactive if y < self.offset: segment = Segment(start - self.pad_onset, t + self.pad_offset) active.add(segment) start = t label = False # currently inactive else: # switching from inactive to active if y > self.onset: start = t label = True # if active at the end, add final segment if label: segment = Segment(start - self.pad_onset, t + self.pad_offset) active.add(segment) # because of padding, some 'active' segments might be overlapping # therefore, we merge those overlapping segments active = active.coverage() # remove short 'active' segments active = Timeline( [s for s in active if s.duration > self.min_duration[1]]) # fill short 'inactive' segments inactive = active.gaps() for s in inactive: if s.duration < self.min_duration[0]: active.add(s) active = active.coverage() return active