使用 python3 模块 face_recognition 比较两个人脸?

Posted

技术标签:

【中文标题】使用 python3 模块 face_recognition 比较两个人脸?【英文标题】:Сompare two faces using python3 module face_recognition? 【发布时间】:2021-12-04 22:44:03 【问题描述】:

抱歉我的英语不好。 我正在尝试使用 python3 模块 'face_recognition' 比较两张面孔

这是一个在python中计算欧几里得距离的例子

pdist([vector1, vector2], '欧几里得')

我只想在 SQL 查询中计算欧几里得距离,因为所有面孔(他们的向量)都将存储在我的数据库中,但我不知道如何使用 SQL 查询来做到这一点。

信息:

MariaDB 版本:10.5.11

Python:3.9.2

 #!/usr/bin/env python3

import cv2
import face_recognition
import mysql.connector as mysql


def get_image_hash(image):
    # Open image
    img = face_recognition.load_image_file(image)

    # Save as black
    #img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    # Get vector
    vector = face_recognition.face_encodings(img)[0]

    vector = (str(vector),)
    
    return vector


# Open DB
conn = mysql.connect(
  host = '127.0.0.1',
  user = 'user',
  passwd = 'password'
)

cur = conn.cursor()
cur.execute("SHOW DATABASES")          

# Check if db 'test' already exist
db_found = False
for db in cur:
    if 'test' in db:
        db_found = True


if not db_found:
    cur.execute("CREATE DATABASE IF NOT EXISTS test;")
    conn.commit()
    
cur.execute("USE test;")


cur.execute("""CREATE TABLE IF NOT EXISTS faces(id_face BIGINT PRIMARY KEY NOT NULL AUTO_INCREMENT, face_hash TEXT)""")                            
                                         
new_image = get_image_hash('test.jpg')

# Add face(array) in DB
cur.execute('''INSERT INTO faces (face_hash) VALUES(%s)''', new_image)
conn.commit()


# Upload a picture for search
find_me_image = get_image_hash('findme.jpg')
#print('d: ', find_me_image[0])

# How should i compare these two arrays in my SQL query to find a similar face?
cur.execute("SELECT * FROM faces WHERE ..... ;")

cur.close()

print('find_me_image: ', str(find_me_image))
print('new_image: ', str(new_image))

结果:

Find_me_image: ('[-0.04221933  0.04460172  0.10287622 -0.14319997 -0.13808066  0.00552465\n -0.04414323 -0.07157505  0.23200855 -0.12091423  0.16892464 -0.16992114\n -0.2487883   0.09141497 -0.14198568  0.1824664  -0.11484738 -0.1130986\n -0.14396232 -0.06075872 -0.00201617  0.07473749 -0.01706937  0.05610432\n -0.11021845 -0.30173326 -0.02712429 -0.10394925 -0.05155517 -0.21909578\n  0.03083897  0.16680503 -0.09715255 -0.0407755  -0.01714687  0.08432341\n -0.01913652 -0.13662203  0.21924476  0.04394831 -0.20848413 -0.03259828\n  0.04784738  0.30321479  0.22730266 -0.02372641 -0.01165112 -0.12765107\n  0.13877977 -0.3403039   0.0424962   0.10813272  0.0511388   0.12078771\n  0.04942191 -0.13038178  0.02736722  0.15339687 -0.24367541  0.10453884\n  0.13450858 -0.09997959  0.01744595 -0.10602434  0.2614505   0.10681546\n -0.12075276 -0.12065229  0.195976   -0.11606392 -0.0447496   0.08198876\n -0.13573587 -0.18409243 -0.19127932  0.01680213  0.35644779  0.16652581\n -0.12988403 -0.00341757 -0.15569599 -0.09128557 -0.03799717  0.09235845\n  0.06296059 -0.07972728  0.00744779  0.07452074  0.23394027 -0.0726112\n -0.00072305  0.2978259  -0.01452125 -0.06529554 -0.08694689  0.01903715\n -0.14941891  0.10714116 -0.1096215   0.00143995  0.00146057  0.00348109\n  0.06795555  0.10826397 -0.18627991  0.21965174 -0.04136307 -0.01491791\n  0.03774849 -0.07495191 -0.03808937 -0.02331351  0.29242265 -0.23740929\n  0.13265632  0.1274993   0.17672779  0.11845816  0.01477844  0.07670261\n  0.11437597 -0.03779818 -0.21296507  0.03480547  0.06180557 -0.01749492\n -0.023851    0.11586148]',)
New_image:  ('[-0.04221933  0.04460172  0.10287622 -0.14319997 -0.13808066  0.00552465\n -0.04414323 -0.07157505  0.23200855 -0.12091423  0.16892464 -0.16992114\n -0.2487883   0.09141497 -0.14198568  0.1824664  -0.11484738 -0.1130986\n -0.14396232 -0.06075872 -0.00201617  0.07473749 -0.01706937  0.05610432\n -0.11021845 -0.30173326 -0.02712429 -0.10394925 -0.05155517 -0.21909578\n  0.03083897  0.16680503 -0.09715255 -0.0407755  -0.01714687  0.08432341\n -0.01913652 -0.13662203  0.21924476  0.04394831 -0.20848413 -0.03259828\n  0.04784738  0.30321479  0.22730266 -0.02372641 -0.01165112 -0.12765107\n  0.13877977 -0.3403039   0.0424962   0.10813272  0.0511388   0.12078771\n  0.04942191 -0.13038178  0.02736722  0.15339687 -0.24367541  0.10453884\n  0.13450858 -0.09997959  0.01744595 -0.10602434  0.2614505   0.10681546\n -0.12075276 -0.12065229  0.195976   -0.11606392 -0.0447496   0.08198876\n -0.13573587 -0.18409243 -0.19127932  0.01680213  0.35644779  0.16652581\n -0.12988403 -0.00341757 -0.15569599 -0.09128557 -0.03799717  0.09235845\n  0.06296059 -0.07972728  0.00744779  0.07452074  0.23394027 -0.0726112\n -0.00072305  0.2978259  -0.01452125 -0.06529554 -0.08694689  0.01903715\n -0.14941891  0.10714116 -0.1096215   0.00143995  0.00146057  0.00348109\n  0.06795555  0.10826397 -0.18627991  0.21965174 -0.04136307 -0.01491791\n  0.03774849 -0.07495191 -0.03808937 -0.02331351  0.29242265 -0.23740929\n  0.13265632  0.1274993   0.17672779  0.11845816  0.01477844  0.07670261\n  0.11437597 -0.03779818 -0.21296507  0.03480547  0.06180557 -0.01749492\n -0.023851    0.11586148]',)

新:

#!/usr/bin/env python3

import cv2
import json
import face_recognition
import mysql.connector as mysql

# DB
conn = mysql.connect(
  host = 'localhost',
  user = '',
  passwd = ''
)


def load(str_data):
    str_data = str_data.replace("[", "").replace("]", "")
    result = []
    for i, line in enumerate(str_data.split("\n")):
        result.append([])
        for element in line.replace("  ", " ").split(" "):
            try:
                result[i].append(float(element))
            except ValueError:
                pass
    return result
    

def distance(model, test):
    distance = 0
    for i, line in enumerate(model):
        dist_line = 0
        for j, element in enumerate(line):
            dist_line += (element - test[i][j]) ** 2
        distance += dist_line ** 0.5
    return distance
    
  
def get_image_hash(image):
    # Open image
    img = face_recognition.load_image_file(image)

    # Save as black
    #img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    # Get vector
    vector = face_recognition.face_encodings(img)[0]

    # We can save only iterable object
    vector = (str(vector),)
    
    return vector


cur = conn.cursor(buffered=True)
cur.execute("SHOW DATABASES")          


# Check if db 'test' already exist
db_found = False
for db in cur:
    if 'test' in db:
        db_found = True

if not db_found:
    cur.execute("CREATE DATABASE IF NOT EXISTS test;")
    conn.commit()
    
cur.execute("USE test;")
cur.execute("""CREATE TABLE IF NOT EXISTS faces(id_face BIGINT PRIMARY KEY NOT NULL AUTO_INCREMENT, face_hash TEXT)""")                            
                                         
# Add face in DB
new_image = get_image_hash('test.jpg')


print('new_image debug: ', new_image)


cur.execute('''INSERT INTO faces (face_hash) VALUES(%s)''', new_image)
conn.commit()


# Find added face
find_me_image = get_image_hash('findme.jpg')
print('debug find_me_image: ', find_me_image)



# Get data from DB
cur.execute("SELECT * FROM faces;")
face_data = cur.fetchall()


# Check
for x in face_data:
  print('1: ', load(find_me_image[0]))
  print('2: ', load(x[1]))
  
  # x[1] == row face_hash
  compare_result = distance(load(find_me_image[0]), load(x[1]))

#print('Result: ', compare_result)

# Got error
'''
Traceback (most recent call last):
  File "/home/user/Desktop/parser_steam/image_recognition/test/./test.py", line 102, in <module>
    compare_result = distance(load(find_me_image[0]), load(x[1]))
  File "/home/user/Desktop/parser_steam/image_recognition/test/./test.py", line 35, in distance
    dist_line += (element - test[i][j]) ** 2
IndexError: list index out of range
'''


cur.close()

错误:

【问题讨论】:

print(Find_me_image == New_image) -> True 这里距离为0... 【参考方案1】:

这就是你需要的!

import json


def load(str_data):
    str_data = str_data.replace("[", "").replace("]", "")
    result = []
    for i, line in enumerate(str_data.split("\n")):
        result.append([])
        for element in line.replace("  ", " ").split(" "):
            try:
                result[i].append(float(element))
            except ValueError:
                pass
    return result


def distance(model, test):
    distance = 0
    for i, line in enumerate(model):
        dist_line = 0
        for j, element in enumerate(line):
            dist_line += (element - test[i][j]) ** 2
        distance += dist_line ** 0.5
    return distance


if __name__ == "__main__":
    Find_me_image = '[-0.04221933  0.04460172  0.10287622 -0.14319997 -0.13808066  0.00552465\n -0.04414323 -0.07157505  0.23200855 -0.12091423  0.16892464 -0.16992114\n -0.2487883   0.09141497 -0.14198568  0.1824664  -0.11484738 -0.1130986\n -0.14396232 -0.06075872 -0.00201617  0.07473749 -0.01706937  0.05610432\n -0.11021845 -0.30173326 -0.02712429 -0.10394925 -0.05155517 -0.21909578\n  0.03083897  0.16680503 -0.09715255 -0.0407755  -0.01714687  0.08432341\n -0.01913652 -0.13662203  0.21924476  0.04394831 -0.20848413 -0.03259828\n  0.04784738  0.30321479  0.22730266 -0.02372641 -0.01165112 -0.12765107\n  0.13877977 -0.3403039   0.0424962   0.10813272  0.0511388   0.12078771\n  0.04942191 -0.13038178  0.02736722  0.15339687 -0.24367541  0.10453884\n  0.13450858 -0.09997959  0.01744595 -0.10602434  0.2614505   0.10681546\n -0.12075276 -0.12065229  0.195976   -0.11606392 -0.0447496   0.08198876\n -0.13573587 -0.18409243 -0.19127932  0.01680213  0.35644779  0.16652581\n -0.12988403 -0.00341757 -0.15569599 -0.09128557 -0.03799717  0.09235845\n  0.06296059 -0.07972728  0.00744779  0.07452074  0.23394027 -0.0726112\n -0.00072305  0.2978259  -0.01452125 -0.06529554 -0.08694689  0.01903715\n -0.14941891  0.10714116 -0.1096215   0.00143995  0.00146057  0.00348109\n  0.06795555  0.10826397 -0.18627991  0.21965174 -0.04136307 -0.01491791\n  0.03774849 -0.07495191 -0.03808937 -0.02331351  0.29242265 -0.23740929\n  0.13265632  0.1274993   0.17672779  0.11845816  0.01477844  0.07670261\n  0.11437597 -0.03779818 -0.21296507  0.03480547  0.06180557 -0.01749492\n -0.023851    0.11586148]'
    New_image = '[-0.04221933  0.04460172  0.10287622 -0.14319997 -0.13808064  0.00552465\n -0.04414323 -0.07157505  0.23200855 -0.12091423  0.16892464 -0.16992114\n -0.2487883   0.09141497 -0.14198568  0.18246  -0.11484738 -0.1130986\n -0.14396232 -0.06075872 -0.0020117  0.07473749 -0.01706937  0.05610432\n -0.11021845 -0.30173326 -0.02712429 -0.10394925 -0.05155517 -0.21909578\n  0.03083897  0.16680503 -0.09715255 -0.0407755  -0.01714687  0.08432341\n -0.01913652 -0.13662203  0.21924476  0.04394831 -0.20848413 -0.03259828\n  0.04784738  0.30321479  0.22730266 -0.02372641 -0.0116112 -0.12765107\n  0.13877977 -0.3403039   0.0424962   0.10813272  0.0511388   0.12078771\n  0.04942191 -0.13038178  0.02736722  0.15339687 -0.24367541  0.10453884\n  0.13450858 -0.09997959  0.01744595 -0.10602434  0.2614505   0.10681546\n -0.12075276 -0.12065229  0.195976   -0.11606392 -0.0447496   0.08198876\n -0.1357387 -0.18409243 -0.19127932  0.01680213  0.35644779  0.16652581\n -0.12988403 -0.00341757 -0.15569599 -0.09128557 -0.03799717  0.09235845\n  0.06296059 -0.07972728  0.00744779  0.07452074  0.23394027 -0.0726112\n -0.00072305  0.2978259  -0.01452125 -0.06529554 -0.08694689  0.0193715\n -0.14941891  0.10714116 -0.1096215   0.00143995  0.00146057  0.00348109\n  0.06795555  0.10826397 -0.18627991  0.21965174 -0.04136307 -0.01491791\n  0.03774849 -0.07495191 -0.03808937 -0.02331351  0.29242265 -0.23740929\n  0.13265632  0.1274993   0.1762779  0.11845816  0.01477844  0.07670261\n  0.11437597 -0.03779818 -0.21296507  0.03480547  0.0618057 -0.01749492\n -0.023851    0.1158648]'

    print(distance(
        load(Find_me_image),
        load(New_image)
    ))

您首先需要使用load 函数转换您的数据。然后使用distance 函数计算距离。 由于你的数据是一样的,我修改New_image数据来测试功能。

【讨论】:

感谢您的帮助!!如果我一开始就正确理解了所有内容,我将从数据库中获取所有(我将有很多“> 1000000”)哈希,然后在python中转换和比较它们?我会将所有图像向量存储在数据库中(我还不知道我必须使用什么类型的数据)并且我需要计算我的图像向量与数据库中所有向量之间的欧几里得距离仅使用 SQL 查询。 不,您可以一个一个地运行该过程,以免 1000000 个示例溢出您的 RAM。数组不是散列而是数组,你不应该在一个数据库中存储多个数据,命名你的列。然后,您可以查看数据库上的触发器,以便在数据库中的每个新人脸输入中运行此距离计算。但你的问题是关于获取数据和计算距离。不要忘记绿色检查是否已回答! 你好文森特!请你检查一下(如果你有空闲时间)为什么当我计算列表之间的欧几里得距离时出现错误:dist_line += (element - test[i][j]) ** 2 I added new code to post。跨度> 嘿,你需要一个二维数组才能让函数在这里工作,你给一维数组 您好!我发现了错误,但我不明白如何修复它。错误是一张照片的最后一个数组包含 2 个元素和其他 4 个元素。你可以尝试自己运行它吗?

以上是关于使用 python3 模块 face_recognition 比较两个人脸?的主要内容,如果未能解决你的问题,请参考以下文章

python3-使用模块

Python3:urllib模块的使用

python3之json模块使用

Python3-2020-测试开发-2- Python3之turtle模块使用

Python3 - tkinter 导入和使用模块

Python3 模块