python-3.x - 如何使用python函数迭代从另一个函数接收的文件

标签 python-3.x opencv for-loop amazon-rekognition

我遇到了我的功能问题。我正在构建一个面部识别系统,它应该像这样工作:

  • 读取视频文件
  • 使用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等),但是每轮它只会覆盖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:\Users\abc123\Desktop\Movie", f + ext), "JPEG" )
    file is not saved in particular directory using PIL im.save

    因为name = './results/pic' + str(currentpic) + '.jpg'解释为字符串或文件名,而不是路径(请参见https://pillow.readthedocs.io/en/stable/reference/Image.html Python convert a str to path type? )

    关于python-3.x - 如何使用python函数迭代从另一个函数接收的文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59678408/

    相关文章:

    Python deepcopy 使用的内存比需要的多

    excel - 使用python对excel中的行进行分组

    python - 通过 python DictReader 从 csv 中读取列表

    python - 如何使用opencv python将YUV_420_888转换为BGR?

    opencv - 如何在 OpenCV 中匹配同一对象的两个不同图像的方向和比例?

    python - 如何在条件为真时至少执行一次循环操作

    c# - 从 MinValue 迭代到 MaxValue 并溢出

    perl - 试图预测 future 的结果,collat​​z,Perl

    Pythondecimal.Decimal以科学记数法产生结果

    c++ - 眼镜检测