-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclassification.py
More file actions
179 lines (156 loc) · 6.87 KB
/
classification.py
File metadata and controls
179 lines (156 loc) · 6.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
"""
Author: SliverCrossing
使用时请注意修改文件路径,以读取正确的图片,将数据集预先分为两类放入两个文件夹中,数据集自行选择,如果数据集不是128*128尺寸请修改对应参数
如果数据是rawdata则先用第一段代码处理变为图片
除了SVC还可以用其他分类器比如RFC、ABC、DTC,从模块中调用对应的函数即可
"""
import sklearn
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
import cv2
from scipy.io import loadmat
import os
import math
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC, LinearSVC
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier, AdaBoostClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
# 图片尺寸
img_size1 = 128
img_size2 = 128
# 将rawdata转为图片,已转换过一次则此段代码注释掉避免每次运行都要重新转换图片
# print(os.listdir("./face/face/rawdata")) # 读取文件路径
# list1 = [] # 用于存放图片尺寸
# for filename in os.listdir("./face/face/rawdata"): # 读取文件夹内的所有图片
# with open("./face/face/rawdata/"+filename, "rb") as file2: # 读取文件
# img_data = file2.read()
# img_data = np.frombuffer(img_data, dtype=np.uint8) # 将文件换出来
# if len(img_data) == 16384: # 只用到128*128的图片,其他的都不用,因此只转换128的
# img = img_data.reshape(img_size1, img_size2) # 转为128*128
# else:
# print("未知图片大小:", len(img_data))
# cv2.imwrite("./face/face/picture/"+filename+".jpg", img)
# if len(img_data) not in list1:
# list1.append(len(img_data))
# print("list1:", list1)
# 导入mat文件,暂时用不着先注释掉
# face_mat_file = loadmat("./face/face/eigenfaces/readImage.mat")
# ev_mat_file = loadmat("./face/face/eigenfaces/ev.mat")
# print("readImage:", face_mat_file)
# print("ev:", ev_mat_file)
# print(type(face_mat_file), len(face_mat_file))
# print(type(ev_mat_file), len(ev_mat_file))
# data1 = ev_mat_file["eigenfaces"]
# print(data1.shape)
# for i in range(0, 99):
# img_data = data1[i].reshape(img_size1, img_size2)
# 因为数据太少,因此采用数据增强,将图片镜像从而扩大训练集,运行过一次后此段代码注释掉从而提高效率
# def flip(image):
# flipped_image = np.fliplr(image)
# return flipped_image
#
#
# file_dir = "./face/face/glasses/"
# for img_name in os.listdir(file_dir):
# img_path = file_dir + img_name
# img = cv2.imread(img_path)
# # 镜像
# flipped_img = flip(img)
# cv2.imwrite(file_dir + img_name[0:-4] + '_fli.jpg', flipped_img)
def img2vec(image, blocksize):
image_w, image_h = img_size1, img_size2
# 图像方块数据转换为向量
img_block_vec = np.zeros((int(image_w * image_h / blocksize / blocksize), blocksize * blocksize))
i = 0
for r in range(0, image.shape[0], blocksize):
for c in range(0, image.shape[1], blocksize):
block = image[r:r + blocksize, c:c + blocksize]
block = np.resize(block, (1, blocksize * blocksize))
img_block_vec[i] = block
i += 1
return img_block_vec
def vec2img(vectors, blocksize):
# 向量数据转换为图像
img_kl = np.zeros((img_size1, img_size2))
i = 0
for r in range(0, img_kl.shape[0], blocksize):
for c in range(0, img_kl.shape[1], blocksize):
block = vectors[i]
block = np.resize(block, (blocksize, blocksize))
i += 1
img_kl[r:r + blocksize, c:c + blocksize] = block
return img_kl.astype(int)
def kl_transform(vectors, principal_n):
# 计算协方差矩阵和特征
cov_matrix = np.cov(vectors.T)
_, fvec = np.linalg.eig(cov_matrix) # 输出的特征值默认降序排列
img_kl_block_vec = np.dot(vectors, fvec)
# 压缩,将非前N个主成分置为0
img_kl_block_vec[:, principal_n:] = 0
return np.dot(img_kl_block_vec, fvec.T)
blocksize = 2 # 像素块
principal_n1 = 16 # 贡献度高的前N个特征值个数
# 展示单张图片的K-L结果
img = cv2.imread("./face/face/glasses/1290.jpg")
image_w, image_h = img_size1, img_size2
new_w, new_h = image_w // blocksize * blocksize, image_h // blocksize * blocksize
img = cv2.resize(img, (new_h, new_w))
vec = img2vec(img, blocksize)
kl1 = vec2img(kl_transform(vec, principal_n1), blocksize)
print("finish")
plt.subplot(1, 2, 1)
plt.imshow(img, 'gray')
plt.subplot(1, 2, 2)
plt.imshow(kl1, 'gray')
plt.show()
file_dir = "./face/face/glasses/"
svc = SVC() # 使用sklearn中的支持向量机模型,要使用其他模型则可以调用对应的sklearn模块
# rfc = RandomForestClassifier()
# dtc = DecisionTreeClassifier()
# abc = AdaBoostClassifier()
# logist = LogisticRegression()
# knn = KNeighborsClassifier()
X = [] # 存放图像名称
Y = [] # 存放分类名称
for f in os.listdir(file_dir): # 从眼镜类中提取图片
img = cv2.imread(file_dir + f)
# 进行K-L变换
image_w, image_h = img_size1, img_size2
new_w, new_h = image_w // blocksize * blocksize, image_h // blocksize * blocksize
img = cv2.resize(img, (new_h, new_w))
X.append(img)
Y.append("glasses")
file_dir = "./face/face/non_glasses/"
for f in os.listdir(file_dir): # 从非眼镜类中提取图片
img = cv2.imread(file_dir + f)
# 进行K-L变换
image_w, image_h = img_size1, img_size2
new_w, new_h = image_w // blocksize * blocksize, image_h // blocksize * blocksize
img = cv2.resize(img, (new_h, new_w))
X.append(img)
Y.append("non_glasses")
# 转为numpy数组便于后续运算
X = np.array(X)
Y = np.array(Y)
# 用train_test_split()函数将数据分割为训练集和测试集。test_size=0.2表示测试集占总数据的20%,random_state=0用于确保每次分割都能得到相同的结果
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2)
# 对数组进行变换以便模型计算
X_train = X_train.reshape(X_train.shape[0], img_size1*img_size2*3)
X_test = X_test.reshape(X_test.shape[0], img_size1*img_size2*3)
svc.fit(X_train, Y_train) # 训练模型
Y_dtc = svc.predict(X_test) # 模型预测
# 输出预测得分并展示结果
acc = accuracy_score(Y_test, Y_dtc)
precision = precision_score(Y_test, Y_dtc, pos_label="glasses")
recall = recall_score(Y_test, Y_dtc, pos_label="glasses")
f1 = f1_score(Y_test, Y_dtc, pos_label="glasses")
print("acc:", acc)
print("precision:", precision)
print("recall:", recall)
print("f1:", f1)
print("Y_dtc:", Y_dtc)
print("Y_test", Y_test)