У меня проблема с моими функциями. Я создаю систему распознавания лиц, которая должна работать следующим образом:
- Чтение видеофайла
- Использование opencv и haarcascade для распознавания кадров видео, где обнаружены человеческие лица
- Сохранить эти кадры локально`
К этому моменту все идет хорошо, вот функция, которую я использую для этих шагов:
import cv2
from imutils.video import FPS
import numpy as np
import argparse
import imutils
import os
async def take_snapshots(file):
cascPath = "haarcascade_frontalface_default.xml"
faceCascade = cv2.CascadeClassifier(cascPath)
# construct the argument parse and parse the arguments
# ap = argparse.ArgumentParser()
# ap.add_argument("-v", "--video", required=True,
# help="video.mp4")
# args = vars(ap.parse_args())
# open a pointer to the video stream and start the FPS timer
# stream = cv2.VideoCapture(args["video"])
stream = cv2.VideoCapture(file)
fps = FPS().start()
try:
# creating a folder named data
if not os.path.exists('data'):
os.makedirs('data')
# if not created then raise error
except OSError:
print('Error: Creating directory of data')
# frame
currentframe = 0
# loop over frames from the video file stream
while True:
# grab the frame from the threaded video file stream
(grabbed, frame) = stream.read()
# if the frame was not grabbed, then we have reached the end
# of the stream
if not grabbed:
break
# resize the frame and convert it to grayscale (while still
# retaining 3 channels)
frame = imutils.resize(frame, width=980)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
frame = np.dstack([frame, frame, frame])
faces = faceCascade.detectMultiScale(
frame,
scaleFactor=1.1,
minNeighbors=4,
minSize=(20, 20),
maxSize=(40, 40),
# flags=cv2.CASCADE_SCALE_IMAGE
)
for (x, y, w, h) in faces:
# cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 0, 0), 3)
if grabbed:
# Save just the rectangle faces in SubRecFaces
# sub_face = frame[y:y+h, x:x+w]
name = './data/frame' + str(currentframe) + '.jpg'
print('Creating...' + name)
# writing the extracted images
cv2.imwrite(name, frame)
currentframe += 1
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
# show the frame and update the FPS counter
# cv2.imshow("Frame", frame)
# cv2.waitKey(1)
fps.update()
# stop the timer and display FPS information
fps.stop()
print("[INFO] elasped time: {:.2f}".format(fps.elapsed()))
print("[INFO] approx. FPS: {:.2f}".format(fps.fps()))
# do a bit of cleanup
stream.release()
cv2.destroyAllWindows()
Возьмите сохраненный кадр и используйте aws rekognition api для обнаружения лиц с него (если вы хотите знать почему, это из-за точности) Сохраните новую копию из кадров, которые включают лица, с ограничивающие рамки
Шаг 4 проходит хорошо, проблем нет. когда код достигает шага 5, я сталкиваюсь с проблемой, когда мой код проходит через каждый кадр, сохраненный на шаге 3, он также пропускает два первых кадра, где нет граней. После этого он сохраняет frame2.jpg как pic0.jpg, как и положено. Проблема в том, что после этого он должен сохранять новую картинку (pic1, pic2 и c) из каждого кадра, но вместо этого он просто перезаписывает pic0.jpg при каждом раунде. Я знаю, что проблема с моим l oop, я просто не могу понять, как это исправить.
Вот функции, которые я использую для шагов 4 и 5:
import boto3
from pathlib import Path
import os
import cv2
import io
from PIL import Image, ImageDraw, ExifTags, ImageColor
async def detect_faces(photo):
image = Image.open(open(photo, 'rb'))
stream = io.BytesIO()
image.save(stream, format=image.format)
image_binary = stream.getvalue()
client = boto3.client('rekognition')
response = client.detect_faces(
Image={'Bytes': image_binary}, Attributes=['ALL'])
draw = ImageDraw.Draw(image)
print('Detected faces in ' + photo)
currentpic = 0
for face in response['FaceDetails']:
print('Confidence: ' + str(face['Confidence']))
box = face['BoundingBox']
imgWidth, imgHeight = image.size
left = imgWidth * box['Left']
top = imgHeight * box['Top']
width = imgWidth * box['Width']
height = imgHeight * box['Height']
# print('Left: ' + '{0:.0f}'.format(left))
# print('Top: ' + '{0:.0f}'.format(top))
# print('Face Width: ' + "{0:.0f}".format(width))
# print('Face Height: ' + "{0:.0f}".format(height))
points = (
(left, top),
(left + width, top),
(left + width, top + height),
(left, top + height),
(left, top)
)
draw.line(points, fill='#00d400', width=2)
name = './results/pic' + str(currentpic) + '.jpg'
print('Creating final pic.....' + name)
image.save(name)
currentpic += 1
return len(response['FaceDetails'])
async def main():
directory_in_str = './data'
pathlist = Path(directory_in_str).glob('**/*.jpg')
try:
if not os.path.exists('results'):
os.makedirs('results')
# if not created then raise error
except OSError:
print('Error: Creating directory of data')
for path in pathlist:
# path is object not string
path_in_str = str(path)
# print(path_in_str)
photo = path_in_str
face_count = await detect_faces(photo)
print("Faces detected: " + str(face_count))
Наконец, вот основная функция, которую я использую для запуска этих функций:
import read_frames_slow
import detect_faces
import asyncio
async def main():
await read_frames_slow.take_snapshots('video.mp4')
await detect_faces.main()
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()
Буду очень признателен за помощь в решении этой проблемы.