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

发布于 2025-02-09 04:57:57 字数 1485 浏览 1 评论 0 原文

我需要通过HTTP将实时图像RGB数据(以Numpy格式)发送到浏览器(基于Web的GUI)的HTML页面。 以下代码可与众所周知的 multipart/x-mixed-replace trick:运行此并访问 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()

但是,根据我的基准,真正的性能瓶颈是 cv2.imencode('。jpg',img)

在我的真实应用中,如果我只是生成图像,则Python的CPU为1%。 当i Imencode(...)时,CPU跳至25%,Chrome为15%。

我也尝试使用PNG格式,但相似。

问题:如何有效地从numpy数组(示例:1000 x 1000像素x 3颜色)将RGB图像数据发送到浏览器HTML页面?

(没有压缩/压缩,它可能会更好,它可能会更好, 呢?

但是如何 =“在此处输入图像描述”>

这是基准

          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)

I need to send realtime image RGB data (in Numpy format) to a HTML page in a browser (web-based GUI), through HTTP.
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.

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).

In my real application, if I just generate the image, the CPU is ~ 1% for Python.
When I imencode(...), the CPU jumps to 25%, and 15% for Chrome.

I also tried with PNG format but it's similar.

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?

(Without compression/decompression it might be better, but how?)

enter image description here

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

尾戒 2025-02-16 04:57:57

尝试使用枕头模块,看看是否可以改善性能。我的基准表明,基于枕头的 gen_frames()生成器功能的每次迭代都需要CV2版本的CPU的一半。

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()

Try using the PILLOW module instead and see if that improves performance. 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.

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()
仅一夜美梦 2025-02-16 04:57:57

根据文档,您可以检查默认优化是否已打开:

OpenCV中的默认优化

使用SSE2,AVX等优化了许多OPENCV函数。它还包含未优化的代码。因此,如果我们的系统支持这些功能,我们应该利用它们(几乎所有现代处理器都支持它们)。默认情况下启用了编译时。因此,如果启用了OpenCV,则运行优化的代码,否则它运行未优化的代码。您可以使用cv.useoptimized()检查是否启用/禁用和cv.setUseOptimized()启用/禁用。

因此,请尝试以下操作:

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

According to the docs you could check if the default optimization is turned on:

Default Optimization in OpenCV

Many of the OpenCV functions are optimized using SSE2, AVX, etc. It contains the unoptimized code also. 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. You can use cv.useOptimized() to check if it is enabled/disabled and cv.setUseOptimized() to enable/disable it.

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
失与倦" 2025-02-16 04:57:57

因为它的架子或MP4压缩对于电影来说也是好的质量,但是压缩本身需要太多的CPU时间来在实时数据上执行它。

如果创建了某些任意协议/格式,则不仅要编程服务器,还需要对客户端进行编程来消耗此协议/格式。因此,仍然应该优选一些标准解决方案。

我相信,您可以在视频会议系统中找到压缩和CPU负载之间的折衷,其中实时相机数据需要通过网络压缩和流式传输。考虑到这一点,我相信这里有可以帮助追求该主题的信息来源:

  • ​://jitsi.org/jitsi-meet/“ rel =“ nofollow noreferrer”> jitsi Meet 或

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.

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. With that in mind I believe here are sources of information that can help pursuing the topic:

穿透光 2025-02-16 04:57:57

也许您可以尝试将其编码为base64以压缩视频/图像,然后将其发送给base64 Mime型EGDATA:Image/jpeg; base64。

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 e.g.data:image/jpeg;base64.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文