python代码实现RGB图像的费歇尔(Fisher)三类分类

python代码实现RGB图像的费歇尔(Fisher)三类分类_第1张图片

'''
1.样本设置  橘子-1 背景-0 苹果-2
2.求Sb 每类均值向量,所有样本均值向量
3.求Sw 三类样本协方差之和
4.求解Sw 和Sb 的特征值
5.求取 W 取 K 个特征向量组成 W 矩阵
6.读入图像,进行RGB变换,变换成3行1 列向量(参考二类分类)
7.y = W(T) x
# 计算三类样本中心的位置
# 求f(x),得到2行1列的判断向量
# Fisher判断类别
'''

import numpy as np
import cv2
import math
from copy import deepcopy

# 设置样本,为了进行对比,与Bayes三类分类使用相同的样本
def Dataset():
    # 共35个样本数据  橘子10 背景10 苹果15
    samples_data = [[199,114,34], [199,113,36], [188,93,11],
                    [196,101,17], [193,97,13], [85,37,23],
                    [192,99,19], [178,83,3], [87,38,24],
                    [87,37,26], [126,137,143], [125,136,142],
                    [131,142,148], [130,141,147], [129,140,146],
                    [181,197,210], [183,201,213], [182,200,212],
                    [180,198,210], [181,199,209], [166,108,94],
                    [167,108,94], [165,107,93], [159,99,89],
                    [156,96,86], [154,94,84], [149,81,78],
                    [155,87,84], [157,82,86], [156,81,85],
                    [156,84,85], [130,58,62], [166,110,93],
                    [150,83,77], [130,58,62]]
    class_lable = [1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2]
    # 橘子--1 背景--0 苹果--2
    return samples_data,class_lable

# 求每类样本均值向量 和 总体均值向量
def Get_Junzhi(samples_data,class_lable):
    L = len(samples_data)
    m = 0  # 水果
    n = 0  # 背景
    k = 0  # 苹果
    r1 = 0
    g1 = 0
    b1 = 0
    r0 = 0
    g0 = 0
    b0 = 0
    r2 = 0
    g2 = 0
    b2 = 0
    mv = [0]
    mean_vector1 = [mv]*3
    mean_vector0 = [mv]*3
    mean_vector2 = [mv]*3
    for i in range(L):
        if class_lable[i] == 1:
            m += 1
        elif class_lable[i] == 0:
            n += 1
        else:
            k += 1

    for i in range(L):
        if i < m:
            r1 += samples_data[i][0]
            g1 += samples_data[i][1]
            b1 += samples_data[i][2]
        elif i >= m+n:
            r2 += samples_data[i][0]
            g2 += samples_data[i][1]
            b2 += samples_data[i][2]
        else:
            r0 += samples_data[i][0]
            g0 += samples_data[i][1]
            b0 += samples_data[i][2]

    mean_vector1 = [[int(r1/m)],[int(g1/m)],[int(b1/m)]]  # 三维均值向量
    mean_vector0 = [[int(r0/n)],[int(g0/n)],[int(b0/n)]]
    mean_vector2 = [[int(r2/k)],[int(g2/k)],[int(b2/k)]]
    mean_all = [[int((r0+r1+r2)/L)],[int((g0+g1+g2)/L)],[int((b0+b1+b2)/L)]]
    # print(mean_vector1)
    # print(mean_vector0)
    # print(mean_vector2)
    # print(mean_all)
    return mean_vector1, mean_vector0, mean_vector2, mean_all

# 求Sb
def Get_Sb(mean_vector1,mean_vector0,mean_vector2,mean_all):
    # 求u-ui
    # #求u-ui的转置
    mean1 = [[0], [0], [0]]
    mean0 = [[0], [0], [0]]
    mean2 = [[0], [0], [0]]
    t1 = [[0,0,0]]
    t0 = [[0,0,0]]
    t2 = [[0,0,0]]
    Sb = [[0,0,0],[0,0,0],[0,0,0]]
    for i in range(3):
        for j in range(1):
            mean1[i][j] = mean_vector1[i][j] - mean_all[i][j]
            mean0[i][j] = mean_vector0[i][j] - mean_all[i][j]
            mean2[i][j] = mean_vector2[i][j] - mean_all[i][j]
            t1[j][i] = mean1[i][j]
            t0[j][i] = mean0[i][j]
            t2[j][i] = mean2[i][j]

    # m1 = np.dot(10,np.dot(mean1,t1))
    # m0 = np.dot(10,np.dot(mean0,t0))   # 疑似错误用法
    # m2 = np.dot(15, np.dot(mean2, t2))
    m_1 = np.dot(mean1,t1)
    m1 = np.dot(10,m_1)
    m_0 = np.dot(mean0,t0)
    m0 = np.dot(10,m_0)
    m_2 = np.dot(mean2,t2)
    m2 = np.dot(15,m_2)


    for i in range(len(m1)):
        for j in range(len(m0)):
            Sb[i][j] = m_1[i][j] + m_0[i][j] + m_2[i][j]

    #print(Sb)
    # 求Sb

    return Sb

# 求协方差之和 Sw
def Get_Cov(samples_data,mean_vector1,mean_vector0,mean_vector2):
    L= len(samples_data)
    m = 10
    n = 10
    k = 15
    cov = [0]*3
    Cov_1 = [cov]*3
    Cov_0 = [cov]*3
    Cov_2 = [cov]*3
    cov_bb1 = 0
    cov_gb1 = 0
    cov_gg1 = 0
    cov_rb1 = 0
    cov_rg1 = 0
    cov_rr1 = 0
    cov_bb0 = 0
    cov_gb0 = 0
    cov_gg0 = 0
    cov_rb0 = 0
    cov_rg0 = 0
    cov_rr0 = 0
    cov_bb2 = 0
    cov_gb2 = 0
    cov_gg2 = 0
    cov_rb2 = 0
    cov_rg2 = 0
    cov_rr2 = 0

    Sw = []
    ve = [0,0,0]


    for i in range(L):
        if i < m:
            cov_rr1 += (samples_data[i][0]-mean_vector1[0][0])*(samples_data[i][0]-mean_vector1[0][0])
            cov_rg1 += (samples_data[i][0]-mean_vector1[0][0])*(samples_data[i][1]-mean_vector1[1][0])
            cov_rb1 += (samples_data[i][0]-mean_vector1[0][0])*(samples_data[i][2]-mean_vector1[2][0])
            cov_gg1 += (samples_data[i][1]-mean_vector1[1][0])*(samples_data[i][1]-mean_vector1[1][0])
            cov_gb1 += (samples_data[i][1]-mean_vector1[1][0])*(samples_data[i][2]-mean_vector1[2][0])
            cov_bb1 += (samples_data[i][2]-mean_vector1[2][0])*(samples_data[i][2]-mean_vector1[2][0])
        elif i >= m+n:
            cov_rr2 += (samples_data[i][0] - mean_vector2[0][0]) * (samples_data[i][0] - mean_vector2[0][0])
            cov_rg2 += (samples_data[i][0] - mean_vector2[0][0]) * (samples_data[i][1] - mean_vector2[1][0])
            cov_rb2 += (samples_data[i][0] - mean_vector2[0][0]) * (samples_data[i][2] - mean_vector2[2][0])
            cov_gg2 += (samples_data[i][1] - mean_vector2[1][0]) * (samples_data[i][1] - mean_vector2[1][0])
            cov_gb2 += (samples_data[i][1] - mean_vector2[1][0]) * (samples_data[i][2] - mean_vector2[2][0])
            cov_bb2 += (samples_data[i][2] - mean_vector2[2][0]) * (samples_data[i][2] - mean_vector2[2][0])
        else:
            cov_rr0 += (samples_data[i][0] - mean_vector0[0][0]) * (samples_data[i][0] - mean_vector0[0][0])
            cov_rg0 += (samples_data[i][0] - mean_vector0[0][0]) * (samples_data[i][1] - mean_vector0[1][0])
            cov_rb0 += (samples_data[i][0] - mean_vector0[0][0]) * (samples_data[i][2] - mean_vector0[2][0])
            cov_gg0 += (samples_data[i][1] - mean_vector0[1][0]) * (samples_data[i][1] - mean_vector0[1][0])
            cov_gb0 += (samples_data[i][1] - mean_vector0[1][0]) * (samples_data[i][2] - mean_vector0[2][0])
            cov_bb0 += (samples_data[i][2] - mean_vector0[2][0]) * (samples_data[i][2] - mean_vector0[2][0])

    a = m-1
    b = n-1
    c = k-1
    Cov_1 = [[cov_rr1/a,cov_rg1/a,cov_rb1/a],[cov_rg1/a,cov_gg1/a,cov_gb1/a],[cov_rb1/a,cov_gb1/a,cov_bb1/a]]
    Cov_0 = [[cov_rr0/b,cov_rg0/b,cov_rb0/b],[cov_rg0/b,cov_gg0/b,cov_gb0/b],[cov_rb0/b,cov_gb0/b,cov_bb0/b]]
    Cov_2 = [[cov_rr2/c,cov_rg2/c,cov_rb2/c],[cov_rg2/c,cov_gg2/c,cov_gb2/c],[cov_rb2/c,cov_gb2/c,cov_bb2/c]]

    for i in range(3):
        for j in range(1):
            a = Cov_1[i][j] + Cov_0[i][j] + Cov_2[i][j]
            b = Cov_1[i][j+1] + Cov_0[i][j+1] + Cov_2[i][j+1]
            c = Cov_1[i][j+2] + Cov_0[i][j+2] + Cov_2[i][j+2]
            ve= [a,b,c]
            V = deepcopy(ve)
            Sw.append(V)
    # print(Sw)

    return Sw

# 求Sw的逆和Sb的乘积的特征值和 特征向量 W以及 W的转置
# 返回 W_T
def Get_tezhengzhi(Sb,Sw):
    Inv_Sw = np.linalg.inv(Sw)
    Sw_Sb = np.dot(Inv_Sw,Sb)
    a, W = np.linalg.eig(Sw_Sb) # a--特征值  W--特征向量

    # 取前最大的2(投影向量的个数)个特征向量组成W矩阵即可,这里取w2,w3
    W_T = [[0, 0, 0], [0, 0, 0]]
    for i in range(3):
        for j in range(1,3):
            W_T[j-1][i] = W[i][j]
    return W_T

# 计算三类样本中心的位置
def Get_Center_XY(mean_vector1,mean_vector0,mean_vector2,W_T):
    XY_1 = np.dot(W_T,mean_vector1)
    XY_0 = np.dot(W_T, mean_vector0)
    XY_2 = np.dot(W_T, mean_vector2)
    XY_center = [XY_1,XY_0,XY_2]
    return XY_center


# 求f(x),得到2行1列的判断向量
# Fisher判断类别
def Get_F(data,W_T,XY_center):
    XY_data = np.dot(W_T,data)
    Cla = [0,0,0]
    for i in range(3):
        x = XY_data[0][0] - XY_center[i][0]
        y = XY_data[1][0] - XY_center[i][1]
        Cla[i] = x*x + y*y

    F_classify = min(Cla)
    if F_classify == Cla[0]:
        F = 1
    elif F_classify == Cla[1]:
        F = 0
    elif F_classify == Cla[2]:
        F = 2
    return F

# RGB 变换
# 改变图像RGB存储形式
# 编成3行1列形式
def Get_RGB(image):
    w = image.shape[0]
    h = image.shape[1]
    data = []
    ve = [[0] for i in range(3)]
    new_data = [ve for i in range(w*h)]
    for i in range(w):
        for j in range(h):
            for k in range(1):  # B G 调换
                a = image[i,j,k+0]
                image[i,j,k+0] = image[i,j,k+2]
                image[i,j,k+2] = a
    # print(image)
    for i in range(w):
        for j in range(h):
            new_data[i*h+j][0][0] = image[i][j][0]
            new_data[i*h+j][1][0] = image[i][j][1]
            new_data[i*h+j][2][0] = image[i][j][2]
            V = deepcopy(ve)
            data.append(V)
    return data

#实现费歇尔三类分类
# 把图片的RGB传进来对每一个像素做分类 橘子赋值 [255,128,0] ,背景赋值 255, 苹果赋值 [255,0,0]
def Get_Cla_Image(test_data, image,W_T,XY_Center):
    w = image.shape[0]
    h = image.shape[1]
    L = len(test_data)

    for i in range(w):
        for j in range(h):
            a = [test_data[i*h+j]]
            F_X = Get_F(a,W_T,XY_center)

            if F_X == 1:
                image[i][j][0] = 0  #  这里图片是RGB形式 橘子
                image[i][j][1] = 128  # 赋值时需要注意
                image[i][j][2] = 255
            elif F_X == 0:    # 背景
                image[i][j] = 255
            elif F_X == 2:
                image[i][j][0] = 0  # 74,114,216 这里图片是RGB形式 苹果
                image[i][j][1] = 0  # 赋值时需要注意
                image[i][j][2] = 255

    return image


test_data, test_lable = Dataset()
m1, m0, m2, mall = Get_Junzhi(test_data,test_lable)
Sb = Get_Sb(m1,m0,m2,mall)
Sw = Get_Cov(test_data,m1,m0,m2)
W_T = Get_tezhengzhi(Sb,Sw)
XY_center = Get_Center_XY(m1,m0,m2,W_T)


image = cv2.imread('JP3.jpg')
test_data = Get_RGB(image)
Fisher_Image = Get_Cla_Image(test_data,image,W_T,XY_center)
cv2.imshow('Fisher_three', Fisher_Image)
cv2.waitKey(0)
cv2.destroyAllWindows()


'''
data = [[72],[61],[69]]
test_data, test_lable = Dataset()
m1, m0, m2, mall = Get_Junzhi(test_data,test_lable)
Sb = Get_Sb(m1,m0,m2,mall)
Sw = Get_Cov(test_data,m1,m0,m2)
W_T = Get_tezhengzhi(Sb,Sw)
XY_center = Get_Center_XY(m1,m0,m2,W_T)
F = Get_F(data,W_T,XY_center)
'''


'''
print(cov1)
print(cov0)
print(cov2)
print(Sb)
'''

 

你可能感兴趣的:(模式识别,python,机器学习,分类算法)