简体   繁体   English

从传入的原始图像数据更新 HTML 页面上的视频帧

[英]Update frames of a video on a HTML page, from incoming raw image data

I have raw image data (1000 x 1000 pixels x 3 bytes per pixel) in Python, that I need to send to a HTML page in realtime, at 20 frames per second (this is 57 MB of data per second!).我在 Python 中有原始图像数据(1000 x 1000 像素 x 3 字节/像素),我需要以每秒 20 帧的速度实时发送到 HTML 页面(这是每秒 57 MB 的数据!)。

I already tried the multipart/x-mixed-replace method (as seen in Sending RGB image data from Python numpy to a browser HTML page ), with various encoding: BMP, PNG, JPG.我已经尝试了multipart/x-mixed-replace方法(如Sending RGB image data from Python numpy to a browser HTML page中所见),具有各种编码:BMP、PNG、JPG。 It is quite intensive for the CPU, so I'm trying alternatives.这对 CPU 来说非常密集,所以我正在尝试替代方案。

I am now getting the raw image data directly in JavaScript with binary XHR HTTP requests.我现在通过二进制 XHR HTTP 请求直接在 JavaScript 中获取原始图像数据。

Question: How to (CPU-efficiently) decode binary RGB data from dozens of binary XHR HTTP requests into a <video> or <img> or <canvas> on a HTML page, with Javascript?问题:如何(高效地)使用 JavaScript 将来自数十个二进制 XHR HTTP 请求的二进制 RGB 数据解码为 HTML 页面上的<video><img><canvas>

oReq = new XMLHttpRequest();
oReq.open("GET", "/imagedata", true);
oReq.responseType = "arraybuffer";
oReq.onload = function (oEvent) {
  var arrayBuffer = oReq.response;
  if (arrayBuffer) {
    var byteArray = new Uint8Array(arrayBuffer);
    // update displayed image
  }
};
oReq.send(null);

Edit: The method given in @VC.One's comment: var byteArray = new Uint8ClampedArray(arrayBuffer); var imgData = new ImageData(byteArray, 1000, 1000); var ctx = myCanvas.getContext('2d'); ctx.putImageData(imgData, 0, 0);编辑:@VC.One 评论中给出的方法: var byteArray = new Uint8ClampedArray(arrayBuffer); var imgData = new ImageData(byteArray, 1000, 1000); var ctx = myCanvas.getContext('2d'); ctx.putImageData(imgData, 0, 0); var byteArray = new Uint8ClampedArray(arrayBuffer); var imgData = new ImageData(byteArray, 1000, 1000); var ctx = myCanvas.getContext('2d'); ctx.putImageData(imgData, 0, 0); works and is lighter for the CPU: 5%-6% for the server sending the data vs. 8%-20% with BMP/PNG/JPG encoding .工作并且对 CPU 来说更轻:5%-6% 用于服务器发送数据,而8%-20% 使用 BMP/PNG/JPG 编码 But Chromium now has two processes in parallel for this task, each of them ~ 15% CPU .但是 Chromium 现在有两个并行的进程来完成这个任务,每个进程都有 ~ 15% CPU So the total performance is not much better.所以整体性能也好不了多少。 Do you see other potential alternatives to efficiently send raw image data from a Python or C++ HTTP server to Chromium?您是否看到其他潜在的替代方案可以有效地将原始图像数据从 Python 或 C++ HTTP 服务器发送到 Chromium?

Also new ImageData(...) requires a 1000x1000x4 bytes array for R, G, B, A. This requires that I send alpha channel that I don't need;同样new ImageData(...)需要一个 1000x1000x4 字节数组用于 R、G、B、A。这要求我发送不需要的 alpha 通道; maybe there's a way with ImageData to only pass a RGB (nxnx3 bytes) array?也许ImageData有办法只传递一个 RGB(nxnx3 字节)数组?


Edit 2: the real bottleneck is the XHR HTTP requests between my process #1 and process #2 (Chrome) on the same computer for up to 100 MB/sec.编辑 2:真正的瓶颈是同一台计算机上我的进程#1 和进程#2 (Chrome) 之间的 XHR HTTP 请求,速度高达 100 MB/秒。 Is there a more direct inter process communication possible between process #1 and Chrome?进程 #1 和 Chrome 之间是否有更直接的进程间通信? (some sort of direct memory access?) (某种直接内存访问?)

See Chrome + another process: interprocess communication faster than HTTP / XHR requests?查看Chrome + 另一个进程:进程间通信比 HTTP/XHR 请求更快?

There is another way, but it will take a lot of new material.还有另一种方法,但需要大量的新材料。 First, use requests on python to send your info to a page, say /internals/port by doing something like this:首先,使用 python 上的请求将您的信息发送到页面,例如/internals/port通过执行以下操作:

import requests

url = 'http://random.com/internals/port'
query = {'field': value}
res = requests.post(url, data=query)

then, use a fetch() from your website in js.然后,在 js 中从您的网站使用fetch() for example:例如:

fetch('/internals/port').then(res=>{
res.text().then(text=>{
//here text is your data. 
// you can also use an await fetch statement so things aren't wrapped up in the two functions. 
})
})

Try instead to send your info in 64bit since you can use data:image/png;64bit as its own 64bit parser:尝试以 64 位发送您的信息,因为您可以使用data:image/png;64bit作为其自己的 64 位解析器:

data:image/png;64bit,xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

if you insist on using binary, then try using a filereader to parse it into 64bit,如果您坚持使用二进制,则尝试使用文件阅读器将其解析为 64 位,

var reader = new FileReader(
  reader.onload = (function(self) {
    return function(e) {
      document.getElementById("img").src = e.target.result;
    }
  })(this);
  reader.readAsDataURL(new Blob([r]));

it will take a bit more time but still worth it.这将需要更多时间,但仍然值得。

you can just use an <img> tag in your html and set the url to a data:image/png;base64 data url that you generate.您可以在 html 中使用<img>标记并将 url 设置为您生成的data:image/png;base64数据 url。 Still, coming back on your comment on the ImageData() class you can just set the alpha to 1, or 100%, since it is the opacity, so just incluce a 1 at the end of the array when you feed it into new ImageData() .尽管如此,回到您对ImageData()类的评论,您可以将 alpha 设置为 1 或 100%,因为它是不透明度,因此当您将其输入new ImageData()时,只需在数组末尾包含一个 1 new ImageData() Good luck on your project, I hope you successfully find a way to do what you want to, whether it be with my answer or with another.祝你的项目好运,我希望你成功地找到一种方法来做你想做的事,无论是我的答案还是其他的。 I believe that I have answered all your questions, and as a final suggestion, try changing your python backend to node.js, and use express requests to post images that can be accessed in pretty much the same way as using requests in python.我相信我已经回答了你所有的问题,作为最后的建议,尝试将你的 python 后端更改为 node.js,并使用快速请求来发布可以访问的图像,其访问方式与在 python 中使用请求的方式几乎相同。 It would be much more efficient and much faster.它会更有效率,也更快。

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

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