0%

基于深度学习的人种识别方法

前言

课程《模式识别》小组作业为基于深度学习的人脸识别,具体识别内容为:通过人脸识别人的性别、年龄、种族、表情、是否为同一人。我在小组内的工作为:通过人脸对人的种族进行识别。

源码地址贴在此处:Face Recognition

任务简介

用有监督学习机制设计并实现模式识别方法,基于人脸图像进行模式分类,如性别(男性、女性)、年龄(儿童、青少年、成年、老年)、表情(微笑、严肃)或者种族(白种人、黄种人、黑人)等。

个人任务

负责通过人脸信息基于神经网络的种族识别网络设计,重点研究神经网络的理论、结构、变体与具体实现方式。

数据库说明

两个文本文件:

  • faceDR:每一个人脸数据的说明(2000个人脸),即类别卷标。

  • faceDS:每一个人脸数据的说明(2000个人脸),即类别卷标。

提示:由于数据是真实数据,会有以下情况:

  1. 有缺失数据(如1228, 1808, 4056, 4135, 4136, and 5004),建议采取合适的预处理技术。

  2. 有错误数据,建议对有错误的人脸记录采取合适的预处理。

部分标签如下所示:

image-20220429153404115

预处理部分

缺失部分

我们小组通过检索所有缺失数据的样本,选择直接剔除。

错误数据部分

这方面主要是存在过黑、过曝等问题,小组采用对所有训练数据归一化标准化的方法,具体实现体现为代码

1
transforms.Normalize(train_mean, train_std)

训练集及测试集

  • faceDR数据作为训练集
  • faceDS数据作为测试集

图像信息可视化

小组将所给样本数据统一转换为 200 X 200三通道灰度PNG格式图片。部分图片如下所示:

image-20220429153655690

算法实现

这里主要是记录本次任务自己所学到的一些东西,作为深度学习的门外汉,这里十分感谢W哥的指导和帮助,让我在这次任务中受益匪浅。

给样本打上标签

具体代码实现主要放在了 Label_Processingtrain文件下。

原有数据库中的样本仅为 (id + .png) 格式,需要把 id与人种信息进行匹配。

提取所需标签信息

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
#  将样本标签分开
label_dir = 'facedata/Label'

with open(label_dir + '/faceDR', encoding='utf-8') as dr_label:
facedr_list = [[buf.strip(')') for buf in line.strip().split(' (_')]
for line in dr_label.readlines()]

with open(label_dir + '/faceDS', encoding='utf-8') as ds_label:
faceds_list = [[buf.strip(')') for buf in line.strip().split(' (_')]
for line in ds_label.readlines()]

# 将 id号与人种组合

facedr = []
faceds = []

for line in facedr_list:
race = line[3].strip().split(' ')[1]
temp = [line[0], race]
facedr.append(temp)
print(facedr[:10])


for line in faceds_list:
race = line[3].strip().split(' ')[1]
temp = [line[0], race]
faceds.append(temp)

# 将数据转为npy格式

np.save('data.npy', facedr)
data = np.load('data.npy')

np.save('./facedata/Label/train.npy', facedr)
np.save('./facedata/Label/test.npy', faceds)

train_label = np.load('./facedata/Label/train.npy')
test_label = np.load('./facedata/Label/test.npy')

样本与标签匹配

基本思想是,每个样本的文件名即其 id,我们已经有了 ( id + 人种 )的数据,那么遍历所有的文件,若文件名中 id 与(id + 人种)的 id为同一个, 即将该人种信息标注于样本文件名中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
for fname in os.listdir(os.path.join('facedata', 'train')):
if not fname.endswith('.png'):
continue
idt, _ = fname.split('.')
filepath = os.path.join('facedata', 'train', fname)
idt_num = int(idt)
for label in train_label:
if idt == label[0]:
os.rename(filepath, filepath.replace('.', '.' + label[1] + '.') )

for fname in os.listdir(os.path.join('facedata', 'test')):
if not fname.endswith('.png'):
continue
idt, _ = fname.split('.')
filepath = os.path.join('facedata', 'test', fname)
idt_num = int(idt)
for label in test_label:
if idt == label[0]:
os.rename(filepath, filepath.replace('.', '.' + label[1] + '.') )

最后查看一下训练集与测试集中的样本分布

1
2
3
4
5
6
7
8
9
10
11
facedr_cnt = {}
faceds_cnt = {}

for value in train_label:
facedr_cnt[value[1]] = facedr_cnt.get(value[1], 0) + 1

for value in test_label:
faceds_cnt[value[1]] = faceds_cnt.get(value[1], 0) + 1

print(facedr_cnt)
print(faceds_cnt)

得到如下分布:

image-20220429162132547

可以看到数据是极度不平衡,在不增加小样本的前提下,这对整个识别系统的训练是十分不友好的,也是后续改进的主要难点。