天天看點

模式識别導論(實驗三) 基于感覺器算法的數字識别

實驗要求:

    1、資料集:

      a) 訓練資料集:“實驗圖像“—”訓練集“目錄下,包含”0“,”1“,…, ”9“共10個子目錄,每一個子目錄下包含對應的數字圖像。對于每一個數字,有20張64×64的訓練圖像。

      b)測試資料集:“實驗圖像“—”測試集“目錄下,包含”0“,”1“,…, ”9“共10個子目錄,每一個子目錄下包含對應的數字圖像。對于每一個數字,有5張64×64的測試圖像。

    2、基本要求:兩個數字(6’,‘9’)的識别,即給定一幅包含單個數字(‘6’或者‘9’)的64×64圖像,程式自動識别出其中的數字。

    3、附加要求:十個數字(‘0’,‘1’,…, ‘9’)的識别,即給定一幅包含單個數字(‘0’,‘1’, …, 或者‘9’)的64×64圖像,程式自動識别出其中的數字。

實驗分析:

對于兩個數字(6’,‘9’)的識别:

首先讀入圖檔,将其01二值化,原理為,計算像素點RGB的和,如果和大于300,判定為空白區域,置為0,否則置為1。

模式識别導論(實驗三) 基于感覺器算法的數字識别

感覺器算法: 

模式識别導論(實驗三) 基于感覺器算法的數字識别

ρ自行取值,在本次實驗中我取0.14效果最好。 

模式識别導論(實驗三) 基于感覺器算法的數字識别

接下來進行測試集測試,測試函數代碼實作如下

模式識别導論(實驗三) 基于感覺器算法的數字識别

在p為0.14的情況下得到的結果如下:

模式識别導論(實驗三) 基于感覺器算法的數字識别

即對6、9二分類,在p為0.14的情況下得到的增光權向量,對測試集分類正确率為100%。在二分類實驗中,因為正确率可達到100%,故沒有對圖檔進行預處理。

附加要求:十個數字(‘0’,‘1’,…, ‘9’)的識别,即給定一幅包含單個數字(‘0’,‘1’, …, 或者‘9’)的64×64圖像,程式自動識别出其中的數字。

  實作如下:

首先,對讀入的圖檔進行預處理,進行圖像分割。

整個過程分兩部,左右分割和上下分割。基本思想是,找到四個點,即連接配接成四條直線,使四條直線最小包含數字。下列代碼為找到最左和最右的列号,以及最上最下的列号。

由于學識淺薄,是以預處理比較粗糙。

模式識别導論(實驗三) 基于感覺器算法的數字識别

 之後利用OpenCV的resize将選出的包圍的像素點,重構成32*32的圖檔,完成預處理。

模式識别導論(實驗三) 基于感覺器算法的數字識别

多分類的三種方法,我采用的方法為:

模式識别導論(實驗三) 基于感覺器算法的數字識别

原因是,該方法将M個分類僅僅分為M個分類,沒有不确定區等其他情況。

訓練主要代碼如下,基本過程類似于二分類。:

模式識别導論(實驗三) 基于感覺器算法的數字識别

test測試代碼如下:

    用每個增光權向量×測試集,找到結果最大的w的下标,判斷是否分類正确。

模式識别導論(實驗三) 基于感覺器算法的數字識别

多分類結果:

在p選擇為0.01的情況下:

模式識别導論(實驗三) 基于感覺器算法的數字識别

在手動選擇的若幹p值中,最優正确率即為96%。

如果不進行圖檔的預處理,正确率在60%左右,正确率很低,是以想到了圖檔分割重構。

實驗代碼:

二分類:

import numpy as np
from matplotlib import pyplot as plt
import cv2

def test(oumiga, list_test, w):

    fail_count = 0
    temp = w * list_test
    temp = np.sum(temp, axis=1)
    for i in range(0, len(list_test)):
        if ((oumiga[i] == 1 and temp[i] <= 0) or (oumiga[i] == -1 and temp[i] >= 0)):
            fail_count += 1

    print('錯誤的數量為:' + str(fail_count) + '    正确率為:' + str(int((1 - (fail_count / len(list_test))) * 100)) + '%')


def train(oumiga, list_train):
    p = 0.14  #損失代價比例
    w = np.asarray([1] * 4097) #增廣權矢量

    fail_count = 1
    while (fail_count != 0):
        fail_count = 0
        temp = w * list_train
        temp = np.sum(temp, axis=1)
        for i in range(0, 40):
            if (temp[i] <= 0 and oumiga[i] == 1):   #如果是6并且小于0
                w = w + p * list_train[i]
                fail_count += 1
            elif (temp[i] >= 0 and oumiga[i] == -1): #如果是9并且大于0
                w = w - p * list_train[i]
                fail_count += 1
        print(fail_count)
        print('增廣權矢量w為:')
        print(w)
    return w #增廣權矢量


if __name__ == "__main__":
    PATH = 'C:/Users/lishu/Desktop/code/PatternRecognition/experience3/'

    list_img = []
    for j in [6,9]:
        for i in range(1,21):
            img = cv2.imread(PATH + 'train/' + str(j) + '/' + str(j) + '-' + str(i) + '.png')
            #把圖檔01兩值化
            temp = np.asarray(img)
            temp = temp.reshape(-1, 3)
            temp = np.sum(temp, axis=1)
            temp = np.where(temp > 300, 0, 1) #RGB和大于300,判定為空白區域,置為0,否則為1
            temp = np.append(temp,1)

            list_img.append(temp.tolist())

    #第二類乘-1處理
    # temp_list1 = [[1] * 4096] * 20
    # temp_list2 = [[-1] * 4096] * 20
    # temp_list1 = [[1]] * 20
    # temp_list2 = [[-1]] * 20
    # temp_fen = temp_list1 + temp_list2
    # temp_fen = np.asarray(temp_fen).reshape(40,-1)
    #
    #
    list_img = np.asarray(list_img)

    # temp = temp_fen * list_img

    oumiga = [1] * 20 + [-1] * 20 #存儲對應訓練集所屬的類

    w = train(oumiga,list_img) #得到增廣權矢量

    #測試集測試
    list_test = []
    for j in [6,9]:
        for i in range(1,6):
            img = cv2.imread(PATH + 'test/' + str(j) + '/' + str(j) + '-' + str(i) + '.png')
            temp = np.asarray(img)
            temp = temp.reshape(-1, 3)
            temp = np.sum(temp, axis=1)
            temp = np.where(temp > 300, 0, 1)
            temp = np.append(temp,1)
            list_test.append(temp.tolist())

    list_test = np.asarray(list_test)

    oumiga_test = [1]*5 + [-1]*5
    test(oumiga_test,list_test,w)
    list_img = np.asarray(list_img)
           

 多分類:

import numpy as np
from matplotlib import pyplot as plt
import cv2

def test(oumiga, list_test, w):
    fail_count = 0

    for i in range(0, len(list_test)):
        temp = w * list_test[i]
        temp = np.sum(temp, axis=1)
        max_index = temp.argmax()
        if max_index != oumiga[i]:
            fail_count += 1
    print('錯誤的數量為:' + str(fail_count)  + '    正确率為:' +  str(int((1 - (fail_count / len(list_test))) * 100)) + '%')


def train(oumiga, list_train):

    p = 0.01 #損失代價比例
    w = np.asarray([[1] * 1025] * 10) #增廣權矢量
    w = w.astype(float)
    fail_count = 1
    count = 0
    while (fail_count != 0):
        count += 1
        fail_count = 0
        for j in range(0,10):
            temp = w[j]* list_train
            temp = np.sum(temp, axis=1)

            for i in range(0, 20*10):
                if (oumiga[i] == j and temp[i] <= 0):  #如果正确分類的結果<0
                    w[j] = w[j] + p * list_train[i]
                    fail_count += 1
                elif(oumiga[i] != j and temp[i] >= 0): #如果錯誤分類的結果>0
                    w[j] = w[j] - p * list_train[i]
                    fail_count += 1
        print(fail_count)
        print(w)
    print('疊代的次數為:' + str(count))
    return w

def preprocess(img):
    img = img.reshape(64,64)
    #分别存儲圖檔上下左右對應的有可用點的行和列
    up = 63
    down = 0
    right = 0
    left = 63
    for i in range(64):
        for j in range(64):
            if (img[i][j] == 1):
                up = min(up, i)
                down = max(down, i)
                left = min(left, j)
                right = max(right, j)

    #重構預處理
    new_img = []
    for i in range(up, down+1):
        temp = []
        for j in range(left, right+1):
            if (img[i][j] == 0):
                temp.append([255,255,255])
            else:
                temp.append([0,0,0])
        new_img.append(temp)

    #把圖檔兩值化
    new_img = np.asarray(new_img).astype("uint8")

    #圖檔resize重構
    new_img = cv2.resize(new_img, (32,32))
    new_img = new_img.reshape(-1, 3)
    new_img = np.sum(new_img, axis=1)
    new_img = np.where(new_img > 300, 0, 1)
    new_img = np.append(new_img, 1)

    return new_img
    # cv2.imwrite('C:/Users/lishu/Desktop/code/PatternRecognition/experience3/img.png', new_img, [int(cv2.IMWRITE_JPEG_QUALITY), 100])

if __name__ == "__main__":
    PATH = 'C:/Users/lishu/Desktop/code/PatternRecognition/experience3/'

    list_img = []
    for j in [x for x in range(0,10)]:
        for i in range(1,21):
            img = cv2.imread(PATH + 'train/' + str(j) + '/' + str(j) + '-' + str(i) + '.png')
            # 把圖檔01兩值化
            temp = np.asarray(img)
            temp = temp.reshape(-1, 3)
            temp = np.sum(temp, axis=1)
            temp = np.where(temp > 300, 0, 1)
            # 預處理 去除多餘空白,重構圖檔
            temp = preprocess(temp)

            list_img.append(temp.tolist())
    list_img = np.asarray(list_img)
    oumiga = []  #存儲對應訓練集所屬的類
    for x in range(0,10):
        oumiga = oumiga + [x] * 20

    w = train(oumiga,list_img) #得到增廣權矢量

    #測試集測試
    list_test = []
    for j in [x for x in range(0,10)]:
        for i in range(1,6):
            img = cv2.imread(PATH + 'test/' + str(j) + '/' + str(j) + '-' + str(i) + '.png')
            temp = np.asarray(img)
            temp = temp.reshape(-1, 3)
            temp = np.sum(temp, axis=1)
            temp = np.where(temp > 300, 0, 1)
            temp = preprocess(temp)  # 預處理

            list_test.append(temp.tolist())

    list_test = np.asarray(list_test)
    oumiga_test = []
    for x in range(0,10):
        oumiga_test = oumiga_test + [x] * 5

    test(oumiga_test,list_test,w)
           

需要實驗圖檔或者有疑問的的小夥伴可以聯系我。

繼續閱讀