如何使用 python 函数遍历从另一个函数接收的文件



我的函数遇到了问题。我正在构建一个人脸识别系统,它应该像这样工作:

  1. 读取视频文件
  2. 使用 opencv 和 haarcascade 识别视频中检测到人脸的帧
  3. 将这些帧保存在本地'

到目前为止,一切顺利,这是我用来执行这些步骤的函数:

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()
  1. 获取保存的帧并使用 AWS rekognition API 从中检测人脸(如果您想知道原因,那是因为准确性(
  2. 从包含面的框架中保存新副本,并带有边界框

当代码到达步骤 5 时,我遇到了一个问题,我的代码遍历了步骤 3 保存的每一帧,它还跳过了没有人脸的前两个帧。之后,它将帧 2.jpg 保存为 pic0.jpg,这是应该的。问题是,之后它应该从每一帧中保存一张新图片(pic1、pic2 等(,但它只是在每一轮中覆盖 pic0.jpg。我知道问题出在我的循环上,我只是不知道如何解决它。

以下是我用于步骤 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()

真的很感激帮助解决这个问题。

使用pathlib.Path对象而不是字符串 (https://pillow.readthedocs.io/en/stable/reference/Image.html(

喜欢

im.save(os.path.join(r"C:Usersabc123DesktopMovie", f + ext), "JPEG" )

在文件中未保存在使用 PIL im.save 的特定目录中

因为name = './results/pic' + str(currentpic) + '.jpg'被解释为字符串或文件名,而不是路径(参见https://pillow.readthedocs.io/en/stable/reference/Image.html,Python 将 str 转换为路径类型?

最新更新