繁体   English   中英

如何避免循环中的代码阻塞

[英]How to avoid code blocking in a loop

我正在尝试从远程视频流服务器提取帧,图像的类型为mjpeg ,然后上传到Google Cloud Storage中的存储桶。

通过我的测试,我能够每秒稳定地提取约30张图像并将帧保存在机器中。 但是,当我尝试使用其客户端库将所有单个框架上传到GCS时,它将等待上传过程首先完成,然后返回并上传新接收到的框架。

例如,在1秒内,我希望接收并上传所有0...30张图像,但是由于我的代码是异步的,因此它仅上传循环中收到的最新图像。

这是我的代码

class GCStream:

    def __init__(self):
        self.client = storage.Client()
        self.bucket = self.client.get_bucket(BUCKET_NAME)
        self.frame = None
        self.fileName = ""
        self.secondCount = 0
        self.startSecond = datetime.datetime.now().second
        self.vs = VideoStream(src=REMOTE_STREAM_MJPEG).start()


    def uploadFrame(self):
        try:
            blob = self.bucket.blob("{}/{}/{}".format(RPID_FOLDER, BY_DAY, self.fileName))
            blob.upload_from_filename(os.path.abspath(self.fileName))
            print("{} uploaded to {}/{}".format(self.fileName, RPID_FOLDER, BY_DAY))
            os.remove(self.fileName)
        except Exception as e:
            print(e)


    def readFrame(self):
        while True:
            self.frame = self.vs.read()
            self.secondCount = self.secondCount + 1

            if datetime.datetime.now().second != self.startSecond:
                self.startSecond = datetime.datetime.now().second
                self.secondCount = 0

            if self.frame is not None:
                self.frame = imutils.resize(self.frame, 800)
                self.fileName = "{}-{}.png".format(datetime.datetime.now().strftime("%H-%M-%S"), self.secondCount)
                cv2.imwrite(self.fileName, self.frame)

                self.uploadFrame()

                if cv2.waitKey(1) & 0xFF == ord('q'):
                    break

        vs.release()
        cv2.destroyAllWindows() 


if __name__ == "__main__":
    stream = GCStream()
    stream.readFrame()

在此处输入图片说明

经过数小时的反复试验,我终于设法实现了我想要的。 实质是在我的程序中使用线程,以便它不会阻止其余代码的处理。

我的程序现在具有单独的线程来分别抓取,处理和上载帧。 因此,一个线程能够收集所有图像,而其他线程将能够同时处理和上传图像。

QUEUE_SIZE = 120

grabbedFrames = Queue(QUEUE_SIZE)
processFrames = Queue(QUEUE_SIZE)


class FrameGraber(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)
        self.vs = VideoStream(src=REMOTE_STREAM_MJPEG).start()

    def run(self):
        global grabbedFrames

        while True:
            frame = self.vs.read()
            if frame is not None:
                grabbedFrames.put(frame)
                time.sleep(0.05)


class GCSUploader(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)
        self.client = storage.Client()
        self.bucket = self.client.get_bucket(BUCKET_NAME)

    def run(self):
        global processFrames

        while True:
            if (not processFrames.empty()):
                fileName = processFrames.get()
                try:
                    blob = self.bucket.blob("{}/{}/{}".format(RPID_FOLDER, BY_DAY, fileName))
                    blob.upload_from_filename(os.path.abspath(fileName))
                    print("{} uploaded to {}/{}".format(fileName, RPID_FOLDER, BY_DAY))
                    os.remove(fileName)
                except Exception as e:
                    print(e)


class FrameProcessor(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)
        self.secondCount = 0
        self.startSecond = datetime.datetime.now().second

    def run(self):
        global grabbedFrames, processFrames
        while True:

            if datetime.datetime.now().second != self.startSecond:
                self.startSecond = datetime.datetime.now().second
                self.secondCount = 0

            if (not grabbedFrames.empty()):
                frame = grabbedFrames.get()
                self.secondCount = self.secondCount + 1
                frame = imutils.resize(frame, 800)
                fileName = "{}-{}.png".format(datetime.datetime.now().strftime("%H-%M-%S"), self.secondCount)
                processFrames.put(fileName)
                cv2.imwrite(fileName, frame)


if __name__ == "__main__":
    uploader = GCSUploader()
    frameGrabber = FrameGraber()
    frameProcessor = FrameProcessor()

    uploader.start()
    frameGrabber.start()
    frameProcessor.start()

    frameProcessor.join()
    frameGrabber.join()
    uploader.join()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM