简体   繁体   English

将 RGB 图像数据从 Python numpy 发送到浏览器 HTML 页面

[英]Sending RGB image data from Python numpy to a browser HTML page

I need to send realtime image RGB data (in Numpy format) to a HTML page in a browser (web-based GUI), through HTTP.我需要通过 HTTP 将实时图像 RGB 数据(Numpy 格式)发送到浏览器(基于 Web 的 GUI)中的 HTML 页面。 The following code works with the well-known multipart/x-mixed-replace trick: run this and access http://127.0.0.1:5000/video_feed : you will see a video in the browser.以下代码适用于众所周知的multipart/x-mixed-replace技巧:运行此代码并访问http://127.0.0.1:5000/video_feed :您将在浏览器中看到一个视频。

from flask import Flask, render_template, Response
import numpy as np, cv2
app = Flask('')
def gen_frames():  
    while True:
        img = np.random.randint(0, 255, size=(1000, 1000, 3))
        ret, buf = cv2.imencode('.jpg', img)
        frame = buf.tobytes()
        yield (b'--frame\r\nContent-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
@app.route('/video_feed')
def video_feed():
    return Response(gen_frames(), mimetype='multipart/x-mixed-replace; boundary=frame')
app.run()

However, according to my benchmark, the real performance bottleneck is the cv2.imencode('.jpg', img) .但是,根据我的基准,真正的性能瓶颈是cv2.imencode('.jpg', img)

In my real application, if I just generate the image, the CPU is ~ 1% for Python.在我的实际应用程序中,如果我只是生成图像,Python 的 CPU 约为 1%。 When I imencode(...) , the CPU jumps to 25%, and 15% for Chrome.当我imencode(...)时,CPU 跳到 25%,Chrome 跳到 15%。

I also tried with PNG format but it's similar.我也尝试过使用 PNG 格式,但它是相似的。

Question: how to efficiently send RGB image data from a numpy array (example: 1000 x 1000 pixels x 3 colors because of RGB) to a browser HTML page?问题:如何有效地将 RGB 图像数据从 numpy 数组(例如:1000 x 1000 像素 x 3 colors 因为 RGB)发送到浏览器 Z4C4AD5FCA2E7A3AAF74DBB1CED00318 页面?

(Without compression/decompression it might be better, but how?) (没有压缩/解压缩可能会更好,但是如何?)

在此处输入图像描述

Here is the benchmark这是基准

          FPS       CPU PYTHON      CPU CHROME
PNG       10.8      20 %            10 %
JPG       14        23 %            12 %
JPG       10.7      16 %            10 %           (with time.sleep to match PNG 10.8 fps)
BMP       19        17 %            23 %
BMP       10.8      8 %             12 %           (with time.sleep to match PNG 10.8 fps)

Try using the PILLOW module instead and see if that improves performance.尝试改用PILLOW模块,看看是否能提高性能。 My benchmark shows that each iteration of the gen_frames() generator function based on PILLOW requires less than half the CPU of the CV2 version.我的基准测试表明,基于 PILLOW 的gen_frames()生成器 function 的每次迭代需要的 CPU 不到 CV2 版本的一半。

from flask import Flask, render_template, Response
from PIL import Image
import numpy as np
from io import BytesIO

app = Flask('')

def gen_frames():
    while True:
        img = np.random.randint(0, 255, size=(1000, 1000, 3), dtype=np.uint8)
        rgb_image = Image.fromarray(img, 'RGB')
        buf = BytesIO()
        rgb_image.save(buf, 'JPEG')
        frame = buf.getbuffer()
        yield (b'--frame\r\nContent-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')

@app.route('/video_feed')
def video_feed():
    return Response(gen_frames(), mimetype='multipart/x-mixed-replace; boundary=frame')

app.run()

According to the docs you could check if the default optimization is turned on:根据文档,您可以检查是否打开了默认优化:

Default Optimization in OpenCV OpenCV 中的默认优化

Many of the OpenCV functions are optimized using SSE2, AVX, etc. It contains the unoptimized code also.许多 OpenCV 函数使用 SSE2、AVX 等进行了优化。它还包含未优化的代码。 So if our system support these features, we should exploit them (almost all modern day processors support them).因此,如果我们的系统支持这些功能,我们应该利用它们(几乎所有现代处理器都支持它们)。 It is enabled by default while compiling.编译时默认启用。 So OpenCV runs the optimized code if it is enabled, otherwise it runs the unoptimized code.所以 OpenCV 如果启用则运行优化代码,否则运行未优化代码。 You can use cv.useOptimized() to check if it is enabled/disabled and cv.setUseOptimized() to enable/disable it.您可以使用 cv.useOptimized() 检查它是否启用/禁用,并使用 cv.setUseOptimized() 启用/禁用它。

So try this:所以试试这个:

In [5]: cv.useOptimized()         # check for optimization
Out[5]: False
In [7]: cv.setUseOptimized(True)  # turn it on if not already turned on

As it stands AVI or MP4 compression would be good quality even for movies, but the compression itself takes too much CPU time to perform it on live data.就目前而言,AVI 或 MP4 压缩即使对于电影来说也是很好的质量,但压缩本身需要太多的 CPU 时间来处理实时数据。

If some arbitrary protocol/format were created, one would not just have to program the server but also the client to consume this protocol/format.如果创建了一些任意协议/格式,则不仅需要对服务器进行编程,还需要对客户端进行编程以使用此协议/格式。 Therefore still some standard solution should be preferred.因此,仍应首选一些标准溶液。

I believe you can find a compromise between compression and CPU load in video conferencing systems, where the live camera data needs to be compressed and streamed via the network.我相信您可以在视频会议系统中找到压缩和 CPU 负载之间的折衷方案,其中实时摄像机数据需要通过网络进行压缩和流式传输。 With that in mind I believe here are sources of information that can help pursuing the topic:考虑到这一点,我相信这里有一些信息来源可以帮助研究这个主题:

Maybe you can try encoding it as base64 for compression of the video/image and then send it to the browser with the base64 mime type egdata:image/jpeg;base64.也许您可以尝试将其编码为 base64 以压缩视频/图像,然后使用 base64 mime 类型 egdata:image/jpeg;Z95A1446A7120E4AF5C0C8878ABB7E 将其发送到浏览器。

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

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