Error: Subscripted assignment dimension mismatch
Show older comments
I'm following the digit classification example but using different datasets. However, I get the following error:
Subscripted assignment dimension mismatch.
Error in hog_svm (line 62)
features(i, :) = extractHOGFeatures(img, 'CellSize', cellSize);
At first, I thought it was because the images being used are of different sizes, so I made them all the same size, but that didn't work. Maybe I resized them in the wrong time? The code is shown below.
url = 'http://www.vision.caltech.edu/Image_Datasets/Caltech101/101_ObjectCategories.tar.gz';
% Store the output in a temporary folder
outputFolder = fullfile(tempdir, 'caltech101'); % define output folder
if ~exist(outputFolder, 'dir') % download only once
disp('Downloading 126MB Caltech101 data set...');
untar(url, outputFolder);
end
rootFolder = fullfile(outputFolder, '101_ObjectCategories');
imgSets = [ imageSet(fullfile(rootFolder, 'airplanes')), ...
imageSet(fullfile(rootFolder, 'ferry')), ...
imageSet(fullfile(rootFolder, 'laptop')) ];
minSetCount = min([imgSets.Count]);
imgSets = partition(imgSets, minSetCount, 'randomize');
% for image = 1:numel(imgSets)
% image = imresize(image, [20 20]);
% end
%numel - total number of array elements
[trainingSets, testSets] = partition(imgSets, 0.3, 'randomize');
img = read(trainingSets(1), 2);
% Extract HOG features and HOG visualization
[hog_2x2, vis2x2] = extractHOGFeatures(img,'CellSize',[2 2]);
[hog_4x4, vis4x4] = extractHOGFeatures(img,'CellSize',[4 4]);
[hog_8x8, vis8x8] = extractHOGFeatures(img,'CellSize',[8 8]);
% Show the original image
figure;
subplot(2,3,1:3); imshow(img);
% Visualize the HOG features
subplot(2,3,4);
plot(vis2x2);
title({'CellSize = [2 2]'; ['Feature length = ' num2str(length(hog_2x2))]});
subplot(2,3,5);
plot(vis4x4);
title({'CellSize = [4 4]'; ['Feature length = ' num2str(length(hog_4x4))]});
subplot(2,3,6);
plot(vis8x8);
title({'CellSize = [8 8]'; ['Feature length = ' num2str(length(hog_8x8))]});
cellSize = [4 4];
hogFeatureSize = length(hog_4x4);
trainingFeatures = [];
trainingLabels = [];
for image = 1:numel(trainingSets)
numImages = trainingSets(image).Count;
features = zeros(numImages, hogFeatureSize, 'single');
for i = 1:numImages
% img = rgb2gray(read(trainingSets(image), i));
% img = imbinarize(img);
img = read(trainingSets(image), i);
lvl = graythresh(img);
img = im2bw(img, lvl);
% img = im2single(img);
% img =imresize(img, .5);
features(i, :) = extractHOGFeatures(img, 'CellSize', cellSize);
end
labels = repmat(trainingSets(image).Description, numImages, 1);
trainingFeatures = [trainingFeatures; features];
trainingLabels = [trainingLabels; labels];
end
classifier = fitcecoc(trainingFeatures, trainingLabels);
[testFeatures, testLabels] = helperExtractHOGFeaturesFromImageSet(testSets, hogFeatureSize, cellSize);
% Make class predictions using the test features.
predictedLabels = predict(classifier, testFeatures);
% Tabulate the results using a confusion matrix.
confMat = confusionmat(testLabels, predictedLabels);
helperDisplayConfusionMatrix(confMat)
Answers (1)
Walter Roberson
on 4 Apr 2016
0 votes
As a debugging step, assign the output of the extraction to a variable, and then check the size of the variable compared to the size of your features array.
Note: your commented out img =imresize(img, .5); would not resize all of the images to the same size: it would resize them to half of the size they were. You would need to provide a particular target size instead of a ratio if you want to resize them to the same size.
23 Comments
Bishwo Gurung
on 4 Apr 2016
Walter Roberson
on 4 Apr 2016
It is okay for the number of rows to not match as you are writing each "first" into a different row of "features".
In this current program, what shows up for size(first) and size(features), and what shows up for the value hogFeatureSize and for size(hog_4x4) ?
Bishwo Gurung
on 4 Apr 2016
Edited: Walter Roberson
on 4 Apr 2016
Walter Roberson
on 4 Apr 2016
size(features) would be a pair of numbers, you only showed one here.
Walter Roberson
on 4 Apr 2016
If you look at http://www.mathworks.com/help/vision/ref/extracthogfeatures.html#output_argument_features then you can see that N will change depending on the size of the image, because the BlocksPerImage will change. You need to resize all of your images to be the same size that you used for the original "img" from your training set.
Bishwo Gurung
on 4 Apr 2016
Bishwo Gurung
on 4 Apr 2016
Walter Roberson
on 4 Apr 2016
That uses "image" as the name of a loop index, and assigns scalar numeric values from 1 to numel(imgSets) to "image". Inside the loop, it resizes the scalar numeric loop counter to be 20 x 20, and assigns the result on top of the loop counter. The next iteration of the loop, MATLAB ignores the change that has been made to the loop counter and goes on to the next scalar value. At no time was anything meaningful saved, and instead the important MATLAB graphics primitive image() has been interfered with.
Then later in your code you read() out of the partitioned imageSet, which effectively fetches a file name from its list of file names and imread()'s the file in. And you do not imresize() that result.
Do not try to imresize() at that stage. Just, after you first do
img = read(trainingSets(1), 2);
then add
train_img_size = size(img);
Then, inside your loop where you have
img = read(trainingSets(image), i);
after that add
img = imresize(img, train_img_size);
Bishwo Gurung
on 4 Apr 2016
Walter Roberson
on 5 Apr 2016
Ah, you could get that if you had RGB images. The adjustment:
train_img_size = [size(img,1), size(img,2)]; %ignore additional planes
Bishwo Gurung
on 6 Apr 2016
Walter Roberson
on 7 Apr 2016
"Information about the image set, specified as a string. When you create an image set by recursively searching folders or by specifying a single folder location, the Description property is set to the folder name."
Notice this is just a string. So when you use
labels = repmat(trainingSets(image).Description, numImages, 1);
the trainingSets(image).Description part is extracting a string (that is to say, a row vector of char) and making vertical copies of it, ending up with a char array with the same width as the number of characters in the string.
Eventually there is a different folder name, which probably has a different width of string. So then when you use
trainingLabels = [trainingLabels; labels];
you are attempting to do a vertical concatenation of a char array of one width and a char array of a different width. That fails.
The fix is easy: change to
labels = repmat({trainingSets(image).Description}, numImages, 1);
Bishwo Gurung
on 8 Apr 2016
Walter Roberson
on 8 Apr 2016
You need the resizing each time you pull out from the set. Do not save the resized image back.
Sometimes it makes sense to pre-process, to run through an image set and create resized versions of them that you save somewhere, and then create a new imageSet from the place you stored the resized versions.
Bishwo Gurung
on 10 Apr 2016
Walter Roberson
on 10 Apr 2016
You do not call the hog routines in that loop. You do not do anything with the img after you convert it to bw
Bishwo Gurung
on 10 Apr 2016
Walter Roberson
on 10 Apr 2016
What I mean is that the error message you should is not possible with the code you show. You have shown us the wrong section of code.
Bishwo Gurung
on 10 Apr 2016
Walter Roberson
on 10 Apr 2016
Take a look at your code
for image = 1:numel(testSets)
numImages = testSets(image).Count;
for i = 1:numImages
img = read(testSets(image), i);
img = imresize(img, train_img_size);
lvl = graythresh(img);
img = im2bw(img, lvl);
end
end
Notice that after you im2bw(), you do not do anything with img, so it will be overwritten with the next iteration of "for i", and that will be carried out over the complete "for image". That is a waste of time, as the end result will be the same as if you had just processed the very last image of the very last set of images.
Do not name a variable "image"; doing so interferes with using the important graphics primitive image(), and confuses the other people reading your code.
The error you are running into is in your line
[testFeatures, testLabels] = helperExtractHOGFeaturesFromImageSet(testSets, hogFeatureSize, cellSize);
which looks like it is doing similar code. You do not show us that routine, though. You are not passing in train_img_size to that routine, so we need to assume that if it is resizing the images at all that it might be doing so to a different size.
Bishwo Gurung
on 11 Apr 2016
Bishwo Gurung
on 11 Apr 2016
Walter Roberson
on 11 Apr 2016
It would seem to make sense to put your HOG extraction code into a function in which you passed an imageSet and a target image size, and returned the feature matrix. That would save you from duplicating the code.
Categories
Find more on Camera Calibration in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!