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