Сравните два лица с помощью модуля face_recognition python3?

#python-3.x #face-recognition #image-recognition

Вопрос:

извините за мой плохой английский. Я пытаюсь сравнить два лица, используя модуль python3 «распознавание лиц»

вот пример вычисления евклидова расстояния в python

pdist([вектор1, вектор2], «евклидово»)

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

Ошибка:
Различное количество элементов в массивах

Комментарии:

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

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

Сначала вам нужно преобразовать ваши данные с помощью load функции. Затем рассчитайте расстояние с помощью distance функции.
Поскольку ваши данные являются именами, я изменяю New_image данные, чтобы протестировать функцию.

Комментарии:

1. спасибо за помощь!! Если я все правильно понял, сначала мне придется получить ВСЕ(у меня их будет много «>1000000») хэши из базы данных, а затем преобразовать и сравнить их в python? Я сохраню все векторы изображений в базе данных(я еще не знаю, какой тип данных для этого я должен использовать), и мне нужно вычислить евклидово расстояние между вектором моего изображения и всеми векторами, которые находятся в базе данных, используя только SQL-запрос.

2. Нет, вы можете запускать процесс по одному, чтобы не переполнять свою оперативную память 1000000 примерами. Массивы-это не хэши, а массивы, и вы не должны хранить кратные данные в одной базе данных, назовите свои столбцы. Затем вы можете посмотреть на триггеры в базе данных, чтобы выполнять этот расчет расстояния при каждом новом вводе лица в БД. Но ваш вопрос касается получения данных и расчета расстояния. Не забудьте поставить зеленую галочку, если ответили!

3. Привет, Винсент! пожалуйста, можете ли вы проверить(если у вас есть свободное время), почему при расчете евклидова расстояния между списками я получаю ошибку: dist_line = (элемент — тест[i][j]) ** 2 Я добавил новый код для публикации.

4. Эй, вам нужен 2D массив, чтобы функция работала, здесь вы даете 1 D массив

5. Bonjour! Я нашел ошибку, но не понимаю, как ее исправить. Ошибка заключается в том, что последний массив одной фотографии содержит 2 элемента, а остальные 4 элемента. можете ли вы попробовать запустить его самостоятельно?