Попытка подсчета лиц с использованием OpenCV, каскадов Хаара и Raspberry PI

Итак, у меня есть проект для камеры следа, чтобы подсчитывать людей, входящих в след, обнаруживая их лица. Доступной мощности нет, поэтому я застрял на Raspberry Pi 3 B+ из-за питания. В настоящее время я использую каскады opencv и Haar для обнаружения лиц. Моя проблема двояка.

  1. Во-первых, мой счетчик больше похож на таймер. Он продолжает увеличиваться все время, пока он заблокирован на том, что он считает лицом. Поведение, которое мне нужно, заключается в том, чтобы оно увеличивалось только один раз, когда оно получает обнаружение, а не снова, пока это обнаружение не будет потеряно, а затем повторно инициализировано. Мне также нужно, чтобы это работало, если обнаружено несколько лиц.
  2. Вторая проблема заключается в том, что каскады Хаара плохо распознают лица. Я играл с параметрами, но не могу получить отличный результат. Также пробовал другие методы, такие как Dlib, но частота кадров делает его практически непригодным для использования на pi 3.

Я опубликую свой код ниже (собранный путем объединения нескольких примеров). В настоящее время также настроено использование многопоточности (еще один эксперимент, направленный на увеличение производительности). Насколько я могу судить, многопоточность работает, но на самом деле ничего не улучшает. Будем очень признательны за любую помощь, которую вы, ребята, могли бы оказать в решении проблемы счетчика или оптимизации каскадов Хаара для использования на 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()

Вам нужно решить первую проблему — отслеживание лица. Найдите отслеживание объектов с помощью OpenCV. Таким образом, каждое новое обнаруженное и отслеживаемое лицо будет увеличивать счетчик.

Jeru Luke 05.05.2022 21:30
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
1
81
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Во-первых, вы можете использовать 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 и очень точно), но вы можете повысить производительность, обнаруживая лица на каждом третьем кадре, а не на всех.

Во-вторых, вы можете сделать наивный способ, который, вероятно, будет работать нормально. Вы можете извлечь центры ограничительных рамок в последнем обнаружении, и если центр из предыдущего кадра находится внутри ограничительной рамки лица в текущем кадре, это, вероятно, тот же человек.

Вы можете сделать это более точно, определив, достаточно ли близок новый центр лица в текущем кадре (центр его ограничительной рамки) к одному из последних центров в последнем кадре с помощью выбранного вами смещения. Если это так, это, вероятно, одно и то же лицо, так что просто не считайте его.

Визуализация:

Надеюсь, он будет работать хорошо для вас!

Отлично. Теперь, как вы предлагаете решить проблему счетчика лиц?

Jeru Luke 05.05.2022 22:36

@JeruLuke Я отредактировал свой комментарий для этого: D, проверьте это!

Roy Amoial 05.05.2022 22:45

Очень простой и эффективный подход+1

Jeru Luke 05.05.2022 22:47

Я как бы надеялся найти способ исправить код, который у меня уже был, но я ценю подробный ответ. Я уже начал работать над установкой mediapipe (согласно их github, установка pip, по-видимому, больше не работает) и посмотрю, что я могу получить, используя этот метод. Я не слишком беспокоился о том, чтобы фиксировать одно и то же лицо более одного раза, поскольку они не будут находиться в кадре очень долго. В основном я хотел, чтобы счетчик увеличивался только один раз для каждой ограничивающей рамки (а не непрерывно, пока была блокировка. В любом случае, еще раз спасибо, и я продолжу и отмечу его как решенный.

jcoop7777 06.05.2022 01:21

@ jcoop7777 jcoop7777 Я не заметил, что установка pip больше не работает. О счетчике. Если вы действительно хотите знать, сколько разных лиц в вашем видео, я думаю, вам нужно заблокировать каждое лицо, чтобы правильно их подсчитать. Если вы хотите только подсчитать количество лиц для каждого кадра (даже если это одно и то же лицо), вы можете просто установить счетчик на 0 после показа изображения в цикле. counter=0. Удачи!

Roy Amoial 06.05.2022 01:56

Другие вопросы по теме