前言

  1. 先用OpenCV判断图片是否模糊,模糊的话需要重拍;
  2. 再用face_recognition检测图片中是否有人脸,有才接着进行下一步;
  3. 再用face_recognition计算图片中每张人脸的128维人脸编码;
  4. 最后用face_recognition将本次计算得到的人脸编码与以前已计算的进行对比,得到一个相似度最高的结果。
  5. 上一步中提到已计算的人脸编码,可以将它们存入向量数据库,如Milvus、Proxima等,这样对比的时候直接从数据库中查询就行。我用的Milvus,官网有它的增删改查文档,SDK我用的PyMilvus,注意安装PyMilvus时要选和你的Milvus的版本对应的版本,不能装错,这点在文档和GitHub中都有说。Milvus有个GUI的管理程序,Attu,在Milvus文档中也有介绍,它可以在网页上查看数据库中的数据。
  6. 只用OpenCV也可以做人脸识别,我没试,参考链接里有。

写这篇文章之前,我从来没接触过这方面,查了一些基础知识,都在参考链接里,感谢他们的分享。

安装

linux

就安装dlib库和windows不一样,其他步骤一样,我只测试了CentOS 7.9.2009,服务器中有miniconda。

conda install -c conda-forge dlib,安装dlib库。

记录安装dlib库失败解决过程,认识conda-forge_后知前觉的博客-CSDN博客_dlib库安装失败

linux安装dlib,以下步骤解决所有问题。_weixin_41899102的博客-CSDN博客_linux安装dlib失败

linux系统下安装dlib_Batman。的博客-CSDN博客_linux安装dlib

windows

相比linux,windows的安装有点复杂

  • pip install cmake
  • pip install boost
  • 从pypi或github或其他地方下载dlib库的whl文件,版本要和你的python版本一致,具体怎么选版本看我的上篇文章,并使用pip install安装
  • pip install face_recognition
  • pip install opencv-python

使用

需要自己准备一些含有人脸的图片放入一个文件夹中,最好是人脸正面;再准备一张人脸图片放在和文件夹同级的目录中,这张图片中的人要和文件夹中某张图片是同一个人。

如有两张周杰伦的图片,一张放在文件夹中,另一张放在和文件夹同级的目录中,然后文件夹中再放一些不是周杰伦的图片。

拿着文件夹外的这张人脸图片,去和文件夹中的所有人脸图片对比,看有没有匹配到同一个人。具体的匹配原理,在代码注释和文章末尾的参考链接中。

本地测试

import face_recognition
import os
import time
from numpy import array  # 若不加这一行,对从文件中读取已保存的128维人脸编码执行eval()时,报错name 'array' is not defined
import cv2t1 = time.time()# 路径中不能有中文
source_img_file_path = r"C:\Users\PC-1\Desktop\ZhouJieLun1.png"
img_folder_path = r"C:\Users\PC-1\Desktop\face_img"# 获取列表的第二个元素
def takeSecond(elem):return elem[1]# 判断图片是否清晰,参数是图片的绝对路径
def getImageVar(imgPath: str) -> bool:image = cv2.imread(imgPath)img2gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)imageVar = cv2.Laplacian(img2gray, cv2.CV_64F).var()  # 一般大于100时认为图片是清晰的,实际需根据情况调节if imageVar <= 100:return Falseelif imageVar > 100:return True# 检测图片中是否有人脸。能接受不完整的人脸,如缺少鼻子以下,此时是能否检测到人脸的阈值之一,人脸中其他部位的缺少情况未测试
def check_face_img(img_path: str) -> bool:img = face_recognition.load_image_file(img_path)  # 加载图像。会将图像加载到 numpy 数组中。result = face_recognition.face_locations(img)  # 返回图像中每张人脸的人脸特征位置列表。图像中没有人脸时,返回空列表if len(result)>0:return Trueelse:return False# 获取图片库中每张图片的128维人脸编码,用于传给face_recognition.face_distance()的face_encodings参数
def get_face_encodings(img_folder_path):img_face_encoding_list = []  # 每个元素是文件夹中所有图片的128维人脸编码img_path_list = []  # 每个元素是文件夹中图片的绝对路径img_list = os.listdir(img_folder_path)for img in img_list:img_path = os.path.join(img_folder_path, img)if getImageVar(img_path) and check_face_img(img_path):img_path_list.append(img_path)img = face_recognition.load_image_file(img_path)  # 加载图像img_face_encoding = face_recognition.face_encodings(img)[0]  # 返回图像中每张人脸的 128 维人脸编码。后面使用face_recognition.face_distance()时,face_recognition.face_distance()的face_encodings参数中的值不能是由face_recognition.face_encodings(img)组成的,而应由face_recognition.face_encodings(img)[0]组成。img_face_encoding_list.append(img_face_encoding)elif not getImageVar(img_path):print(f'{img_path}图片太模糊,请重新拍摄,入库时已忽略此图片')elif not check_face_img(img_path):print(f'{img_path}没有检测到完整人脸,请重新拍摄,入库时已忽略此图片')return img_face_encoding_list, img_path_list
img_face_encoding_list, img_path_list = get_face_encodings(img_folder_path)# 从本地文件读取已保存的图片库中每张图片的128维人脸编码,节省计算时间
def get_face_encodings_from_file():with open(r"C:\Users\PC-1\Desktop\img_face_encoding_list.txt", 'r', encoding='utf-8') as f:img_face_encoding_list = eval(f.read())  # 需from numpy import array,否则eval()报错name 'array' is not definedimg_path_list=[]img_list = os.listdir(img_folder_path)for img in img_list:img_path = os.path.join(img_folder_path, img)img_path_list.append(img_path)return img_face_encoding_list, img_path_list
# img_face_encoding_list, img_path_list = get_face_encodings_from_file()if getImageVar(source_img_file_path) and check_face_img(source_img_file_path):img = face_recognition.load_image_file(source_img_file_path)# face_locations = face_recognition.face_locations(img)  # 返回图像中每张人脸的人脸特征位置列表。face_locations为(顶部、右侧、底部、左侧)顺序找到的人脸位置的元组列表source_img_face_encoding = face_recognition.face_encodings(img)[0]result = face_recognition.face_distance(face_encodings=img_face_encoding_list, face_to_compare=source_img_face_encoding)  # 给定人脸编码列表,将它们与已知的人脸编码进行比较,并得到每个比较人脸的欧氏距离。距离大小为面孔的相似程度。欧氏距离越小相似度越大。欧氏距离的典型阈值是0.6,即小于0.6的可认为匹配成功。face_encodings是要比较的人脸编码列表,face_to_compare是要与之进行比较的人脸编码。temp_list = list(zip(img_path_list, result))temp_list.sort(key=takeSecond)  # 将原列表按列表中每个子元素中的第二个元素的值进行升序排列print(temp_list)if temp_list[0][-1] < 0.6:  # 升序排列后第一个元素的相似度最高,如果它的欧氏距离小于0.6,认为匹配成功print(temp_list[0])else:print('匹配失败')  # 有可能不是本人,也有可能是本次拍摄时不清晰
elif not getImageVar(source_img_file_path):print('图片太模糊,请重新拍摄')
elif not check_face_img(source_img_file_path):print('没有检测到完整人脸,请重新拍摄')t2 = time.time()
print(t2-t1)  # 每次运行都计算所有图片的特征值,与6张图片对比耗时4.7秒;直接从本地文件读取已保存的图片库中每张图片的128维人脸编码,与6张图片对比耗时0.6秒。

img_face_encoding_list.txt的内容的示例

[array([-0.01729634,  0.10430054,  0.07625537,  0.03276102, -0.07866749,-0.02818274, -0.06889073, -0.04842021,  0.13796961, -0.05026057, 0.23302871,  0.00723806, -0.2370982 , -0.01487464, -0.06505933, 0.10084826, -0.1636425 , -0.07501083, -0.12756079, -0.10016631, 0.04007092,  0.0581928 ,  0.03240498, -0.01134465, -0.13176998,-0.2787565 , -0.07050405, -0.09639949,  0.09951212, -0.14790948,0.03040591,  0.0431371 , -0.15323421,  0.01086914,  0.0220076 ,0.01904444, -0.00923841, -0.06280316,  0.18326622,  0.03018811,-0.14447245, -0.01474072, -0.01069712,  0.24571334,  0.24511024,0.02628675, -0.04335158, -0.0862942 ,  0.06775976, -0.25436637,0.011755  ,  0.20667061,  0.05011301,  0.13582194,  0.05677999,-0.16563055,  0.02566983,  0.11052104, -0.15707225, -0.00112594,0.02829274, -0.05549442, -0.03616317, -0.05381152,  0.13676476,0.04478186, -0.09165385, -0.12494379,  0.12897444, -0.18318115,-0.00553679,  0.09620941, -0.12292095, -0.19553109, -0.20274746,0.08238635,  0.38079879,  0.18709588, -0.14765534,  0.01780803,-0.05188759, -0.02483106,  0.03612664, -0.0149317 , -0.10475352,-0.05023222, -0.05713973,  0.07221895,  0.14290087, -0.05685572,0.01866397,  0.22389664, -0.04868836,  0.01686323,  0.02283146,-0.01206459, -0.05818488,  0.05559994, -0.09816868,  0.00713632,0.06758018, -0.11922558,  0.04631898,  0.06196419, -0.13793124,0.0963118 ,  0.01178237, -0.03925588,  0.04579747,  0.01644197,-0.13718042, -0.04710923,  0.24413618, -0.24439959,  0.27725762,0.2127548 ,  0.04380967,  0.12280341,  0.07158501,  0.13633233,-0.03227835, -0.03378378, -0.09766266, -0.03692475,  0.01623037,-0.04219364, -0.03954222, -0.04019544]), array([-3.03432867e-02,  5.43443598e-02,  6.78744391e-02,  2.58869212e-02,-1.23072207e-01, -7.02521503e-02, -4.98226285e-02, -1.72496010e-02, 7.67212510e-02, -4.26685344e-03,  1.95951223e-01, -1.67683400e-02, -2.15903431e-01, -4.35754284e-03, -3.12260389e-02,  7.05019981e-02, -1.18235752e-01, -8.07965323e-02, -1.49761930e-01, -1.44610867e-01,3.96064669e-02,  4.81094792e-02,  8.37654807e-03, -3.67331831e-03,-1.19957335e-01, -2.90346920e-01, -8.59770030e-02, -1.07959040e-01,1.21038556e-01, -1.51315838e-01,  3.27938870e-02,  4.70837858e-03,-1.73844323e-01, -3.17394398e-02,  2.35435199e-02,  1.66472271e-02,-1.98804624e-02, -9.39380080e-02,  1.69165611e-01,  6.68221340e-03,-1.77107140e-01,  1.08059309e-02,  2.33938862e-02,  2.76533812e-01,2.21089691e-01,  2.53173988e-02, -1.82928685e-02, -5.52510098e-02,6.09008260e-02, -2.64982283e-01,  3.63944210e-02,  1.93908125e-01,1.00877725e-01,  1.14827916e-01,  7.65965059e-02, -1.46504432e-01,3.48312259e-02,  1.25334620e-01, -1.56430572e-01,  2.46226899e-02,2.86777914e-02, -3.82297374e-02, -1.68778505e-02, -1.19121701e-01,1.69600606e-01,  4.99524400e-02, -8.64719599e-02, -1.21018678e-01,1.09727934e-01, -1.94434166e-01, -3.34550738e-02,  8.30303952e-02,-1.11592978e-01, -1.87120140e-01, -2.38885000e-01,  1.09276593e-01,3.92007828e-01,  2.01715931e-01, -1.94086283e-01,  2.30474807e-02,-8.15587863e-02, -1.26086362e-02,  2.73021199e-02, -1.08986711e-02,-1.09373406e-01, -5.31885028e-03, -8.07625800e-02,  6.63535371e-02,1.74903929e-01, -9.10659656e-02,  3.04515511e-02,  1.86322704e-01,-2.50804201e-02,  9.74564068e-03,  2.13033091e-02, -3.06630391e-04,-1.11615628e-01,  3.51248235e-02, -9.08284336e-02,  1.10836141e-03,1.00318097e-01, -1.36240765e-01,  5.00137471e-02,  8.65165964e-02,-1.79704651e-01,  1.37958780e-01,  5.58579108e-04, -7.75038823e-02,1.49468854e-02,  1.46387927e-02, -8.91202837e-02, -3.77928428e-02,2.32269630e-01, -2.34496534e-01,  2.73653299e-01,  2.40941241e-01,3.94841023e-02,  1.35746434e-01,  5.84627874e-02,  1.05018303e-01,-5.28650098e-02, -1.84285827e-02, -1.11144938e-01, -4.56666909e-02,1.28744273e-02, -4.79294769e-02, -4.71757315e-02, -6.85334997e-03]), array([-1.19727597e-01,  2.37059481e-02,  5.41203022e-02, -5.31067979e-03,-1.02095716e-01, -6.70940429e-02,  5.28478026e-02, -9.28077772e-02, 1.14727125e-01, -5.81904836e-02,  1.65611401e-01, -9.44045261e-02, -2.55105197e-01, -4.14437950e-02, -2.89703198e-02,  1.06697828e-01, -9.61818695e-02, -1.10643283e-01, -1.84341758e-01, -9.77335051e-02,8.45019799e-03,  6.26069605e-02, -1.26636475e-02,  5.73121430e-03,-1.16348065e-01, -2.58341700e-01, -7.38507137e-02, -1.35549113e-01,6.04273453e-02, -6.86645284e-02,  3.62175442e-02,  1.11231357e-01,-1.17278963e-01, -5.90739734e-02,  2.98288725e-02,  3.80353555e-02,8.69030412e-03, -8.14783499e-02,  2.00276792e-01, -3.30614746e-02,-1.73424274e-01, -8.51858705e-02,  8.01797211e-02,  1.89619228e-01,1.80681810e-01, -3.04257311e-02,  8.26369599e-03, -1.84000656e-02,3.17999758e-02, -2.45052502e-01, -3.82037610e-02,  1.40862808e-01,1.22625537e-01,  9.89214256e-02,  5.23140244e-02, -1.46283448e-01,-8.13427381e-03,  1.29438370e-01, -1.73568085e-01,  7.16047511e-02,1.99302640e-02, -1.64908677e-01, -6.60278201e-02, -2.77188811e-02,1.60548747e-01,  8.64261240e-02, -8.74619484e-02, -1.47788346e-01,1.73828602e-01, -1.89269871e-01, -4.95751537e-02,  8.37096721e-02,-1.09814622e-01, -1.14491023e-01, -2.01664209e-01,  2.60536000e-03,3.81230652e-01,  1.08411252e-01, -1.66443884e-01, -6.42048474e-03,-1.52495116e-01, -6.41984940e-02, -2.20064986e-02,  8.72708671e-03,-3.22415009e-02, -1.00544520e-01, -9.76137221e-02, -1.15213916e-04,2.00150207e-01, -7.71829262e-02,  1.90558862e-02,  1.59315109e-01,-2.54158806e-02, -5.27779348e-02, -2.89773215e-02, -4.60110046e-03,-1.19977474e-01, -8.91544484e-03, -2.61534844e-03, -5.38323261e-02,9.46650878e-02, -1.22638777e-01,  4.54899520e-02,  9.24251229e-02,-1.47666842e-01,  1.31898567e-01, -3.10513265e-02, -2.91747078e-02,3.84223610e-02, -3.18786129e-02, -2.67100539e-02, -5.41412318e-03,2.24448472e-01, -1.44214451e-01,  2.11022705e-01,  1.61338180e-01,-4.03464250e-02,  1.21684045e-01,  2.53224019e-02,  1.12374000e-01,-1.62403062e-02,  1.75351724e-02, -1.21122740e-01, -1.05977543e-01,1.91601515e-02, -2.42309403e-02, -3.90784908e-03,  9.26381629e-03])]

将人脸编码存入Milvus

文档中的示例代码

先放出文档中的基本使用的代码,我是按照文档中的提示一步一步复制的,这里我只测试了插入和查询,每一页末尾都有下一步的提示(截图中的中文是浏览器翻译的),代码使用时需将host改成你自己的服务器ip。

代码注释中的中文文档链接现在已经跳转到英文文档了,因为我反馈了中文文档有问题,后来官方就删了中文文档,或者虽然没删但不让你访问中文文档了。

from pymilvus import connections, CollectionSchema, FieldSchema, DataType, Collection
import random# 代码是从2.0.0中文文档复制的
# 从gitee的README中https://gitee.com/milvus-io/milvus#%E5%90%AF%E5%8A%A8-milvus中'安装 Milvus 单机版'进入中文文档https://milvus.io/cn/docs/v2.0.0/install_standalone-docker.md
# 从github的README中https://github.com/milvus-io/milvus#install-milvus中'Standalone Quick Start Guide'进入英文文档https://milvus.io/docs/v2.0.x/install_standalone-docker.md
# 中文文档可能有字母大小写错误(会导致报错),最好看英文文档connections.connect(alias="default", host='YOUR HOST', port='19530')  # 构建一个 Milvus 连接,alias是创建的Milvus连接的别名# 准备架构,包括字段架构、集合架构和集合名称。
book_id = FieldSchema(name="book_id", dtype=DataType.INT64, is_primary=True, )
word_count = FieldSchema(name="word_count", dtype=DataType.INT64,  )
book_intro = FieldSchema(name="book_intro", dtype=DataType.FLOAT_VECTOR,  # 一个集合中必须有一个字段是DataType.FLOAT_VECTOR或DataType.BINARY_VECTOR类型,文档原话The collection to create must contain a primary key field and a vector field. INT64 is the only supported data type for the primary key field in current release of Milvus. from https://milvus.io/cn/docs/v2.0.0/create_collection.md#Prepare-Schemadim=2  # 向量列数,一个向量有多少个元素就有多少列。)
schema = CollectionSchema(fields=[book_id, word_count, book_intro], description="Test book search")
collection_name = "book"# 使用架构创建集合
collection = Collection(name=collection_name, schema=schema, using='default',  # 服务器别名,要在哪个服务器创建集合shards_num=2,consistency_level="Strong")# 准备要插入的数据。要插入的数据的数据类型必须与集合的架构匹配,否则 Milvus 将引发异常。
data = [[i for i in range(2000)],[i for i in range(10000, 12000)],[[random.random() for _ in range(2)] for _ in range(2000)],]collection = Collection("book")      # Get an existing collection.
mr = collection.insert(data)  # 插入数据# 为向量构建索引。矢量索引是元数据的组织单位,用于加速矢量相似性搜索。如果没有在向量上构建索引,Milvus将默认执行暴力搜索。
index_params = {  # 准备索引参数"metric_type":"L2","index_type":"IVF_FLAT","params":{"nlist":1024}}
# 通过指定矢量字段名称和索引参数来构建索引
collection = Collection("book")      # Get an existing collection.
collection.create_index(field_name="book_intro", index_params=index_params)# Milvus 中的所有搜索和查询操作都在内存中执行。在执行向量相似性搜索之前将 collection 加载到内存中。
collection = Collection("book")      # Get an existing collection.
collection.load()search_params = {"metric_type": "L2", "params": {"nprobe": 10}}  # 准备适合你的搜索场景的参数。下面的示例定义了搜索将使用欧式距离计算,并从 IVF_FLAT 索引构建的十个最近的聚类中检索向量。
results = collection.search(  # 进行向量搜索data=[[0.1, 0.2]], anns_field="book_intro", param=search_params, limit=10,  # 输出相似度最高的向量结果的数量expr=None,consistency_level="Strong"  # 从gitee的README进入的中文文档(https://milvus.io/cn/docs/v2.0.0/search.md#%E8%BF%9B%E8%A1%8C%E5%90%91%E9%87%8F%E6%90%9C%E7%B4%A2)中这里错写成strong,会有下面两行的报错,源码中说这个参数的介绍在https://github.com/milvus-io/milvus/blob/master/docs/developer_guides/how-guarantee-ts-works.md,看了参数介绍中'if no consistency level was specified, search will use the consistency level when you create the collection.',再看Collection()创建集合时的代码(https://milvus.io/cn/docs/v2.0.0/create_collection.md#Create-a-collection-with-the-schema),发现是大小写错了。从github的README进入的英文文档没错。# raise InvalidConsistencyLevel(0, f"invalid consistency level: {consistency_level}") from e# pymilvus.client.exceptions.InvalidConsistencyLevel: <InvalidConsistencyLevel: (code=0, message=invalid consistency level: strong)>
)
# 查看最相似向量的 primary key 及其距离值
print(results[0].ids)
print(results[0].distances)
collection.release()  # 搜索完成时释放 Milvus 中加载的 collection 以减少内存消耗connections.disconnect("default")  # 断开 Milvus 连接

我的实际代码

使用时需将host改成你自己的服务器ip

import face_recognition
import os
import time
import random
from pymilvus import connections, CollectionSchema, FieldSchema, DataType, Collection
import cv2# 路径中不能有中文
img_folder_path = r"C:\Users\PC-1\Desktop\face_img"# 判断图片是否清晰,参数是图片的绝对路径
def getImageVar(imgPath: str) -> bool:image = cv2.imread(imgPath)img2gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)imageVar = cv2.Laplacian(img2gray, cv2.CV_64F).var()  # 一般大于100时认为图片是清晰的,实际需根据情况调节if imageVar <= 100:return Falseelif imageVar > 100:return True# 检测图片中是否有人脸。能接受不完整的人脸,如缺少鼻子以下,此时是能否检测到人脸的阈值之一,人脸中其他部位的缺少情况未测试
def check_face_img(img_path: str) -> bool:img = face_recognition.load_image_file(img_path)  # 加载图像。会将图像加载到 numpy 数组中。result = face_recognition.face_locations(img)  # 返回图像中每张人脸的人脸特征位置列表。图像中没有人脸时,返回空列表if len(result)>0:return Trueelse:return Falseconnections.connect(alias="default", host='YOUR HOST', port='19530')  # 构建一个 Milvus 连接,alias是创建的Milvus连接的别名# 准备架构,包括字段架构、集合架构和集合名称。
face_id = FieldSchema(name="face_id", dtype=DataType.INT64, is_primary=True, auto_id=False  # 关闭自动赋值自增id,实际人员的id由前端传入)
face_feature_vector = FieldSchema(name="face_feature_vector", dtype=DataType.FLOAT_VECTOR,  # 128维人脸编码是浮点数。一个集合中必须有一个字段是DataType.FLOAT_VECTOR或DataType.BINARY_VECTOR类型,文档原话The collection to create must contain a primary key field and a vector field. INT64 is the only supported data type for the primary key field in current release of Milvus. from https://milvus.io/cn/docs/v2.0.0/create_collection.md#Prepare-Schemadim=128  # face_recognition.face_encodings()返回的列表再取第一个元素,值是128维人脸编码。向量列数,一个向量有多少个元素就有多少列。)
schema = CollectionSchema(fields=[face_id, face_feature_vector], description="face feature vector test test test")
collection_name = "face_feature_vector_test_test"# 使用架构创建集合
collection = Collection(name=collection_name, schema=schema, using='default',  # 服务器别名,要在哪个服务器创建集合shards_num=2,consistency_level="Strong")# 准备要插入的数据。要插入的数据的数据类型必须与集合的架构匹配,否则 Milvus 将引发异常。
img_list = os.listdir(img_folder_path)
for img in img_list:img_path = os.path.join(img_folder_path, img)if getImageVar(img_path) and check_face_img(img_path):img = face_recognition.load_image_file(img_path)  # 加载图像img_face_encoding = face_recognition.face_encodings(img)[0]  # 返回图像中每张人脸的 128 维人脸编码。后面使用face_recognition.face_distance()时,face_recognition.face_distance()的face_encodings参数中的值不能是由face_recognition.face_encodings(img)组成的,而应由face_recognition.face_encodings(img)[0]组成。temp_id = random.randint(0, 100000)  # face_id字段的值,能唯一确定一个人,暂时随机产生,实际应由前端传入collection = Collection("face_feature_vector_test_test")      # Get an existing collection.mr = collection.insert([ [temp_id], [img_face_encoding] ])  # 插入数据。from https://github.com/milvus-io/milvus/discussions/10713# print(mr)  # 插入操作的执行结果elif not getImageVar(img_path):print(f'{img_path}图片太模糊,请重新拍摄,入库时已忽略此图片')elif not check_face_img(img_path):print(f'{img_path}没有检测到完整人脸,请重新拍摄,入库时已忽略此图片')# 为向量构建索引。矢量索引是元数据的组织单位,用于加速矢量相似性搜索。如果没有在向量上构建索引,Milvus将默认执行暴力搜索。
index_params = {  # 准备索引参数"metric_type":"L2","index_type":"IVF_FLAT","params":{"nlist":1024}}
# 通过指定矢量字段名称和索引参数来构建索引
collection = Collection("face_feature_vector_test_test")      # Get an existing collection.
collection.create_index(field_name="face_feature_vector", index_params=index_params)# Milvus 中的所有搜索和查询操作都在内存中执行。在执行向量相似性搜索之前将 collection 加载到内存中。
collection = Collection("face_feature_vector_test_test")      # Get an existing collection.
collection.load()connections.disconnect("default")  # 断开 Milvus 连接

从Milvus中查询

相似度有个阈值,返回符合阈值的所有结果。我这里的阈值0.2、0.6均来自参考链接中的文章。使用时需将host改成你自己的服务器ip

import face_recognition
import os
import time
import random
from pymilvus import connections, CollectionSchema, FieldSchema, DataType, Collection
import cv2t1 = time.time()# 路径中不能有中文
# source_img_file_path = r"C:\Users\PC-1\Desktop\ZhouJieLun1.png"
source_img_file_path = r"C:\Users\PC-1\Desktop\LinJunJie2.png"# 判断图片是否清晰,参数是图片的绝对路径
def getImageVar(imgPath: str) -> bool:image = cv2.imread(imgPath)img2gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)imageVar = cv2.Laplacian(img2gray, cv2.CV_64F).var()  # 一般大于100时认为图片是清晰的,实际需根据情况调节if imageVar <= 100:return Falseelif imageVar > 100:return True# 检测图片中是否有人脸。能接受不完整的人脸,如缺少鼻子以下,此时是能否检测到人脸的阈值之一,人脸中其他部位的缺少情况未测试
def check_face_img(img_path: str) -> bool:img = face_recognition.load_image_file(img_path)  # 加载图像。会将图像加载到 numpy 数组中。result = face_recognition.face_locations(img)  # 返回图像中每张人脸的人脸特征位置列表。图像中没有人脸时,返回空列表if len(result)>0:return Trueelse:return Falseif getImageVar(source_img_file_path) and check_face_img(source_img_file_path):connections.connect(alias="default", host='YOUR HOST', port='19530')  # 构建一个 Milvus 连接,alias是创建的Milvus连接的别名# Milvus 中的所有搜索和查询操作都在内存中执行。在执行向量相似性搜索之前将 collection 加载到内存中。collection = Collection("face_feature_vector_test_test")      # Get an existing collection.collection.load()search_params = {"metric_type": "L2", "params": {"nprobe": 10}}  # 准备适合你的搜索场景的参数。下面的示例定义了搜索将使用欧式距离计算,并从 IVF_FLAT 索引构建的十个最近的聚类中检索向量。img = face_recognition.load_image_file(source_img_file_path)  # 加载图像img_face_encoding = face_recognition.face_encodings(img)[0]results = collection.search(  # 进行向量搜索data=[img_face_encoding], anns_field="face_feature_vector", param=search_params, limit=2,  # 输出相似度最高的向量结果的数量,即输出几个与被匹配人脸最相似的人脸特征向量expr=None,consistency_level="Strong"  # 从gitee的README进入的中文文档(https://milvus.io/cn/docs/v2.0.0/search.md#%E8%BF%9B%E8%A1%8C%E5%90%91%E9%87%8F%E6%90%9C%E7%B4%A2)中这里错写成strong,会有下面两行的报错,源码中说这个参数的介绍在https://github.com/milvus-io/milvus/blob/master/docs/developer_guides/how-guarantee-ts-works.md,看了参数介绍中'if no consistency level was specified, search will use the consistency level when you create the collection.',再看Collection()创建集合时的代码(https://milvus.io/cn/docs/v2.0.0/create_collection.md#Create-a-collection-with-the-schema),发现是大小写错了。从github的README进入的英文文档没错。# raise InvalidConsistencyLevel(0, f"invalid consistency level: {consistency_level}") from e# pymilvus.client.exceptions.InvalidConsistencyLevel: <InvalidConsistencyLevel: (code=0, message=invalid consistency level: strong)>)# 查看最相似向量的 primary key 及其距离值id_list = results[0].idsdistance_list = results[0].distances# print(id_list)# print(distance_list)if (len(list(id_list)) > 0) and (list(distance_list)[0] <= 0.2):print(list(id_list)[0])print(list(distance_list)[0])else:print('这是else,因欧氏距离全都大于0.2,不一定真实地匹配成功,0.2这个阈值是暂时写的,具体需根据情况测试确定')print(id_list)print(distance_list)# collection.release()  # 搜索完成时释放 Milvus 中加载的 collection 以减少内存消耗connections.disconnect("default")  # 断开 Milvus 连接
elif not getImageVar(source_img_file_path):print('图片太模糊,请重新拍摄')
elif not check_face_img(source_img_file_path):print('没有检测到完整人脸,请重新拍摄')t2 = time.time()
print(t2-t1)

从Milvus中删除人脸信息

根据字段的值删除当前这条数据,目前(Milvus 2.0.1,PyMilvus 2.0.2)只能根据主键的值去删除,不能用其他字段。使用时需将host改成你自己的服务器ip

from pymilvus import connections, CollectionSchema, FieldSchema, DataType, Collectionconnections.connect(alias="default", host='YOUR HOST', port='19530')  # 构建一个 Milvus 连接,alias是创建的Milvus连接的别名expr = "face_id in [835193322]"  # 删除时只能用in,不能用其他运算符,如==,文档中有说明
collection = Collection("face_feature_vector_test_test")      # Get an existing collection.
result = collection.delete(expr)
print(result)connections.disconnect("default")  # 断开 Milvus 连接

参考链接

Python中读取图片的6种方式 - 知乎

人脸识别和人脸对比

Python的开源人脸识别库:离线识别率高达99.38%(附源码) - 腾讯云开发者社区-腾讯云

opencv 训练人脸对比_Python 人脸检测方法总结_叽咕叽咕咕咕咕的博客-CSDN博客

Windows-安装dlib库(亲测绝对可以,超详细)_防空洞的仓鼠的博客-CSDN博客_dlib库安装

人脸检测识别-python库包or开源项目(仅CPU)_LEILEI18A的博客-CSDN博客

Python 人脸识别 face_recognition - 知乎

Python 使用 face_recognition 人脸识别 - 我是ed - 博客园

手把手教你用python实现人脸识别,识别率高达99.38% - 知乎

[深度学习] Python人脸识别库face_recognition使用教程_落痕的寒假的博客-CSDN博客_python人脸识别库

Python face_recognition 库人脸识别/匹配教程_allway2的博客-CSDN博客_face_locations

Python OpenCV 计算机视觉学习(人脸识别)01_ou.cs的博客-CSDN博客

基于OpenCv的人脸识别(Python完整代码)_Cheney822的博客-CSDN博客_python opencv 人脸识别

用Python实现简单的人脸识别,10分钟搞定!(附源码)_hwtl070359898的博客-CSDN博客_python人脸识别

Python Opencv 摄像头人脸检测与库中对比_ou.cs的博客-CSDN博客_python opencv人脸比对

用Python实现一个简单的——人脸相似度对比_不脱发的程序猿的博客-CSDN博客_人脸相似度对比

检测图片是否模糊

3行代码Python搞定图片清晰度识别,原来我们看到的不一定是这样的_爱喵的程序员的博客-CSDN博客

如何进行模糊检测 - 知乎

python opencv 如何检测模糊图像?自动判断模糊程度 cv2.Laplacian().var()_Dontla的博客-CSDN博客

OpenCV实战系列图像模糊检测 - 知乎

利用Laplacian变换进行图像模糊检测 - Arkenstone - 博客园

Python+Opencv检测模糊图片_技术挖掘者的博客-CSDN博客

实用技巧 | 使用OpenCV进行模糊检测 - 腾讯云开发者社区-腾讯云

使用OpenCV对手机中照片进行模糊检测 - 知乎

OpenCV通过边缘检测判断图片是否模糊_王小鹏鹏的博客-CSDN博客_图像模糊判断

保存人脸数据到数据库

人脸识别之数据库存取_西瓜不甜柠檬不酸的博客-CSDN博客

人脸识别——MySQL数据库存储人脸特征信息解决方案_Starzkg的博客-CSDN博客_人脸识别特征保存

face_recognition + opencv +摄像头 + 自建数据库实现人脸检测和识别_( ?_?)的博客-CSDN博客

Milvus 图形化管理工具 Attu 来袭! - 知乎

强大的向量数据库:Milvus - 知乎

Milvus2.0 | 向量数据库Python极简入门_訢詡的博客-CSDN博客_milvus python

Milvus 如何实现数据动态更新与查询 - 掘金

Milvus 2.0 新版本一览:重新定义向量数据库 - 腾讯云开发者社区-腾讯云

前所未有的 Milvus 源码架构解析 - 知乎

Milvus 解析 | 前所未有的 Milvus 源码架构解析-技术圈, 截止到我发这篇文章时,内容与上一个链接一样,但文章结尾多一个二维码

Milvus 避坑攻略 - 知乎

Milvus数据备份迁移

这是额外补充的内容,本文未用到

how to migrating data from Milvus 2.x cluster to other Milvus 2.x cluster? · Issue #18268 · milvus-io/milvus · GitHub

0325 直播报名|Milvus 数据迁移工具与 Milvus v1.0 - 知乎

Milvus 数据迁移工具 -- Milvusdm - Zilliz的个人空间 - OSCHINA - 中文开源技术交流社区

Milvus 数据迁移工具-Milvusdm_腾讯新闻

GitHub - milvus-io/milvus-tools: A data migration tool for Milvus.

Milvus 数据迁移工具-Milvusdm 介绍 & Milvus 社区小组成立_哔哩哔哩_bilibili

python人脸识别和人脸对比,face_recognition和OpenCV相关推荐

  1. Python | 人脸识别系统 — 人脸比对 代码部分

    本博客为人脸识别系统的人脸比对代码解释 人脸识别系统博客汇总:人脸识别系统-博客索引 项目GitHub地址:Su-Face-Recognition: A face recognition for us ...

  2. Python | 人脸识别系统 — 人脸识别

    博客汇总:Python | 人脸识别系统 - 博客索引 GitHub地址:Su-Face-Recognition 注:阅读本博客前请先参考 工具安装.环境配置:Python | 人脸识别系统 - 简介 ...

  3. python人脸识别、人脸关键点检测、性别检测

    python人脸识别.人脸关键点检测.性别检测 文章目录 根据人脸预测年龄性别和情绪 (python + keras)(三) 一款入门级的人脸.视频.文字检测以及识别的项目. age-gender-e ...

  4. Android 百度人脸识别、人脸采集、文字识别(身份证),人证对比

    Android 百度人脸识别.人脸采集.文字识别(身份证),人证对比 Android 拍照.图片压缩(兼容7.0) 由于公司的项目赶在 "某某打车" 事件期间,所以你懂得.老板说要 ...

  5. 人脸识别,人脸对比技术及案例实现方案

    人脸识别,人脸对比技术及案例实现方案 一.各个人脸识别公司.系统简介 1.1 虹软 1.2 Face++旷视 1.3 云脉 1.4 腾讯AI 1.5 1MB轻量级人脸检测模型 1.6 SeetaFac ...

  6. SSM+ajax使用百度AI人脸识别(人脸对比)功能心得

    最近做毕业设计,算是自己第一次独立完成一个系统,使用了百度ai的接口,查询了大部分网络上的博客,也来分享一下自己的经验. 1.首先,使用之前先注册一个百度AI开放平台的账号 2.登录之后,创建属于自己 ...

  7. 基于insightface实现的人脸识别和人脸注册

    本教程的人脸识别是使用的是insightface库进行开发的,该库使用的框架为ONNX,使用的是Anaconda环境. 代码地址:点击下载 安装环境 安装insightface ,安装命令如下. py ...

  8. 调用远程摄像头进行人脸识别_人脸识别技术植入手机APP

    随着物联网技术的日益成熟,我们看到已经有很多APP用到了人脸识别技术,特别是金融和互联网领域的应用纷纷加入了人脸识别.表示,人脸识别技术基于人的脸部特征信息进行身份识别,为互联网金融等行业解决在线多维 ...

  9. 人脸识别:人脸数据集

    日萌社 人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度学习实战(不定时更新) 人脸识别功能实现的原理介绍与算法介绍 人脸识别:人脸数据集 A ...

最新文章

  1. python爬虫requests-Python爬虫(三)Requests库
  2. 微积分笔记(一)--预备知识
  3. 【python】 读取Excel文件并绘制图表
  4. java注解类型_Java注解类型
  5. 我的新发现:AVL树旋转的一个特性
  6. 散列表(算法导论笔记)
  7. Zookeeper——一致性协议:Zab协议
  8. 【Python】http.client库的用法
  9. [转载] 令牌桶算法和漏桶算法python_排序算法(七):Bucket Sort 桶排序
  10. js-01_面向对象选项卡
  11. win7未能成功安装驱动服务器,win7插入鼠标提示未能成功安装设备驱动程序的解决办法...
  12. Python之堆排序算法实现
  13. 浅谈5G和4G有哪些区别?
  14. 在线客服技术详解(理论)
  15. java中 字符串的补位
  16. Unity SRP初识之URP
  17. EXCEL中进行经纬度坐标排重
  18. sql 获取当前年份的12个月
  19. # 7-3 二分法求多项式单根
  20. 《操作系统真象还原》第十章

热门文章

  1. 两台电脑传文件|如何快速传输几百G的文件
  2. [ELK]使用脚本写入带scripted field的index pattern时发生的错误
  3. Web认证Wifi接入-captive portal
  4. 选择远程控制软件最需要关注的五件事情
  5. 手机待机功耗测试软件,移动端相关功耗测试杂谈
  6. Python-学习笔记
  7. 王道操作系统思维导图
  8. c#实现日历_GUI
  9. C语言中的 outtextxy(x5, y5,s);的问题
  10. ESP8266的softAP例程应用出错、重启