写这篇文章之前,我从来没接触过这方面,查了一些基础知识,都在参考链接里,感谢他们的分享。
就安装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
相比linux,windows的安装有点复杂
需要自己准备一些含有人脸的图片放入一个文件夹中,最好是人脸正面;再准备一张人脸图片放在和文件夹同级的目录中,这张图片中的人要和文件夹中某张图片是同一个人。
如有两张周杰伦的图片,一张放在文件夹中,另一张放在和文件夹同级的目录中,然后文件夹中再放一些不是周杰伦的图片。
拿着文件夹外的这张人脸图片,去和文件夹中的所有人脸图片对比,看有没有匹配到同一个人。具体的匹配原理,在代码注释和文章末尾的参考链接中。
import face_recognition
import os
import time
from numpy import array # 若不加这一行,对从文件中读取已保存的128维人脸编码执行eval()时,报错name 'array' is not defined
import cv2
t1 = 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 False
elif 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 True
else:
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 defined
img_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])]
先放出文档中的基本使用的代码,我是按照文档中的提示一步一步复制的,这里我只测试了插入和查询,每一页末尾都有下一步的提示(截图中的中文是浏览器翻译的),代码使用时需将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-Schema
dim=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:
)
# 查看最相似向量的 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 False
elif 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 True
else:
return False
connections.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-Schema
dim=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 连接
相似度有个阈值,返回符合阈值的所有结果。我这里的阈值0.2、0.6均来自参考链接中的文章。使用时需将host改成你自己的服务器ip
import face_recognition
import os
import time
import random
from pymilvus import connections, CollectionSchema, FieldSchema, DataType, Collection
import cv2
t1 = 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 False
elif 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 True
else:
return False
if 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:
)
# 查看最相似向量的 primary key 及其距离值
id_list = results[0].ids
distance_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 2.0.1,PyMilvus 2.0.2)只能根据主键的值去删除,不能用其他字段。使用时需将host改成你自己的服务器ip
from pymilvus import connections, CollectionSchema, FieldSchema, DataType, Collection
connections.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 避坑攻略 - 知乎
这是额外补充的内容,本文未用到
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