Browse Source

feat: Update LoudFE & VAFE to not keep adjacent features

Otherwise features tend to cluster
main
Rob Hallam 1 month ago
parent
commit
460819d678
1 changed files with 29 additions and 18 deletions
  1. +29
    -18
      pipeline/feature_extractors.py

+ 29
- 18
pipeline/feature_extractors.py View File

@@ -200,7 +200,7 @@ class LoudAudioFeatureExtractor(FeatureExtractor):

teardown() is used to clean up temporary files created during setup (if specified by config)
"""
_CONFIG_DEFAULT_NUM_FEATURES = 5 # keep the top 5 loudnesses
_CONFIG_DEFAULT_NUM_FEATURES = 15 # keep the top 5 loudnesses
_CONFIG_DEFAULT_MIN_DURATION = 5.00 # seconds
def __init__(self, input_files=None, config=None,
num_features=_CONFIG_DEFAULT_NUM_FEATURES,
@@ -255,28 +255,33 @@ class LoudAudioFeatureExtractor(FeatureExtractor):

return loudness_features

def _keep_num(self, features, num=_CONFIG_DEFAULT_NUM_FEATURES) -> list:
def _keep_num(self, features, num=_CONFIG_DEFAULT_NUM_FEATURES, margin=10.0) -> list:
"""Keep the top n features (default: 5)

Approach:
- for range in 0-n
+ expand the nth top feature to min duration
(move start back by 0.5*min_duration, end forward by 0.5*min_duration)
+ drop any features that are now in that feature's range
+ drop any features that are now in that feature's range (plus margin)
- return the top n features

Each feature is a Feature object, with an Interval object
"""
keep_features = []
# ensure features are sorted by score
features = sorted(features, key=lambda x: x.score, reverse=True)
for i in range(num):
current_feature = features.pop(0)
# expand the feature to min_duration
features[i].interval.move_start(-0.5*self._min_duration, relative=True)
features[i].interval.move_end(0.5*self._min_duration, relative=True)
# drop any features that are now in that feature's range
current_feature.interval.move_start(-0.5*self._min_duration, relative=True)
current_feature.interval.move_end(0.5*self._min_duration, relative=True)
keep_features.append(current_feature)
# drop any features that are now in that feature's range (plus margin)
features = [f for f in features if
f.interval.start < features[i].interval.start or
f.interval.end > features[i].interval.end]
(f.interval.end < current_feature.interval.start-margin or
f.interval.start > current_feature.interval.end+margin)]

return features[:num]
return keep_features

def setup(self):
"""extract audio from video files to be processed by pyloudnorm
@@ -322,7 +327,7 @@ class VideoActivityFeatureExtractor(FeatureExtractor):

#TODO: minimum duration -- consider whether to do here, or expand duration post-consolidation
"""
_CONFIG_DEFAULT_NUM_FEATURES = 5 # keep the top 5 activity moments
_CONFIG_DEFAULT_NUM_FEATURES = 15 # keep the top 5 activity moments
_CONFIG_DEFAULT_MIN_DURATION = 5.00 # seconds
def __init__(self, input_files=None, config=None,
num_features=_CONFIG_DEFAULT_NUM_FEATURES,
@@ -379,28 +384,34 @@ class VideoActivityFeatureExtractor(FeatureExtractor):
scores = sorted(scores, key=lambda x: x[1], reverse=True)
return scores[:int(len(scores) * (percent / 100))]

def _keep_num(self, features, num=_CONFIG_DEFAULT_NUM_FEATURES) -> list:
def _keep_num(self, features, num=_CONFIG_DEFAULT_NUM_FEATURES, margin=10.0) -> list:
"""Keep the top n features (default: 5)

Approach:
- for range in 0-n
+ expand the nth top feature to min duration
(move start back by 0.5*min_duration, end forward by 0.5*min_duration)
+ drop any features that are now in that feature's range
+ drop any features that are now in that feature's range (plus margin)
- return the top n features

Each feature is a Feature object, with an Interval object
"""
keep_features = []
# ensure features are sorted by score
features = sorted(features, key=lambda x: x.score, reverse=True)
for i in range(num):
current_feature = features.pop(0)
# expand the feature to min_duration
features[i].interval.move_start(-0.5*self._min_duration, relative=True)
features[i].interval.move_end(0.5*self._min_duration, relative=True)
# drop any features that are now in that feature's range
current_feature.interval.move_start(-0.5*self._min_duration, relative=True)
current_feature.interval.move_end(0.5*self._min_duration, relative=True)
keep_features.append(current_feature)
# drop any features that are now in that feature's range (plus margin)
features = [f for f in features if
f.interval.start < features[i].interval.start or
f.interval.end > features[i].interval.end]
(f.interval.end < current_feature.interval.start-margin or
f.interval.start > current_feature.interval.end+margin)]

return keep_features

return features[:num]

def setup(self):
pass


Loading…
Cancel
Save