(2D-2D PCA)算法实现

import numpy as np
from PIL import Image
import time
from numpy.core.fromnumeric import size
from numpy.lib.function_base import append, cov
import copy

def PCAReg(train_samples, test_samples, rate):
    print('----------------------PCA------------------------------')
    time_0 = time.time()
    M = len(train_samples)

    for i in range(0,len(train_samples)):
        train_samples[i] = train_samples[i].flatten()
    for i in range(0,len(test_samples)):
        test_samples[i] = test_samples[i].flatten()
    train_samples_orgin = copy.deepcopy(train_samples)#必须备份一次
    pic_shape = train_samples[0].shape
    print(pic_shape)#(10304,)
    # print(train_samples)
    #中心化
    mean_pic = np.zeros(pic_shape)
    for p in train_samples:
        mean_pic = mean_pic + p
    mean_pic = mean_pic/float(len(train_samples))
    # print(mean_pic)
    for i in range(0,len(train_samples)):
        train_samples[i] = train_samples[i] - mean_pic
    M = len(train_samples)
   
    print(train_samples[0].shape)#(10304,)
    pic_all = train_samples[0]
    for i in range(1,M):
        #垂直拼接
        pic_all = np.vstack( (pic_all,train_samples[i]) )
    print(pic_all.shape)#(200, 10304)
    # print(pic_all)

    #计算协方差矩阵
    cov_m = np.zeros((pic_all.shape[1],pic_all.shape[1]))
    cov_m = np.dot(pic_all.T,pic_all)
    # print('协方差矩阵为')
    # print(cov_m)
    print('协方差矩阵shape')
    print(cov_m.shape)#(10304, 10304)

    #求特征值与特征向量
    cval, cvec = np.linalg.eig(cov_m)#耗时大,调试时不用
    # cval = np.random.rand(5600)
    # cvec = np.random.rand(5600,5600)
    print(cval.shape)#(10304,)
    print(cvec.shape)#(10304, 10304)
    sorted_index = np.argsort(cval)
    cval.sort()
    cval_sorted = cval
    cval_sorted = cval_sorted[::-1]
    # print('特征值从大到小')
    # print(cval_sorted)
    #求特征向量的总和
    sum_cval = 0
    for c in cval:
        sum_cval += c
    dim_cnt = 0
    cval_sum = 0#组成投影矩阵的特征向量的特征值总和
    while cval_sum < rate * sum_cval:
        cval_sum = cval_sum + cval_sorted[dim_cnt]
        dim_cnt = dim_cnt + 1
    print('特征值总和')
    print(sum_cval)
    print('选取的特征值总和')
    print(cval_sum)
    print('选取的特征值的个数')
    print(dim_cnt)
    #构造投影矩阵
    # X = cvec[sorted_index[:-dim_cnt-1:-1],:]
    X = cvec[:,sorted_index[:-dim_cnt-1:-1]]#尝试一下是不是列的问题

    print('投影矩阵shape')
    print(X.shape)#(110, 10304)

   
    tra_loc = []
    tst_loc = []
    kk = 1
    for p in train_samples_orgin:
        img_loc = np.empty((dim_cnt,),dtype=float)#错在此处
        # if kk == 1:
        #     print('np.dot(np.dot(p,X.T),X) .shape')
        #     print(np.dot(p,X.T).shape)
        #     kk=0
        img_loc = np.dot(X.T,p).flatten()
        tra_loc.append(img_loc)
    tra_loc_np = tra_loc[0]
    for i in range(1,len(tra_loc)):
        tra_loc_np = np.vstack((tra_loc_np, tra_loc[i]))
        # print('tra_loc_np.shape')
        # print(tra_loc_np.shape)
   
    for p in test_samples:
        img_loc = np.empty((dim_cnt,),dtype=float)
        img_loc = np.dot(X.T,p).flatten()
        tst_loc.append(img_loc)
    tst_loc_np = tst_loc[0]
    for i in range(1,len(tst_loc)):
        tst_loc_np = np.vstack((tst_loc_np,tst_loc[i]))
    print('tra_loc_np的shape为')
    print(tra_loc_np.shape)
    print('tst_loc_np的shape为')
    print(tst_loc_np.shape)

    min_dist_sample = np.zeros((len(tst_loc_np),),dtype=int)
    for i in range(0,len(tst_loc_np)):
        min_dist = float('inf')
        for j in range(0,len(tra_loc_np)):
            dist = np.linalg.norm(tst_loc_np[i] - tra_loc_np[j])
            if dist < min_dist:
                min_dist = dist
                min_dist_sample[i] = j
    # print(min_dist_sample)
    true_num = 0
    for i in range(0,len(min_dist_sample)):
        if(min_dist_sample[i]//5 == i//5):#坑爹,Python整除是//
            true_num = true_num + 1
    print('PCA人脸识别准确率为:' + str(true_num * 1.0/len(test_samples)) )
    time_1 = time.time()
    print('PCA人脸图像表示和识别共耗时: ' + str(time_1-time_0)+'  秒')
def PCA2DReg(train_samples, test_samples, rate):
    print('----------------------2DPCA------------------------')
    time_0 = time.time()
    train_samples_orgin = copy.deepcopy(train_samples)
    #图片矩阵大小m*n pic_shape = (n,m)
    pic_shape = train_samples[0].shape
    print('pic_shape:')
    print(pic_shape)#(80, 70)

    #求均值
    mean_pic = np.zeros(pic_shape)
    for p in train_samples:
        mean_pic = mean_pic + p
    mean_pic = mean_pic/float(len(train_samples))

    #求协方差矩阵
    #大小n*n
    cov_m = np.zeros((pic_shape[1],pic_shape[1]),dtype=float)
    for tra_s in train_samples:
        #中心化
        diff = tra_s - mean_pic
        #求协方差矩阵
        cov_m = cov_m + np.dot(diff.T,diff)
    cval, cvec = np.linalg.eig(cov_m)
    print('cvec.shape')
    print(cvec.shape)
    sorted_index = np.argsort(cval)
    cval.sort()
    cval_sorted = cval
    cval_sorted = cval_sorted[::-1]
    # print('特征值从大到小')
    # print(cval_sorted)
    #求特征向量的总和
    sum_cval = 0
    for c in cval:
        sum_cval += c
    dim_cnt = 0
    cval_sum = 0#组成投影矩阵的特征向量的特征值总和
    while cval_sum < rate * sum_cval:
        cval_sum = cval_sum + cval_sorted[dim_cnt]
        dim_cnt = dim_cnt + 1
    print('特征值总和')
    print(sum_cval)
    print('选取的特征值总和')
    print(cval_sum)
    print('选取的特征值的个数')
    print(dim_cnt)
    #构造投影矩阵
    X = cvec[:,sorted_index[:-dim_cnt-1 : -1]]
    print('投影矩阵shape')
    print(X.shape)#(70, 20)
    tra_loc = []
    tst_loc = []
    for p in train_samples_orgin:
        img_loc = np.empty((dim_cnt,),dtype=float)#错在此处
        img_loc = np.dot(p,X).flatten()
        tra_loc.append(img_loc)
    tra_loc_np = tra_loc[0]
    for i in range(1,len(tra_loc)):
        tra_loc_np = np.vstack((tra_loc_np, tra_loc[i]))
        # print('tra_loc_np.shape')
        # print(tra_loc_np.shape)
   
    for p in test_samples:
        img_loc = np.empty((dim_cnt,),dtype=float)
        img_loc = np.dot(p,X).flatten()
        tst_loc.append(img_loc)
    tst_loc_np = tst_loc[0]
    for i in range(1,len(tst_loc)):
        tst_loc_np = np.vstack((tst_loc_np,tst_loc[i]))
    # print('tra_loc_np的shape为')
    # print(tra_loc_np.shape)
    # print('tst_loc_np的shape为')
    # print(tst_loc_np.shape)

    min_dist_sample = np.zeros((len(tst_loc_np),),dtype=int)
    for i in range(0,len(tst_loc_np)):
        min_dist = float('inf')
        for j in range(0,len(tra_loc_np)):
            dist = np.linalg.norm(tst_loc_np[i] - tra_loc_np[j])
            if dist < min_dist:
                min_dist = dist
                min_dist_sample[i] = j
    # print(min_dist_sample)
    true_num = 0
    for i in range(0,len(min_dist_sample)):
        if(min_dist_sample[i]//5 == i//5):#坑爹,Python整除是//
            true_num = true_num + 1
    print('2DPCA人脸识别准确率为:' + str(true_num * 1.0/len(test_samples)) )
    time_1 = time.time()
    print('2DPCA人脸图像表示和识别共耗时: ' + str(time_1-time_0)+'  秒')
def PCA2DAlternativeReg(train_sampls,test_samples, rate):
    print('----------------Alternative2DPCA--------------------')
    time_0 = time.time()
    train_samples_orgin = copy.deepcopy(train_samples)
    #图片矩阵大小m*n pic_shape = (n,m)
    pic_shape = train_samples[0].shape
    print('pic_shape:')
    print(pic_shape)#(80, 70)

    #求均值
    mean_pic = np.zeros(pic_shape)
    for p in train_samples:
        mean_pic = mean_pic + p
    mean_pic = mean_pic/float(len(train_samples))

    #求协方差矩阵
    #大小n*n
    cov_m = np.zeros((pic_shape[0],pic_shape[0]),dtype=float)
    for tra_s in train_samples:
        #中心化
        diff = tra_s - mean_pic
        #求协方差矩阵
        cov_m = cov_m + np.dot(diff,diff.T)
    cval, cvec = np.linalg.eig(cov_m)
    print('cvec.shape')
    print(cvec.shape)
    sorted_index = np.argsort(cval)
    cval.sort()
    cval_sorted = cval
    cval_sorted = cval_sorted[::-1]
    # print('特征值从大到小')
    # print(cval_sorted)
    #求特征向量的总和
    sum_cval = 0
    for c in cval:
        sum_cval += c
    dim_cnt = 0
    cval_sum = 0#组成投影矩阵的特征向量的特征值总和
    while cval_sum < rate * sum_cval:
        cval_sum = cval_sum + cval_sorted[dim_cnt]
        dim_cnt = dim_cnt + 1
    print('特征值总和')
    print(sum_cval)
    print('选取的特征值总和')
    print(cval_sum)
    print('选取的特征值的个数')
    print(dim_cnt)
    #构造投影矩阵
    Z = cvec[:,sorted_index[:-dim_cnt-1 : -1]]
    print('投影矩阵shape')
    print(Z.shape)#(80, 21)
    tra_loc = []
    tst_loc = []
    for p in train_samples_orgin:
        img_loc = np.empty((dim_cnt,),dtype=float)#错在此处
        img_loc = np.dot(Z.T,p).flatten()
        # print('np.dot(np.dot(p.T,p),X) .shape')
        # print(img_loc.shape)
        tra_loc.append(img_loc)
    tra_loc_np = tra_loc[0]
    for i in range(1,len(tra_loc)):
        tra_loc_np = np.vstack((tra_loc_np, tra_loc[i]))
        # print('tra_loc_np.shape')
        # print(tra_loc_np.shape)
   
    for p in test_samples:
        img_loc = np.empty((dim_cnt,),dtype=float)
        img_loc = np.dot(Z.T,p).flatten()
        tst_loc.append(img_loc)
    tst_loc_np = tst_loc[0]
    for i in range(1,len(tst_loc)):
        tst_loc_np = np.vstack((tst_loc_np,tst_loc[i]))
    # print('tra_loc_np的shape为')
    # print(tra_loc_np.shape)
    # print('tst_loc_np的shape为')
    # print(tst_loc_np.shape)

    min_dist_sample = np.zeros((len(tst_loc_np),),dtype=int)
    for i in range(0,len(tst_loc_np)):
        min_dist = float('inf')
        for j in range(0,len(tra_loc_np)):
            dist = np.linalg.norm(tst_loc_np[i] - tra_loc_np[j])
            if dist < min_dist:
                min_dist = dist
                min_dist_sample[i] = j
    # print(min_dist_sample)
    true_num = 0
    for i in range(0,len(min_dist_sample)):
        if(min_dist_sample[i]//5 == i//5):#坑爹,Python整除是//
            true_num = true_num + 1
    print('Alternative2DPCA人脸识别准确率为:' + str(true_num * 1.0/len(test_samples)) )
    time_1 = time.time()
    print('Alternative2DPCA人脸图像表示和识别共耗时: ' + str(time_1-time_0)+'  秒')
def PCA2D2DReg(train_samples, test_samples, rate):
    print('-------------------2D2DPCA--------------------')
    time_0 = time.time()
    train_samples_orgin = copy.deepcopy(train_samples)
    #图片矩阵大小m*n pic_shape = (n,m)
    pic_shape = train_samples[0].shape
    print('pic_shape:')
    print(pic_shape)#(80, 70)

    #求均值
    mean_pic = np.zeros(pic_shape)
    for p in train_samples:
        mean_pic = mean_pic + p
    mean_pic = mean_pic/float(len(train_samples))

    #求协方差矩阵
    #大小n*n
    cov_m_z = np.zeros((pic_shape[0],pic_shape[0]),dtype=float)
    cov_m_x = np.zeros((pic_shape[1],pic_shape[1]),dtype=float)
    for tra_s in train_samples:
        #中心化
        diff = tra_s - mean_pic
        #求协方差矩阵
        cov_m_z = cov_m_z + np.dot(diff,diff.T)
        cov_m_x = cov_m_x + np.dot(diff.T,diff)
    cval_z, cvec_z = np.linalg.eig(cov_m_z)
    cval_x, cvec_x = np.linalg.eig(cov_m_x)
    print('cvec_z.shape')
    print(cvec_z.shape)
    print('cvec_x.shape')
    print(cvec_x.shape)

    sorted_index_z = np.argsort(cval_z)
    cval_z.sort()
    cval_sorted_z = cval_z
    cval_sorted_z = cval_sorted_z[::-1]
    sorted_index_x = np.argsort(cval_x)
    cval_x.sort()
    cval_sorted_x = cval_x
    cval_sorted_x = cval_sorted_x[::-1]
    #求特征向量的总和
    sum_cval_z = 0
    sum_cval_x = 0
    for c in cval_z:
        sum_cval_z += c
    for c in cval_x:
        sum_cval_x += c
    dim_cnt_z = 0
    dim_cnt_x = 0
    cval_sum_z = 0#组成投影矩阵的特征向量的特征值总和
    cval_sum_x = 0
    while cval_sum_z < 0.95 * sum_cval_z:
        cval_sum_z = cval_sum_z + cval_sorted_z[dim_cnt_z]
        dim_cnt_z = dim_cnt_z + 1
    while cval_sum_x < rate * sum_cval_x:
        cval_sum_x = cval_sum_x + cval_sorted_x[dim_cnt_x]
        dim_cnt_x = dim_cnt_x + 1
    #构造投影矩阵
    Z = cvec_z[:,sorted_index_z[:-dim_cnt_z-1 : -1]]
    X = cvec_x[:,sorted_index_x[:-dim_cnt_x-1 : -1]]
    print('投影矩阵Z.shape')
    print(Z.shape)#(80, 21)
    print('投影矩阵X.shape')
    print(X.shape)#(80, 21)
    tra_loc = []
    tst_loc = []
    for p in train_samples_orgin:
        img_loc = np.empty((dim_cnt_z,),dtype=float)#错在此处
        img_loc = np.dot(np.dot(Z.T,p),X).flatten()
        # print('np.dot(np.dot(p.T,p),X) .shape')
        # print(img_loc.shape)
        tra_loc.append(img_loc)
    tra_loc_np = tra_loc[0]
    for i in range(1,len(tra_loc)):
        tra_loc_np = np.vstack((tra_loc_np, tra_loc[i]))
        # print('tra_loc_np.shape')
        # print(tra_loc_np.shape)
   
    for p in test_samples:
        img_loc = np.empty((dim_cnt_z,),dtype=float)
        img_loc = np.dot(np.dot(Z.T,p),X).flatten()
        tst_loc.append(img_loc)
    tst_loc_np = tst_loc[0]
    for i in range(1,len(tst_loc)):
        tst_loc_np = np.vstack((tst_loc_np,tst_loc[i]))

    min_dist_sample = np.zeros((len(tst_loc_np),),dtype=int)
    for i in range(0,len(tst_loc_np)):
        min_dist = float('inf')
        for j in range(0,len(tra_loc_np)):
            dist = np.linalg.norm(tst_loc_np[i] - tra_loc_np[j])
            if dist < min_dist:
                min_dist = dist
                min_dist_sample[i] = j
    # print(min_dist_sample)
    true_num = 0
    for i in range(0,len(min_dist_sample)):
        if(min_dist_sample[i]//5 == i//5):#坑爹,Python整除是//
            true_num = true_num + 1
    print('2D2DPCA人脸识别准确率为:' + str(true_num * 1.0/len(test_samples)) )
    time_1 = time.time()
    print('2D2DPCA人脸图像表示和识别共耗时: ' + str(time_1-time_0)+'  秒')
train_samples =  []
test_samples = []
for i in range(1,41):
    for j in range(1,11):
        # img = Image.open('C:\\ORLdatabase\\'+str(i*10+j-10)+'_'+str(i)+'.jpg')
        img = Image.open('C:\\ORLdatabase\\s'+str(i)+'\\'+str(j)+'.pgm')
        # print(img.size)#宽乘高,如1920*1080,与我们矩阵的顺序是反的
        img_processed = np.empty((img.size[1],img.size[0]), dtype = float)
        for m in range(img.size[1]):
            for n in range(img.size[0]):
                p = img.getpixel((n,m))
                #归一化
                img_processed[m,n] = p/255.0

        if j < 6 :
            train_samples.append(img_processed)
        else:
            test_samples.append(img_processed)

ta = copy.deepcopy(train_samples)
ts = copy.deepcopy(test_samples)
#由于python的机制问题,以下PCAReg要深拷贝一份,不然后续3个函数会出错
rate = 0.95#后续更改此值可以改变投影矩阵的大小
PCAReg(ta,ts,rate)#耗时极长,建议注释掉不运行
PCA2DReg(train_samples,test_samples,rate)
PCA2DAlternativeReg(train_samples,test_samples,rate)
PCA2D2DReg(train_samples, test_samples,rate)
posted @ 2021-11-16 21:45  betaForever  阅读(292)  评论(0)    收藏  举报