diff --git a/approach1.m b/approach1.m new file mode 100644 index 0000000..11612fd --- /dev/null +++ b/approach1.m @@ -0,0 +1,189 @@ +% Jervis Muindi +% Biometrics Final Project +% 11th December 2011 + +% Does classification on test data set. +% By applying nearest neighbor directly +% on extracted features. +function approach1() +% Does a test for classifying the handwritten images. + +disp('reading data'); +% assume, we have loaded +[train_data, train_labels ] = readDATA(); + +[test_data, test_labels] = loadHndDATA(); + +sizeTrain = size(train_data,2); +sizeTest = size(test_data,2); +sizeTest = 50; + +%Do a quick nearest neighbor test classification. +errors = 0; +for i = 1:sizeTest + + fprintf('test %d - ', i); + tv = test_data{i}; + tv = tv(:); + + minIdx = 0; + minDist = Inf; + + for j = 1:sizeTrain + + av = train_data{j}; + av = av(:); + diff = tv - av; + dist = norm(diff,2); + + if(dist < minDist) + minDist = dist; + %disp(j); + minIdx = j; + end + %disp('running'); + %disp(dist); + + end + %error('s'); + + %save result; + + result(i) = train_labels{minIdx}; + + + %do accuracy checking in line + if( test_labels(i) ~= result(i) ) + errors = errors + 1; + + end + + tot = i; + curr_acc = (tot - errors) / tot; + + if( test_labels(i) ~= result(i) ) + + fprintf('Curr Accuracy: %f | %d,%d.\n', curr_acc, test_labels(i),result(i) ); + figure; + im = [test_data{i} train_data{minIdx} ]; + imshow(im); + continue; + end + + fprintf('Curr Accuracy: %f.\n', curr_acc); + +end + + + +end + + + + + + + + + + + +%{ +K NEaREST NEIGHTBOR + +function testhnd() +% Does a test for classifying the handwritten images. + +disp('reading data'); +% assume, we have loaded +[train_data, train_labels ] = readDATA(); + +[test_data, test_labels] = loadHndDATA(); + +sizeTrain = size(train_data,2); +%sizeTrain = 10000; +sizeTest = size(test_data,2); +sizeTest = 200; +%Do a quick nearest neighbor test classification. +errors = 0; + + + +for i = 1:sizeTest + + fprintf('test %d - ', i); + tv = test_data{i}; + tv = tv(:); + + + minIdx = 0; + minDist = Inf; + + arr(1) = 0; + arr(2) = 0; + arr(3) = 0; + for j = 1:sizeTrain + + av = train_data{j}; + av = av(:); + diff = tv - av; + dist = norm(diff,2); + + if(dist < minDist) + minDist = dist; + %disp(j); + minIdx = j; + + prev_first = arr(1); + prev_sec = arr(2); + + arr(1) = minIdx; + arr(2) = prev_first; + arr(3) = prev_sec; + + end + %disp('running'); + %disp(dist); + + end + + num = [train_labels{arr(1)};train_labels{arr(2)} ;train_labels{arr(3)}]; + indices = zeros(10,1); + + for ii = 1:3 + indices(num(ii)+1) = indices(num(ii)+1) + 1; + end + + [x,number] = max(indices); + + %error('s'); + + %save result; + result(i) = number - 1; + + %result(i) = train_labels{minIdx}; + + + %do accuracy checking in line + if( test_labels(i) ~= result(i) ) + errors = errors + 1; + + end + tot = i; + curr_acc = (tot - errors) / tot; + + if( test_labels(i) ~= result(i) ) + + fprintf('Curr Accuracy: %f | %d,%d.\n', curr_acc, test_labels(i),result(i) ); + figure; + continue; + end + fprintf('Curr Accuracy: %f.\n', curr_acc ); + +end + + + +end + +%} diff --git a/approach2.m b/approach2.m new file mode 100644 index 0000000..d791393 --- /dev/null +++ b/approach2.m @@ -0,0 +1,189 @@ +% Jervis Muindi +% Does classification on test data set. +% By applying nearest neighbor directly +% on extracted digits that have been bounded to +% a box. +function approach2() +% Does a test for classifying the handwritten images. + +disp('reading data'); +% assume, we have loaded +[train_data, train_labels ] = readDATA(); +train_data = procTD(train_data);% Process the trainig data to bound image to a bounding box. + +[test_data, test_labels] = loadHndDATA(); + +sizeTrain = size(train_data,2); +sizeTest = size(test_data,2); +sizeTest = 200; + +%Do a quick nearest neighbor test classification. +errors = 0; +for i = 1:sizeTest + + fprintf('test %d - ', i); + tv = test_data{i}; + tv = proc(tv); %process the test image so that it's also bound to a box of 28 x 28. + tv = tv(:); + + minIdx = 0; + minDist = Inf; + + for j = 1:sizeTrain + + av = train_data{j}; + av = av(:); + diff = tv - av; + dist = norm(diff,2); + + if(dist < minDist) + minDist = dist; + %disp(j); + minIdx = j; + end + %disp('running'); + %disp(dist); + + end + %error('s'); + + %save result; + + result(i) = train_labels{minIdx}; + + + %do accuracy checking in line + if( test_labels(i) ~= result(i) ) + errors = errors + 1; + + end + + tot = i; + curr_acc = (tot - errors) / tot; + + if( test_labels(i) ~= result(i) ) + + fprintf('Curr Accuracy: %f | %d,%d.\n', curr_acc, test_labels(i),result(i) ); + %figure; + im = [test_data{i} train_data{minIdx} ]; + %imshow(im); + continue; + end + + fprintf('Curr Accuracy: %f.\n', curr_acc); + +end + + + +end + + + + + + + + + + + +%{ +K NEaREST NEIGHTBOR + +function testhnd() +% Does a test for classifying the handwritten images. + +disp('reading data'); +% assume, we have loaded +[train_data, train_labels ] = readDATA(); + +[test_data, test_labels] = loadHndDATA(); + +sizeTrain = size(train_data,2); +%sizeTrain = 10000; +sizeTest = size(test_data,2); +sizeTest = 200; +%Do a quick nearest neighbor test classification. +errors = 0; + + + +for i = 1:sizeTest + + fprintf('test %d - ', i); + tv = test_data{i}; + tv = tv(:); + + + minIdx = 0; + minDist = Inf; + + arr(1) = 0; + arr(2) = 0; + arr(3) = 0; + for j = 1:sizeTrain + + av = train_data{j}; + av = av(:); + diff = tv - av; + dist = norm(diff,2); + + if(dist < minDist) + minDist = dist; + %disp(j); + minIdx = j; + + prev_first = arr(1); + prev_sec = arr(2); + + arr(1) = minIdx; + arr(2) = prev_first; + arr(3) = prev_sec; + + end + %disp('running'); + %disp(dist); + + end + + num = [train_labels{arr(1)};train_labels{arr(2)} ;train_labels{arr(3)}]; + indices = zeros(10,1); + + for ii = 1:3 + indices(num(ii)+1) = indices(num(ii)+1) + 1; + end + + [x,number] = max(indices); + + %error('s'); + + %save result; + result(i) = number - 1; + + %result(i) = train_labels{minIdx}; + + + %do accuracy checking in line + if( test_labels(i) ~= result(i) ) + errors = errors + 1; + + end + tot = i; + curr_acc = (tot - errors) / tot; + + if( test_labels(i) ~= result(i) ) + + fprintf('Curr Accuracy: %f | %d,%d.\n', curr_acc, test_labels(i),result(i) ); + figure; + continue; + end + fprintf('Curr Accuracy: %f.\n', curr_acc ); + +end + + + +end + +%} diff --git a/approach3.m b/approach3.m new file mode 100644 index 0000000..e204546 --- /dev/null +++ b/approach3.m @@ -0,0 +1,190 @@ +% Jervis Muindi +% Does classification on test data set. +% By applying nearest neighbor directly +% on extracted digits that have been bounded to +% a box and also thickening the test images by 2 pixels. +function approach3() +% Does a test for classifying the handwritten images. + +disp('reading data'); +% assume, we have loaded +[train_data, train_labels ] = readDATA(); +train_data = procTD(train_data);% Process the trainig data to bound image to a bounding box. + +[test_data, test_labels] = loadHndDATA(); + +sizeTrain = size(train_data,2); +sizeTest = size(test_data,2); +sizeTest = 50; + +%Do a quick nearest neighbor test classification. +errors = 0; +for i = 1:sizeTest + + fprintf('test %d - ', i); + tv = test_data{i}; + %process the test image so that it's also bound to a box of 28 x 28 and also thicken it by adding 2 pixels to digit outline.. + tv = proc2(tv); + tv = tv(:); + + minIdx = 0; + minDist = Inf; + + for j = 1:sizeTrain + + av = train_data{j}; + av = av(:); + diff = tv - av; + dist = norm(diff,2); + + if(dist < minDist) + minDist = dist; + %disp(j); + minIdx = j; + end + %disp('running'); + %disp(dist); + + end + %error('s'); + + %save result; + + result(i) = train_labels{minIdx}; + + + %do accuracy checking in line + if( test_labels(i) ~= result(i) ) + errors = errors + 1; + + end + + tot = i; + curr_acc = (tot - errors) / tot; + + if( test_labels(i) ~= result(i) ) + + fprintf('Curr Accuracy: %f | %d,%d.\n', curr_acc, test_labels(i),result(i) ); + figure; + im = [test_data{i} train_data{minIdx} ]; + %imshow(im); + continue; + end + + fprintf('Curr Accuracy: %f.\n', curr_acc); + +end + + + +end + + + + + + + + + + + +%{ +K NEaREST NEIGHTBOR + +function testhnd() +% Does a test for classifying the handwritten images. + +disp('reading data'); +% assume, we have loaded +[train_data, train_labels ] = readDATA(); + +[test_data, test_labels] = loadHndDATA(); + +sizeTrain = size(train_data,2); +%sizeTrain = 10000; +sizeTest = size(test_data,2); +sizeTest = 200; +%Do a quick nearest neighbor test classification. +errors = 0; + + + +for i = 1:sizeTest + + fprintf('test %d - ', i); + tv = test_data{i}; + tv = tv(:); + + + minIdx = 0; + minDist = Inf; + + arr(1) = 0; + arr(2) = 0; + arr(3) = 0; + for j = 1:sizeTrain + + av = train_data{j}; + av = av(:); + diff = tv - av; + dist = norm(diff,2); + + if(dist < minDist) + minDist = dist; + %disp(j); + minIdx = j; + + prev_first = arr(1); + prev_sec = arr(2); + + arr(1) = minIdx; + arr(2) = prev_first; + arr(3) = prev_sec; + + end + %disp('running'); + %disp(dist); + + end + + num = [train_labels{arr(1)};train_labels{arr(2)} ;train_labels{arr(3)}]; + indices = zeros(10,1); + + for ii = 1:3 + indices(num(ii)+1) = indices(num(ii)+1) + 1; + end + + [x,number] = max(indices); + + %error('s'); + + %save result; + result(i) = number - 1; + + %result(i) = train_labels{minIdx}; + + + %do accuracy checking in line + if( test_labels(i) ~= result(i) ) + errors = errors + 1; + + end + tot = i; + curr_acc = (tot - errors) / tot; + + if( test_labels(i) ~= result(i) ) + + fprintf('Curr Accuracy: %f | %d,%d.\n', curr_acc, test_labels(i),result(i) ); + figure; + continue; + end + fprintf('Curr Accuracy: %f.\n', curr_acc ); + +end + + + +end + +%} diff --git a/binarize.m b/binarize.m new file mode 100644 index 0000000..332989c --- /dev/null +++ b/binarize.m @@ -0,0 +1,21 @@ + +function r = binarize(A) + + r = size(A,1); + c = size(A,2); + + for i=1:r + for j = 1:c + + if(A(i,j) > 0.1) + A(i,j) = 1; + else + A(i,j) = 0; + end + + end + end + + r=A; + +end diff --git a/darken.m b/darken.m new file mode 100644 index 0000000..ef35f2a --- /dev/null +++ b/darken.m @@ -0,0 +1,21 @@ + + +function r = darken(A) +%convert from white background to black background + + rows = size(A,1); + cols = size(A,2); + + for i = 1:rows + for j = 1:cols + if(A(i,j) == 1) + A(i,j) = 0; + else + A(i,j) = 1; %prev was : 1 - A(i,j). right now we're binarizing img. + end + end + end + + r = A; +end + diff --git a/extract.m b/extract.m new file mode 100644 index 0000000..9d4afb1 --- /dev/null +++ b/extract.m @@ -0,0 +1,27 @@ + +%extracts just the outline of the number. find find the topleft pixel and +% the bottom right pixel. +function r = extract(A) + r = size(A,1); + c = size(A,2); + + x = []; + y = []; + for i=1:r + for j=1:c + if(A(i,j) == 1) + x = [x; i]; + y = [y; j]; + end + end + end + + minx = min(x); + maxx = max(x); + miny = min(y); + maxy = max(y); + + r = A(minx:maxx,miny:maxy); + +end + diff --git a/pca.m b/pca.m new file mode 100644 index 0000000..2d75d23 --- /dev/null +++ b/pca.m @@ -0,0 +1,129 @@ +function [ signals, PC, V ] = pca( data ) +% Perform PCA. +% Data is the data matrix having dimensions in the columns and each image vector in the rows +% data - of size M by N +% PC - the principal components +% V - M by 1 of variances +% proj - the projected data +% + + +% Create the mean vector. This contains the means of each dimension +% of the data matrix (the cols) + +[M,N] = size(data); +mn = mean(data,2); +%mn = mn'; %covnert to column vector + +% subtract the mean of each dimension from the data matrix +disp('subtracting means..'); +size(mn) +data = data - repmat(mn,1,N); + +%calculate the convariance matrix. +size(data) +disp('computing conv'); + +covariance = 1 / (N-1) * (data * data') ; + +disp('finding eig vals'); +%find the eigen vectors and eigen values +[PC, V] = eig(covariance); + +%extract diagonal of matrix as vector which has the eigen values. +V = diag(V); + +%sort the eigen values in decreasing order +[sorted, rindices] = sort(V, 'descend'); + + +V = sorted; +disp(' e v'); +V +rindices = rindices(1:10, :); +%size(rindices) + +%PC = PC(:, rindices); + +disp('doing projections'); +%project the original data set. +signals = PC' * data; + +%{ +disp('orig data'); +size(data) +disp('proj data'); +size(signals) + +error('xxxxxxx'); +%} + + + +end + +%{ +function [ signals, PC, V ] = pca( data ) +% Perform PCA. +% Data is the data matrix having dimensions in the columns and each image vector in the rows +% data - of size M by N +% PC - the principal components +% V - M by 1 of variances +% proj - the projected data +% + + +% Create the mean vector. This contains the means of each dimension +% of the data matrix (the cols) + +[M,N] = size(data); +mn = mean(data,2); + +% subtract the mean of each dimension from the data matrix +disp('subtracting means..'); + +data = data - repmat(mn,1,N); + +%calculate the convariance matrix. +size(data) +disp('computing conv'); + +covariance = 1 / (N-1) * (data * data') ; + +disp('finding eig vals'); +%find the eigen vectors and eigen values +[PC, V] = eig(covariance); + +%extract diagonal of matrix as vector which has the eigen values. +V = diag(V); + +%sort the eigen values in decreasing order +[sorted, rindices] = sort(V, 'descend'); + + +V = sorted; + +%rindices = rindices(1:20, :); +%size(rindices) + +PC = PC(:, rindices); + +disp('doing projections'); +%project the original data set. +signals = PC' * data; + + +disp('orig data'); +size(data) +disp('proj data'); +size(signals) + +error('xxxxxxx'); + + + + +end + + +%} \ No newline at end of file diff --git a/proc.m b/proc.m new file mode 100644 index 0000000..c9ab221 --- /dev/null +++ b/proc.m @@ -0,0 +1,22 @@ +% Jervis Muindi +% Biometrics Final Project +% 11th December 2011 + +function r = proc( image ) +%Process given image by bouding digits to bounding box. +% this also thickens the image. should be used for handwrittend +% self gathered test images. + + + %process img sample. + + img_sample = image; + img_sample = binarize(img_sample); + img_sample = extract(img_sample); % bound it + img_sample = imresize(img_sample, [28 28]); % resize + img_sample = binarize(img_sample); % re-binarize + + r = img_sample; + +end + diff --git a/proc2.m b/proc2.m new file mode 100644 index 0000000..1146808 --- /dev/null +++ b/proc2.m @@ -0,0 +1,23 @@ +% Jervis Muindi +% Biometrics Final Project +% 11th December 2011 + +function r = proc2( image ) + %Process given image by bouding digits to bounding box. + % this also thickens the image. should be used for handwrittend + % self gathered test images. + + + %process img sample. + + img_sample = image; + img_sample = binarize(img_sample); + img_sample = extract(img_sample); % bound it + img_sample = imresize(img_sample, [28 28]); % resize + img_sample = binarize(img_sample); % re-binarize + img_sample = thicken(img_sample); % thicken + + r = img_sample; + +end + diff --git a/procTD.m b/procTD.m new file mode 100644 index 0000000..ef2c60b --- /dev/null +++ b/procTD.m @@ -0,0 +1,33 @@ +% Jervis Muindi +% Biometrics Final Project +% 11th December 2011 + +function r = procTD( images ) +% Process the traing data (image cell array) by bouding digits to bounding box. +% this is for trainig data. + + + length = size(images,2); + + %process all img samples. + disp('Processing images in Training Set...'); + for i = 1:length + + if(mod(i,1000) == 0) + fprintf('Processed %d of 60000 training samples\n',i); + end + + img_sample = images{i}; + img_sample = binarize(img_sample); + img_sample = extract(img_sample); % bound it + img_sample = imresize(img_sample, [28 28]); % resize + img_sample = binarize(img_sample); % re-binarize + + images{i} = img_sample; + + end + + r = images; + +end + diff --git a/testhnd.m b/testhnd.m new file mode 100644 index 0000000..2e4f9bc --- /dev/null +++ b/testhnd.m @@ -0,0 +1,188 @@ +function testhnd() +% Does a test for classifying the handwritten images. + +disp('reading data'); +% assume, we have loaded +[train_data, train_labels ] = readDATA(); + +[test_data, test_labels] = loadHndDATA(); + +train_data = preprocTD(train_data); % convert pixel to bounded box + +sizeTrain = size(train_data,2); +sizeTest = size(test_data,2); +sizeTest = 200; +%Do a quick nearest neighbor test classification. +errors = 0; + + + +for i = 1:sizeTest + + fprintf('test %d - ', i); + tv = test_data{i}; + tv = preproc(tv); % pre process and bind it to box + tv = tv(:); + + + minIdx = 0; + minDist = Inf; + + for j = 1:sizeTrain + + av = train_data{j}; + av = av(:); + diff = tv - av; + dist = norm(diff,2); + + if(dist < minDist) + minDist = dist; + %disp(j); + minIdx = j; + end + %disp('running'); + %disp(dist); + + end + %error('s'); + + %save result; + + result(i) = train_labels{minIdx}; + + + %do accuracy checking in line + if( test_labels(i) ~= result(i) ) + errors = errors + 1; + + end + tot = i; + curr_acc = (tot - errors) / tot; + + + if( test_labels(i) ~= result(i) ) + + fprintf('Curr Accuracy: %f | %d,%d.\n', curr_acc, test_labels(i),result(i) ); + %figure; + im = [test_data{i} train_data{minIdx} ]; + %imshow(im); + continue; + end + + fprintf('Curr Accuracy: %f.\n', curr_acc); + +end + + + +end + + + + + + + + + + + +%{ +K NEaREST NEIGHTBOR + +function testhnd() +% Does a test for classifying the handwritten images. + +disp('reading data'); +% assume, we have loaded +[train_data, train_labels ] = readDATA(); + +[test_data, test_labels] = loadHndDATA(); + +sizeTrain = size(train_data,2); +%sizeTrain = 10000; +sizeTest = size(test_data,2); +sizeTest = 200; +%Do a quick nearest neighbor test classification. +errors = 0; + + + +for i = 1:sizeTest + + fprintf('test %d - ', i); + tv = test_data{i}; + tv = tv(:); + + + minIdx = 0; + minDist = Inf; + + arr(1) = 0; + arr(2) = 0; + arr(3) = 0; + for j = 1:sizeTrain + + av = train_data{j}; + av = av(:); + diff = tv - av; + dist = norm(diff,2); + + if(dist < minDist) + minDist = dist; + %disp(j); + minIdx = j; + + prev_first = arr(1); + prev_sec = arr(2); + + arr(1) = minIdx; + arr(2) = prev_first; + arr(3) = prev_sec; + + end + %disp('running'); + %disp(dist); + + end + + num = [train_labels{arr(1)};train_labels{arr(2)} ;train_labels{arr(3)}]; + indices = zeros(10,1); + + for ii = 1:3 + indices(num(ii)+1) = indices(num(ii)+1) + 1; + end + + [x,number] = max(indices); + + %error('s'); + + %save result; + result(i) = number - 1; + + %result(i) = train_labels{minIdx}; + + + %do accuracy checking in line + if( test_labels(i) ~= result(i) ) + errors = errors + 1; + + end + tot = i; + curr_acc = (tot - errors) / tot; + + if( test_labels(i) ~= result(i) ) + + fprintf('Curr Accuracy: %f | %d,%d.\n', curr_acc, test_labels(i),result(i) ); + figure; + continue; + end + fprintf('Curr Accuracy: %f.\n', curr_acc ); + +end + + + +end + +%} diff --git a/thicken.m b/thicken.m new file mode 100644 index 0000000..451d86e --- /dev/null +++ b/thicken.m @@ -0,0 +1,46 @@ + +%thickens number outline +function r = thicken(A) + + %essentially binarize image. + rows = size(A,1); + cols = size(A,2); + + A = binarize(A); + + + %then we add a 1-px to outline to thicken it. + + thickness = 3; + + for i = 1:rows + for j = 1:cols + if(A(i,j) == 0) % at a zero pixel + %check if border pixel ahead to the east. + if( j+thickness <= cols && A(i,j+thickness) == 1) % check east + + for x = 1:thickness + A(i,j+x-1) = 1; + end + %A(i,j) = 1; + + end + + if( i+thickness <= rows && A(i+thickness,j) == 1) % check south + + for x = 1:thickness + A(i+x-1,j) = 1; + end + %A(i,j) = 1; + + end + + + end + end + end + + + + r = A; +end