Mercurial > hg > camir-aes2014
diff core/magnatagatune/MTTTagFeatureGenreBasic.m @ 0:e9a9cd732c1e tip
first hg version after svn
author | wolffd |
---|---|
date | Tue, 10 Feb 2015 15:05:51 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/magnatagatune/MTTTagFeatureGenreBasic.m Tue Feb 10 15:05:51 2015 +0000 @@ -0,0 +1,218 @@ +classdef MTTTagFeatureGenreBasic < MTTAudioFeature & handle + + + properties(Constant = true) + + my_revision = str2double(substr('$Rev: 99 $', 5, -1)); + end + + % --- + % here come the internal clip properties. + % the database is stored as a global variable + % --- + properties + + my_params = struct(... + ... % --- + ... % these are GenreBasic parameters + ... % --- + 'pct_genres', 1, ... % 1/100 percentile genre tags used + 'empty_genres', 0 ... % allow empty genres to persist + ); + end + + methods + + % --- + % constructor: pointer to feature in database + % --- + function feature = MTTTagFeatureGenreBasic(varargin) + + feature = feature@MTTAudioFeature(varargin{:}); + end + + function data = extract(feature, clip) + % process tag information and build the tag vector + + % --- + % get total number of tags. + % + % NOTE: the highest tag id should match the size of the + % tagdb lexicon + % --- +% num_tags = clip.my_db.genredb.size(); + + if feature.my_params.pct_genres ~= 0 + % no tags, f.e. for parameter experiments in + % higher level features + [tagids, score] = clip.my_db.genredb.annotids_for_owner(clip.id); + + % save lexicon + data.lexicon = clip.my_db.genredb.lexicon; + + % save to data structure + data.tags.ids = tagids; + data.tags.scores = score; + end + + % save info data + data.info.type = 'MTTTagFeatureGenreBasic'; + data.info.owner = clip; + data.info.owner_id = clip.id; + data.info.creatorrev = feature.my_revision; + + % save parameters + data.info.params = feature.my_params; + + data.final.vector = []; + data.final.vector_info = struct(); + data.final.dim = 0; + end + + + % --- + % NOTE: the following transforms are just stated fro + % future use by now + % --- + function define_global_transform(features) + % --- + % compute the relevant tags, and save + % them in the commom place + % --- + + % compute extreme cases + if features(1).my_params.pct_genres == 1 && features(1).my_params.empty_genres + % all tags allowed + + common.rel_dimensions.tags.ids = 1:numel(features(1).data.lexicon); + common.rel_dimensions.tags.id_pos = 1:numel(features(1).data.lexicon); + + % set common feature values + features(1).my_db.set_common(common); + return; + + elseif features(1).my_params.pct_genres == 0 + % no tags, f.e. for parameter experiments in + % higher level features + + common.rel_dimensions.tags.ids = []; + common.rel_dimensions.tags.id_pos = []; + + % set common feature values + features(1).my_db.set_common(common); + return; + end + + + allids = sparse(numel(features), numel(features(1).data.lexicon)); + for i = 1:numel(features) + + allids(i,features(i).data.tags.ids) = ... + allids(i,features(i).data.tags.ids) + features(i).data.tags.scores; + end + + % --- + % get usage of tags and filter not-used tags + % --- + tagsum = sum(allids, 1); + nonzero = tagsum > 0; + + % --- + % NOTE: We remove the empty genres, then + % sort by weight / number of appearance and cut off + ids = find(nonzero); + [null, idx] = sort(tagsum(ids),'descend'); + ids = ids(idx); + + % cutoff + num_tags = ceil( features(1).my_params.pct_genres * numel(ids)); + valid_ids = ids(1:min(end, num_tags)); + + % --- + % NOTE: make sure that the positions for the tags + % stay correctly assigned / consistent + % --- + id_pos = sparse(size(valid_ids)); + id_pos(valid_ids) = 1:num_tags; + + % save to common data structure + common.rel_dimensions.tags.ids = valid_ids; + common.rel_dimensions.tags.id_pos = id_pos; + + % set common feature values + features(1).my_db.set_common(common); + end + + function finalise(features) + + for i = 1:numel(features) + + % check for neccesary parameters + if isempty(features(i).my_db.commondb) + + error('Define the global transformation first') + return; + end + + if features(i).my_params.pct_genres == 0 + vector_info.labels = {}; + + % save into feature struct + features(i).data.final.dim = 0; + features(i).data.final.vector = []; + features(i).data.final.vector_info = vector_info; + return; + end + % get valid tag ids + valid_ids = features(i).common.rel_dimensions.tags.ids; + num_tags = numel(valid_ids); + + % --- + % get vector positions for contined ids, + % and sort out the non_allowed id's + % --- + id_pos = features(i).common.rel_dimensions.tags.id_pos; + + [has_ids, has_pos] = intersect(features(i).data.tags.ids, valid_ids); + + score = features(i).data.tags.scores; + + % create feature vector + vector = zeros(num_tags,1); + vector(id_pos(has_ids)) = score(has_pos); + + % --- + % NOTE: this labelling costs to much space + % --- + vector_info.labels = features(i).data.lexicon(valid_ids); + + % save into feature struct + features(i).data.final.dim = num_tags; + features(i).data.final.vector = vector; + features(i).data.final.vector_info = vector_info; + end + end + + function [a1] = visualise(feature) + + % get tag descriptions form first clip + tags = MTTClip(feature(1).owner_id()).my_db.genres; + + % works for multiple feature instances + for i = 1:numel(feature) + + clip = MTTClip(feature(i).owner_id()); + + % plot feature data + h = bar(feature(i).data.final.vector); + a1 = gca; + + set(a1,'XTick', 1:feature(i).data.final.dim,... + 'XTickLabel', tags); + title(sprintf('clip %d: %s by %s, genres', ... + clip.id, clip.title(),clip.artist())); + end + end + + end +end \ No newline at end of file