KNN分类器,用于简单的数字识别

时间:2015-11-03 00:11:59

标签: matlab image-processing computer-vision pattern-recognition

实际上,我有一项任务,要求识别单个十进制数字作为文本识别过程的一部分。我已经获得了一组一些数字的JPEG格式图像。每个图像的大小为160 x 160像素。在检查了一些资源后,我设法编写了这段代码,但是:

1)我不确定是否正确读取图像并在矩阵中调整它们的大小是正确与否的。

2)假设我有30个数字图像的数字[0-9]每个数字有三个图像我有10个图像用于测试每个图像只有一个数字。如何计算每个测试和火车之间的距离一个循环 ?因为在我计算欧几里得的代码中,它给出了输出零。

3)如何使用混淆矩阵计算精度?

% number of train data
Train = 30;
%number of test data
Test =10;
% to store my images
tData = uint8(zeros(160,160,30));
tTest = uint8(zeros(160,160,10));


for k=1:Test 
  s1='im-';
  s2=num2str(k);
  t = strcat('testy/im-',num2str(k),'.jpg'); 
  im=rgb2gray(imread(t));
  I=imresize(im,[160 160]);
  tTest(:,:,k)=I;


  %case testing if it belongs to zero     

  for l=1:3

   ss1='zero-';
   ss2=num2str(l);
   t1 = strcat('data/zero-',num2str(l),'.jpg'); 
   im1=rgb2gray(imread(t1));

   I1=imresize(im1,[160 160]);
   tData(:,:,l)=I1;

  % Euclidean distance 
 distance= sqrt(sum(bsxfun(@minus, tData(:,:,k), tTest(:,:,l)).^2, 2));
   [d,index] = sort(distance);
  %k=3
   % index_close(l) = index(l:3);
   %x_close = I(index_close,:);

  end      
end

2 个答案:

答案 0 :(得分:0)

首先,我认为10个测试数据还不够。 只需使用以下功能,data_test是您的训练数据(),data_label是他们的标签。将图像重新调整为更小的尺寸! 我认为默认距离度量是欧几里德距离,但您可以选择其他方式,例如City-block方法。

Class = knnclassify(data_test, data_train, lab_train, 11);
fprintf('11-NN Accuracy: %f\n', sum(Class == lab_test')/length(lab_test));


Class = knnclassify(data_test, data_train, lab_train, 1, 'cityblock');
fprintf('1-NN Accuracy (cityblock): %f\n', sum(Class == lab_test')/length(lab_test));

好了,现在你有整体的准确性,但这不是一个好的衡量标准,最好分别计算每个班级的准确度,然后计算他们的平均值。 你可以像这样计算一个特定的类(id)精度,

    idLocations = (lab_test == id);
    NumberOfId = sum(idLocations); 
    NumberOfCurrect =sum (lab_test (idLocations) == Class(idLocations));
    NumberOfCurrect/NumberOfId %Class id accuracy

答案 1 :(得分:0)

你的问题是:

1)图像重新调整尺寸确实会影响整个过程的准确性。 答:正如您在问题中提到的,您的图片尺寸已经是160 x 160,imresize不会影响它,但如果您的图片尺寸太小而不是60 * 60,它会执行插值以增加空间图像的尺寸,可能会影响数字的结构和形状,以解决这些变化,你的训练数据应该有更多的样本(每个类至少50个样本),并且一些预处理应该应用于数据,如数字图像的偏斜。

2)欧几里德距离是一个很好的衡量标准,但不是处理这类问题的最佳方法,因为它的分布是球形分布,它可以给不同的数字提供相同的距离。如果你在MATLAB中工作,要注意变量转换,你就会有所不同,所以这个变量本质上应该是双倍的。这可能是错误距离计算的原因之一。在这一行distance= sqrt(sum(bsxfun(@minus, tData(:,:,k), tTest(:,:,l)).^2, 2));中,你是逐列求矩阵,所以这个输出将是一个行向量(1×160),它在每个角上都有和。我认为它应该是这样的:distance= sqrt(sum(sum(bsxfun(@minus, tData(:,:,k), tTest(:,:,l)).^2, 2)));我刚刚在那里增加了一笔金额来获得整个矩阵的差异总和尝试它是否有帮助。

3)为了精确检查分类器的准确性,顺便说一下,你必须有一个大的训练数据集,在交叉验证过程中创建的混淆矩阵,你将训练数据分成训练样本和测试样本,所以你知道样本中的输出类,现在执行分类过程,为num_classe X num_classes(在你的情况下为10 X 10)准备一个矩阵,其中行类似于实际类,列属于预测。从测试中获取样本并预测输出类,假设您的分类器预测为5,并且样本的实际类也在confusion_matrix(5,5)中输入+1;如果您的分类器已将其预测为3,则应在confusion_matrix(5,3)处执行+1。最后添加confusion_mat的对角元素,并将其除以测试样本的总数。输出将是分类器的准确性。

P.S。尝试每班至少50个样本,并在交叉验证期间将训练数据除以85:10的比例,其中90%的样本应用于训练,其余10%应用于测试分类器。

希望它对你有所帮助。 随时分享您的想法。

谢谢