Building a KNN classifier with multiple classes that identifies different audio - matlab

I am in the process of building a KNN algorithm with the purpose of identifying and categorizing common engine problems in Matlab. I have been using the builds from the book 'An Introduction To audio Analysis: A Matlab Approach' which contains exactly what I need to continue my experiment. The problem is that when I identify where the audio samples are kept on my computer, the system claims that it gives out the message "audio sample path is not valid!" Below is the original algorithm the authors of the book have supplied
function kNN_model_add_class(modelName, className, classPath, ...
listOfStatistics, stWin, stStep, mtWin, mtStep)
%
% function kNN_model_add_class(modelName, className, classPath, ...
% listOfStatistics, stWin, stStep, mtWin, mtStep)
%
% This function adds an audio class to the kNN classification model
%
% ARGUMENTS;
% - modelName: the filename of the model (mat file)
% - className: the name of the audio class to be added to the model
% - classPath: the path of the directory where the audio segments of the
% new class are stored
% - listOfStatistics: list of mid-term statistics (cell array)
% - stWin, stStep: short-term window size and step
% - mtWin, mtStep: mid-term window size and step
%
% Example:
% kNN_model_add_class('modelSpeech.mat', 'speech', './Music/', ...
% {'mean','std',}, 0.050, 0.025, 2.0, 1.0);
%
if ~exist(classPath,'dir')
error('Audio sample path is not valid!');
else
classPath = [classPath filesep];
end
% check if the model elaready exists:
fp = fopen(modelName, 'r');
if fp>0 % check if file already exists
load(modelName);
end
% Feature extraction:
D = dir([classPath '*.wav']);
F = [];
for (i=1:length(D)) % for each wav file in the given path:
curFileName = [classPath D(i).name];
FileNamesTemp{i} = curFileName;
% mid-term feature extraction for each wav file:
midFeatures = featureExtractionFile(curFileName, ...
stWin, stStep, mtWin, mtStep, listOfStatistics);
% long-term averaging:
longFeatures = mean(midFeatures,2);
F = [F longFeatures];
end
% save the model:
Statistics = listOfStatistics;
fp = fopen(modelName, 'r');
if fp<0 % model does not exist --> generate
ClassNames{1} = className;
Features{1} = F;
FileNames{1} = FileNamesTemp;
save(modelName, 'ClassNames', 'Features', ...
'Statistics', 'stWin', 'stStep', 'mtWin', 'mtStep', 'FileNames');
else
load(modelName);
ClassNames{end+1} = className;
Features{end+1} = F;
FileNames{end+1} = FileNamesTemp;
save(modelName, 'ClassNames', 'Features', ...
'Statistics', 'stWin', 'stStep', 'mtWin', 'mtStep', 'FileNames');
end
Here is the way that I have implemented it into my own project.
%Knn algorithm training
%path to folder containing the audio segements
strDir ='/Users/itsolutions/Documents/MATLAB/Wav_engine_edits ';
%mid-term statistics to be used:
Statistics = {'mean','median','std','stdbymean','max','min'};
%short-term and mid-term, processing windon length and step:
stWin = 0.040; stStep = 0.040;
mtWin = 2.0; mtStep = 1.0;
%perform feature extraction
kNN_model_add_class ('model8.mat','connection rod noise', [ strDir '/Connection_rod_edits/'],Statistics, stWin, stStep, mtWin, mtStep);
kNN_model_add_class ('model8.mat','detonation noise', [strDir ' /Detonation_noise_edits/'],Statistics, stWin, stSteo, mtWin, mtStep)
%kNN_model_add_class ('model8.mat','Engine bearing noise' [strDir '/Engine Bearing Noise edits/'],Statistics, stWin, stStep, mtWin, mtStep);
Any ideas? I have looked into the objects present in the function knn_model_add_class() and have found that it is still using wavread, which in the 2016b version of matlab in invalid syntax now.
Could anyone give me a hand? Seems like I am going in circles and it is something really obvious that i can't see.
Regards
M.Brown
Edit:
Using the process of elimination I have found that the error comes from this piece of code
if ~exist(classPath,'dir')
error('Audio sample path is not valid!');
else
classPath = [classPath filesep];
end
The code cannot seem to find the audio samples in question. I have contacted the author of the book, but until then does anybody know why the matlab file path won't recognize the wav files?

Related

How to do an animate plot in MATLAB from a sequence of matrices

I have code that uses Wolff's Algorithm to simulate the XY Model in MATLAB and I want to implement a pcolor/color map to demonstrate each spin according to their angles across the system. But I want it to be live and changing as the angles change.
Any idea how to do this?
This is an example of how I want it to look https://i.stack.imgur.com/aSp7s.png
If you save each snapshot of the lattice in a cell array A{t}, you can use the following function to view and save it as a video (if fileName is not empty, the function saves an mp4 video).
Another option is to adapt the function view_lattice to run your simulation (which, honestly, I wouldn't recommend, for performance issues). I will mark where you should edit for doing a "live" simulation
This is at least MATLAB R2019b (although it may be compatible with earlier versions, but no guarantee).
File view_lattice.m
function view_lattice(A,fileName)
% for a 'live' simulation, you will have to remove A from the input
% parameters and add the ones you need for the XY Wolff algorithm,
% which will be used to calculate each configuration A in the time loop below
% you will also need to remove the assert statements for 'live' simulation
%
% otherwise, you save snapshots from your simulation
% and use this function as is
%
% A -> A{k}[m,n] snapshot k containing the angles of spins in lattice site at row m and col n
% fileName -> if contains string, then records a video with the snapshots and name it with this string
assert(iscell(A) && all(cellfun(#(a)isnumeric(a) && ismatrix(a),A)),'A must be cell of numeric matrices');
assert(ischar(fileName),'fileName must be either an empty char or contain a file name');
recordVideo = ~isempty(fileName);
if recordVideo
vw = setup_video(fileName);
else
vw = [];
end
% setting some default axis properties to speed-up plotting
set(0,'DefaultAxesPlotBoxAspectRatio',[1 1 1],'DefaultAxesDataAspectRatioMode','manual','DefaultAxesDataAspectRatio',[1,1,1],'DefaultAxesNextPlot','replace');
fh = figure;
ax=axes;
for t = 1:numel(A) % for 'live' simulation, this loop should be the time loop
% here you calculate the new configuration A
% and call the function below with A instead of A{t}
vw = record_frame(vw,fh,ax,A{t},t,recordVideo);
end
% any video to close?
if recordVideo
vw.close();
end
end
function vw = record_frame(vw,fh,ax,A,t,recordVideo)
imagesc(ax,A);
title(ax,sprintf('snapshot %g',t)); % if you want, y
axis(ax,'square');
daspect(ax,[1,1,1]);
pause(0.01);
if recordVideo
vframe = getframe(fh);
vw.writeVideo(vframe);
end
end
function vw = setup_video(fileName)
vid_id = num2str(rand,'%.16g');
vid_id = vid_id(3:6);
vid_id = [fileName,'_',vid_id];
% Initialize video
vw = VideoWriter([vid_id,'.mp4'], 'MPEG-4'); %open video file
vw.Quality = 100;
vw.FrameRate = 16;
vw.open();
end
Test script: test.m
clearvars
close all
A = cell(1,30);
for t = 1:numel(A)
% creating a sequence of random snapshots only for illustration
A{t} = rand(20,20);
end
% viewing the animation and saving it as a video with name test
view_lattice(A,'test');
Output

Loading saved cv.DescriptorMatcher in MATLAB (mexopencv)

I have recently started working in mexopencv and I am new to it. However, I have made a database of keypoints and features of images for ORB and SURF and saved it in a .mat file along with the trained matchers.
Matcher used:
FLANN based matcher (for SURF points)
BruteForce - Hamming (for ORB points)
It works fine if I train the data in the same script and try to find the image from the databse. However, when I try to find the image from the database in another script by loading the keypoints data and the matcher, it fails.
The code for making database is:
%% OPTIONS
SURF_Threshold = 40000;
%% SETUP
SURF = cv.SURF('HessianThreshold', SURF_Threshold);
ORB = cv.ORB;
opts = {'KDTree', 'Trees',5}; %Dictionary required for FLANN
matcherFLANN = cv.DescriptorMatcher('FlannBasedMatcher', 'Index',opts);
matcherBF = cv.DescriptorMatcher('BruteForce-Hamming');
foldername = uigetdir;
oldFolder = cd(foldername);
files = [dir('*.jpg');dir('*.png')]; %Look for jpg files in the directory.
N = size(files,1); %numel the files
%Create empty training sets
trainDataORB = struct('name', cell(N,1), 'pts',cell(N,1), 'feat',cell(N,1));
trainDataSURF = struct('name', cell(N,1), 'pts',cell(N,1), 'feat',cell(N,1));
%% TRAINING
for i=1:N
% read image
img = imread((files(i).name));
%Extracting keypoints and descriptors (features) for both
[trainDataSURF(i).pts, trainDataSURF(i).feat] = SURF.detectAndCompute(img);
[trainDataORB(i).pts, trainDataORB(i).feat] = SURF.detectAndCompute(img);
trainDataSURF(i).name = files(i).name;
trainDataORB(i).name = files(i).name;
% add to training set to match against for each of descriptor
matcherFLANN.add(trainDataSURF(i).feat);
matcherBF.add(trainDataORB(i).feat);
end
% build index
matcherFLANN.train();
matcherBF.train();
%% SAVING DATA
%Navigate back to old folder
cd(oldFolder);
save('training_data.mat', 'matcherFLANN', 'matcherBF', 'trainDataSURF','trainDataORB');
The matcher objects are then loaded with in another scrip (with cleared workspace):
load('training_data.mat');
Which returns the error:
Error using DescriptorMatcher_ Object not found id=109
Error in cv.DescriptorMatcher/match (line 461)
matches = DescriptorMatcher_(this.id, 'match', queryDescriptors, varargin{:});
Error in detection_Test (line 27)
matches = matcherFLANN.match(feat);
Any help would be gladly welcomed.

face recognition using surf features and knn search tree

i have been working on a project on face recognition using surf features and knn search tree using matlab 2014A the problem i am facing is that i am not able to match the results from knn search tree to manually with each file in data base so i can specify which face resembles the sample the most. Can anybody help me how to find the three nearest neighbours in data base?
this is my code
% Combine all features into dataset
i have 128 surf features for each face in database
featureDataset = double(vertcat(imageCollection.featureVectors));
% instantiate a kd tree
imageFeatureKDTree = KDTreeSearcher(featureDataset);
query.wholeImage = imread('F\:trio.jpg');
faceDetector = vision.CascadeObjectDetector();
bbox = step(faceDetector, query.wholeImage)
Out=query.wholeImage;
for k = 1:size(bbox,1)
figure; axesHandle=axes; imshow(query.wholeImage); title('Query Image');
rectangleHandle=imrect(axesHandle,bbox(k,:)) ;
% Consider only selected region
query.image=imcrop(query.wholeImage,getPosition(rectangleHandle));
query.image=rgb2gray(query.image);
% Detect SURF features
query.points = detectSURFFeatures(query.image);
% Extract SURF descriptors
[query.featureVectors,query.points] = ...
extractFeatures(query.image,query.points,'SURFSize',128);
[matches, distance] = knnsearch(imageFeatureKDTree,query.featureVectors,'Distance','euclidean','K',3);
indexIntervals = [0, cumsum([imageCollection.featureCount])] + 1;
counts = histc(matches(:, 1), indexIntervals);
counts1=histc(matches(:, 2), indexIntervals);
counts2=histc(matches(:, 3+), indexIntervals);
if max(counts)==0
disp('No Features Matched')
else
for i = 1:numel(imageCollection) % Scale each image
if (counts(i)==max(counts))
name=srcFiles(i).name;
end
if (counts(i)==max(counts1))
name1=srcFiles(i).name;
end
if (counts(i)==max(counts2))
name2=srcFiles(i).name;
end
end
t1 = strcmpi(name(1:10),name1(1:10));t2=strcmpi(name(1:10),name2(1:10));
t3=strcmpi(name1(1:10),name2(1:10));
if((t1==1)||(t2==1)||(t3==1))
Out = insertObjectAnnotation(Out,'rectangle',bbox(k,:),name(1:length(name)-1));
else if (t3==1)
Out = insertObjectAnnotation(Out,'rectangle',bbox(k,:),name1(1:length(name)-1));
else
Out = insertObjectAnnotation(Out,'rectangle',bbox(k,:),'not matched');
end
end
end
end
imshow(Out)

Reading labview binary files in Matlab?

I have large .bin files (10GB-60GB) created by Labview software, the .bin files represent the output of two sensors used from experiments that I have done.
The problem I have is importing the data into Matlab, the only way I have achieved this so far is by converting the .bin files to .txt files in Labview software then Importing the data into MATLAB using the following code:
Nlines = 1e6; % set number of lines to sample per cycle
sample_rate = (1); %sample rate
DECE= 1000;% decimation factor
TIME = (0:sample_rate:sample_rate*((Nlines)-1));%first inctance of time vector
format = '%f\t%f';
fid = fopen('H:\PhD backup\Data/ONK_PP260_G_text.txt');
while(~feof(fid))
C = textscan(fid, format, Nlines, 'CollectOutput', true);
d = C{1}; % immediately clear C at this point you need the memory!
clearvars C ;
TIME = ((TIME(end)+sample_rate):sample_rate:(sample_rate*(size(d,1)))+(TIME(end)));%shift Time along
plot((TIME(1:DECE:end)),(d(1:DECE:end,:)))%plot and decimate
hold on;
clearvars d;
end
fclose(fid);
The basic idea behind my code is to conserve RAM by reading Nlines of data from .txt on disk to Matlab variable C in RAM, plotting C then clearing C. This process occurs in loop so the data is plotted in chunks until the end of the .txt file is reached.
I want to read the .bin file directly into MATLAB rather than converting it to .txt first because it takes hours for the conversion to complete and I have a lot of data. Here are some examples of my data but in manageable sizes:
https://www.dropbox.com/sh/rzut4zbrert9fm0/q9SiZYmrdG
Here is a description of the binary data:
http://forums.ni.com/t5/LabVIEW/Loading-Labview-Binary-Data-into-Matlab/td-p/1107587
Someone has all ready written a Matlab script to import Labveiw .bin files but their script will only work with very small files:
% LABVIEWLOAD Load Labview binary data into Matlab
%
% DATA = LABVIEWLOAD(FNAME,DIM); % Loads the Labview data in binary
% format from the file specified by FNAME, given the NUMBER of
% dimensions (not the actual dimensions of the data in the binary
% file) of dimensions specified by DIM.
%
% LABVIEWLOAD will repeatedly grab data until the end of the file.
% Labview arrays of the same number of dimensions can be repeatedly
% appended to the same binary file. Labview arrays of any dimensions
% can be read.
%
% DATA = LABVIEWLOAD(FNAME,DIM,PREC); % Loads the data with the specified
% precision, PREC.
%
% Note: This script assumes the default parameters were used in the
% Labview VI "Write to Binary File". Labview uses the Big Endian
% binary number format.
%
% Examples:
% D = labviewload('Data.bin',2); % Loads in Data.bin assuming it
% contains double precision data and two dimensions.
%
% D = labviewload('OthereData.bin',3,'int8'); % Loads in
% OtherData.bin assuming it contains 8 bit integer values or
% boolean values.
%
% Jeremiah Smith
% 4/8/10
% Last Edit: 5/6/10
function data = labviewload(fname,dim,varargin)
siz = [2^32 2^16 2^8 1]'; % Array dimension conversion table
% Precision Input
if nargin == 2
prec = 'double';
elseif nargin == 3
prec = varargin{1};
else
error('Too many inputs.')
end
%% Initialize Values
fid = fopen(fname,'r','ieee-be'); % Open for reading and set to big-endian binary format
fsize = dir(fname); % File information
fsize = fsize.bytes; % Files size in bytes
%% Preallocation
rows = [];
columns = [];
I = 0;
while fsize ~= ftell(fid)
dims = [];
for i=1:1:dim
temp = fread(fid,4);
temp = sum(siz.*temp);
dims = [dims,temp];
end
I = I + 1;
% fseek(fid,prod(dims)*8,'cof'); % Skip the actual data
temp = fread(fid,prod(dims),prec,0,'ieee-be'); % Skip the actual data (much faster for some reason)
end
fseek(fid,0,'bof'); % Reset the cursor
data = repmat({NaN*ones(dims)},I,1); % Preallocate space, assumes each section is the same
%% Load and parse data
for j=1:1:I
dims = []; % Actual array dimensions
for i=1:1:dim
temp = fread(fid,4);
temp = sum(siz.*temp);
dims = [dims,temp];
end
clear temp i
temp = fread(fid,prod(dims),prec,0,'ieee-be'); % 11 is the values per row,
% double is the data type, 0 is the bytes to skip, and
% ieee-be specified big endian binary data
%% Reshape the data into the correct array configuration
if dim == 1
temp = reshape(temp,1,dims);
else
evalfunc = 'temp = reshape(temp';
for i=1:1:dim
evalfunc = [evalfunc ',' num2str(dims(dim-i+1))];
end
if dim ~= 2
eval([evalfunc ');'])
else
eval([evalfunc ')'';'])
end
end
data{j} = temp; % Save the data
end
fclose(fid); % Close the file
The code has the following error message, when you try to process even relatively small .bin files:
Error using ones
Maximum variable size allowed by the program is exceeded.
Error in labviewload (line 65)
data = repmat({NaN*ones(dims)},I,1); % Preallocate space, assumes each section is the same
Can you help me modify the code so that I can open large .bin files? Any help will be much appreciated.
Cheers,
Jim

PCA codes input, use for PalmPrint Recognition

I'm new to Matlab.
I'm trying to apply PCA function(URL listed below)into my palm print recognition program to generate the eigenpalms. My palm print grey scale images dimension are 450*400.
Before using it, I was trying to study these codes and add some codes to save the eigenvector as .mat file. Some of the %comments added by me for my self understanding.
After a few days of studying, I still unable to get the answers.
I decided to ask for helps.I have a few questions to ask regarding this PCA.m.
PCA.m
What is the input of the "options" should be? of "PCA(data,details,options)"
(is it an integer for reduced dimension? I was trying to figure out where is the "options" value passing, but still unable to get the ans. The msgbox of "h & h2", is to check the codes run until where. I was trying to use integer of 10, but the PCA.m processed dimension are 400*400.)
The "eigvector" that I save as ".mat" file is ready to perform Euclidean distance classifier with other eigenvector? (I'm thinking that eigvector is equal to eigenpalm, like in face recognition, the eigen faces. I was trying to convert the eigenvector matrix back to image, but the image after PCA process is in Black and many dots on it)
mySVD.m
In this function, there are two values that can be changed, which are MAX_MATRIX_SIZE set by 1600 and EIGVECTOR_RATIO set by 0.1%. May I know these values will affect the results? ( I was trying to play around with the values, but I cant see the different. My palm print image dimension is set by 450*400, so the Max_matrix_size should set at 180,000?)
** I hope you guys able to understand what I'm asking, please help, Thanks guys (=
Original Version : http://www.cad.zju.edu.cn/home/dengcai/Data/code/PCA.m
mySVD: http://www.cad.zju.edu.cn/home/dengcai/Data/code/mySVD.m
% Edited Version by me
function [eigvector, eigvalue] = PCA(data,details,options)
%PCA Principal Component Analysis
%
% Usage:
% [eigvector, eigvalue] = PCA(data, options)
% [eigvector, eigvalue] = PCA(data)
%
% Input:
% data - Data matrix. Each row vector of fea is a data point.
% fea = finite element analysis ?????
% options.ReducedDim - The dimensionality of the reduced subspace. If 0,
% all the dimensions will be kept.
% Default is 0.
%
% Output:
% eigvector - Each column is an embedding function, for a new
% data point (row vector) x, y = x*eigvector
% will be the embedding result of x.
% eigvalue - The sorted eigvalue of PCA eigen-problem.
%
% Examples:
% fea = rand(7,10);
% options=[]; %store an empty matrix in options
% options.ReducedDim=4;
% [eigvector,eigvalue] = PCA(fea,4);
% Y = fea*eigvector;
%
% version 3.0 --Dec/2011
% version 2.2 --Feb/2009
% version 2.1 --June/2007
% version 2.0 --May/2007
% version 1.1 --Feb/2006
% version 1.0 --April/2004
%
% Written by Deng Cai (dengcai AT gmail.com)
%
if (~exist('options','var'))
%A = exist('name','kind')
% var = Checks only for variables.
%http://www.mathworks.com/help/matlab/matlab_prog/symbol-reference.html#bsv2dx9-1
%The tilde "~" character is used in comparing arrays for unequal values,
%finding the logical NOT of an array,
%and as a placeholder for an input or output argument you want to omit from a function call.
options = [];
end
h2 = msgbox('not yet');
ReducedDim = 0;
if isfield(options,'ReducedDim')
%tf = isfield(S, 'fieldname')
h2 = msgbox('checked');
ReducedDim = options.ReducedDim;
end
[nSmp,nFea] = size(data);
if (ReducedDim > nFea) || (ReducedDim <=0)
ReducedDim = nFea;
end
if issparse(data)
data = full(data);
end
sampleMean = mean(data,1);
data = (data - repmat(sampleMean,nSmp,1));
[eigvector, eigvalue] = mySVD(data',ReducedDim);
eigvalue = full(diag(eigvalue)).^2;
if isfield(options,'PCARatio')
sumEig = sum(eigvalue);
sumEig = sumEig*options.PCARatio;
sumNow = 0;
for idx = 1:length(eigvalue)
sumNow = sumNow + eigvalue(idx);
if sumNow >= sumEig
break;
end
end
eigvector = eigvector(:,1:idx);
end
%dt get from C# program, user ID and name
evFolder = 'ev\';
userIDName = details; %get ID and Name
userIDNameWE = strcat(userIDName,'\');%get ID and Name with extension
filePath = fullfile('C:\Users\***\Desktop\Data Collection\');
userIDNameFolder = strcat(filePath,userIDNameWE); %ID and Name folder
userIDNameEVFolder = strcat(userIDNameFolder,evFolder);%EV folder in ID and Name Folder
userIDNameEVFile = strcat(userIDNameEVFolder,userIDName); % EV file with ID and Name
if ~exist(userIDNameEVFolder, 'dir')
mkdir(userIDNameEVFolder);
end
newFile = strcat(userIDNameEVFile,'_1');
searchMat = strcat(newFile,'.mat');
if exist(searchMat, 'file')
filePattern = strcat(userIDNameEVFile,'_');
D = dir([userIDNameEVFolder, '*.mat']);
Num = length(D(not([D.isdir])))
Num=Num+1;
fileName = [filePattern,num2str(Num)];
save(fileName,'eigvector');
else
newFile = strcat(userIDNameEVFile,'_1');
save(newFile,'eigvector');
end
You pass options in a structure, for instance:
options.ReducedDim = 2;
or
options.PCARatio =0.4;
The option ReducedDim selects the number of dimensions you want to use to represent the final projection of the original matrix. For instance if you pick option.ReducedDim = 2 you use only the two eigenvectors with largest eigenvalues (the two principal components) to represent your data (in effect the PCA will return the two eigenvectors with largest eigenvalues).
PCARatio instead allows you to pick the number of dimensions as the first eigenvectors with largest eigenvalues that account for fraction PCARatio of the total sum of eigenvalues.
In mySVD.m, I would not increase the default values unless you expect more than 1600 eigenvectors to be necessary to describe your dataset. I think you can safely leave the default values.