svmclassify is extremely slow

4 views (last 30 days)
Jakob Sørensen
Jakob Sørensen on 31 Jan 2014
Answered: Shashank Prasanna on 31 Jan 2014
Hey there,
I'm trying to use the built-in Support Vector Machine (SVM) tools in Matlab to classify an image. Its a 1000x1000(x3) pixels image, containing two seperate colors (grayscale, but its a jpg).
I first use svmtrain on a subset of the data, more precisely 500 data points where R, G and B are used as features for each point (so a 500x3 array).
Then I use the struct returned from the operation above, in svmclassify on the full image, except it is transformed to be a 1,000,000 x 3 array. This however seems to take forever (~400 seconds) despite of a reasonably fast laptop. In addition it eats up all the memory (8 GB) during the process, meaning that I can't really use the PC in the time it's busy.
Can it really be that svmclassify does not work on data of this size? Or have I messed something up in my code (see below)?
Edit: I just tested using another JPEG-image, of the same size and read in the same way (using imread) and this seems to work reasonably fast. Why the large difference depending on the image?
Code:
function cimg = classifyImage(img)
cimg = 0; % Needed if the script stops due to errors
if size(img,3) ~= 3
errordlg('Data error: Image must be handed as an M-by-N-by-3 array');
return;
elseif ~isnumeric(img)
errordlg('Data error: Handed data does not appear to be an image');
return;
end
% Get size of the original image, which is ultimately used to restore the
% classified image, from the vector which comes from the classification
im_height = size(img,1);
im_width = size(img,2);
% Convert image to MNx3 matrix, where each row is a point and the columns
% represent RGB values.
red_layer = img(:,:,1);
green_layer = img(:,:,2);
blue_layer = img(:,:,3);
red_layer = red_layer(:);
green_layer = green_layer(:);
blue_layer = blue_layer(:);
img_vector = [red_layer green_layer blue_layer];
size(blue_layer)
% Aquire features
figure(1);
imshow(img);
title('Select background');
[xBack, yBack] = ginput(2);
title('Select foreground');
[xFront, yFront] = ginput(2);
xBack = round(xBack);
yBack = round(yBack);
xFront = round(xFront);
yFront = round(yFront);
close(1);
background = img(xBack(1):xBack(2),yBack(1):yBack(2),:);
foreground = img(xFront(1):xFront(2),yFront(1):yFront(2),:);
bg_red = background(:,:,1);
bg_red = bg_red(:);
bg_green = background(:,:,2);
bg_green = bg_green(:);
bg_blue = background(:,:,3);
bg_blue = bg_blue(:);
fg_red = foreground(:,:,1);
fg_red = fg_red(:);
fg_green = foreground(:,:,2);
fg_green = fg_green(:);
fg_blue = foreground(:,:,3);
fg_blue = fg_blue(:);
bg_feats = [bg_red bg_green bg_blue];
fg_feats = [fg_red fg_green fg_blue];
features = [bg_feats; fg_feats];
groups = [-ones(length(bg_red),1); ones(length(fg_red),1)];
[features, groups] = reduceFeatures(features,groups,500);
options = optimset('maxiter',1000);
tic
disp('Training...')
svm_struct = svmtrain(double(features), groups, 'kernel_function', 'rbf', ...
'method', 'QP', ...
'quadprog_opts',options)
toc
disp('Classifying...')
cimg = svmclassify(svm_struct,double(img_vector));
toc
disp('Re-assembling image...')
cimg = reshape(cimg, im_height, im_width);
toc
disp('Profit!')

Answers (1)

Shashank Prasanna
Shashank Prasanna on 31 Jan 2014
Hi Jakob,
Do you have access to MATLAB prerelease?
If you do, feel free to check out the new fitcsvm function for SVM where you should see performance improvements. We'd be happy to hear any feedback you may have subsequently.
Regards, Shashank

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!