为 AI 人脸识别准备数据集





5.00/5 (3投票s)
在本文中,我们将讨论如何准备数据集,以便向 CNN 提供正确的数据。
引言
如果你看过电影《少数派报告》,你可能还记得汤姆·克鲁斯走进 Gap 商店的场景。一个视网膜扫描仪读取了他的眼睛,并为他播放了一个定制广告。 现在是 2020 年。 我们不需要视网膜扫描仪,因为我们有人工智能 (AI) 和机器学习 (ML)!
在本系列中,我们将向你展示如何使用深度学习来执行面部识别,然后 - 基于识别出的面部 - 使用神经网络 文本到语音 (TTS) 引擎来播放定制广告。欢迎你在 CodeProject 上浏览代码,或下载 .zip 文件,在你自己的机器上浏览代码。
我们假设你熟悉 AI/ML 的基本概念,并且能够使用 Python。
本系列由五篇文章组成
获取数据集
在前一篇文章中,我们描述了在图像中检测人脸的过程。现在我们知道如何从较大的图片或视频中获得裁剪的人脸图像,假设我们已经完成了这项练习,并最终获得了一个数据集(人脸集)来训练我们的 CNN。 但是,在训练之前,我们需要处理这个数据集以对数据进行分类和规范化。 在本文中,我们将创建一个数据集解析器/处理器,并在 Yale 人脸数据集上运行它,该数据集包含 15 个不同人物的 165 张灰度图像。 这个数据集很小,但足以满足我们的目的 - 学习。
准备一个解析器
数据集解析器将驻留在两个类中 - 一个抽象的更通用的类,以及一个处理所选数据集的细节的类。 让我们看看父类的构造函数。
class FaceDataSet(metaclass=abc.ABCMeta):
def __init__(self, path, extension_list, n_classes):
self.path = path
self.ext_list = extension_list
self.n_classes = n_classes
self.objects = []
self.labels = []
self.obj_validation = []
self.labels_validation = []
self.number_labels = 0
构造函数参数是
path
:包含数据集样本(图像)的文件夹的路径extension_list
:要在path
定义的文件夹中查找的文件的扩展名(一个或多个)n_classes
:将数据集分类成的类的数量; 对于 Yale 数据集,这将是 15,因为这是数据集中人物的数量
我们还创建了下一个类对象
objects
:用于 CNN 训练的图像labels
:对图像(对象)进行分类的标签(主题编号)obj_validation
:用于在训练后验证 CNN 的图像子集labels_validation
:obj_validation
列表的分类器(标签)number_labels
:数据集中标签的总数
get_data()
方法是我们将在实例化 FaceDataSet
类后调用的方法。
def get_data(self):
img_path_list = os.listdir(self.path)
self.objects, self.labels = self.fetch_img_path(img_path_list, self.path, vgg_img_processing)
self.process_data(vgg_img_processing)
self.print_dataSet()
该方法由两个主要调用组成:从定义的路径获取图像并处理它们。 为了获取图像,我们循环访问 path
定义的文件夹中的文件。 然后,我们使用 SK-Image 将这些文件加载为灰度图像。 此调用返回一个包含图像中每个像素的 NumPy 数组。
def fetch_img_path(self, img_path_list, path, vgg_img_processing):
images = []
labels = []
for img_path in img_path_list:
if self.__check_ext(img_path):
img_abs_path = os.path.abspath(os.path.join(path, img_path))
image = io.imread(img_abs_path, as_gray=True)
label = self.process_label(img_path)
images.append(image)
labels.append(label)
return images, labels
def __check_ext(self, file_path):
for ext in self.ext_list:
if file_path.endswith(ext):
return True
return False
process_label()
是 FaceDataSet
类中的一个抽象方法; 它的实现在 YaleDataSet
类中进行,我们在其中解析数据集中图像文件的名称。 文件名采用“subjectXX.*”格式。 该方法从文件名中提取“XX”编号并将其分配给图像。
class YaleFaceDataSet(FaceDataSet):
def __init__(self, path, ext_list, n_classes):
super().__init__(path, ext_list, n_classes)
def process_label(self, img_path):
val = int(os.path.split(img_path)[1].split(".")[0].replace("subject", "")) - 1
if val not in self.labels:
self.number_labels+=1
return val
最后,process_data()
方法看起来像这样
def split_training_set(self):
return train_test_split(self.objects, self.labels, test_size=0.3,
random_state=random.randint(0, 100))
def process_data(self, vgg_img_processing):
self.objects, self.img_obj_validation, self.labels, self.img_labels_validation = \
self.split_training_set()
self.labels = np_utils.to_categorical(self.labels, self.n_classes)
self.labels_validation = np_utils.to_categorical(self.img_labels_validation, self.n_classes)
self.objects = Common.reshape_transform_data(self.objects)
self.obj_validation = Common.reshape_transform_data(self.img_obj_validation)
在此方法中,我们将数据集分成两部分。 第二部分包含用于验证训练结果的图像。 我们使用 Scikit-Learn 中的 train_test_split()
方法,并将标签转换为分类变量。 如果图像的分类为“2”(来自 subject02),则其分类变量将为 [0 1 0 0 0 0 0 0 0 0 0 0 0 0 0] – 一个 15 维(类数)向量,其中第 2 个分量为 1。
class Common:
@staticmethod
def reshape_transform_data(data):
data = numpy.array(data)
result = Common.reshape_data(data)
return Common.to_float(result)
@staticmethod
def reshape_data(data):
return data.reshape(data.shape[0], constant.IMG_WIDTH, constant.IMG_HEIGHT, 1)
@staticmethod
def to_float(value):
return value.astype('float32')/255
reshape_transform_data()
方法重塑数据以适应灰度模式。 在图像处理中,彩色图像被认为是 3 通道网格; 换句话说,它们被分成 3 种颜色 (RGB)。 灰度图像只有一个通道。 因此,最初的彩色图像需要以“1”结尾进行重塑。
to_float()
方法通过将每个像素值除以 255(像素值介于 0 和 255 之间)来规范化数据,这会将整个像素矩阵置于 0-1 空间,以便更好地进行数值输入和更快的收敛。 现在我们可以在 main.py 文件中设置我们的数据集,该文件将用作我们应用程序的入口点。
ext_list = ['gif', 'centerlight', 'glasses', 'happy', 'sad', 'leflight',
'wink', 'noglasses', 'normal', 'sleepy', 'surprised', 'rightlight']
n_classes = 15
# Set up dataSet
dataSet = YaleFaceDataSet(constant.FACE_DATA_PATH, ext_list, n_classes)
对数据集进行分类
...
下一步?
现在我们有一个经过处理的、分类的数据集,可以用于 CNN 训练。 在下一篇文章中,我们将把我们的 CNN 放在一起,并对其进行面部识别训练。 敬请关注!