Итак, у меня есть проект для камеры следа, чтобы подсчитывать людей, входящих в след, обнаруживая их лица. Доступной мощности нет, поэтому я застрял на Raspberry Pi 3 B+ из-за питания. В настоящее время я использую каскады opencv и Haar для обнаружения лиц. Моя проблема двояка.
Я опубликую свой код ниже (собранный путем объединения нескольких примеров). В настоящее время также настроено использование многопоточности (еще один эксперимент, направленный на увеличение производительности). Насколько я могу судить, многопоточность работает, но на самом деле ничего не улучшает. Будем очень признательны за любую помощь, которую вы, ребята, могли бы оказать в решении проблемы счетчика или оптимизации каскадов Хаара для использования на Pi. ** Следует также отметить использование высококачественной камеры Rasp Pi и объективов Ardu Cam.
from __future__ import print_function
from imutils.video import VideoStream
from imutils.video.pivideostream import PiVideoStream
from imutils.video import FPS
from picamera.array import PiRGBArray
from picamera import PiCamera
import argparse
import imutils
import time
import cv2
# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-c", "--cascade", type=str,
default = "haarcascade_frontalface_default.xml",
help = "path to haar cascade face detector")
args = vars(ap.parse_args())
detector = cv2.CascadeClassifier(args["cascade"])
size = 40
counter = 0
# created threaded video
print("[INFO] using threaded frames")
vs = PiVideoStream().start()
time.sleep(2.0)
# loop over some frames...this time using the threaded stream
while True:
# grab the frame from the threaded video stream and resize it
# to have a maximum width of 400 pixels (trying larger frame size)
frame = vs.read()
frame = imutils.resize(frame, width=450)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# perform face detection
rects = detector.detectMultiScale(gray, scaleFactor=1.05,
minNeighbors=6, minSize=(size, size),
flags=cv2.CASCADE_SCALE_IMAGE)
# loop over the bounding boxes
for (x, y, w, h) in rects:
# draw the face bounding box on the image
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
# Increment counter when face is found
counter += 1
print(counter)
# show the output frame
cv2.imshow("Frame", frame)
key = cv2.waitKey(1) & 0xFF
# do a bit of cleanup
cv2.destroyAllWindows()
vs.stop()
Во-первых, вы можете использовать Dlib, как вы сказали, но для производительности вам нужно использовать метод «HOG» (гистограмма ориентированных градиентов) вместо «CNN».
locations = face_recognition.face_locations(frame, model = "hog")
Но если вы действительно хотите получить более высокую производительность, я рекомендую вам использовать Mediapipe для этой цели.
Загрузите Mediapipe на свой rpi3:
sudo pip3 install mediapipe-rpi3
Вот пример кода из документации Mediapipe для детектора лиц:
import cv2
import mediapipe as mp
mp_face_detection = mp.solutions.face_detection
mp_drawing = mp.solutions.drawing_utils
# For webcam input:
cap = cv2.VideoCapture(0)
with mp_face_detection.FaceDetection(
model_selection=0, min_detection_confidence=0.5) as face_detection:
while cap.isOpened():
success, image = cap.read()
if not success:
print("Ignoring empty camera frame.")
# If loading a video, use 'break' instead of 'continue'.
continue
# To improve performance, optionally mark the image as not writeable to
# pass by reference.
image.flags.writeable = False
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
results = face_detection.process(image)
# Draw the face detection annotations on the image.
image.flags.writeable = True
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
if results.detections:
for detection in results.detections:
mp_drawing.draw_detection(image, detection)
# Flip the image horizontally for a selfie-view display.
cv2.imshow('MediaPipe Face Detection', cv2.flip(image, 1))
if cv2.waitKey(5) & 0xFF == 27:
break
cap.release()
Я не уверен, сколько FPS вы получите (но точно лучше, чем Dlib и очень точно), но вы можете повысить производительность, обнаруживая лица на каждом третьем кадре, а не на всех.
Во-вторых, вы можете сделать наивный способ, который, вероятно, будет работать нормально. Вы можете извлечь центры ограничительных рамок в последнем обнаружении, и если центр из предыдущего кадра находится внутри ограничительной рамки лица в текущем кадре, это, вероятно, тот же человек.
Вы можете сделать это более точно, определив, достаточно ли близок новый центр лица в текущем кадре (центр его ограничительной рамки) к одному из последних центров в последнем кадре с помощью выбранного вами смещения. Если это так, это, вероятно, одно и то же лицо, так что просто не считайте его.
Визуализация:
Надеюсь, он будет работать хорошо для вас!
Отлично. Теперь, как вы предлагаете решить проблему счетчика лиц?
@JeruLuke Я отредактировал свой комментарий для этого: D, проверьте это!
Очень простой и эффективный подход+1
Я как бы надеялся найти способ исправить код, который у меня уже был, но я ценю подробный ответ. Я уже начал работать над установкой mediapipe (согласно их github, установка pip, по-видимому, больше не работает) и посмотрю, что я могу получить, используя этот метод. Я не слишком беспокоился о том, чтобы фиксировать одно и то же лицо более одного раза, поскольку они не будут находиться в кадре очень долго. В основном я хотел, чтобы счетчик увеличивался только один раз для каждой ограничивающей рамки (а не непрерывно, пока была блокировка. В любом случае, еще раз спасибо, и я продолжу и отмечу его как решенный.
@ jcoop7777 jcoop7777 Я не заметил, что установка pip больше не работает. О счетчике. Если вы действительно хотите знать, сколько разных лиц в вашем видео, я думаю, вам нужно заблокировать каждое лицо, чтобы правильно их подсчитать. Если вы хотите только подсчитать количество лиц для каждого кадра (даже если это одно и то же лицо), вы можете просто установить счетчик на 0 после показа изображения в цикле. counter=0
. Удачи!
Вам нужно решить первую проблему — отслеживание лица. Найдите отслеживание объектов с помощью OpenCV. Таким образом, каждое новое обнаруженное и отслеживаемое лицо будет увеличивать счетчик.