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

Matlab 用于简单数字识别的KNN分类器,matlab,image-processing,computer-vision,pattern-recognition,Matlab,Image Processing,Computer Vision,Pattern Recognition,事实上,我有一个任务,需要识别单个十进制数字,作为文本识别过程的一部分。我已经收到一组JPEG格式的某些数字的图像。每个图像的大小为160 x 160像素。在检查了此处的一些资源后,我成功地编写了此代码,但: 1) 我不确定读取图像并在矩阵中调整大小以容纳它们是否正确 2) 假设我有30个数字[0-9]的列车数据图像,每个数字有三个图像,我有10个测试图像,每个图像只有一个数字。如何计算每个测试和循环中列车之间的距离?因为在我的计算欧几里德的代码中,它给出了一个零输出 3) 如何利用混淆矩阵计算

事实上,我有一个任务,需要识别单个十进制数字,作为文本识别过程的一部分。我已经收到一组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

首先,我认为10个测试数据是不够的。 只需使用下面的函数,data_test是您的训练数据(),data_label是它们的标签。将图像大小重新调整为较小的大小! 我认为默认的距离度量是欧几里德距离,但您可以选择其他方法,例如城市街区方法

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

首先,我认为10个测试数据是不够的。 只需使用下面的函数,data_test是您的训练数据(),data_label是它们的标签。将图像大小重新调整为较小的大小! 我认为默认的距离度量是欧几里德距离,但您可以选择其他方法,例如城市街区方法

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) 图像重新调整大小会影响整个过程的准确性。 回答:正如您在问题中提到的,您的图像已经是160 x 160的大小,
imresize
不会影响它,但是如果您的图像太小,比如说60*60,它将执行插值以增加图像的空间尺寸,这可能会影响数字的结构和形状,以解决这些变化,你们的训练数据应该有更多的样本(每堂课至少50个样本),并且一些预处理应该应用在数据上,比如数字图像的去偏

2) 欧几里德距离是很好的度量,但不是处理这类问题的最佳方法,因为它的分布是一个球形分布,它可以为不同的数字提供相同的距离。如果您在MATLAB中工作,请注意变量转换的问题,您将取差,因此这两个变量本质上都应该是双变量。这可能是距离计算错误的原因之一。在这一行中,
distance=sqrt(总和(bsxfun(@减号,tData(:,:,k),tTest(:,:,l))。^2,2)
您是按列求和矩阵,因此该矩阵的输出将是一个行向量(1 X 160),每个角都有和。我认为应该是这样的:
distance=sqrt(sum(sum(bsxfun(@减号,tData(:,:,k),tTest(:,:,l))。^2,2))我刚刚在那里添加了一个求和,用于获取整个矩阵的差异之和,无论是否有用,都可以尝试

3) 为了精确地检查分类器的准确性,您必须有一个大的训练数据集,顺便说一句,在交叉验证过程中创建了混淆矩阵,您将训练数据分为训练样本和测试样本,这样您就知道样本中的输出类,现在执行分类过程,为num_classe X num_类(在您的例子中是10 X 10)准备一个矩阵,其中行类似于实际的类,列属于预测。从test and predict output类中抽取一个样本,假设您的分类器predict 5,样本的实际类也是5,并将+1放入混淆矩阵(5,5);如果你的分类器预测它为3,你应该在混淆矩阵(5,3)上做+1。最后,添加矩阵的对角线元素,并将其除以测试样本总数。输出将是您的分类器的准确性

另外,每堂课至少有50个样本,在交叉验证期间,将训练数据按85:10的比例划分,其中90%的样本用于训练,其余10%用于测试分类器

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


谢谢你,因为你的问题是:

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

2) 欧几里德距离是很好的度量,但不是处理这类问题的最佳方法,因为它的分布是一个球形分布,它可以为不同的数字提供相同的距离。如果您在MATLAB中工作,请注意变量转换的问题,您将取差,因此这两个变量本质上都应该是双变量。这可能是距离计算错误的原因之一。在这一行中,
distance=sqrt(总和(bsxfun(@减号,tData(:,:,k),tTest(:,:,l))。^2,2)
您是按列求和矩阵,因此该矩阵的输出将是一个行向量(1 X 160),每个角都有和。我认为应该是这样的:
distance=sqrt(sum(sum(bsxfun(@减号,tData(:,:,k),tTest(:,:,l))。^2,2))我刚刚在那里添加了一个求和,以获得整个matr的差异之和