This week, I continued to work on face recognition, and the first step I took was face tracking. The system can detect the face automatically and use the holder to move the face to the center of the screen. Here is my code👇
Track_Display.py
import cv2
from picamera2 import Picamera2
import libcamera
from adafruit_servokit import ServoKit
step = 1
# 初始化伺服电机控制
kit = ServoKit(channels=16)
# 初始伺服角度
pan = 90
tilt = 90
kit.servo[0].angle = pan
kit.servo[1].angle = tilt
# 摄像头分辨率
dispW, dispH = 640, 480
# 人脸检测模型加载
face_cascade = cv2.CascadeClassifier('./source/haarcascade_frontalface_default.xml')
def Track_Display():
"""摄像头视频采集与人脸检测"""
global pan, tilt
# 初始化摄像头
picamera = Picamera2()
config = picamera.create_preview_configuration(
main={"format": 'RGB888', "size": (dispW, dispH)},
raw={"format": "SRGGB12", "size": (1920, 1080)}
)
config["transform"] = libcamera.Transform(hflip=1, vflip=1)
picamera.configure(config)
picamera.start()
try:
while True:
# 捕获帧
frame = picamera.capture_array()
frame[..., [0, 2]] = frame[..., [2, 0]] # B 和 R 通道交换
# 转换为灰度图
gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 10)
# 人脸检测与伺服控制
for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2)
Xcent = x + w / 2
Ycent = y + h / 2
# 限制伺服角度范围
pan = max(0, min(180, pan))
tilt = max(0, min(180, tilt))
if (Xcent - dispW / 2) >=35:
pan -= step
if (Xcent - dispW / 2) <=-35:
pan += step
if (Ycent - dispH / 2) >= 35:
tilt += step
if (Ycent - dispH / 2) <= -35:
tilt -= step
# 设置伺服角度
kit.servo[0].angle = pan
kit.servo[1].angle = tilt
# 显示图像
frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
cv2.imshow("Camera Output", frame)
# 按 'q' 退出
if cv2.waitKey(1) & 0xFF == ord('q'):
break
finally:
# 释放资源
picamera.stop()
cv2.destroyAllWindows()
main.py
import Track_Display
try:
Track_Display.Track_Display()
except KeyboardInterrupt:
exit()
And here is the results👇
https://www.youtube.com/watch?v=UrInJ1_HSI0
Then, I added some other functions. If the face is located at the center of the screen, the program can take a photo and save it automatically, and then compare the photo with the database to determine if the face in these two images is from the same person. Here is the code👇
Face_Recognition.py
import cv2
import dlib
import numpy as np
# Load Dlib's face detection and face recognition models
detector = dlib.get_frontal_face_detector()
shape_predictor = dlib.shape_predictor('./source/shape_predictor_68_face_landmarks.dat')
face_encoder = dlib.face_recognition_model_v1('./source/dlib_face_recognition_resnet_model_v1.dat')
def get_face_encoding(image_path):
# Load image
img = cv2.imread(image_path)
# Convert to RGB (Dlib uses RGB images)
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# Detect faces
faces = detector(img_rgb)
if len(faces) == 0:
raise ValueError(f"No face found in the image:{image_path}")
if len(faces) > 1:
raise ValueError(f"Not only one face found in the image:{image_path}")
# Get the first face's landmarks
landmarks = shape_predictor(img_rgb, faces[0])
# Get the face encoding
encoding = face_encoder.compute_face_descriptor(img_rgb, landmarks)
return np.array(encoding)
def compare_faces(image_path1, image_path2):
# Get face encodings
encoding1 = get_face_encoding(image_path1)
encoding2 = get_face_encoding(image_path2)
# Compute the distance between the encodings
distance = np.linalg.norm(encoding1 - encoding2)
# Use a threshold to determine if they are the same person
threshold = 0.5 # You can adjust this threshold
return distance < threshold
def main(name):
# Paths to your images
image_path1 = f'image/data/{name}.jpg'
image_path2 = 'image/output.jpg'
# Compare the images
try:
if compare_faces(image_path1, image_path2):
print("The images are of the same person.")
else:
print("The images are of different people.")
except ValueError as e:
print(e)
main.py
import Track_Display
import Face_Recognition
try:
print("Track_Display开启")
Track_Display.Track_Display()
print("Track_Display结束")
print("Face_Recognition开启")
print("请输入您的姓名:")
mainname = input()
Face_Recognition.main(mainname)
print("Face_Recognition结束")
except KeyboardInterrupt:
exit()
Track_Display.py
import cv2
from picamera2 import Picamera2
import libcamera
from adafruit_servokit import ServoKit
import time
step = 1
# 初始化伺服电机控制
kit = ServoKit(channels=16)
temp = 0
temp1 = 0
temp2 = 0
temp3 = 0
temp4 = 0
# 初始伺服角度
pan = 90
tilt = 90
kit.servo[0].angle = pan
kit.servo[1].angle = tilt
# 摄像头分辨率
dispW, dispH = 640, 480
# 人脸检测模型加载
face_cascade = cv2.CascadeClassifier('./source/haarcascade_frontalface_default.xml')
def Track_Display():
"""摄像头视频采集与人脸检测"""
global pan, tilt,temp1,temp2,temp3,temp4,temp
# 初始化摄像头
picamera = Picamera2()
config = picamera.create_preview_configuration(
main={"format": 'RGB888', "size": (dispW, dispH)},
raw={"format": "SRGGB12", "size": (1920, 1080)}
)
config["transform"] = libcamera.Transform(hflip=1, vflip=1)
picamera.configure(config)
picamera.start()
try:
while True:
# 捕获帧
time.sleep(0.1)
frame = picamera.capture_array()
frame[..., [0, 2]] = frame[..., [2, 0]] # B 和 R 通道交换
# 转换为灰度图
gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
# 人脸检测与伺服控制
for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2)
Xcent = x + w / 2
Ycent = y + h / 2
# 限制伺服角度范围
pan = max(0, min(180, pan))
tilt = max(0, min(180, tilt))
if (Xcent - dispW / 2) >=35:
pan -= step
else:
temp1 = 1
if (Xcent - dispW / 2) <=-35:
pan += step
else:
temp2 = 1
if (Ycent - dispH / 2) >= 35:
tilt += step
else:
temp3 = 1
if (Ycent - dispH / 2) <= -35:
tilt -= step
else:
temp4 = 1
if temp1 ==1 and temp2 == 1 and temp3 == 1 and temp4 == 1:
temp = 1
if temp == 1:
frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
print ("拍摄中~")
cv2.imwrite("./image/output.jpg",frame)
print ("图片拍摄完成!")
break
kit.servo[0].angle = pan
kit.servo[1].angle = tilt
#//time.sleep(0.1)
if temp == 1:
break
else:
temp1 = 0
temp2 = 0
temp3 = 0
temp4 = 0
# 显示图像
frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
cv2.imshow("Camera Output", frame)
# 按 'q' 退出
if cv2.waitKey(1) & 0xFF == ord('q'):
break
finally:
# 释放资源
picamera.stop()
cv2.destroyAllWindows()
Here is the result👇