[英]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.