前言

如标题,就是通过提取的人脸特征向量,写一个欧几里得 SQL 语句,查询数据库里相似度排前 TOP_K 个的数据记录。做法虽然另类,业务层市面上有现成的面部检索 API,技术层现在有向量数据库。

用 MySQL 关系型存储 128 维人脸向量,先是进行欧式距离计算就要对每维循环,开根号后还要排序。数据一旦特别多的时候,这查询速度可想而知。但是可能就是有特别小众的需求,下面就从特征提取到 SQL 拼写几个步骤开始梳理。

打开网易新闻 查看更多图片

环境

python 3.8

opencv-python 4.8

dlib 19.24.2

mysql 5.7

特征向量提取

其实这一步可以跳过,但是没有这个,随便造的人脸向量数据不标准。这里就以读取图片人脸方式,用 dlib 库的人脸关键点检测器和面部识别模型,生成一个 128D 向量。这里有一个注意的是在生成向量时,windows 可能会出现下面错误。

Could not locate zlibwapi.dll. Please make sure it is in your library path!

确实 zlibwapi 库,这里要先下载,这里我已经放在gitee.com/gaoxingqufuhchao/opencv_demo上面。解压后 zlibwapi.lib 文件放到 CUDA 安装位置的 lib 中,zlibwapi.dll 文件放到 CUDA 安装位置的 bin 中,最后执行下面代码。

向量数据采集入库 (表结构)

打开网易新闻 查看更多图片

自定义欧氏距离计算函数

由于欧几里得距离需要将两个点的每维数值求差,在 MySQL 中也就是要循环向量被逗号分割的每个数值,然后分别求差在平方累加,最后开根号就是距离值,数越小越相似。以下语句中用到了 SUBSTRING_INDEX 函数通过循环 1 到 128 取出指定长度串,最后的 SUBSTRING_INDEX 是取出最后的数值就是循环每维数值。

SQL 语句

查询就要调用上面函数,通过指定向量与每条库里的向量值算距离,随后按顺序排列查询 TOP5

打开网易新闻 查看更多图片

其他

在实际应用中,可能是有一个预登陆账号,然后人脸身份验证类似验证码,所以可能是先有了用户标识,也是取出库里已有的用户人脸特征,然后用库里的人脸向量和摄像头采集的向量做对比。下面就用 numpy 演示两个人脸向量的欧氏距离计算和 OBS 虚拟摄像头人脸采集。

欧氏距离

OBS 虚拟摄像头人脸采集