将图像数组转换为 io 字节对象以使用 'rb' 模拟打开

Turn image array to io bytes object to simulare open with 'rb'

我正在尝试使用请求将视频帧发送到远程服务器,我使用的代码是

def send_request(frame_path = "frame_on_disk_1.jpeg"):

    files = {'upload': with open(frame_path,"rb")}
    r = requests.post(URL, files=files)

    return r

所以我将帧写入磁盘,然后在发送到服务器时将它们作为字节读取,这不是最好的方法。

但是,我不确定如何将下面代码中的数组 由下面代码中的变量 frame 表示,直接转换为读取字节对象而不触及磁盘。

import cv2

cap = cv2.VideoCapture("video.MOV")


count = 0
while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()

    cv2.imwrite(f"all_frames/frame_num_{count}.png",frame)

您可以使用 io.BytesIO and cv2.imencode 将图像编码到内存缓冲区中。

我还使用了一个队列,这样帧就会被排队,然后 HTTP 请求在一个单独的线程中完成。

import traceback

import cv2

from io import BytesIO
from queue import Queue
from threading import Thread

from requests import Session


URL = "http://example.com"
THREADS = 5
SAMPLE = "sample.mov"


class UploaderThread(Thread):
    def __init__(self, q, s):
        super().__init__()

        self.q = q
        self.s = s

    def run(self):
        for count, file in iter(self.q.get, "STOP"):
            try:
                r = self.s.post(URL, files={"upload": file})
            except Exception:
                traceback.print_exc()
            else:
                print(f"Frame ({count}): {r}")


def main():
    cap = cv2.VideoCapture(SAMPLE)
    q = Queue()
    s = Session()
    count = 0

    threads = []

    for _ in range(THREADS):
        t = UploaderThread(q, s)
        t.start()
        threads.append(t)

    while True:
        ret, frame = cap.read()
        count += 1

        if not ret:
            break

        _, img = cv2.imencode(".png", frame)

        q.put_nowait((count, BytesIO(img)))

    for _ in range(THREADS):
        q.put("STOP")


if __name__ == "__main__":
    main()