Elasticsearch 和 Python构建面部识别系统—Elastic Stack 实战手册

本文涉及的产品
Elasticsearch Serverless通用抵扣包,测试体验金 200元
简介: 你是否曾经尝试在图像中搜索目标? Elasticsearch 可以帮助你存储,分析和搜索图像或视频中的目标。

970X90.png

· 更多精彩内容,请下载阅读全本《Elastic Stack实战手册》

· 加入创作人行列,一起交流碰撞,参与技术圈年度盛事吧

创作人:刘晓国

你是否曾经尝试在图像中搜索目标? Elasticsearch 可以帮助你存储,分析和搜索图像或视频中的目标。

在本文中,我们将向你展示如何构建一个使用 Python 进行面部识别的系统。 了解有关如何检测和编码面部信息的更多信息-并在搜索中找到匹配项。

1.png

我们将参照代码: https://github.com/liu-xiao-guo/face_detection_elasticsearch。你可以把这个代码下载到本地的电脑:
$ pwd
/Users/liuxg/python/face_detection
$ tree -L 2
.
├── README.md
├── getVectorFromPicture.py
├── images
│   ├── shay.png
│   ├── simon.png
│   ├── steven.png
│   └── uri.png
├── images_to_be_recognized
│   └── facial-recognition-blog-elastic-founders-match.png
└── recognizeFaces.py

在上面的代码中,有如下的两个 python 文件:

  • getVectorFromPicture.py:导入在 images 目录下的图像。这些图像将被导入到 Elasticsearch 中
  • recognizeFaces.py:识别位于 images_to_be_recognized 目录下的图像文件

基础知识

面部识别

面部识别是使用面部特征来识别用户的过程,例如,为了实现身份验证机制(例如解锁智能手机)。 它根据人的面部细节捕获,分析和比较模式。 此过程可以分为三个步骤:

  • 人脸检测:识别数字图像中的人脸
  • 人脸数据编码:将人脸特征转换为数字表示
  • 脸部比对:搜寻和比较脸部特征

在示例中,我们将引导你完成每个步骤。

128 维向量

可以将面部特征转换为一组数字信息,以便进行存储和分析。

2.png

Vector data type

Elasticsearch 提供了 dense_vector 数据类型来存储浮点值的 dense vectors。 向量中的最大尺寸数不应超过 2048,这足以存储面部特征表示。

现在,让我们实现所有这些概念。

准备

要检测面部并编码信息,你需要执行以下操作:

  1. Python:在此示例中,我们将使用 Python 3
  2. Elasticsearch 集群:你可以免费使用 阿里云Elasticsearch 来启动集群。本文中,我将进行一个本地的部署 Elasticsearch 及 Kibana。
  3. 人脸识别库:一个简单的人脸识别 Python 库。
  4. Python Elasticsearch 客户端:Elasticsearch的官方Python客户端。
客户端下载: https://elasticsearch-py.readthedocs.io/en/v7.10.1/

Python教程:https://elasticstack.blog.csdn.net/article/details/111573923

Python下载::https://www.python.org/downloads/

注意,我们已经在 Ubuntu 20.04 LTS 和 Ubuntu 18.04 LTS 上测试了以下说明。 根据你的操作系统,可能需要进行一些更改。尽管下面的安装步骤是针对 Ubuntu 操作系统的,但是我们可以按照同样的步骤在 Mac OS 上进行同样的顺序进行安装(部分指令会有所不同)。

安装 Python 和 Python 库

随 Python 3 的安装一起提供了 Ubuntu 20.04 和其他版本的 Debian Linux。

如果你的系统不是这种情况,则可以点击下载并安装 Python: https://www.python.org/downloads/

要确认您的版本是最新版本,可以运行以下命令:

sudo apt update 
sudo apt upgrade

确认 Python 版本为 3.x:

python3 -V

或者:

python --version

安装 pip3 来管理 Python 库:

sudo apt install -y python3-pip

安装 face_recognition 库所需的 cmake:

pip3 install CMake

将 cmake bin 文件夹添加到 $PATH 目录中:

export PATH=$CMake_bin_folder:$PATH

在我的测试中,上述步骤可以不需要。你只要在任何一个 terminal 中打入 cmake 命令,如果能看到被执行,那么就可以不用上面的命令了。

最后,在开始编写主程序脚本之前,安装以下库:

pip3 install dlib 
pip3 install numpy 
pip3 install face_recognition  
pip3 install elasticsearch

从图像中检测和编码面部信息

使用 face_recognition 库,我们可以从图像中检测人脸,并将人脸特征转换为 128 维向量。

3.png

为此,我们创建一个叫做 getVectorFromPicture.py:

getVectorFromPicture.py

import face_recognition 
import numpy as np 
import sys
import os
from pathlib import Path
from elasticsearch import Elasticsearch
 
es = Elasticsearch([{'host':'localhost','port':9200}])
 
cwd = os.getcwd()
print("cwd: " + cwd)
 
# Get the images directory
rootdir = cwd + "/images"
print("rootdir: " + rootdir)
 
for subdir, dirs, files in os.walk(rootdir):
    for file in files:
        print(os.path.join(subdir, file))
        file_path = os.path.join(subdir, file)
 
        image = face_recognition.load_image_file(file_path)
 
        # detect the faces from the images
        face_locations = face_recognition.face_locations(image)
 
        # encode the 128-dimension face encoding for each face in the image
        face_encodings = face_recognition.face_encodings(image, face_locations)
 
        # Display the 128-dimension for each face detected
        for face_encoding in face_encodings:
            print("Face found ==>  ", face_encoding.tolist())
            print("name: " + Path(file_path).stem)
            name = Path(file_path).stem
            face_encoding = face_encoding.tolist()
 
            # format a dictionary to be indexed
            e = {
                "face_name": name,
                "face_encoding": face_encoding 
            }
 
            res = es.index(index = 'faces', doc_type ='_doc', body = e)

首先,我们需要声明的是:你需要修改上面的 Elasticsearch 的地址,如果你的 Elasticsearch 不是运行于 localhost:9200。上面的代码非常之简单。它把当前目录下的子目录 images 下的所有文件都扫描一遍,并针对每个文件进行编码。我们使用 Python client API 接口把数据导入到 Elasticsearch 中去。在我们的 images 文件夹中,有四个文件。

在导入数据之前,我们需要在 Kibana 中创建一个叫做 faces 的索引:

PUT faces
{
  "mappings": {
    "properties": {
      "face_name": {
        "type": "keyword"
      },
      "face_encoding": {
        "type": "dense_vector",
        "dims": 128
      }
    }
  }
}

让我们执行 getVectorFromPicture.py 以获取 Elastic 创始人图像的面部特征表示。

python3 getVectorFromPicture.py

4.png

现在,我们可以将面部特征表示存储到 Elasticsearch 中。

5.png

我们可以在 Elasticsearch 中看到四个文档:

GET faces/_count
{
  "count" : 4,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  }
}

我们也可以查看 faces 索引的文档:

GET faces/_search

6.png

匹配面孔

假设我们在 Elasticsearch 中索引了四个文档,其中包含 Elastic 创始人的每个面部表情。 现在,我们可以使用创始人的其他图像来匹配各个图像。

7.png

为此,我们需要创建一个叫做 recognizeFaces.py 的文件。

recognizeFaces.py

import face_recognition
import numpy as np
from elasticsearch import Elasticsearch
import sys
import os
 
from elasticsearch import Elasticsearch
 
es = Elasticsearch([{'host': 'localhost', 'port': 9200}])
 
cwd = os.getcwd()
# print("cwd: " + cwd)
 
# Get the images directory
rootdir = cwd + "/images_to_be_recognized"
# print("rootdir: {0}".format(rootdir))
 
for subdir, dirs, files in os.walk(rootdir):
    for file in files:
        print(os.path.join(subdir, file))
        file_path = os.path.join(subdir, file)
 
        image = face_recognition.load_image_file(file_path)
 
        # detect the faces from the images
        face_locations = face_recognition.face_locations(image)
 
        # encode the 128-dimension face encoding for each face in the image
        face_encodings = face_recognition.face_encodings(image, face_locations)
 
        # Display the 128-dimension for each face detected
        i = 0
        for face_encoding in face_encodings:
            i += 1
            print("Face", i)
            response = es.search(
                index="faces",
                body={
                    "size": 1,
                    "_source": "face_name",
                    "query": {
                        "script_score": {
                            "query": {
                                "match_all": {}
                            },
                            "script": {
                                "source": "cosineSimilarity(params.query_vector, 'face_encoding')",
                                "params": {
                                    "query_vector": face_encoding.tolist()
                                }
                            }
                        }
                    }
                }
            )
 
            # print(response)
 
            for hit in response['hits']['hits']:
                # double score=float(hit['_score'])
                print("score: {}".format(hit['_score']))
                if float(hit['_score']) > 0.92:
                    print("==> This face  match with ", hit['_source']['face_name'], ",the score is", hit['_score'])
                else:
                    print("==> Unknown face")

这个文件的写法也非常简单。它从目录 images_to_be_recognized 中获取需要识别的文件,并对这个图片进行识别。我们使用 cosineSimilarity 函数来计算给定查询向量和存储在 Elasticsearch 中的文档向量之间的余弦相似度。

 # Display the 128-dimension for each face detected
        i = 0
        for face_encoding in face_encodings:
            i += 1
            print("Face", i)
            response = es.search(
                index="faces",
                body={
                    "size": 1,
                    "_source": "face_name",
                    "query": {
                        "script_score": {
                            "query": {
                                "match_all": {}
                            },
                            "script": {
                                "source": "cosineSimilarity(params.query_vector, 'face_encoding')",
                                "params": {
                                    "query_vector": face_encoding.tolist()
                                }
                            }
                        }
                    }
                }
            )

假设分数低于 0.92 被认为是未知面孔:

for hit in response['hits']['hits']:
                # double score=float(hit['_score'])
                print("score: {}".format(hit['_score']))
                if float(hit['_score']) > 0.92:
                    print("==> This face  match with ", hit['_source']['face_name'], ",the score is", hit['_score'])
                else:
                    print("==> Unknown face")

执行上面的 Python 代码:

8.png

该脚本能够检测出得分匹配度高于 0.92 的所有面孔

搜寻进阶

面部识别和搜索可以结合使用,以用于高级用例。 你可以使用 Elasticsearch 构建更复杂的查询,例如 geo_queries,query-dsl-bool-query 和 search-aggregations。

例如,以下查询将 cosineSimilarity 搜索应用于200公里半径内的特定位置:

GET /_search 
{ 
  "query": { 
    "script_score": { 
      "query": { 
    "bool": { 
      "must": { 
        "match_all": {} 
      }, 
      "filter": { 
        "geo_distance": { 
          "distance": "200km", 
          "pin.location": { 
            "lat": 40, 
            "lon": -70 
          } 
        } 
      } 
    } 
  }, 
       "script": { 
                "source": "cosineSimilarity(params.query_vector, 'face_encoding')", 
                 "params": { 
                 "query_vector":[ 
                        -0.14664565,
                       0.07806452,
                       0.03944433,
                       ...
                       ...
                       ...
                       -0.03167224,
                       -0.13942884
                    ] 
                } 
           } 
    } 
  } 
}

将 cosineSimilarity 与其他 Elasticsearch 查询结合使用,可以无限地实现更复杂的用例。

结论

面部识别可能与许多用例相关,并且你可能已经在日常生活中使用了它。 上面描述的概念可以推广到图像或视频中的任何对象检测,因此你可以将用例扩展到非常大的应用场景。

参考:

相关实践学习
以电商场景为例搭建AI语义搜索应用
本实验旨在通过阿里云Elasticsearch结合阿里云搜索开发工作台AI模型服务,构建一个高效、精准的语义搜索系统,模拟电商场景,深入理解AI搜索技术原理并掌握其实现过程。
ElasticSearch 最新快速入门教程
本课程由千锋教育提供。全文搜索的需求非常大。而开源的解决办法Elasricsearch(Elastic)就是一个非常好的工具。目前是全文搜索引擎的首选。本系列教程由浅入深讲解了在CentOS7系统下如何搭建ElasticSearch,如何使用Kibana实现各种方式的搜索并详细分析了搜索的原理,最后讲解了在Java应用中如何集成ElasticSearch并实现搜索。  
相关文章
|
2月前
|
人工智能 JavaScript API
零基础构建MCP服务器:TypeScript/Python双语言实战指南
作为一名深耕技术领域多年的博主摘星,我深刻感受到了MCP(Model Context Protocol)协议在AI生态系统中的革命性意义。MCP作为Anthropic推出的开放标准,正在重新定义AI应用与外部系统的交互方式,它不仅解决了传统API集成的复杂性问题,更为开发者提供了一个统一、安全、高效的连接框架。在过去几个月的实践中,我发现许多开发者对MCP的概念理解透彻,但在实际动手构建MCP服务器时却遇到了各种技术壁垒。从环境配置的细节问题到SDK API的深度理解,从第一个Hello World程序的调试到生产环境的部署优化,每一个环节都可能成为初学者的绊脚石。因此,我决定撰写这篇全面的实
435 67
零基础构建MCP服务器:TypeScript/Python双语言实战指南
|
2月前
|
机器学习/深度学习 算法 量子技术
GQNN框架:让Python开发者轻松构建量子神经网络
为降低量子神经网络的研发门槛并提升其实用性,本文介绍一个名为GQNN(Generalized Quantum Neural Network)的Python开发框架。
51 4
GQNN框架:让Python开发者轻松构建量子神经网络
|
20天前
|
人工智能 自然语言处理 安全
Python构建MCP服务器:从工具封装到AI集成的全流程实践
MCP协议为AI提供标准化工具调用接口,助力模型高效操作现实世界。
252 1
|
21天前
|
安全 JavaScript Java
Python中None与NoneType的真相:从单例对象到类型系统的深度解析
本文通过10个真实场景,深入解析Python中表示“空值”的None与NoneType。从单例模式、函数返回值,到类型注解、性能优化,全面揭示None在语言设计与实际编程中的核心作用,帮助开发者正确高效地处理“无值”状态,写出更健壮、清晰的Python代码。
112 3
|
2月前
|
算法 数据可视化 数据挖掘
基于EM期望最大化算法的GMM参数估计与三维数据分类系统python源码
本内容展示了基于EM算法的高斯混合模型(GMM)聚类实现,包含完整Python代码、运行效果图及理论解析。程序使用三维数据进行演示,涵盖误差计算、模型参数更新、结果可视化等关键步骤,并附有详细注释与操作视频,适合学习EM算法与GMM模型的原理及应用。
|
3月前
|
数据采集 数据可视化 JavaScript
用Python采集CBC新闻:如何借助海外代理IP构建稳定采集方案
本文介绍了如何利用Python技术栈结合海外代理IP采集加拿大CBC新闻数据。内容涵盖使用海外代理IP的必要性、青果代理IP的优势、实战爬取流程、数据清洗与可视化分析方法,以及高效构建大规模新闻采集方案的建议。适用于需要获取国际政治经济动态信息的商业决策、市场预测及学术研究场景。
|
4月前
|
JSON 安全 数据可视化
Elasticsearch(es)在Windows系统上的安装与部署(含Kibana)
Kibana 是 Elastic Stack(原 ELK Stack)中的核心数据可视化工具,主要与 Elasticsearch 配合使用,提供强大的数据探索、分析和展示功能。elasticsearch安装在windows上一般是zip文件,解压到对应目录。文件,elasticsearch8.x以上版本是自动开启安全认证的。kibana安装在windows上一般是zip文件,解压到对应目录。elasticsearch的默认端口是9200,访问。默认用户是elastic,密码需要重置。
1732 0
|
5月前
|
安全 Java Linux
Linux安装Elasticsearch详细教程
Linux安装Elasticsearch详细教程
754 1
|
10月前
|
存储 安全 数据管理
如何在 Rocky Linux 8 上安装和配置 Elasticsearch
本文详细介绍了在 Rocky Linux 8 上安装和配置 Elasticsearch 的步骤,包括添加仓库、安装 Elasticsearch、配置文件修改、设置内存和文件描述符、启动和验证 Elasticsearch,以及常见问题的解决方法。通过这些步骤,你可以快速搭建起这个强大的分布式搜索和分析引擎。
385 5

相关产品

  • 检索分析服务 Elasticsearch版
  • 推荐镜像

    更多