Обнаружение лиц на Python с использованием OpenCV и MySQL

Я пишу программу для распознавания лиц, где данные берутся из MySQL, и сделал её с использованием pymysql, но знания pymysql и OpenCV 3.0+ хромают. Я подгонял под нужную мне СУБД и версию OpenCV коды с этого сайта: https://dev.to/pranay749254/simple-face-recognizing-system-using-python-and-opencv

Причём, первые два благополучно создали фотки и yml-образ, но на этапе распознавания начались проблемы с выводом данных на экран: программа чуть-чуть подвигалась, а потом зависла и выдала ошибки, связанные с putText и индексами строки profile. Сначала попробовал ключи, соответствующие названиям столбцов, на что компилятор "сказал", что нужны значения числового, а не кортежного типа, потом попробовал индексы с цифрами, как в примерах, но появилась ошибка, причину которой я не знаю. Как правильно из БД извлечь строки и разбить их по нужным ключам, а потом передать их в putText?

insert_or_update.py

import cv2
import numpy as np
import pymysql
from pymysql.cursors import DictCursor

faceDetect = cv2.CascadeClassifier('haarcascade_frontalface_default.xml');
cam = cv2.VideoCapture(0);

def insertOrUpdate(Id, Name, Age, Gen, CR):
    conn = pymysql.connect(host='localhost', user='root', password='', db='facebase', charset='utf8mb4', cursorclass=DictCursor)
    with conn.cursor() as cursor:
        cmd = "SELECT * FROM people WHERE ID=%s"
        cursor.execute(cmd, Id)
        count_row = cursor.rowcount


if (count_row > 0):
    with conn.cursor() as cursor:
        cmd = "UPDATE people SET Name=%s, Age=%s, Gender=%s, CR=%s WHERE ID=%s"
        cursor.execute(cmd, (Name, Age, Gen, CR, Id))
        conn.commit()
else:
    with conn.cursor() as cursor:
        cmd = "INSERT INTO people(ID, Name, Age, Gender, CR) Values(%s, %s, %s, %s, %s)"
        cursor.execute(cmd, (Id, Name, Age, Gen, CR))
        conn.commit()

conn.close()


Id = input('Enter User Id')
name = input('Enter User Name')
age = input('Enter User Age')
gen = input('Enter User Gender')
cr = input('Enter User Criminal Records')
insertOrUpdate(Id, name, age, gen, cr)
sampleNum = 0
while(True):
    ret, img = cam.read();
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    faces = faceDetect.detectMultiScale(gray, 1.3, 5);
    for(x, y, w, h) in faces:
        sampleNum = sampleNum + 1;
        cv2.imwrite("dataSet/User." + str(Id) + "." + str(sampleNum) + ".jpg", gray[y:y+h, x:x+w])
        cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)
        cv2.waitKey(100);
    cv2.imshow("Face", img);
    cv2.waitKey(1);
    if(sampleNum > 20):
        break;

cam.release()
cv2.destroyAllWindows()

training.py

import os
import cv2
import numpy as np
from PIL import Image

recognizer = cv2.face.LBPHFaceRecognizer_create();
path = 'dataSet'

def getImagesWithID(path):
    imagepaths = [os.path.join(path, f) for f in os.listdir(path)]
    faces=[]
    IDs=[]
    for imagepath in imagepaths:
        faceImg = Image.open(imagepath).convert('L');
        faceNp = np.array(faceImg, 'uint8')
        ID = int(os.path.split(imagepath)[-1].split('.')[1])
        faces.append(faceNp)
        IDs.append(ID)
        cv2.imshow("training", faceNp)
        cv2.waitKey(10)
    return np.array(IDs), faces

IDs, faces = getImagesWithID(path)
recognizer.train(faces, IDs)
recognizer.write('recognizer/trainningData.yml')
cv2.destroyAllWindows()

recognition.py

import cv2
import numpy as np
import os
import pymysql
from pymysql.cursors import DictCursor

faceDetect = cv2.CascadeClassifier('haarcascade_frontalface_default.xml');
cam = cv2.VideoCapture(0);
rec = cv2.face.LBPHFaceRecognizer_create();
rec.read("recognizer/trainningData.yml")
font = cv2.FONT_HERSHEY_SIMPLEX

def getProfile(id):
    conn = pymysql.connect(host='localhost', user='root', password='', db='facebase', charset='utf8mb4', cursorclass=DictCursor)
    with conn.cursor() as cursor:
        cmd = "SELECT * FROM people WHERE ID=%s"
        cursor.execute(cmd, id)
        rows = cursor.fetchall()
        profile = None
        for row in rows:
            profile = row
    conn.close()
    return profile

while(True):
    ret, img = cam.read();
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    faces = faceDetect.detectMultiScale(gray, 1.3, 5);
    for(x, y, w, h) in faces:
        cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)
        id, conf = rec.predict(gray[y:y+h, x:x+w])
        profile = getProfile(id)
        if(profile != None):
            cv2.putText(img, "Name : " + str(profile[1]), (x, y+h+20), font, (0, 255, 0), 2);
            cv2.putText(img, "Age : " + str(profile[2]), (x, y+h+45), font, (0, 255, 0), 2);
            cv2.putText(img, "Gender : " + str(profile[3]), (x, y+h+70), font, (0, 255, 0), 2);
            cv2.putText(img, "Criminal Records : " + str(profile[4]), (x, y+h+95), font, (0, 0, 255), 2);
    cv2.imshow("Face", img);
    if(cv2.waitKey(1)==ord('q')):
        break;
cam.release()
cv2.destroyAllWindows()

Ошибки:

D:\Python\python.exe C:/face_detection_mysql/recognition.py
Traceback (most recent call last):
  File "C:/face_detection_mysql/recognition.py", line 34, in <module>
    cv2.putText(img, "Name : " + str(profile[1]), (x, y+h+20), font, (0, 255, 0), 2);
KeyError: 1
[ WARN:0] global C:\projects\opencv-python\opencv\modules\videoio\src\cap_msmf.cpp (674) SourceReaderCB::~SourceReaderCB terminating async callback

Process finished with exit code -805306369 (0xCFFFFFFF)

Просто вывести строку могу, а присвоить profile, вернуть из функции и поместить в putText - нет, так как нужен тип действительных чисел вместо кортежа.

test_output.py

import cv2
import numpy as np
import os
import pymysql

def getProfile(id):
    conn = pymysql.connect(host='localhost', user='root', password='', db='facebase', charset='utf8mb4')
    with conn.cursor() as cursor:
        cmd = "SELECT * FROM people WHERE ID=%s"
        cursor.execute(cmd, id)
        for row in cursor:
            print(row)
    conn.close()

getProfile(1)

Результат:

D:\Python\python.exe C:/face_detection_mysql/test_output.py
(1, 'Vladimir', 23, 'M', 'None')

Process finished with exit code 0

recognition.py

import cv2
import numpy as np
import os
import pymysql

faceDetect = cv2.CascadeClassifier('haarcascade_frontalface_default.xml');
cam = cv2.VideoCapture(0);
rec = cv2.face.LBPHFaceRecognizer_create();
rec.read("recognizer/trainningData.yml")
font = cv2.FONT_HERSHEY_SIMPLEX

def getProfile(id):
    conn = pymysql.connect(host='localhost', user='root', password='', db='facebase', charset='utf8mb4')
    with conn.cursor() as cursor:
        cmd = "SELECT * FROM people WHERE ID=%s"
        cursor.execute(cmd, id)
        profile = None
        for row in cursor:
            profile = row
    conn.close()
    return profile

while(True):
    ret, img = cam.read();
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    faces = faceDetect.detectMultiScale(gray, 1.3, 5);
    for(x, y, w, h) in faces:
        cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)
        id, conf = rec.predict(gray[y:y+h, x:x+w])
        profile = getProfile(id)
        if(profile != None):
            cv2.putText(img, "Name : " + str(profile[1]), (x, y+h+20), font, (0, 255, 0), 2);
            cv2.putText(img, "Age : " + str(profile[2]), (x, y+h+45), font, (0, 255, 0), 2);
            cv2.putText(img, "Gender : " + str(profile[3]), (x, y+h+70), font, (0, 255, 0), 2);
            cv2.putText(img, "Criminal Records : " + str(profile[4]), (x, y+h+95), font, (0, 0, 255), 2);
    cv2.imshow("Face", img);
    if(cv2.waitKey(1)==ord('q')):
        break;
cam.release()
cv2.destroyAllWindows()

Результат:

D:\Python\python.exe C:/face_detection_mysql/recognition.py
Traceback (most recent call last):
  File "C:/face_detection_mysql/recognition.py", line 32, in <module>
    cv2.putText(img, "Name : " + str(profile[1]), (x, y+h+20), font, (0, 255, 0), 2);
TypeError: must be real number, not tuple
[ WARN:0] global C:\projects\opencv-python\opencv\modules\videoio\src\cap_msmf.cpp (674) SourceReaderCB::~SourceReaderCB terminating async callback

Process finished with exit code -805306369 (0xCFFFFFFF)

Как вернуть массив строк, если в видеопотоке будет несколько лиц? Также я путаюсь в этих индексах - почему к элементам массива profile нельзя обратиться по названиям столбцов?

Попробовал раскидать значения ключей строки по разным переменным с помощью fetchone - та же проблема: просто вывести могу, а загнать в putText - нет по той же самой причине. Даже явное преобразование в строку посредством str() не помогло.

recognition.py

import cv2
import numpy as np
import os
import pymysql

faceDetect = cv2.CascadeClassifier('haarcascade_frontalface_default.xml');
cam = cv2.VideoCapture(0);
rec = cv2.face.LBPHFaceRecognizer_create();
rec.read("recognizer/trainningData.yml")
font = cv2.FONT_HERSHEY_SIMPLEX

def getProfile(id):
    conn = pymysql.connect(host='localhost', user='root', password='', db='facebase', charset='utf8mb4')
    name = None
    age = None
    gen = None
    cr = None
    with conn.cursor() as cursor:
        cmd = "SELECT * FROM people WHERE ID=%s"
        cursor.execute(cmd, id)
        id, name, age, gen, cr = cursor.fetchone()
    conn.close()
    return id, name, age, gen, cr

while(True):
    ret, img = cam.read();
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    faces = faceDetect.detectMultiScale(gray, 1.3, 5);
    for(x, y, w, h) in faces:
        cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)
        id, conf = rec.predict(gray[y:y+h, x:x+w])
        id, name, age, gen, cr = getProfile(id)
        if(name != None and age != None and gen != None and cr != None):
            cv2.putText(img, "Name : " + str(name), (x, y+h+20), font, (0, 255, 0), 2);
            cv2.putText(img, "Age : " + str(age), (x, y+h+45), font, (0, 255, 0), 2);
            cv2.putText(img, "Gender : " + str(gen), (x, y+h+70), font, (0, 255, 0), 2);
            cv2.putText(img, "Criminal Records : " + str(cr), (x, y+h+95), font, (0, 0, 255), 2);
    cv2.imshow("Face", img);
    if(cv2.waitKey(1)==ord('q')):
        break;
cam.release()
cv2.destroyAllWindows()

Ошибки:

D:\Python\python.exe C:/face_detection_mysql/recognition.py
Traceback (most recent call last):
  File "C:/face_detection_mysql/recognition.py", line 34, in <module>
    cv2.putText(img, "Name : " + str(name), (x, y+h+20), font, (0, 255, 0), 2);
TypeError: must be real number, not tuple
[ WARN:0] global C:\projects\opencv-python\opencv\modules\videoio\src\cap_msmf.cpp (674) SourceReaderCB::~SourceReaderCB terminating async callback

Process finished with exit code -805306369 (0xCFFFFFFF)

Результат работы первого кода в PHPMyAdmin Папка с проектом dataSet recognizer Пример фоток для тренировки


Ответы (0 шт):