Streamlit使数据科学家和机器学习从业者能够快速构建数据和机器学习应用。在这篇文章中,我们将看看我们如何使用Streamlit来构建一个人脸验证应用程序。然而,在我们开始验证人脸之前,我们必须先检测它们。在计算机视觉中,人脸检测是在图像中对人脸进行定位和定位的任务。人脸验证是比较两个或多个图像的相似性的过程。
下面的图片显示了我们在这篇文章中要做的应用。现场演示位于这里。

把这个项目带入生活
用MTCNN检测人脸
MTCNN是Multi-Task Cascaded Convolutional Neural Network的缩写,在本文中首次提出。该框架由三个阶段组成:
- 在第一步中,候选窗口和它们的边界盒回归向量是通过被称为提议网络(P-Net)的浅层CNN产生的。
- 下一步使用一个复杂的CNN来拒绝非面部窗口。本文将这个CNN称为精炼网络(R-Net)。
- 然后,它使用一个更复杂的CNN来细化结果并输出五个面部地标的位置。
上述三级级联框架的输入是一张已经被调整为不同比例的图像,以建立一个图像金字塔。
在这篇文章中,我们将使用Iván de Paz Centeno的论文的实现。它可以作为一个pip安装包使用。
pip install mtcnn
人脸识别和验证模型
VGGFace指的是根据牛津大学视觉几何小组(VGG)的计算机视觉数据集开发的人脸识别模型。这个系列的主要模型是VGGFace和VGGFace2。深度人脸识别》论文提出了一个用于人脸识别和验证的大规模数据集。该论文描述了一种通过比较人脸在欧几里得空间的嵌入来验证人脸的方法。这是用Triplet损失来完成的。在这个实现中,相似的人脸之间的欧几里得距离很小,而不同的人脸则较大。
本文介绍了VGGFace2。它提出了一个新的大规模人脸数据集,包含9131个主题的331万张图像。每个主题平均有362.6张图像。在这个数据集上训练的模型被称为VGGFace2。这些模型可以在这个GitHub repo上找到。我们将使用这个模型的Keras实现来验证人脸。我们需要做的第一件事是检测人脸,然后获得他们的嵌入。该文件将这些嵌入称为人脸描述符。然后,这些描述符之间的距离将用余弦相似度来计算。
在Keras中,我们可以使用keras-vggface包来使用VGGDFace模型。你必须从GitHub上安装它。
pip install git+https://github.com/rcmalli/keras-vggface.git
设置Streamlit应用程序
在我们开始处理这个应用程序之前,你需要安装所有的要求。这些要求可以在这里找到。下载该文件后,通过pip安装所有的需求。
pip install -r requirements.txt
导入所有的需求
现在打开一个新的Python文件(最好命名为app.py ),在文件的顶部导入所有的需求:
MTCNN将用于人脸检测Streamlit用于设置网络应用程序Matplotlib用于显示人脸Circle用于标记脸部的地标Rectangle用于在检测到的人脸周围创建一个方框Image打开一个图像文件cosine计算人脸之间的余弦相似度VGGface用于获得人脸嵌入preprocess_input将图像转换为模型所需的格式
from mtcnn.mtcnn import MTCNN
import streamlit as st
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
from matplotlib.patches import Circle
from PIL import Image
from numpy import asarray
from scipy.spatial.distance import cosine
from keras_vggface.vggface import VGGFace
from keras_vggface.utils import preprocess_input
设置下拉菜单
下一步是设置下拉选项。幸运的是,Streamlit为建立一个HTML页面提供了各种小工具:

在这种情况下,我们需要创建一个select_box 。选择框函数期望有一个标签和选择框所需的选项。将该函数分配给一个变量,使我们能够捕获用户选择的选项:
choice = st.selectbox("Select Option",[
"Face Detection",
"Face Detection 2",
"Face Verification"
])
定义主函数
我们需要做的下一件事是创建一个主函数,负责处理用户的各种选择。在这个函数中,我们将建立起检测脸部以及验证脸部的代码。
让我们从实现人脸检测功能开始。第一步是检查用户是否选择了人脸检测选项。之后,以下是接下来发生的事情:
- 使用Streamlit的
file_uploader,上传文件 - 使用Pillow打开图像,并将其转换为NumPy数组
- 在关闭Matplotlib坐标轴后,将图像可视化
- 创建一个
MTCNN检测器来检测人脸 - 获得人脸和面部地标的坐标
- 使用
Circle和Rectangle来显示带有边界框和面部地标的人脸
def main():
fig = plt.figure()
if choice == "Face Detection":
uploaded_file = st.file_uploader("Choose File", type=["jpg","png"])
if uploaded_file is not None:
data = asarray(Image.open(uploaded_file))
plt.axis("off")
plt.imshow(data)
ax = plt.gca()
detector = MTCNN()
faces = detector.detect_faces(data)
for face in faces:
x, y, width, height = face['box']
rect = Rectangle((x, y), width, height, fill=False, color='maroon')
ax.add_patch(rect)
for _, value in face['keypoints'].items():
dot = Circle(value, radius=2, color='maroon')
ax.add_patch(dot)
st.pyplot(fig)

除了显示图像中的点和边界框,我们还可以返回检测到的人脸。这个过程与我们上面所做的类似。唯一的区别是,我们使用检测到的人脸的坐标来提取人脸。之后,我们使用Pillow将数组转换为图像。
results = detector.detect_faces(pixels)
x1, y1, width, height = results[0]["box"]
x2, y2 = x1 + width, y1 + height
face = pixels[y1:y2, x1:x2]

我们使用Streamlitbeta_columns ,在左边显示图像,在右边显示检测到的人脸。下面是该部分的完整代码。
elif choice == "Face Detection 2":
uploaded_file = st.file_uploader("Choose File", type=["jpg","png"])
if uploaded_file is not None:
column1, column2 = st.beta_columns(2)
image = Image.open(uploaded_file)
with column1:
size = 450, 450
resized_image = image.thumbnail(size)
image.save("thumb.png")
st.image("thumb.png")
pixels = asarray(image)
plt.axis("off")
plt.imshow(pixels)
detector = MTCNN()
results = detector.detect_faces(pixels)
x1, y1, width, height = results[0]["box"]
x2, y2 = x1 + width, y1 + height
face = pixels[y1:y2, x1:x2]
image = Image.fromarray(face)
image = image.resize((224, 224))
face_array = asarray(image)
with column2:
plt.imshow(face_array)
st.pyplot(fig)
人脸验证
为了验证人脸,我们首先需要使用VGGFace模型获得人脸嵌入。在模型中传递include_top=False ,意味着我们对模型的最终分类层不感兴趣。这很重要,因为我们只对学习人脸嵌入感兴趣。 之后,我们将计算两个人脸嵌入的余弦相似度。我们还设置了一个0.50的阈值来确定人脸相似度。我们可以使用Streamlit列来展示两张脸的并列情况。
elif choice == "Face Verification":
column1, column2 = st.beta_columns(2)
with column1:
image1 = st.file_uploader("Choose File", type=["jpg","png"])
with column2:
image2 = st.file_uploader("Select File", type=["jpg","png"])
if (image1 is not None) & (image2 is not None):
col1, col2 = st.beta_columns(2)
image1 = Image.open(image1)
image2 = Image.open(image2)
with col1:
st.image(image1)
with col2:
st.image(image2)
filenames = [image1,image2]
faces = [extract_face(f) for f in filenames]
samples = asarray(faces, "float32")
samples = preprocess_input(samples, version=2)
model = VGGFace(model= "resnet50" , include_top=False, input_shape=(224, 224, 3),
pooling= "avg" )
# perform prediction
embeddings = model.predict(samples)
thresh = 0.5
score = cosine(embeddings[0], embeddings[1])
if score <= thresh:
st.success( " >face is a match (%.3f <= %.3f) " % (score, thresh))
else:
st.error(" >face is NOT a match (%.3f > %.3f)" % (score, thresh))
我们还创建了一个函数,用来检测和返回上传图片中的人脸该函数:
- 使用MTCNN来检测人脸
- 从图像中提取人脸
- 使用Pillow将图像数组转换为图像
- 将图像的大小调整到所需的大小
- 将图像作为一个NumPy数组返回
def extract_face(file):
pixels = asarray(file)
plt.axis("off")
plt.imshow(pixels)
detector = MTCNN()
results = detector.detect_faces(pixels)
x1, y1, width, height = results[0]["box"]
x2, y2 = x1 + width, y1 + height
face = pixels[y1:y2, x1:x2]
image = Image.fromarray(face)
image = image.resize((224, 224))
face_array = asarray(image)
return face_array

我们也可以用两张不相似的脸来演示:

这个实现的最后一件事是运行主函数。
if __name__ == "__main__":
main()
这个项目的代码和要求可以在这里找到。
使用Streamlit共享来部署应用程序
Streamlit允许我们只需点击两下按钮就能部署机器学习应用程序。前往share.streamlit.com,设置一个免费账户。点击 "新应用程序 "按钮,开始部署过程。对于这个免费版本,应用程序需要在GitHub上免费提供。

之后,你将选择你想部署的仓库,并点击部署按钮。该仓库需要有一个requirements.txt 文件,其中包含你的应用程序所需的所有库。

最后的思考
在这篇文章中,你已经看到了如何使用Streamlit和Keras构建和部署一个图像验证应用程序。Streamlit可以用来构建和部署各种数据科学和机器学习应用。它的语法也是相当容易掌握的。在VGG模型中,我们使用了ResNet架构,你可以尝试不同的模型,如VGG16和SENet 50,并比较其结果。如果你觉得雄心勃勃,你还可以进一步微调模型。
就这样吧,伙计们!