annotate 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
rev   line source
wolffd@0 1 classdef MTTTagFeatureGenreBasic < MTTAudioFeature & handle
wolffd@0 2
wolffd@0 3
wolffd@0 4 properties(Constant = true)
wolffd@0 5
wolffd@0 6 my_revision = str2double(substr('$Rev: 99 $', 5, -1));
wolffd@0 7 end
wolffd@0 8
wolffd@0 9 % ---
wolffd@0 10 % here come the internal clip properties.
wolffd@0 11 % the database is stored as a global variable
wolffd@0 12 % ---
wolffd@0 13 properties
wolffd@0 14
wolffd@0 15 my_params = struct(...
wolffd@0 16 ... % ---
wolffd@0 17 ... % these are GenreBasic parameters
wolffd@0 18 ... % ---
wolffd@0 19 'pct_genres', 1, ... % 1/100 percentile genre tags used
wolffd@0 20 'empty_genres', 0 ... % allow empty genres to persist
wolffd@0 21 );
wolffd@0 22 end
wolffd@0 23
wolffd@0 24 methods
wolffd@0 25
wolffd@0 26 % ---
wolffd@0 27 % constructor: pointer to feature in database
wolffd@0 28 % ---
wolffd@0 29 function feature = MTTTagFeatureGenreBasic(varargin)
wolffd@0 30
wolffd@0 31 feature = feature@MTTAudioFeature(varargin{:});
wolffd@0 32 end
wolffd@0 33
wolffd@0 34 function data = extract(feature, clip)
wolffd@0 35 % process tag information and build the tag vector
wolffd@0 36
wolffd@0 37 % ---
wolffd@0 38 % get total number of tags.
wolffd@0 39 %
wolffd@0 40 % NOTE: the highest tag id should match the size of the
wolffd@0 41 % tagdb lexicon
wolffd@0 42 % ---
wolffd@0 43 % num_tags = clip.my_db.genredb.size();
wolffd@0 44
wolffd@0 45 if feature.my_params.pct_genres ~= 0
wolffd@0 46 % no tags, f.e. for parameter experiments in
wolffd@0 47 % higher level features
wolffd@0 48 [tagids, score] = clip.my_db.genredb.annotids_for_owner(clip.id);
wolffd@0 49
wolffd@0 50 % save lexicon
wolffd@0 51 data.lexicon = clip.my_db.genredb.lexicon;
wolffd@0 52
wolffd@0 53 % save to data structure
wolffd@0 54 data.tags.ids = tagids;
wolffd@0 55 data.tags.scores = score;
wolffd@0 56 end
wolffd@0 57
wolffd@0 58 % save info data
wolffd@0 59 data.info.type = 'MTTTagFeatureGenreBasic';
wolffd@0 60 data.info.owner = clip;
wolffd@0 61 data.info.owner_id = clip.id;
wolffd@0 62 data.info.creatorrev = feature.my_revision;
wolffd@0 63
wolffd@0 64 % save parameters
wolffd@0 65 data.info.params = feature.my_params;
wolffd@0 66
wolffd@0 67 data.final.vector = [];
wolffd@0 68 data.final.vector_info = struct();
wolffd@0 69 data.final.dim = 0;
wolffd@0 70 end
wolffd@0 71
wolffd@0 72
wolffd@0 73 % ---
wolffd@0 74 % NOTE: the following transforms are just stated fro
wolffd@0 75 % future use by now
wolffd@0 76 % ---
wolffd@0 77 function define_global_transform(features)
wolffd@0 78 % ---
wolffd@0 79 % compute the relevant tags, and save
wolffd@0 80 % them in the commom place
wolffd@0 81 % ---
wolffd@0 82
wolffd@0 83 % compute extreme cases
wolffd@0 84 if features(1).my_params.pct_genres == 1 && features(1).my_params.empty_genres
wolffd@0 85 % all tags allowed
wolffd@0 86
wolffd@0 87 common.rel_dimensions.tags.ids = 1:numel(features(1).data.lexicon);
wolffd@0 88 common.rel_dimensions.tags.id_pos = 1:numel(features(1).data.lexicon);
wolffd@0 89
wolffd@0 90 % set common feature values
wolffd@0 91 features(1).my_db.set_common(common);
wolffd@0 92 return;
wolffd@0 93
wolffd@0 94 elseif features(1).my_params.pct_genres == 0
wolffd@0 95 % no tags, f.e. for parameter experiments in
wolffd@0 96 % higher level features
wolffd@0 97
wolffd@0 98 common.rel_dimensions.tags.ids = [];
wolffd@0 99 common.rel_dimensions.tags.id_pos = [];
wolffd@0 100
wolffd@0 101 % set common feature values
wolffd@0 102 features(1).my_db.set_common(common);
wolffd@0 103 return;
wolffd@0 104 end
wolffd@0 105
wolffd@0 106
wolffd@0 107 allids = sparse(numel(features), numel(features(1).data.lexicon));
wolffd@0 108 for i = 1:numel(features)
wolffd@0 109
wolffd@0 110 allids(i,features(i).data.tags.ids) = ...
wolffd@0 111 allids(i,features(i).data.tags.ids) + features(i).data.tags.scores;
wolffd@0 112 end
wolffd@0 113
wolffd@0 114 % ---
wolffd@0 115 % get usage of tags and filter not-used tags
wolffd@0 116 % ---
wolffd@0 117 tagsum = sum(allids, 1);
wolffd@0 118 nonzero = tagsum > 0;
wolffd@0 119
wolffd@0 120 % ---
wolffd@0 121 % NOTE: We remove the empty genres, then
wolffd@0 122 % sort by weight / number of appearance and cut off
wolffd@0 123 ids = find(nonzero);
wolffd@0 124 [null, idx] = sort(tagsum(ids),'descend');
wolffd@0 125 ids = ids(idx);
wolffd@0 126
wolffd@0 127 % cutoff
wolffd@0 128 num_tags = ceil( features(1).my_params.pct_genres * numel(ids));
wolffd@0 129 valid_ids = ids(1:min(end, num_tags));
wolffd@0 130
wolffd@0 131 % ---
wolffd@0 132 % NOTE: make sure that the positions for the tags
wolffd@0 133 % stay correctly assigned / consistent
wolffd@0 134 % ---
wolffd@0 135 id_pos = sparse(size(valid_ids));
wolffd@0 136 id_pos(valid_ids) = 1:num_tags;
wolffd@0 137
wolffd@0 138 % save to common data structure
wolffd@0 139 common.rel_dimensions.tags.ids = valid_ids;
wolffd@0 140 common.rel_dimensions.tags.id_pos = id_pos;
wolffd@0 141
wolffd@0 142 % set common feature values
wolffd@0 143 features(1).my_db.set_common(common);
wolffd@0 144 end
wolffd@0 145
wolffd@0 146 function finalise(features)
wolffd@0 147
wolffd@0 148 for i = 1:numel(features)
wolffd@0 149
wolffd@0 150 % check for neccesary parameters
wolffd@0 151 if isempty(features(i).my_db.commondb)
wolffd@0 152
wolffd@0 153 error('Define the global transformation first')
wolffd@0 154 return;
wolffd@0 155 end
wolffd@0 156
wolffd@0 157 if features(i).my_params.pct_genres == 0
wolffd@0 158 vector_info.labels = {};
wolffd@0 159
wolffd@0 160 % save into feature struct
wolffd@0 161 features(i).data.final.dim = 0;
wolffd@0 162 features(i).data.final.vector = [];
wolffd@0 163 features(i).data.final.vector_info = vector_info;
wolffd@0 164 return;
wolffd@0 165 end
wolffd@0 166 % get valid tag ids
wolffd@0 167 valid_ids = features(i).common.rel_dimensions.tags.ids;
wolffd@0 168 num_tags = numel(valid_ids);
wolffd@0 169
wolffd@0 170 % ---
wolffd@0 171 % get vector positions for contined ids,
wolffd@0 172 % and sort out the non_allowed id's
wolffd@0 173 % ---
wolffd@0 174 id_pos = features(i).common.rel_dimensions.tags.id_pos;
wolffd@0 175
wolffd@0 176 [has_ids, has_pos] = intersect(features(i).data.tags.ids, valid_ids);
wolffd@0 177
wolffd@0 178 score = features(i).data.tags.scores;
wolffd@0 179
wolffd@0 180 % create feature vector
wolffd@0 181 vector = zeros(num_tags,1);
wolffd@0 182 vector(id_pos(has_ids)) = score(has_pos);
wolffd@0 183
wolffd@0 184 % ---
wolffd@0 185 % NOTE: this labelling costs to much space
wolffd@0 186 % ---
wolffd@0 187 vector_info.labels = features(i).data.lexicon(valid_ids);
wolffd@0 188
wolffd@0 189 % save into feature struct
wolffd@0 190 features(i).data.final.dim = num_tags;
wolffd@0 191 features(i).data.final.vector = vector;
wolffd@0 192 features(i).data.final.vector_info = vector_info;
wolffd@0 193 end
wolffd@0 194 end
wolffd@0 195
wolffd@0 196 function [a1] = visualise(feature)
wolffd@0 197
wolffd@0 198 % get tag descriptions form first clip
wolffd@0 199 tags = MTTClip(feature(1).owner_id()).my_db.genres;
wolffd@0 200
wolffd@0 201 % works for multiple feature instances
wolffd@0 202 for i = 1:numel(feature)
wolffd@0 203
wolffd@0 204 clip = MTTClip(feature(i).owner_id());
wolffd@0 205
wolffd@0 206 % plot feature data
wolffd@0 207 h = bar(feature(i).data.final.vector);
wolffd@0 208 a1 = gca;
wolffd@0 209
wolffd@0 210 set(a1,'XTick', 1:feature(i).data.final.dim,...
wolffd@0 211 'XTickLabel', tags);
wolffd@0 212 title(sprintf('clip %d: %s by %s, genres', ...
wolffd@0 213 clip.id, clip.title(),clip.artist()));
wolffd@0 214 end
wolffd@0 215 end
wolffd@0 216
wolffd@0 217 end
wolffd@0 218 end