天天看點

機器學習實戰:K-近鄰(KNN)算法識别26個大寫英文字母(A到Z)(含拍照檢驗步驟詳解)

步驟一:收集資料集

資料集來自于Character Recognition in Natural Images網站。

具體的檔案連結為:link 中的EnglishHnd.tgz檔案。

在該檔案夾中,Img檔案内含有Sample001—Sample062等62個檔案,每個檔案中含有55張900*1200像素的圖檔。其中Sample001—Sample010檔案中是0-9數字的圖像;其中Sample011—Sample036檔案中是26個大寫英文字母的圖像;Sample037—Sample062檔案中是26個小寫英文字母的圖像。

本文中,隻使用Sample011—Sample036檔案,處理大寫英文字母圖像。

步驟二:批量處理圖像

1.由于每一幅圖像像素點都為900 * 1200,每一個檔案夾中含有55幅圖檔,26個英文字母有26個檔案夾,則最終訓練的0,1資料量将要達到

z = 900 ∗ 1200 ∗ 55 ∗ 26 = 1544400000   z = 900*1200*55*26=1544400000\, z=900∗1200∗55∗26=1544400000

處理這麼大的資料量,在pycharm環境中,用python處理這些資料時,如果不用GPU加速,可能會提示memory error錯誤。

是以,需要把檔案夾中的圖檔像素按比例處理到大小為75*100。

2.用Photoshop批量處理圖像(CS5.1版本)的具體步驟如下:

① 在ps中打開Sample011檔案夾中的圖像img011-001.png。

② 按下‘Alt+F9’,出現動作欄:

機器學習實戰:K-近鄰(KNN)算法識别26個大寫英文字母(A到Z)(含拍照檢驗步驟詳解)

③ 建立動作,并點選記錄(動作名稱自取)。

機器學習實戰:K-近鄰(KNN)算法識别26個大寫英文字母(A到Z)(含拍照檢驗步驟詳解)
機器學習實戰:K-近鄰(KNN)算法識别26個大寫英文字母(A到Z)(含拍照檢驗步驟詳解)

④ 點選:圖像——圖像大小——修改像素點大小,并限制比例——确定

機器學習實戰:K-近鄰(KNN)算法識别26個大寫英文字母(A到Z)(含拍照檢驗步驟詳解)

⑤ 點選:檔案——儲存——檔案——關閉

⑥點選下圖所示按鈕停止動作:

機器學習實戰:K-近鄰(KNN)算法識别26個大寫英文字母(A到Z)(含拍照檢驗步驟詳解)

⑦動作錄入結束。之後可以點選檔案——自動——批處理來處理檔案夾中的所有圖像,但是我一打開PS批處理就會自動彈出,不知道什麼原因。是以,我使用另外一種方法,打開到Sample011檔案夾,把所有的圖像都一起拖到PS面闆中:

機器學習實戰:K-近鄰(KNN)算法識别26個大寫英文字母(A到Z)(含拍照檢驗步驟詳解)

⑧拖到PS面闆後,對每一副圖像都點選如下按鈕。記得光标要讓移動到自己命名的動作上。就可以對每一副圖像進行處理。(笨辦法,但是很有效,每2分鐘大約能處理55張圖檔)

機器學習實戰:K-近鄰(KNN)算法識别26個大寫英文字母(A到Z)(含拍照檢驗步驟詳解)

這樣,就可以依次處理Sample011—Sample036等26個檔案中的圖像。處理後,這些檔案夾中圖檔的像素大小都變為了75*100。

步驟三:批量處理圖像,轉化為二進制‘txt’檔案

用MATLAB處理,把這26個檔案夾中的每一副圖像處理為一個1*7500的數組并儲存在另一個檔案夾中,轉換為相應的txt檔案。

此時,我的Sample檔案路徑在:

E:\Machinelearning\MachineLearninginAction\DEMO\machinelearninginaction\Ch02\EnglishHnd\Img
           

轉換後的TXT檔案名稱為’0_0’到’0_54’,再到’25_54’。’ _ ‘之前的數為26個英文字母的序列,如0對應A,1對應B,以此類推;’_'之後的數為55張照片轉換成的對應的檔案。

批量轉換為相應txt檔案的MATLAB代碼為:

%識别26個大寫字母
for i=11:36      %i為檔案夾Sample011—Sample036,如果需要識别小寫字母的,則改成i=37:62
    Jia_numble=int2str(i);   %i轉化為字元串形式
    Wenjianjia_name=strcat('Sample0',strcat(Jia_numble,'\'));   %把兩字元串結合在一起
    file_pathshort =  'E:\Machine learning\MachineLearninginAction\DEMO\machinelearninginaction\Ch02\EnglishHnd\Img\';  %存儲圖像的檔案夾路徑
    file_path=strcat(file_pathshort,Wenjianjia_name)
    img_path_list = dir(strcat(file_path,'*.png'));   %擷取該檔案夾中所有'png'格式的圖像名稱
    img_num = length(img_path_list);                  %擷取圖像總數量
    Matrix=zeros(55,7500);                            %55幅圖檔,像素點為75*100
    if img_num > 0                                    %有滿足條件的圖像
	    for j = 1:img_num                             %逐一讀取圖像
		    image_name = img_path_list(j).name;       % 圖像名,如‘img011-041.png’
        
		    I = imread(strcat(file_path,image_name));
		    fprintf('%d %d %s\n',j,img_num,strcat(file_path,image_name))   % 顯示正在處理的圖像名
		
            i1=rgb2gray(I);           %i1灰階圖像
        
            i2=im2bw(i1);             % i2是二值圖像,不需要求門檻值
        
		    %圖像處理過程
		    N=size(i2)                %求圖像維數

		    %轉換為一維數組
		    re=reshape(i2,1,prod(N)); % prod是累乘,prod(N)=75*100=7500
		
            re=~re;        %數組取反
        
		    %放在矩陣裡
		    Matrix(j,:)=re;           %Matrix每一行中為檔案中圖像的
        end
    end

    str1=int2str(i-11)                %str1是從0開始,一直到26的整數,為txt檔案夾的名字
    str2=strcat(str1,'_')

    for N = 1:img_num
        chr = int2str(N-1)               %N轉化為字元串形式
        file_retrit='E:\Machine learning\MachineLearninginAction\DEMO\machinelearninginaction\Ch02\EnglishHnd\txt\';
        str=strcat(file_retrit,strcat(strcat(str2,chr),'.txt'))    
        fid=fopen(str,'wt');             %寫的方式打開檔案(若不存在,建立檔案);
        fprintf(fid,'%d',Matrix(N,:));   % d 表示以整數形式寫入資料,這正是我想要的;
        fclose(fid);                     %關閉檔案
    end
    
 end
           

代碼運作結束後,可以在txt檔案夾中找到各種txt檔案,如下圖:

機器學習實戰:K-近鄰(KNN)算法識别26個大寫英文字母(A到Z)(含拍照檢驗步驟詳解)

為了便于了解,把該檔案夾改名為:training_A_TO_Z(訓練集資料檔案)。

步驟四:用手機拍照并把二值化後的像素矩陣存為txt檔案

①在紙上寫一個大寫的B,并用手機拍照:

機器學習實戰:K-近鄰(KNN)算法識别26個大寫英文字母(A到Z)(含拍照檢驗步驟詳解)

②用手機自行剪輯的小一點:

機器學習實戰:K-近鄰(KNN)算法識别26個大寫英文字母(A到Z)(含拍照檢驗步驟詳解)

③然後,用 link 中用PS處理數字2的方法,處理該圖檔,改成75*100像素大小。

再用MATLAB處理該圖像,得到一組測試集文本檔案:test_b_recognise.txt

MATLAB代碼如下:

%單個圖檔轉化為txt檔案
i=imread('E:\Machine learning\MachineLearninginAction\DEMO\machinelearninginaction\Ch02\B.jpg'); %圖檔的存儲路徑
i1=rgb2gray(i);    %i1灰階圖像
i2=im2bw(i1);      %i2是二值圖像,不需要求門檻值
for j=1:75
    for k=1:100
        if i2(j,k)==0
            i2(j,k)=1;
        else
            i2(j,k)=0;
        end
    end
end
fid=fopen('E:\Machine learning\MachineLearninginAction\DEMO\machinelearninginaction\Ch02\test_b_recognise.txt','wt'); %寫的方式打開檔案(若不存在,建立檔案);
fprintf(fid,'%d',i2);    %d 表示以整數形式寫入資料,這正是我想要的;
fclose(fid);             %關閉檔案
           

步驟五:用KNN算法識别大寫字母

所用到的Python代碼及其解釋如下:

from numpy import *
import operator
from os import listdir

def classify0(inX, dataSet, labels, k):   #對于該函數的解釋,見後面圖中
    dataSetSize = dataSet.shape[0]
    diffMat = tile(inX, (dataSetSize,1)) - dataSet
    sqDiffMat = diffMat**2
    sqDistances = sqDiffMat.sum(axis=1)  #every hang add together
    distances = sqDistances**0.5
    sortedDistIndicies = distances.argsort()
    classCount={}          
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]

def img_myself_A_TO_Z(filename):   #該函數是針對文本中為1*7500的數組進行處理,傳回一個1*7500的數組
    returnVect=zeros((1,7500))
    fr=open(filename)
    lineStr=fr.readline()          #讀取一行,即1*7500個字元
    for i in range(7500):
        returnVect[0,i]=int(lineStr[i])
    return returnVect

def handwriting_A_TO_Z(filename):  #filename為待測試的txt檔案,本例中為'test_b_recognise.txt'檔案
    hwLabels = []
    trainingFileList = listdir('training_A_TO_Z')  #儲存訓練集'training_A_TO_Z'檔案夾中所有的檔案名到清單trainingFileList中
    m = len(trainingFileList)
    trainingMat = zeros((m, 7500))                #每行儲存一個圖像
    for i in range(m):
        fileNameStr = trainingFileList[i]         #第i個檔案的檔案名儲存在fileNameStr中,如‘0_0.txt’
        fileStr = fileNameStr.split('.')[0]       #把檔案名用‘.’分開成兩部分,取第一部分,如把‘0_0.txt’分開成‘0_0’與‘txt’兩部分,0代表取前一部分
        classNumStr = int(fileStr.split('_')[0])  #同理,取‘0_0’中前一部分0,并轉換為int類型
        hwLabels.append(classNumStr)              #訓練集的标簽矩陣
        trainingMat[i, :] = img2vector('training_A_TO_Z/%s' % fileNameStr)   #打開training_A_TO_Z檔案夾下的檔案,讀取并轉化為1*7500的矩陣後,添加到trainingMat的對應行中,組成訓練集的矩陣
    test_myself=img_myself(filename)              #讀取filename檔案并轉化為1*7500的矩陣,組成測試集
    test_myself_label=classify0(test_myself,trainingMat,hwLabels,5)   #進行訓練并測試,把結果放到test_myself_label中
    print("The test_myself_label is ",test_myself_label)

    List1=['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'] #把結果轉化為對應的字母

    print("The test_myself_label is ",List1[test_myself_label])
           

classify0()函數的解釋如下圖:

機器學習實戰:K-近鄰(KNN)算法識别26個大寫英文字母(A到Z)(含拍照檢驗步驟詳解)

最後檢驗識别效果:

得到運作結果:

機器學習實戰:K-近鄰(KNN)算法識别26個大寫英文字母(A到Z)(含拍照檢驗步驟詳解)

識别正确!

繼續閱讀